From ae37602516c480bd2d1763364ecf2809fb882cde Mon Sep 17 00:00:00 2001 From: Ian C Date: Sat, 27 Oct 2012 22:59:31 +0000 Subject: Check-in before server relocation. --- WPZX81/WPZX81/ZX81/Emulation.cs | 231 ++++++---------------------------------- 1 file 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 times /// elements. /// - public ushort[] Screen {get {return display.Screen;}} + public ushort[] Screen {get {return screen;}} #endregion @@ -337,10 +248,18 @@ namespace WPZX81.ZX81 /// 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(); } /// @@ -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; } -- cgit v1.2.3