diff options
| -rw-r--r-- | WPZX81/WPZX81/ZX81/Emulation.cs | 231 | 
1 files changed, 34 insertions, 197 deletions
| diff --git a/WPZX81/WPZX81/ZX81/Emulation.cs b/WPZX81/WPZX81/ZX81/Emulation.cs index f7a851a..fdc0ef7 100644 --- a/WPZX81/WPZX81/ZX81/Emulation.cs +++ b/WPZX81/WPZX81/ZX81/Emulation.cs @@ -33,62 +33,8 @@ namespace WPZX81.ZX81      {
          #region Private data
 -        private class Display
 -        {
 -            private ushort[] screen;
 -            private int x;
 -            private int y;
 -            private int w;
 -            private int h;
 -
 -            public Display(int w, int h)
 -            {
 -                this.screen = new ushort[w * h];
 -                this.w = w;
 -                this.h = h;
 -                this.x = 0;
 -                this.y = 0;
 -            }
 -
 -            public ushort[] Screen {get {return screen;}}
 -
 -            private int count;
 -            private int invalid;
 -
 -            public void Reset()
 -            {
 -                Debug.WriteLine("Display: {0} writes done ({1} invalid).  Ended up at {2},{3} out of {4}, {5}", count, invalid, x, y, w, h);
 -                count = 0;
 -                invalid = 0;
 -
 -                x = 0;
 -                y = 0;
 -
 -                this.screen = new ushort[w * h];
 -            }
 -
 -            public void Write(ushort v)
 -            {
 -                if (x < w)
 -                {
 -                    screen[x++ + y * w] = v;
 -                }
 -                else
 -                {
 -                    invalid++;
 -                }
 -
 -                count++;
 -            }
 -
 -            public void NextLine()
 -            {
 -                x = 0;
 -                y = (y + 1) % h;
 -            }
 -        }
 -
          private Clock       clock;
 +        private ushort[]    screen;
          private byte[]      mem;
          private int         vsync;
          private bool        hsync;
 @@ -99,7 +45,6 @@ namespace WPZX81.ZX81          private int         ramtop;
          private byte[]      matrix;
          private int         lastR6;
 -        private Display     display;
          // Some system variables
          //
 @@ -133,6 +78,11 @@ namespace WPZX81.ZX81              0xc3, 0x07, 0x02,       /* JP $0207             */
          };
 +        private byte[] retPatch = new byte[]
 +        {
 +            0xc9                    /* ret                  */
 +        };
 +
          private byte[] fastPatch = new byte[]
          {
              0xed, ED_WAITKEY,       /* (START KEY WAIT)     */
 @@ -206,6 +156,8 @@ namespace WPZX81.ZX81          {
              Patch(0x2fc, savePatch);
              Patch(0x347, loadPatch);
 +            Patch(0x2bc, retPatch);
 +
              // Patch(0x4ca, fastPatch);
              // Patch(0x2bb, keyboardPatch);
              // Patch(0xf3a, pausePatch);
 @@ -243,58 +195,17 @@ namespace WPZX81.ZX81              }
          }
 -        private bool OperationCallback(ICpu sender)
 +        private void GenerateScreen()
          {
 -            // During VSYNC, keep resetting the clock
 -            //
 -            if (vsync > 0)
 -            {
 -                vsync++;
 -                clock.CycleCount = 0;
 -            }
 -            else
 +            ushort p = PeekWord(D_FILE);
 +
 +            for(int y = 0; y < 24; y++)
              {
 -                // If we're out of VSYNC, see if we need to generate an interrupt
 -                //
 -                if (clock.CycleCount >= 224)
 +                for(int x = 0; x < 32; x++)
                  {
 -                    clock.CycleCount -= 224;
 -
 -                    if (nmiGenerator)
 -                    {
 -                        Z80.NonMaskableInterrupt(0xff);
 -                    }
 +                    p++;
                  }
              }
 -
 -            // Maskable interupts are tied to bit 6 of the refresh register.
 -            //
 -            if ((Z80.Refresh & 0x40) == 0) // && lastR6 == 0x20)
 -            {
 -                Z80.MaskableInterrupt(0xff);
 -                display.NextLine();
 -                lineCounter = (lineCounter + 1) % 8;
 -            }
 -
 -            // Record last bit 6 of the refresh register
 -            //
 -            lastR6 = Z80.Refresh & 0x20;
 -
 -            // The frame finishes when VSYNC is triggered (ie. HYSNC is off).
 -            // Note we wait until we've had a good few opcodes with VSYNC happening as some hi-res routines trigger short blasts of VSYNC.
 -            //
 -            if (vsync > 20 && !vsyncNoted)
 -            {
 -                display.Reset();
 -                vsyncNoted = true;
 -                return false;
 -            }
 -            else
 -            {
 -                // Make sure we're not in a state where good operations aren't happening
 -                //
 -                return (Z80.ExecutedInstructions < 65000);
 -            }
          }
          #endregion
 @@ -326,7 +237,7 @@ namespace WPZX81.ZX81          /// This array must have <see cref="Width"/> times <see cref="Height"/>
          /// elements.
          /// </summary>
 -        public ushort[] Screen {get {return display.Screen;}}
 +        public ushort[] Screen {get {return screen;}}
          #endregion
 @@ -337,10 +248,18 @@ namespace WPZX81.ZX81          /// </summary>
          public void Run()
          {
 -            display.Reset();
 -            Z80.ExecutedInstructions = 0;
 -            Z80.Run(OperationCallback);
 -            Debug.WriteLine("Executed instructions {0}", Z80.ExecutedInstructions);
 +            // Check FAST flag
 +            //
 +            if ((mem[CDFLAG] & 0x80) == 0)
 +            {
 +                Z80.Run();
 +                Z80.Run();
 +                Z80.Run();
 +            }
 +
 +            Z80.Run();
 +
 +            GenerateScreen();
          }
          /// <summary>
 @@ -375,7 +294,10 @@ namespace WPZX81.ZX81              rambot = Settings.StaticRamAt0x2000 ? 0x2000 : 0x4000;
              ramtop = Settings.RamPack ? 0x8000 : 0x4400;
 -            mem.Initialize();
 +            for(int f = 0 ; f < mem.Length; f++)
 +            {
 +                mem[f] = 0;
 +            }
              for(int f = 0 ; f < 8; f++)
              {
 @@ -410,8 +332,8 @@ namespace WPZX81.ZX81          {
              matrix = new byte[8];
              mem = new byte[0x10000];
 -            display = new Display(Width, Height);
 -            clock = new Clock(16000, 50, 1, 50);
 +            screen = new ushort[Width * Height];
 +            clock = new Clock(0, 16000, 1, 0);
              Z80 = new Z80Cpu();
              Z80.Initialise(this, this, clock);
              Z80.EDNopEvent += EDCallback;
 @@ -424,56 +346,7 @@ namespace WPZX81.ZX81          byte IMemory.Read(ushort address)
          {
 -            // Reads above 0x8000 are grabbed by the ULA to generate the display.  We only do this if the hysnc generator is enabled.
 -            //
 -            if (address >= 0x8000 && hsync)
 -            {
 -                byte b = mem[address & 0x7fff];
 -
 -                // Opcodes with bit 6 are still passed to the CPU.
 -                //
 -                if ((b & 0x20) == 0x20)
 -                {
 -                    for(int pixel = 0; pixel < 8; pixel++)
 -                    {
 -                        display.Write(0xffff);
 -                    }
 -
 -                    return b;
 -                }
 -                else
 -                {
 -                    int inv = (b & 0x80);
 -                    b |= 0x3f;
 -
 -                    int bitmap = mem[(int)Z80.InterruptVector << 8 | (int)b << 3 | lineCounter];
 -
 -                    if (inv != 0)
 -                    {
 -                        bitmap = ~bitmap;
 -                    }
 -
 -                    for(int pixel = 7; pixel >= 0; pixel--)
 -                    {
 -                        if ((bitmap & (1 << pixel)) == 0)
 -                        {
 -                            display.Write(0xffff);
 -                        }
 -                        else
 -                        {
 -                            display.Write(0);
 -                        }
 -                    }
 -
 -                    // Return NOP
 -                    //
 -                    return 0;
 -                }
 -            }
 -            else
 -            {
 -                return mem[address];
 -            }
 +            return mem[address & 0x7fff];
          }
          void IMemory.Write(ushort address, byte value)
 @@ -499,19 +372,6 @@ namespace WPZX81.ZX81                  // ULA
                  //
                  case 0xfe:
 -
 -                    // Once the ULA is read the vsync video level is triggered and the HYSNC switched off if NMI generation is off.
 -                    // Rather than just a boolean, we not how many opcode VSYNC has been active.  This stops us getting
 -                    // confused by IN A,(FE) / OUT (FF),A pairs used to reset the ULA LINECTR.
 -                    //
 -                    vsync = 1;
 -                    vsyncNoted = false;
 -
 -                    if (!nmiGenerator)
 -                    {
 -                        hsync = false;
 -                    }
 -
                      switch(device&0xff00)
                      {
                          case 0xfe00:
 @@ -558,29 +418,6 @@ namespace WPZX81.ZX81          {
              switch(device & 0xff)
              {
 -                // Turns off the NMI generator
 -                //
 -                case 0xfd:
 -                    nmiGenerator = false;
 -                    break;
 -
 -                // Turns on the NMI generator
 -                //
 -                case 0xfe:
 -                    nmiGenerator = true;
 -                    clock.CycleCount = 0;
 -                    break;
 -
 -                // The ZX81 sends an OUT FF,A after the VSYNC to start HYSNC generation,
 -                // which puts the ULA back to 'white' output and releases the reset on the
 -                // ULA LINECTR.
 -                //
 -                case 0xff:
 -                    vsync = 0;
 -                    hsync = true;
 -                    lineCounter = 0;
 -                    break;
 -
                  default:
                      break;
              }
 | 
