diff --git a/Assets/NES/Palettes/FCEUX.pal b/Assets/NES/Palettes/FCEUX (2.2.0).pal similarity index 66% rename from Assets/NES/Palettes/FCEUX.pal rename to Assets/NES/Palettes/FCEUX (2.2.0).pal index 2b8ea5d63e..7bf9128fb5 100644 Binary files a/Assets/NES/Palettes/FCEUX.pal and b/Assets/NES/Palettes/FCEUX (2.2.0).pal differ diff --git a/Assets/gamedb/gamedb_sega_gg.txt b/Assets/gamedb/gamedb_sega_gg.txt index 82224fb10d..a8a1d105bb 100644 --- a/Assets/gamedb/gamedb_sega_gg.txt +++ b/Assets/gamedb/gamedb_sega_gg.txt @@ -231,7 +231,7 @@ B19256C6716147A9744F5BD528F14450 Magic Knight Rayearth 2 - Making of Magic Knig 846D48D0F4024C8094117599D0E1EEF1 Magic Knight Rayearth (J) GG SRAM=8192 Japan E496FF2196C372F4D6111538950D25CA Magical Puzzle Popils (W) (En,Ja) GG Puzzle SRAM=8192 World 3AF0C6DDF5F00A493E1F159FCEDC0933 Magical Taruruuto-kun (J) GG Japan -B0C35BC53AB7C184D34E5624F69AAD24 The Majors Pro Baseball (U) GG Sports;Baseball SRAM=128;GGLink USA +B0C35BC53AB7C184D34E5624F69AAD24 The Majors Pro Baseball (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA A15C5219F766D516D1B8D9A09B9A2BB4 Mappy (J) GG Japan B83F36FD113A8F75F1A29652ACB641FC Marble Madness (UE) GG Arcade USA;Europe BA846684A66E90372C3C234955EE28BC Marko's Magic Football (E) (En,Fr,De,Es) GG Europe @@ -461,9 +461,9 @@ A23E89266DDAD3C856E7401D04A49C6C Woody Pop (W) (Rev 1) GG World 13F72ACFEA47587F9AA9F655BF98653C World Class Leader Board Golf (UE) GG Sports;Golf USA;Europe D95D381C6AFFB8345EE5457655E393D1 World Cup USA 94 (UE) (En,Fr,De,Es,It,Nl,Pt,Sv) GG Sports;Soccer USA;Europe D8939B64458FAF174CDC1241F777CB59 World Derby (J) GG GGLink Japan -E7EABBFC7A1F1339C4720249AEA92A32 World Series Baseball '95 (U) GG Sports;Baseball SRAM=128;GGLink USA -59359FC38865CFF00C90D6EB148DDC2F World Series Baseball (U) GG Sports;Baseball SRAM=128;GGLink USA -05CAC33029F0CAAC27774504C1AA8597 World Series Baseball (U) (Rev 1) GG Sports;Baseball SRAM=128;GGLink USA +E7EABBFC7A1F1339C4720249AEA92A32 World Series Baseball '95 (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA +59359FC38865CFF00C90D6EB148DDC2F World Series Baseball (U) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA +05CAC33029F0CAAC27774504C1AA8597 World Series Baseball (U) (Rev 1) GG Sports;Baseball SRAM=128;GGLink;EEPROM USA D810E851AD60ED5BA50B6246C2CE12F2 WWF Raw (UE) GG Sports;Wrestling USA;Europe 571AC03B80E3075C699CD583BF8651FD X-Men - Gamemaster's Legacy (UE) GG Marvel USA;Europe CA15F2BA2507EBD836C42D9D10231EB1 X-Men - Mojo World (UE) GG Marvel USA;Europe diff --git a/Assets/gamedb/gamedb_sega_sms.txt b/Assets/gamedb/gamedb_sega_sms.txt index 1f16380c3b..b3a7102c79 100644 --- a/Assets/gamedb/gamedb_sega_sms.txt +++ b/Assets/gamedb/gamedb_sega_sms.txt @@ -106,7 +106,7 @@ F2535DF9BDC3A84221303FA62D61AD6E Back to the Future Part II (E) SMS Europe 3D24A52E98E6C85D7C059386451CE749 Back to the Future Part III (E) SMS PAL Europe 8A94DED3D95AA46DAE8800B92E66D3EE Baku Baku (B) SMS Brazil 7A5D3B9963E316CB7F73BBDC2A7311C6 Bank Panic (E) SMS Europe -26DF4404950CB8DA47235833C0C101C6 Bart vs. the Space Mutants (E) SMS Europe +26DF4404950CB8DA47235833C0C101C6 Bart vs. the Space Mutants (E) SMS PAL Europe CBA2EC2940619956359801618E7AAB17 Bart vs. the World (E) SMS Europe 0069B1BD9C5B6B88ACE6324D7E61539F Basketball Nightmare (E) SMS Sports;Basketball Europe 215876A62D3CA48D28E98CD8A2C70A15 Batman Returns (E) SMS Europe diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 6de9d9cdc3..b8754a9bcb 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -470,7 +470,7 @@ namespace BizHawk.Client.Common System = "PSX" }; } - else if (ext == ".iso" || ext == ".cue" || ext == ".ccd") + else if (ext == ".iso" || ext == ".cue" || ext == ".ccd" || ext == ".mds") { if (file.IsArchive) { @@ -494,7 +494,7 @@ namespace BizHawk.Client.Common throw new InvalidOperationException("\r\n" + discMountJob.OUT_Log); } - var disc = discMountJob.OUT_Disc; + var disc = discMountJob.OUT_Disc; // ----------- // TODO - use more sophisticated IDer diff --git a/BizHawk.Client.Common/tools/Cheat.cs b/BizHawk.Client.Common/tools/Cheat.cs index 15ec5fb62a..4680168276 100644 --- a/BizHawk.Client.Common/tools/Cheat.cs +++ b/BizHawk.Client.Common/tools/Cheat.cs @@ -284,29 +284,61 @@ namespace BizHawk.Client.Common case WatchSize.Byte: return (byte?)_val; case WatchSize.Word: - if (addr == _watch.Address) + if (_watch.BigEndian) { + if (addr == _watch.Address) + { + return (byte)(_val & 0xFF); + } return (byte)(_val >> 8); } - - return (byte)(_val & 0xFF); - case WatchSize.DWord: - if (addr == _watch.Address) + else { + if (addr == _watch.Address) + { + return (byte)(_val >> 8); + } + return (byte)(_val & 0xFF); + } + case WatchSize.DWord: + if (_watch.BigEndian) + { + if (addr == _watch.Address) + { + return (byte)((_val >> 24) & 0xFF); + } + + if (addr == _watch.Address + 1) + { + return (byte)((_val >> 16) & 0xFF); + } + + if (addr == _watch.Address + 2) + { + return (byte)((_val >> 8) & 0xFF); + } + + return (byte)(_val & 0xFF); + } + else + { + if (addr == _watch.Address) + { + return (byte)(_val & 0xFF); + } + + if (addr == _watch.Address + 1) + { + return (byte)((_val >> 8) & 0xFF); + } + + if (addr == _watch.Address + 2) + { + return (byte)((_val >> 16) & 0xFF); + } + return (byte)((_val >> 24) & 0xFF); } - - if (addr == _watch.Address + 1) - { - return (byte)((_val >> 16) & 0xFF); - } - - if (addr == _watch.Address + 2) - { - return (byte)((_val >> 8) & 0xFF); - } - - return (byte)(_val & 0xFF); } } diff --git a/BizHawk.Client.DiscoHawk/MainDiscoForm.cs b/BizHawk.Client.DiscoHawk/MainDiscoForm.cs index f74b095c74..cdd2c1a0f7 100644 --- a/BizHawk.Client.DiscoHawk/MainDiscoForm.cs +++ b/BizHawk.Client.DiscoHawk/MainDiscoForm.cs @@ -111,7 +111,7 @@ namespace BizHawk.Client.DiscoHawk foreach (string str in files) { string ext = Path.GetExtension(str).ToUpper(); - if(!ext.In(new string[]{".CUE",".ISO",".CCD"})) + if(!ext.In(new string[]{".CUE",".ISO",".CCD", ".MDS"})) { return new List(); } diff --git a/BizHawk.Client.EmuHawk/FileLoader.cs b/BizHawk.Client.EmuHawk/FileLoader.cs index 1e6d123c78..0009646fb4 100644 --- a/BizHawk.Client.EmuHawk/FileLoader.cs +++ b/BizHawk.Client.EmuHawk/FileLoader.cs @@ -51,11 +51,11 @@ namespace BizHawk.Client.EmuHawk return new[] { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", - ".EXE", ".PRG", ".D64", "*G64", ".CRT", ".TAP", ".32X" + ".EXE", ".PRG", ".D64", "*G64", ".CRT", ".TAP", ".32X", ".MDS" }; } - return new[] { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".32X" }; + return new[] { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF", ".32X", ".MDS" }; } } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 7929f31a90..170dbb2322 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -2077,13 +2077,13 @@ namespace BizHawk.Client.EmuHawk if (VersionInfo.DeveloperBuild) { return FormatFilter( - "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.32x;*.col;*.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.vb;*.ngp;*.ngc;*.psf;*.minipsf;*.nsf;%ARCH%", + "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.lnx;*.m3u;*.cue;*.ccd;*.mds;*.exe;*.gb;*.gbc;*.gba;*.gen;*.md;*.32x;*.col;*.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.tap;*.sgb;*.xml;*.z64;*.v64;*.n64;*.ws;*.wsc;*.dsk;*.do;*.po;*.vb;*.ngp;*.ngc;*.psf;*.minipsf;*.nsf;%ARCH%", "Music Files", "*.psf;*.minipsf;*.sid;*.nsf", - "Disc Images", "*.cue;*.ccd;*.m3u", + "Disc Images", "*.cue;*.ccd;*.mds;*.m3u", "NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%", "Super NES", "*.smc;*.sfc;*.xml;%ARCH%", "Master System", "*.sms;*.gg;*.sg;%ARCH%", - "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;%ARCH%", + "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%", "TI-83", "*.rom;%ARCH%", "Archive Files", "%ARCH%", "Savestate", "*.state", @@ -2095,7 +2095,7 @@ namespace BizHawk.Client.EmuHawk "Gameboy Advance", "*.gba;%ARCH%", "Colecovision", "*.col;%ARCH%", "Intellivision", "*.int;*.bin;*.rom;%ARCH%", - "PlayStation", "*.cue;*.ccd;*.m3u", + "PlayStation", "*.cue;*.ccd;*.mds;*.m3u", "PSX Executables (experimental)", "*.exe", "PSF Playstation Sound File", "*.psf;*.minipsf", "Commodore 64", "*.prg; *.d64, *.g64; *.crt; *.tap;%ARCH%", @@ -2109,17 +2109,17 @@ namespace BizHawk.Client.EmuHawk } return FormatFilter( - "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.gb;*.gbc;*.gba;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.32x;*.smc;*.sfc;*.a26;*.a78;*.lnx;*.col;*.int;*.rom;*.m3u;*.cue;*.ccd;*.sgb;*.z64;*.v64;*.n64;*.ws;*.wsc;*.xml;*.dsk;*.do;*.po;*.psf;*.ngp;*.ngc;*.prg;*.d64;*.g64;*.minipsf;*.nsf;%ARCH%", - "Disc Images", "*.cue;*.ccd;*.m3u", + "Rom Files", "*.nes;*.fds;*.unf;*.sms;*.gg;*.sg;*.gb;*.gbc;*.gba;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.32x;*.smc;*.sfc;*.a26;*.a78;*.lnx;*.col;*.int;*.rom;*.m3u;*.cue;*.ccd;*.mds;*.sgb;*.z64;*.v64;*.n64;*.ws;*.wsc;*.xml;*.dsk;*.do;*.po;*.psf;*.ngp;*.ngc;*.prg;*.d64;*.g64;*.minipsf;*.nsf;%ARCH%", + "Disc Images", "*.cue;*.ccd;*.mds;*.m3u", "NES", "*.nes;*.fds;*.unf;*.nsf;%ARCH%", "Super NES", "*.smc;*.sfc;*.xml;%ARCH%", - "PlayStation", "*.cue;*.ccd;*.m3u", + "PlayStation", "*.cue;*.ccd;*.mds;*.m3u", "PSF Playstation Sound File", "*.psf;*.minipsf", "Nintendo 64", "*.z64;*.v64;*.n64", "Gameboy", "*.gb;*.gbc;*.sgb;%ARCH%", "Gameboy Advance", "*.gba;%ARCH%", "Master System", "*.sms;*.gg;*.sg;%ARCH%", - "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;%ARCH%", + "PC Engine", "*.pce;*.sgx;*.cue;*.ccd;*.mds;%ARCH%", "Atari 2600", "*.a26;%ARCH%", "Atari 7800", "*.a78;%ARCH%", "Atari Lynx", "*.lnx;%ARCH%", diff --git a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index 02752e22b6..b237bf0a68 100644 --- a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -526,7 +526,16 @@ namespace BizHawk.Client.EmuHawk { if (_addr + j + DataSize <= _domain.Size) { - rowStr.AppendFormat(_digitFormatString, MakeValue(_addr + j)); + int t_val = 0; + int t_next = 0; + + for (int k = 0; k < DataSize; k++) + { + t_next = MakeValue(1, _addr + j + k); + t_val += (t_next << ((DataSize - k - 1) * 8)); + } + + rowStr.AppendFormat(_digitFormatString, t_val); } else { @@ -569,7 +578,7 @@ namespace BizHawk.Client.EmuHawk { if (Global.CheatList.IsActive(_domain, address)) { - return Global.CheatList.GetCheatValue(_domain, address, (WatchSize)DataSize ).Value; + return Global.CheatList.GetCheatValue(_domain, address, (WatchSize)dataSize ).Value; } switch (dataSize) diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 7958b5be1a..f22d02380d 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -1071,6 +1071,8 @@ + + SMS.cs @@ -1186,12 +1188,14 @@ - - - - - - + + + + + + + + True True diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Execute.cs deleted file mode 100644 index ee77ddde91..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Execute.cs +++ /dev/null @@ -1,12491 +0,0 @@ -using BizHawk.Common.NumberExtensions; -using BizHawk.Emulation.Common; -using System; - -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public partial class Z80A - { - private int totalExecutedCycles; - public int TotalExecutedCycles { get { return totalExecutedCycles; } set { totalExecutedCycles = value; } } - - private int expectedExecutedCycles; - public int ExpectedExecutedCycles { get { return expectedExecutedCycles; } set { expectedExecutedCycles = value; } } - - private int pendingCycles; - public int PendingCycles { get { return pendingCycles; } set { pendingCycles = value; } } - - private int EI_pending; - - private ushort temp_WZ; - - public bool Debug; - public Action Logger; - - /// - /// Runs the CPU for a particular number of clock cycles. - /// - /// The number of cycles to run the CPU emulator for. Specify -1 to run for a single instruction. - public void ExecuteCycles(int cycles) - { - expectedExecutedCycles += cycles; - pendingCycles += cycles; - - sbyte Displacement; - - byte TB; byte TBH; byte TBL; byte TB1; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR; - - bool Interruptable; - - while (pendingCycles > 0) - { - Interruptable = true; - - if (halted) - { - ++RegR; - totalExecutedCycles += 4; pendingCycles -= 4; - } - else - { - if (Debug) - { - Logger(State()); - } - - if (MemoryCallbacks != null) - { - MemoryCallbacks.CallExecutes(RegPC.Word); - } - - ++RegR; - switch (FetchFirstMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // LD BC, nn - RegBC.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x02: // LD (BC), A - RegWZ.Low = (byte)((RegBC.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegBC.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x03: // INC BC - ++RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x04: // INC B - RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // DEC B - RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // LD B, n - RegBC.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x07: // RLCA - RegAF.Word = TableRotShift[0, 0, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // EX AF, AF' - TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // ADD HL, BC - RegWZ = (ushort)(RegHL + 1); - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x0A: // LD A, (BC) - RegAF.High = ReadMemoryWrapper(RegBC.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegBC.Word + 1); - break; - case 0x0B: // DEC BC - --RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x0C: // INC C - RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // DEC C - RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // LD C, n - RegBC.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x0F: // RRCA - RegAF.Word = TableRotShift[0, 1, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // DJNZ d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (--RegBC.High != 0) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 13; pendingCycles -= 13; - } - else - { - totalExecutedCycles += 8; pendingCycles -= 8; - } - break; - case 0x11: // LD DE, nn - RegDE.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x12: // LD (DE), A - RegWZ.Low = (byte)((RegDE.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegDE.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x13: // INC DE - ++RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x14: // INC D - RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // DEC D - RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // LD D, n - RegDE.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x17: // RLA - RegAF.Word = TableRotShift[0, 2, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // JR d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x19: // ADD HL, DE - RegWZ = (ushort)(RegHL + 1); - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x1A: // LD A, (DE) - RegAF.High = ReadMemoryWrapper(RegDE.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegDE.Word + 1); - break; - case 0x1B: // DEC DE - --RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x1C: // INC E - RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // DEC E - RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // LD E, n - RegDE.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x1F: // RRA - RegAF.Word = TableRotShift[0, 3, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // JR NZ, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x21: // LD HL, nn - RegHL.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x22: // LD (nn), HL - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegHL.Low); - WriteMemoryWrapper(TUS, RegHL.High); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x23: // INC HL - ++RegHL.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x24: // INC H - RegAF.Low = (byte)(TableInc[++RegHL.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x25: // DEC H - RegAF.Low = (byte)(TableDec[--RegHL.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x26: // LD H, n - RegHL.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x27: // DAA - RegAF.Word = TableDaa[RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // JR Z, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x29: // ADD HL, HL - RegWZ = (ushort)(RegHL + 1); - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x2A: // LD HL, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegHL.Low = ReadMemoryWrapper(TUS++); RegHL.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x2B: // DEC HL - --RegHL.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x2C: // INC L - RegAF.Low = (byte)(TableInc[++RegHL.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2D: // DEC L - RegAF.Low = (byte)(TableDec[--RegHL.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2E: // LD L, n - RegHL.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x2F: // CPL - RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // JR NC, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x31: // LD SP, nn - RegSP.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x32: // LD (nn), A - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ.Low = (byte)((temp_WZ + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(temp_WZ, RegAF.High); - totalExecutedCycles += 13; pendingCycles -= 13; - break; - case 0x33: // INC SP - ++RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x34: // INC (HL) - TB = ReadMemoryWrapper(RegHL.Word); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemoryWrapper(RegHL.Word, TB); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x35: // DEC (HL) - TB = ReadMemoryWrapper(RegHL.Word); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemoryWrapper(RegHL.Word, TB); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x36: // LD (HL), n - WriteMemoryWrapper(RegHL.Word, FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x37: // SCF - RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // JR C, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x39: // ADD HL, SP - RegWZ = (ushort)(RegHL + 1); - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x3A: // LD A, (nn) - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegAF.High = ReadMemoryWrapper(temp_WZ); - totalExecutedCycles += 13; pendingCycles -= 13; - RegWZ.Word = (ushort)(temp_WZ + 1); - break; - case 0x3B: // DEC SP - --RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x3C: // INC A - RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // DEC A - RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // LD A, n - RegAF.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x3F: // CCF - RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // LD B, B - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x41: // LD B, C - RegBC.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x42: // LD B, D - RegBC.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x43: // LD B, E - RegBC.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x44: // LD B, H - RegBC.High = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x45: // LD B, L - RegBC.High = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x46: // LD B, (HL) - RegBC.High = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x47: // LD B, A - RegBC.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x48: // LD C, B - RegBC.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x49: // LD C, C - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4A: // LD C, D - RegBC.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4B: // LD C, E - RegBC.Low = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4C: // LD C, H - RegBC.Low = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4D: // LD C, L - RegBC.Low = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4E: // LD C, (HL) - RegBC.Low = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x4F: // LD C, A - RegBC.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x50: // LD D, B - RegDE.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x51: // LD D, C - RegDE.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x52: // LD D, D - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x53: // LD D, E - RegDE.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x54: // LD D, H - RegDE.High = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x55: // LD D, L - RegDE.High = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x56: // LD D, (HL) - RegDE.High = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x57: // LD D, A - RegDE.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x58: // LD E, B - RegDE.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x59: // LD E, C - RegDE.Low = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5A: // LD E, D - RegDE.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5B: // LD E, E - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5C: // LD E, H - RegDE.Low = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5D: // LD E, L - RegDE.Low = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5E: // LD E, (HL) - RegDE.Low = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x5F: // LD E, A - RegDE.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x60: // LD H, B - RegHL.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x61: // LD H, C - RegHL.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x62: // LD H, D - RegHL.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x63: // LD H, E - RegHL.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x64: // LD H, H - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x65: // LD H, L - RegHL.High = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x66: // LD H, (HL) - RegHL.High = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x67: // LD H, A - RegHL.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x68: // LD L, B - RegHL.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x69: // LD L, C - RegHL.Low = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x6A: // LD L, D - RegHL.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x6B: // LD L, E - RegHL.Low = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x6C: // LD L, H - RegHL.Low = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x6D: // LD L, L - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x6E: // LD L, (HL) - RegHL.Low = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x6F: // LD L, A - RegHL.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x70: // LD (HL), B - WriteMemoryWrapper(RegHL.Word, RegBC.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x71: // LD (HL), C - WriteMemoryWrapper(RegHL.Word, RegBC.Low); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x72: // LD (HL), D - WriteMemoryWrapper(RegHL.Word, RegDE.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x73: // LD (HL), E - WriteMemoryWrapper(RegHL.Word, RegDE.Low); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x74: // LD (HL), H - WriteMemoryWrapper(RegHL.Word, RegHL.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x75: // LD (HL), L - WriteMemoryWrapper(RegHL.Word, RegHL.Low); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x76: // HALT - Halt(); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x77: // LD (HL), A - RegWZ.Low = (byte)((RegHL.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegHL.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x78: // LD A, B - RegAF.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x79: // LD A, C - RegAF.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7A: // LD A, D - RegAF.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7B: // LD A, E - RegAF.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7C: // LD A, H - RegAF.High = RegHL.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7D: // LD A, L - RegAF.High = RegHL.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7E: // LD A, (HL) - RegAF.High = ReadMemoryWrapper(RegHL.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegHL.Word + 1); - break; - case 0x7F: // LD A, A - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // ADD A, B - RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // ADD A, C - RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // ADD A, D - RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // ADD A, E - RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // ADD A, H - RegAF.Word = TableALU[0, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x85: // ADD A, L - RegAF.Word = TableALU[0, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x86: // ADD A, (HL) - RegWZ = (ushort)(RegHL + 1); - RegAF.Word = TableALU[0, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x87: // ADD A, A - RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // ADC A, B - RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // ADC A, C - RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // ADC A, D - RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // ADC A, E - RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // ADC A, H - RegAF.Word = TableALU[1, RegAF.High, RegHL.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8D: // ADC A, L - RegAF.Word = TableALU[1, RegAF.High, RegHL.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8E: // ADC A, (HL) - RegAF.Word = TableALU[1, RegAF.High, ReadMemoryWrapper(RegHL.Word), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x8F: // ADC A, A - RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // SUB B - RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // SUB C - RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // SUB D - RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // SUB E - RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // SUB H - RegAF.Word = TableALU[2, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x95: // SUB L - RegAF.Word = TableALU[2, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x96: // SUB (HL) - RegAF.Word = TableALU[2, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x97: // SUB A, A - RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // SBC A, B - RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // SBC A, C - RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // SBC A, D - RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // SBC A, E - RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // SBC A, H - RegAF.Word = TableALU[3, RegAF.High, RegHL.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9D: // SBC A, L - RegAF.Word = TableALU[3, RegAF.High, RegHL.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9E: // SBC A, (HL) - RegAF.Word = TableALU[3, RegAF.High, ReadMemoryWrapper(RegHL.Word), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x9F: // SBC A, A - RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // AND B - RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA1: // AND C - RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA2: // AND D - RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA3: // AND E - RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA4: // AND H - RegAF.Word = TableALU[4, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA5: // AND L - RegAF.Word = TableALU[4, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA6: // AND (HL) - RegAF.Word = TableALU[4, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xA7: // AND A - RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // XOR B - RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA9: // XOR C - RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAA: // XOR D - RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAB: // XOR E - RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAC: // XOR H - RegAF.Word = TableALU[5, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAD: // XOR L - RegAF.Word = TableALU[5, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAE: // XOR (HL) - RegAF.Word = TableALU[5, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xAF: // XOR A - RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // OR B - RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB1: // OR C - RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB2: // OR D - RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB3: // OR E - RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB4: // OR H - RegAF.Word = TableALU[6, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB5: // OR L - RegAF.Word = TableALU[6, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB6: // OR (HL) - RegAF.Word = TableALU[6, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xB7: // OR A - RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // CP B - RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB9: // CP C - RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBA: // CP D - RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBB: // CP E - RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBC: // CP H - RegAF.Word = TableALU[7, RegAF.High, RegHL.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBD: // CP L - RegAF.Word = TableALU[7, RegAF.High, RegHL.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBE: // CP (HL) - RegAF.Word = TableALU[7, RegAF.High, ReadMemoryWrapper(RegHL.Word), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xBF: // CP A - RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // RET NZ - if (!RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC1: // POP BC - RegBC.Low = ReadMemoryWrapper(RegSP.Word++); RegBC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC2: // JP NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC3: // JP nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - RegPC.Word = TUS; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC4: // CALL NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xC5: // PUSH BC - WriteMemoryWrapper(--RegSP.Word, RegBC.High); WriteMemoryWrapper(--RegSP.Word, RegBC.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC6: // ADD A, n - RegAF.Word = TableALU[0, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xC7: // RST $00 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x00; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC8: // RET Z - if (RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC9: // RET - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCA: // JP Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCB: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // RLC B - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x01: // RLC C - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x02: // RLC D - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x03: // RLC E - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x04: // RLC H - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x05: // RLC L - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x06: // RLC (HL) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x07: // RLC A - TUS = TableRotShift[1, 0, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x08: // RRC B - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x09: // RRC C - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x0A: // RRC D - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x0B: // RRC E - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x0C: // RRC H - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x0D: // RRC L - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x0E: // RRC (HL) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x0F: // RRC A - TUS = TableRotShift[1, 1, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x10: // RL B - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x11: // RL C - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x12: // RL D - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x13: // RL E - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x14: // RL H - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x15: // RL L - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x16: // RL (HL) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x17: // RL A - TUS = TableRotShift[1, 2, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x18: // RR B - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x19: // RR C - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x1A: // RR D - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x1B: // RR E - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x1C: // RR H - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x1D: // RR L - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x1E: // RR (HL) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x1F: // RR A - TUS = TableRotShift[1, 3, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x20: // SLA B - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x21: // SLA C - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x22: // SLA D - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x23: // SLA E - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x24: // SLA H - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x25: // SLA L - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x26: // SLA (HL) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x27: // SLA A - TUS = TableRotShift[1, 4, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x28: // SRA B - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x29: // SRA C - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2A: // SRA D - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2B: // SRA E - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2C: // SRA H - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2D: // SRA L - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2E: // SRA (HL) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x2F: // SRA A - TUS = TableRotShift[1, 5, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x30: // SL1 B - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x31: // SL1 C - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x32: // SL1 D - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x33: // SL1 E - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x34: // SL1 H - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x35: // SL1 L - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x36: // SL1 (HL) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x37: // SL1 A - TUS = TableRotShift[1, 6, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x38: // SRL B - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegBC.High]; - RegBC.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x39: // SRL C - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegBC.Low]; - RegBC.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x3A: // SRL D - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegDE.High]; - RegDE.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x3B: // SRL E - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegDE.Low]; - RegDE.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x3C: // SRL H - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegHL.High]; - RegHL.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x3D: // SRL L - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegHL.Low]; - RegHL.Low = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x3E: // SRL (HL) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper(RegHL.Word)]; - WriteMemoryWrapper(RegHL.Word, (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x3F: // SRL A - TUS = TableRotShift[1, 7, RegAF.Low + 256 * RegAF.High]; - RegAF.High = (byte)(TUS >> 8); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x40: // BIT 0, B - RegFlagZ = (RegBC.High & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x41: // BIT 0, C - RegFlagZ = (RegBC.Low & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x42: // BIT 0, D - RegFlagZ = (RegDE.High & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x43: // BIT 0, E - RegFlagZ = (RegDE.Low & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x44: // BIT 0, H - RegFlagZ = (RegHL.High & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // BIT 0, L - RegFlagZ = (RegHL.Low & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x46: // BIT 0, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x47: // BIT 0, A - RegFlagZ = (RegAF.High & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x48: // BIT 1, B - RegFlagZ = (RegBC.High & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x49: // BIT 1, C - RegFlagZ = (RegBC.Low & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4A: // BIT 1, D - RegFlagZ = (RegDE.High & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4B: // BIT 1, E - RegFlagZ = (RegDE.Low & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4C: // BIT 1, H - RegFlagZ = (RegHL.High & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // BIT 1, L - RegFlagZ = (RegHL.Low & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4E: // BIT 1, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x4F: // BIT 1, A - RegFlagZ = (RegAF.High & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x50: // BIT 2, B - RegFlagZ = (RegBC.High & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x51: // BIT 2, C - RegFlagZ = (RegBC.Low & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x52: // BIT 2, D - RegFlagZ = (RegDE.High & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x53: // BIT 2, E - RegFlagZ = (RegDE.Low & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x54: // BIT 2, H - RegFlagZ = (RegHL.High & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // BIT 2, L - RegFlagZ = (RegHL.Low & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x56: // BIT 2, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x57: // BIT 2, A - RegFlagZ = (RegAF.High & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x58: // BIT 3, B - RegFlagZ = (RegBC.High & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x59: // BIT 3, C - RegFlagZ = (RegBC.Low & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5A: // BIT 3, D - RegFlagZ = (RegDE.High & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5B: // BIT 3, E - RegFlagZ = (RegDE.Low & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5C: // BIT 3, H - RegFlagZ = (RegHL.High & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // BIT 3, L - RegFlagZ = (RegHL.Low & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5E: // BIT 3, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x5F: // BIT 3, A - RegFlagZ = (RegAF.High & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x60: // BIT 4, B - RegFlagZ = (RegBC.High & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x61: // BIT 4, C - RegFlagZ = (RegBC.Low & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x62: // BIT 4, D - RegFlagZ = (RegDE.High & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x63: // BIT 4, E - RegFlagZ = (RegDE.Low & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x64: // BIT 4, H - RegFlagZ = (RegHL.High & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // BIT 4, L - RegFlagZ = (RegHL.Low & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x66: // BIT 4, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x67: // BIT 4, A - RegFlagZ = (RegAF.High & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x68: // BIT 5, B - RegFlagZ = (RegBC.High & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x69: // BIT 5, C - RegFlagZ = (RegBC.Low & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6A: // BIT 5, D - RegFlagZ = (RegDE.High & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6B: // BIT 5, E - RegFlagZ = (RegDE.Low & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6C: // BIT 5, H - RegFlagZ = (RegHL.High & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // BIT 5, L - RegFlagZ = (RegHL.Low & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6E: // BIT 5, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x6F: // BIT 5, A - RegFlagZ = (RegAF.High & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x70: // BIT 6, B - RegFlagZ = (RegBC.High & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x71: // BIT 6, C - RegFlagZ = (RegBC.Low & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x72: // BIT 6, D - RegFlagZ = (RegDE.High & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x73: // BIT 6, E - RegFlagZ = (RegDE.Low & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x74: // BIT 6, H - RegFlagZ = (RegHL.High & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x75: // BIT 6, L - RegFlagZ = (RegHL.Low & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x76: // BIT 6, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x77: // BIT 6, A - RegFlagZ = (RegAF.High & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x78: // BIT 7, B - RegFlagZ = (RegBC.High & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegBC.High.Bit(3); - RegFlag5 = RegBC.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x79: // BIT 7, C - RegFlagZ = (RegBC.Low & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegBC.Low.Bit(3); - RegFlag5 = RegBC.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7A: // BIT 7, D - RegFlagZ = (RegDE.High & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegDE.High.Bit(3); - RegFlag5 = RegDE.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7B: // BIT 7, E - RegFlagZ = (RegDE.Low & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegDE.Low.Bit(3); - RegFlag5 = RegDE.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7C: // BIT 7, H - RegFlagZ = (RegHL.High & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegHL.High.Bit(3); - RegFlag5 = RegHL.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // BIT 7, L - RegFlagZ = (RegHL.Low & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegHL.Low.Bit(3); - RegFlag5 = RegHL.Low.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7E: // BIT 7, (HL) - RegFlagZ = (ReadMemoryWrapper(RegHL.Word) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x7F: // BIT 7, A - RegFlagZ = (RegAF.High & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegAF.High.Bit(3); - RegFlag5 = RegAF.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x80: // RES 0, B - RegBC.High &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x81: // RES 0, C - RegBC.Low &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x82: // RES 0, D - RegDE.High &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x83: // RES 0, E - RegDE.Low &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x84: // RES 0, H - RegHL.High &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x85: // RES 0, L - RegHL.Low &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x86: // RES 0, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x01))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x87: // RES 0, A - RegAF.High &= unchecked((byte)~0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x88: // RES 1, B - RegBC.High &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x89: // RES 1, C - RegBC.Low &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8A: // RES 1, D - RegDE.High &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8B: // RES 1, E - RegDE.Low &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8C: // RES 1, H - RegHL.High &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8D: // RES 1, L - RegHL.Low &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8E: // RES 1, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x02))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x8F: // RES 1, A - RegAF.High &= unchecked((byte)~0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x90: // RES 2, B - RegBC.High &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x91: // RES 2, C - RegBC.Low &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x92: // RES 2, D - RegDE.High &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x93: // RES 2, E - RegDE.Low &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x94: // RES 2, H - RegHL.High &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x95: // RES 2, L - RegHL.Low &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x96: // RES 2, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x04))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x97: // RES 2, A - RegAF.High &= unchecked((byte)~0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x98: // RES 3, B - RegBC.High &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x99: // RES 3, C - RegBC.Low &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9A: // RES 3, D - RegDE.High &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9B: // RES 3, E - RegDE.Low &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9C: // RES 3, H - RegHL.High &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9D: // RES 3, L - RegHL.Low &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9E: // RES 3, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x08))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x9F: // RES 3, A - RegAF.High &= unchecked((byte)~0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA0: // RES 4, B - RegBC.High &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA1: // RES 4, C - RegBC.Low &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA2: // RES 4, D - RegDE.High &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA3: // RES 4, E - RegDE.Low &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA4: // RES 4, H - RegHL.High &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA5: // RES 4, L - RegHL.Low &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA6: // RES 4, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x10))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xA7: // RES 4, A - RegAF.High &= unchecked((byte)~0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA8: // RES 5, B - RegBC.High &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA9: // RES 5, C - RegBC.Low &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAA: // RES 5, D - RegDE.High &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAB: // RES 5, E - RegDE.Low &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAC: // RES 5, H - RegHL.High &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAD: // RES 5, L - RegHL.Low &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAE: // RES 5, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x20))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xAF: // RES 5, A - RegAF.High &= unchecked((byte)~0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB0: // RES 6, B - RegBC.High &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB1: // RES 6, C - RegBC.Low &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB2: // RES 6, D - RegDE.High &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB3: // RES 6, E - RegDE.Low &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB4: // RES 6, H - RegHL.High &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB5: // RES 6, L - RegHL.Low &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB6: // RES 6, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x40))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xB7: // RES 6, A - RegAF.High &= unchecked((byte)~0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB8: // RES 7, B - RegBC.High &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB9: // RES 7, C - RegBC.Low &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBA: // RES 7, D - RegDE.High &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBB: // RES 7, E - RegDE.Low &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBC: // RES 7, H - RegHL.High &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBD: // RES 7, L - RegHL.Low &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBE: // RES 7, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) & unchecked((byte)~0x80))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xBF: // RES 7, A - RegAF.High &= unchecked((byte)~0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC0: // SET 0, B - RegBC.High |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC1: // SET 0, C - RegBC.Low |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC2: // SET 0, D - RegDE.High |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC3: // SET 0, E - RegDE.Low |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC4: // SET 0, H - RegHL.High |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC5: // SET 0, L - RegHL.Low |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC6: // SET 0, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x01))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xC7: // SET 0, A - RegAF.High |= unchecked((byte)0x01); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC8: // SET 1, B - RegBC.High |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xC9: // SET 1, C - RegBC.Low |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xCA: // SET 1, D - RegDE.High |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xCB: // SET 1, E - RegDE.Low |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xCC: // SET 1, H - RegHL.High |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xCD: // SET 1, L - RegHL.Low |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xCE: // SET 1, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x02))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xCF: // SET 1, A - RegAF.High |= unchecked((byte)0x02); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD0: // SET 2, B - RegBC.High |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD1: // SET 2, C - RegBC.Low |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD2: // SET 2, D - RegDE.High |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD3: // SET 2, E - RegDE.Low |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD4: // SET 2, H - RegHL.High |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD5: // SET 2, L - RegHL.Low |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD6: // SET 2, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x04))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xD7: // SET 2, A - RegAF.High |= unchecked((byte)0x04); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD8: // SET 3, B - RegBC.High |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xD9: // SET 3, C - RegBC.Low |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xDA: // SET 3, D - RegDE.High |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xDB: // SET 3, E - RegDE.Low |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xDC: // SET 3, H - RegHL.High |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xDD: // SET 3, L - RegHL.Low |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xDE: // SET 3, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x08))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xDF: // SET 3, A - RegAF.High |= unchecked((byte)0x08); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE0: // SET 4, B - RegBC.High |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE1: // SET 4, C - RegBC.Low |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE2: // SET 4, D - RegDE.High |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE3: // SET 4, E - RegDE.Low |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE4: // SET 4, H - RegHL.High |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE5: // SET 4, L - RegHL.Low |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE6: // SET 4, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x10))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xE7: // SET 4, A - RegAF.High |= unchecked((byte)0x10); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE8: // SET 5, B - RegBC.High |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xE9: // SET 5, C - RegBC.Low |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEA: // SET 5, D - RegDE.High |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEB: // SET 5, E - RegDE.Low |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEC: // SET 5, H - RegHL.High |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xED: // SET 5, L - RegHL.Low |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEE: // SET 5, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x20))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xEF: // SET 5, A - RegAF.High |= unchecked((byte)0x20); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF0: // SET 6, B - RegBC.High |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF1: // SET 6, C - RegBC.Low |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF2: // SET 6, D - RegDE.High |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF3: // SET 6, E - RegDE.Low |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF4: // SET 6, H - RegHL.High |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF5: // SET 6, L - RegHL.Low |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF6: // SET 6, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x40))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xF7: // SET 6, A - RegAF.High |= unchecked((byte)0x40); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF8: // SET 7, B - RegBC.High |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xF9: // SET 7, C - RegBC.Low |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xFA: // SET 7, D - RegDE.High |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xFB: // SET 7, E - RegDE.Low |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xFC: // SET 7, H - RegHL.High |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xFD: // SET 7, L - RegHL.Low |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xFE: // SET 7, (HL) - WriteMemoryWrapper(RegHL.Word, (byte)(ReadMemoryWrapper(RegHL.Word) | unchecked((byte)0x80))); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xFF: // SET 7, A - RegAF.High |= unchecked((byte)0x80); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - } - break; - case 0xCC: // CALL Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xCD: // CALL nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - break; - case 0xCE: // ADC A, n - RegAF.Word = TableALU[1, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xCF: // RST $08 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x08; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD0: // RET NC - if (!RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD1: // POP DE - RegDE.Low = ReadMemoryWrapper(RegSP.Word++); RegDE.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD2: // JP NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD3: // OUT n, A - WriteHardware(FetchMemoryWrapper(RegPC.Word++), RegAF.High); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD4: // CALL NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xD5: // PUSH DE - WriteMemoryWrapper(--RegSP.Word, RegDE.High); WriteMemoryWrapper(--RegSP.Word, RegDE.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD6: // SUB n - RegAF.Word = TableALU[2, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xD7: // RST $10 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x10; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD8: // RET C - if (RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD9: // EXX - TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; - TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; - TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // JP C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xDB: // IN A, n - RegAF.High = ReadHardware((ushort)FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xDC: // CALL C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xDD: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // LD BC, nn - RegBC.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x02: // LD (BC), A - RegWZ.Low = (byte)((RegBC.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegBC.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x03: // INC BC - ++RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x04: // INC B - RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // DEC B - RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // LD B, n - RegBC.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x07: // RLCA - RegAF.Word = TableRotShift[0, 0, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // EX AF, AF' - TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // ADD IX, BC - RegWZ = (ushort)(RegIX + 1); - TI1 = (short)RegIX.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIX.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x0A: // LD A, (BC) - RegAF.High = ReadMemoryWrapper(RegBC.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegBC.Word + 1); - break; - case 0x0B: // DEC BC - --RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x0C: // INC C - RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // DEC C - RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // LD C, n - RegBC.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x0F: // RRCA - RegAF.Word = TableRotShift[0, 1, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // DJNZ d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (--RegBC.High != 0) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 13; pendingCycles -= 13; - } - else - { - totalExecutedCycles += 8; pendingCycles -= 8; - } - break; - case 0x11: // LD DE, nn - RegDE.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x12: // LD (DE), A - RegWZ.Low = (byte)((RegDE.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegDE.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x13: // INC DE - ++RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x14: // INC D - RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // DEC D - RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // LD D, n - RegDE.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x17: // RLA - RegAF.Word = TableRotShift[0, 2, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // JR d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x19: // ADD IX, DE - RegWZ = (ushort)(RegIX + 1); - TI1 = (short)RegIX.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIX.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x1A: // LD A, (DE) - RegAF.High = ReadMemoryWrapper(RegDE.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegDE.Word + 1); - break; - case 0x1B: // DEC DE - --RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x1C: // INC E - RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // DEC E - RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // LD E, n - RegDE.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x1F: // RRA - RegAF.Word = TableRotShift[0, 3, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // JR NZ, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x21: // LD IX, nn - RegIX.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x22: // LD (nn), IX - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegIX.Low); - WriteMemoryWrapper(TUS, RegIX.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x23: // INC IX - ++RegIX.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x24: // INC IXH - RegAF.Low = (byte)(TableInc[++RegIX.High] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x25: // DEC IXH - RegAF.Low = (byte)(TableDec[--RegIX.High] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x26: // LD IXH, n - RegIX.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x27: // DAA - RegAF.Word = TableDaa[RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // JR Z, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x29: // ADD IX, IX - RegWZ = (ushort)(RegIX + 1); - TI1 = (short)RegIX.Word; TI2 = (short)RegIX.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIX.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x2A: // LD IX, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegIX.Low = ReadMemoryWrapper(TUS++); RegIX.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x2B: // DEC IX - --RegIX.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x2C: // INC IXL - RegAF.Low = (byte)(TableInc[++RegIX.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2D: // DEC IXL - RegAF.Low = (byte)(TableDec[--RegIX.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2E: // LD IXL, n - RegIX.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x2F: // CPL - RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // JR NC, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x31: // LD SP, nn - RegSP.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x32: // LD (nn), A - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ.Low = (byte)((temp_WZ + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(temp_WZ, RegAF.High); - totalExecutedCycles += 13; pendingCycles -= 13; - break; - case 0x33: // INC SP - ++RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x34: // INC (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - TB = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), TB); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x35: // DEC (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - TB = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), TB); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x36: // LD (IX+d), n - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x37: // SCF - RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // JR C, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x39: // ADD IX, SP - RegWZ = (ushort)(RegIX + 1); - TI1 = (short)RegIX.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIX.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x3A: // LD A, (nn) - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegAF.High = ReadMemoryWrapper(temp_WZ); - totalExecutedCycles += 13; pendingCycles -= 13; - RegWZ = (ushort)(temp_WZ + 1); - break; - case 0x3B: // DEC SP - --RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x3C: // INC A - RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // DEC A - RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // LD A, n - RegAF.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x3F: // CCF - RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // LD B, B - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x41: // LD B, C - RegBC.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x42: // LD B, D - RegBC.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x43: // LD B, E - RegBC.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x44: // LD B, IXH - RegBC.High = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // LD B, IXL - RegBC.High = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x46: // LD B, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegBC.High = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x47: // LD B, A - RegBC.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x48: // LD C, B - RegBC.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x49: // LD C, C - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4A: // LD C, D - RegBC.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4B: // LD C, E - RegBC.Low = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4C: // LD C, IXH - RegBC.Low = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // LD C, IXL - RegBC.Low = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4E: // LD C, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegBC.Low = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x4F: // LD C, A - RegBC.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x50: // LD D, B - RegDE.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x51: // LD D, C - RegDE.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x52: // LD D, D - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x53: // LD D, E - RegDE.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x54: // LD D, IXH - RegDE.High = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // LD D, IXL - RegDE.High = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x56: // LD D, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegDE.High = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x57: // LD D, A - RegDE.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x58: // LD E, B - RegDE.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x59: // LD E, C - RegDE.Low = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5A: // LD E, D - RegDE.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5B: // LD E, E - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5C: // LD E, IXH - RegDE.Low = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // LD E, IXL - RegDE.Low = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5E: // LD E, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegDE.Low = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x5F: // LD E, A - RegDE.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x60: // LD IXH, B - RegIX.High = RegBC.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x61: // LD IXH, C - RegIX.High = RegBC.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x62: // LD IXH, D - RegIX.High = RegDE.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x63: // LD IXH, E - RegIX.High = RegDE.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x64: // LD IXH, IXH - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // LD IXH, IXL - RegIX.High = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x66: // LD H, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegHL.High = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x67: // LD IXH, A - RegIX.High = RegAF.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x68: // LD IXL, B - RegIX.Low = RegBC.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x69: // LD IXL, C - RegIX.Low = RegBC.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6A: // LD IXL, D - RegIX.Low = RegDE.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6B: // LD IXL, E - RegIX.Low = RegDE.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6C: // LD IXL, IXH - RegIX.Low = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // LD IXL, IXL - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6E: // LD L, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegHL.Low = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x6F: // LD IXL, A - RegIX.Low = RegAF.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x70: // LD (IX+d), B - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x71: // LD (IX+d), C - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x72: // LD (IX+d), D - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x73: // LD (IX+d), E - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x74: // LD (IX+d), H - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x75: // LD (IX+d), L - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x76: // HALT - Halt(); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x77: // LD (IX+d), A - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x78: // LD A, B - RegAF.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x79: // LD A, C - RegAF.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7A: // LD A, D - RegAF.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7B: // LD A, E - RegAF.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7C: // LD A, IXH - RegAF.High = RegIX.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // LD A, IXL - RegAF.High = RegIX.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7E: // LD A, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.High = ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x7F: // LD A, A - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // ADD A, B - RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // ADD A, C - RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // ADD A, D - RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // ADD A, E - RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // ADD A, IXH - RegAF.Word = TableALU[0, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x85: // ADD A, IXL - RegAF.Word = TableALU[0, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x86: // ADD A, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[0, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x87: // ADD A, A - RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // ADC A, B - RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // ADC A, C - RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // ADC A, D - RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // ADC A, E - RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // ADC A, IXH - RegAF.Word = TableALU[1, RegAF.High, RegIX.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8D: // ADC A, IXL - RegAF.Word = TableALU[1, RegAF.High, RegIX.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8E: // ADC A, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[1, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), RegFlagC ? 1 : 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x8F: // ADC A, A - RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // SUB B - RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // SUB C - RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // SUB D - RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // SUB E - RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // SUB IXH - RegAF.Word = TableALU[2, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x95: // SUB IXL - RegAF.Word = TableALU[2, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x96: // SUB (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[2, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x97: // SUB A, A - RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // SBC A, B - RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // SBC A, C - RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // SBC A, D - RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // SBC A, E - RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // SBC A, IXH - RegAF.Word = TableALU[3, RegAF.High, RegIX.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9D: // SBC A, IXL - RegAF.Word = TableALU[3, RegAF.High, RegIX.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9E: // SBC A, (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[3, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), RegFlagC ? 1 : 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x9F: // SBC A, A - RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // AND B - RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA1: // AND C - RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA2: // AND D - RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA3: // AND E - RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA4: // AND IXH - RegAF.Word = TableALU[4, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA5: // AND IXL - RegAF.Word = TableALU[4, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA6: // AND (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[4, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xA7: // AND A - RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // XOR B - RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA9: // XOR C - RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAA: // XOR D - RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAB: // XOR E - RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAC: // XOR IXH - RegAF.Word = TableALU[5, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAD: // XOR IXL - RegAF.Word = TableALU[5, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAE: // XOR (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[5, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xAF: // XOR A - RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // OR B - RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB1: // OR C - RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB2: // OR D - RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB3: // OR E - RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB4: // OR IXH - RegAF.Word = TableALU[6, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB5: // OR IXL - RegAF.Word = TableALU[6, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB6: // OR (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[6, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xB7: // OR A - RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // CP B - RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB9: // CP C - RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBA: // CP D - RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBB: // CP E - RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBC: // CP IXH - RegAF.Word = TableALU[7, RegAF.High, RegIX.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBD: // CP IXL - RegAF.Word = TableALU[7, RegAF.High, RegIX.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBE: // CP (IX+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - RegAF.Word = TableALU[7, RegAF.High, ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xBF: // CP A - RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // RET NZ - if (!RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC1: // POP BC - RegBC.Low = ReadMemoryWrapper(RegSP.Word++); RegBC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC2: // JP NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC3: // JP nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - RegPC.Word = TUS; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC4: // CALL NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xC5: // PUSH BC - WriteMemoryWrapper(--RegSP.Word, RegBC.High); WriteMemoryWrapper(--RegSP.Word, RegBC.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC6: // ADD A, n - RegAF.Word = TableALU[0, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xC7: // RST $00 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x00; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC8: // RET Z - if (RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC9: // RET - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCA: // JP Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCB: // (Prefix) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIX.Word + Displacement); - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // RLC (IX+d)→B - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x01: // RLC (IX+d)→C - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x02: // RLC (IX+d)→D - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x03: // RLC (IX+d)→E - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x04: // RLC (IX+d)→H - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x05: // RLC (IX+d)→L - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x06: // RLC (IX+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x07: // RLC (IX+d)→A - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x08: // RRC (IX+d)→B - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x09: // RRC (IX+d)→C - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0A: // RRC (IX+d)→D - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0B: // RRC (IX+d)→E - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0C: // RRC (IX+d)→H - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0D: // RRC (IX+d)→L - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0E: // RRC (IX+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0F: // RRC (IX+d)→A - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x10: // RL (IX+d)→B - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x11: // RL (IX+d)→C - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x12: // RL (IX+d)→D - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x13: // RL (IX+d)→E - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x14: // RL (IX+d)→H - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x15: // RL (IX+d)→L - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x16: // RL (IX+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x17: // RL (IX+d)→A - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x18: // RR (IX+d)→B - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x19: // RR (IX+d)→C - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1A: // RR (IX+d)→D - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1B: // RR (IX+d)→E - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1C: // RR (IX+d)→H - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1D: // RR (IX+d)→L - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1E: // RR (IX+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1F: // RR (IX+d)→A - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x20: // SLA (IX+d)→B - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x21: // SLA (IX+d)→C - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x22: // SLA (IX+d)→D - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x23: // SLA (IX+d)→E - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x24: // SLA (IX+d)→H - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x25: // SLA (IX+d)→L - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x26: // SLA (IX+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x27: // SLA (IX+d)→A - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x28: // SRA (IX+d)→B - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x29: // SRA (IX+d)→C - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2A: // SRA (IX+d)→D - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2B: // SRA (IX+d)→E - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2C: // SRA (IX+d)→H - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2D: // SRA (IX+d)→L - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2E: // SRA (IX+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2F: // SRA (IX+d)→A - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x30: // SL1 (IX+d)→B - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x31: // SL1 (IX+d)→C - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x32: // SL1 (IX+d)→D - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x33: // SL1 (IX+d)→E - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x34: // SL1 (IX+d)→H - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x35: // SL1 (IX+d)→L - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x36: // SL1 (IX+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x37: // SL1 (IX+d)→A - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x38: // SRL (IX+d)→B - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x39: // SRL (IX+d)→C - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegBC.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3A: // SRL (IX+d)→D - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3B: // SRL (IX+d)→E - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegDE.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3C: // SRL (IX+d)→H - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3D: // SRL (IX+d)→L - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegHL.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3E: // SRL (IX+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3F: // SRL (IX+d)→A - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIX.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - RegAF.High = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x40: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x41: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x42: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x43: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x44: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x45: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x46: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x47: // BIT 0, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x48: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x49: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4A: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4B: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4C: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4D: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4E: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4F: // BIT 1, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x50: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x51: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x52: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x53: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x54: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x55: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x56: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x57: // BIT 2, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x58: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x59: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5A: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5B: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5C: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5D: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5E: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5F: // BIT 3, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x60: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x61: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x62: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x63: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x64: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x65: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x66: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x67: // BIT 4, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x68: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x69: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6A: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6B: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6C: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6D: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6E: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6F: // BIT 5, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x70: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x71: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x72: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x73: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x74: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x75: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x76: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x77: // BIT 6, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x78: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x79: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7A: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7B: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7C: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7D: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7E: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7F: // BIT 7, (IX+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x80: // RES 0, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x81: // RES 0, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x82: // RES 0, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x83: // RES 0, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x84: // RES 0, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x85: // RES 0, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x86: // RES 0, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x87: // RES 0, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x88: // RES 1, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x89: // RES 1, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8A: // RES 1, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8B: // RES 1, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8C: // RES 1, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8D: // RES 1, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8E: // RES 1, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8F: // RES 1, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x90: // RES 2, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x91: // RES 2, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x92: // RES 2, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x93: // RES 2, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x94: // RES 2, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x95: // RES 2, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x96: // RES 2, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x97: // RES 2, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x98: // RES 3, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x99: // RES 3, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9A: // RES 3, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9B: // RES 3, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9C: // RES 3, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9D: // RES 3, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9E: // RES 3, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9F: // RES 3, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA0: // RES 4, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA1: // RES 4, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA2: // RES 4, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA3: // RES 4, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA4: // RES 4, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA5: // RES 4, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA6: // RES 4, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA7: // RES 4, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA8: // RES 5, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA9: // RES 5, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAA: // RES 5, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAB: // RES 5, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAC: // RES 5, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAD: // RES 5, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAE: // RES 5, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAF: // RES 5, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB0: // RES 6, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB1: // RES 6, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB2: // RES 6, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB3: // RES 6, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB4: // RES 6, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB5: // RES 6, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB6: // RES 6, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB7: // RES 6, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB8: // RES 7, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB9: // RES 7, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBA: // RES 7, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBB: // RES 7, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBC: // RES 7, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBD: // RES 7, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBE: // RES 7, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBF: // RES 7, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) & unchecked((byte)~0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC0: // SET 0, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC1: // SET 0, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC2: // SET 0, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC3: // SET 0, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC4: // SET 0, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC5: // SET 0, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC6: // SET 0, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC7: // SET 0, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x01)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC8: // SET 1, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC9: // SET 1, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCA: // SET 1, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCB: // SET 1, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCC: // SET 1, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCD: // SET 1, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCE: // SET 1, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCF: // SET 1, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x02)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD0: // SET 2, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD1: // SET 2, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD2: // SET 2, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD3: // SET 2, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD4: // SET 2, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD5: // SET 2, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD6: // SET 2, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD7: // SET 2, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x04)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD8: // SET 3, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD9: // SET 3, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDA: // SET 3, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDB: // SET 3, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDC: // SET 3, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDD: // SET 3, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDE: // SET 3, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDF: // SET 3, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x08)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE0: // SET 4, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE1: // SET 4, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE2: // SET 4, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE3: // SET 4, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE4: // SET 4, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE5: // SET 4, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE6: // SET 4, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE7: // SET 4, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x10)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE8: // SET 5, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE9: // SET 5, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEA: // SET 5, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEB: // SET 5, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEC: // SET 5, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xED: // SET 5, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEE: // SET 5, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEF: // SET 5, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x20)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF0: // SET 6, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF1: // SET 6, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF2: // SET 6, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF3: // SET 6, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF4: // SET 6, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF5: // SET 6, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF6: // SET 6, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF7: // SET 6, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x40)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF8: // SET 7, (IX+d)→B - RegBC.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF9: // SET 7, (IX+d)→C - RegBC.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegBC.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFA: // SET 7, (IX+d)→D - RegDE.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFB: // SET 7, (IX+d)→E - RegDE.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegDE.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFC: // SET 7, (IX+d)→H - RegHL.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFD: // SET 7, (IX+d)→L - RegHL.Low = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegHL.Low); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFE: // SET 7, (IX+d) - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFF: // SET 7, (IX+d)→A - RegAF.High = (byte)(ReadMemoryWrapper((ushort)(RegIX.Word + Displacement)) | unchecked((byte)0x80)); - WriteMemoryWrapper((ushort)(RegIX.Word + Displacement), RegAF.High); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - } - break; - case 0xCC: // CALL Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xCD: // CALL nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - break; - case 0xCE: // ADC A, n - RegAF.Word = TableALU[1, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xCF: // RST $08 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x08; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD0: // RET NC - if (!RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD1: // POP DE - RegDE.Low = ReadMemoryWrapper(RegSP.Word++); RegDE.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD2: // JP NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD3: // OUT n, A - WriteHardware(FetchMemoryWrapper(RegPC.Word++), RegAF.High); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD4: // CALL NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xD5: // PUSH DE - WriteMemoryWrapper(--RegSP.Word, RegDE.High); WriteMemoryWrapper(--RegSP.Word, RegDE.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD6: // SUB n - RegAF.Word = TableALU[2, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xD7: // RST $10 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x10; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD8: // RET C - if (RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD9: // EXX - TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; - TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; - TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // JP C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xDB: // IN A, n - RegAF.High = ReadHardware((ushort)FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xDC: // CALL C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xDD: // <- - // Invalid sequence. - totalExecutedCycles += 1337; pendingCycles -= 1337; - break; - case 0xDE: // SBC A, n - RegAF.Word = TableALU[3, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xDF: // RST $18 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x18; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE0: // RET PO - if (!RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE1: // POP IX - RegIX.Low = ReadMemoryWrapper(RegSP.Word++); RegIX.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0xE2: // JP PO, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xE3: // EX (SP), IX - TUS = RegSP.Word; TBL = ReadMemoryWrapper(TUS++); TBH = ReadMemoryWrapper(TUS--); - WriteMemoryWrapper(TUS++, RegIX.Low); WriteMemoryWrapper(TUS, RegIX.High); - RegIX.Low = TBL; RegIX.High = TBH; - RegWZ = RegIX; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE4: // CALL C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xE5: // PUSH IX - WriteMemoryWrapper(--RegSP.Word, RegIX.High); WriteMemoryWrapper(--RegSP.Word, RegIX.Low); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xE6: // AND n - RegAF.Word = TableALU[4, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xE7: // RST $20 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x20; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE8: // RET PE - if (RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE9: // JP IX - RegWZ = RegIX; - RegPC.Word = RegIX.Word; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEA: // JP PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xEB: // EX DE, HL - TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // CALL PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xED: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x02: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x03: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x04: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x07: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x11: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x12: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x13: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x14: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x17: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x19: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x21: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x22: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x23: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x24: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x25: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x26: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x27: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x29: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x31: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x32: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x33: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x34: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x35: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x36: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x37: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x39: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // IN B, C - RegBC.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.High > 127; - RegFlagZ = RegBC.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x41: // OUT C, B - WriteHardware(RegBC.Low, RegBC.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x42: // SBC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x43: // LD (nn), BC - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegBC.Low); - WriteMemoryWrapper(TUS, RegBC.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x44: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x46: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x47: // LD I, A - RegI = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x48: // IN C, C - RegBC.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.Low > 127; - RegFlagZ = RegBC.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x49: // OUT C, C - WriteHardware(RegBC.Low, RegBC.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x4A: // ADC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x4B: // LD BC, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegBC.Low = ReadMemoryWrapper(TUS++); RegBC.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x4E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4F: // LD R, A - RegR = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x50: // IN D, C - RegDE.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.High > 127; - RegFlagZ = RegDE.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x51: // OUT C, D - WriteHardware(RegBC.Low, RegDE.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x52: // SBC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x53: // LD (nn), DE - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegDE.Low); - WriteMemoryWrapper(TUS, RegDE.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x54: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x56: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x57: // LD A, I - RegAF.High = RegI; - RegFlagS = RegI > 127; - RegFlagZ = RegI == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x58: // IN E, C - RegDE.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.Low > 127; - RegFlagZ = RegDE.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x59: // OUT C, E - WriteHardware(RegBC.Low, RegDE.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x5A: // ADC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x5B: // LD DE, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegDE.Low = ReadMemoryWrapper(TUS++); RegDE.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x5E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5F: // LD A, R - RegAF.High = (byte)(RegR & 0x7F); - RegFlagS = (byte)(RegR & 0x7F) > 127; - RegFlagZ = (byte)(RegR & 0x7F) == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x60: // IN H, C - RegHL.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.High > 127; - RegFlagZ = RegHL.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x61: // OUT C, H - WriteHardware(RegBC.Low, RegHL.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x62: // SBC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x63: // LD (nn), HL - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegHL.Low); - WriteMemoryWrapper(TUS, RegHL.High); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x64: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x66: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x67: // RRD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x68: // IN L, C - RegHL.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.Low > 127; - RegFlagZ = RegHL.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x69: // OUT C, L - WriteHardware(RegBC.Low, RegHL.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x6A: // ADC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x6B: // LD HL, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegHL.Low = ReadMemoryWrapper(TUS++); RegHL.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x6C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x6E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6F: // RLD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x70: // IN 0, C - TB = ReadHardware((ushort)RegBC.Low); - RegFlagS = TB > 127; - RegFlagZ = TB == 0; - RegFlagH = false; - RegFlagP = TableParity[TB]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x71: // OUT C, 0 - WriteHardware(RegBC.Low, 0); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x72: // SBC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x73: // LD (nn), SP - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegSP.Low); - WriteMemoryWrapper(TUS, RegSP.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x74: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x75: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x76: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x77: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x78: // IN A, C - RegAF.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x79: // OUT C, A - WriteHardware(RegBC.Low, RegAF.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x7A: // ADC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x7B: // LD SP, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegSP.Low = ReadMemoryWrapper(TUS++); RegSP.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x7E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x85: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x86: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x87: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x95: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x96: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x97: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // LDI - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA1: // CPI - RegWZ = (ushort)(RegWZ + 1); - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA2: // INI - RegWZ = (ushort)(RegBC + 1); - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA3: // OUTI - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // LDD - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA9: // CPD - RegWZ = (ushort)(RegWZ - 1); - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAA: // IND - RegWZ = (ushort)(RegBC - 1); - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAB: // OUTD - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // LDIR - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB1: // CPIR - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB2: // INIR - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB3: // OTIR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // LDDR - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB9: // CPDR - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBA: // INDR - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBB: // OTDR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xED: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - } - break; - case 0xEE: // XOR n - RegAF.Word = TableALU[5, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xEF: // RST $28 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x28; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF0: // RET P - if (!RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF1: // POP AF - RegAF.Low = ReadMemoryWrapper(RegSP.Word++); RegAF.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF2: // JP P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF3: // DI - IFF1 = IFF2 = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // CALL P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xF5: // PUSH AF - WriteMemoryWrapper(--RegSP.Word, RegAF.High); WriteMemoryWrapper(--RegSP.Word, RegAF.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF6: // OR n - RegAF.Word = TableALU[6, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xF7: // RST $30 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x30; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF8: // RET M - if (RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF9: // LD SP, IX - RegSP.Word = RegIX.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xFA: // JP M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xFB: // EI - EI_pending = 2; - Interruptable = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // CALL M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xFD: // <- - // Invalid sequence. - totalExecutedCycles += 1337; pendingCycles -= 1337; - break; - case 0xFE: // CP n - RegAF.Word = TableALU[7, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xFF: // RST $38 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x38; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - } - break; - case 0xDE: // SBC A, n - RegAF.Word = TableALU[3, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xDF: // RST $18 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x18; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE0: // RET PO - if (!RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE1: // POP HL - RegHL.Low = ReadMemoryWrapper(RegSP.Word++); RegHL.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xE2: // JP PO, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xE3: // EX (SP), HL - TUS = RegSP.Word; TBL = ReadMemoryWrapper(TUS++); TBH = ReadMemoryWrapper(TUS--); - WriteMemoryWrapper(TUS++, RegHL.Low); WriteMemoryWrapper(TUS, RegHL.High); - RegHL.Low = TBL; RegHL.High = TBH; - RegWZ = RegHL; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xE4: // CALL PO, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagP) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xE5: // PUSH HL - WriteMemoryWrapper(--RegSP.Word, RegHL.High); WriteMemoryWrapper(--RegSP.Word, RegHL.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE6: // AND n - RegAF.Word = TableALU[4, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xE7: // RST $20 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x20; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE8: // RET PE - if (RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE9: // JP HL - RegWZ = RegHL; - RegPC.Word = RegHL.Word; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEA: // JP PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xEB: // EX DE, HL - TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // CALL PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xED: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x02: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x03: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x04: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x07: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x11: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x12: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x13: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x14: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x17: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x19: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x21: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x22: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x23: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x24: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x25: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x26: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x27: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x29: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x31: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x32: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x33: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x34: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x35: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x36: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x37: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x39: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // IN B, C - RegBC.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.High > 127; - RegFlagZ = RegBC.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x41: // OUT C, B - WriteHardware(RegBC.Low, RegBC.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x42: // SBC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x43: // LD (nn), BC - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegBC.Low); - WriteMemoryWrapper(TUS, RegBC.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x44: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x46: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x47: // LD I, A - RegI = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x48: // IN C, C - RegBC.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.Low > 127; - RegFlagZ = RegBC.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x49: // OUT C, C - WriteHardware(RegBC.Low, RegBC.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x4A: // ADC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x4B: // LD BC, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegBC.Low = ReadMemoryWrapper(TUS++); RegBC.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x4E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4F: // LD R, A - RegR = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x50: // IN D, C - RegDE.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.High > 127; - RegFlagZ = RegDE.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x51: // OUT C, D - WriteHardware(RegBC.Low, RegDE.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x52: // SBC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x53: // LD (nn), DE - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegDE.Low); - WriteMemoryWrapper(TUS, RegDE.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x54: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x56: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x57: // LD A, I - RegAF.High = RegI; - RegFlagS = RegI > 127; - RegFlagZ = RegI == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x58: // IN E, C - RegDE.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.Low > 127; - RegFlagZ = RegDE.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x59: // OUT C, E - WriteHardware(RegBC.Low, RegDE.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x5A: // ADC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x5B: // LD DE, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegDE.Low = ReadMemoryWrapper(TUS++); RegDE.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x5E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5F: // LD A, R - RegAF.High = (byte)(RegR & 0x7F); - RegFlagS = (byte)(RegR & 0x7F) > 127; - RegFlagZ = (byte)(RegR & 0x7F) == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x60: // IN H, C - RegHL.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.High > 127; - RegFlagZ = RegHL.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x61: // OUT C, H - WriteHardware(RegBC.Low, RegHL.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x62: // SBC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x63: // LD (nn), HL - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegHL.Low); - WriteMemoryWrapper(TUS, RegHL.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x64: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x66: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x67: // RRD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x68: // IN L, C - RegHL.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.Low > 127; - RegFlagZ = RegHL.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x69: // OUT C, L - WriteHardware(RegBC.Low, RegHL.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x6A: // ADC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x6B: // LD HL, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegHL.Low = ReadMemoryWrapper(TUS++); RegHL.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x6E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6F: // RLD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x70: // IN 0, C - TB = ReadHardware((ushort)RegBC.Low); - RegFlagS = TB > 127; - RegFlagZ = TB == 0; - RegFlagH = false; - RegFlagP = TableParity[TB]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x71: // OUT C, 0 - WriteHardware(RegBC.Low, 0); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x72: // SBC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x73: // LD (nn), SP - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegSP.Low); - WriteMemoryWrapper(TUS, RegSP.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x74: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x75: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x76: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x77: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x78: // IN A, C - RegAF.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x79: // OUT C, A - WriteHardware(RegBC.Low, RegAF.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x7A: // ADC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x7B: // LD SP, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegSP.Low = ReadMemoryWrapper(TUS++); RegSP.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x7E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x85: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x86: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x87: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x95: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x96: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x97: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // LDI - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA1: // CPI - RegWZ = (ushort)(RegWZ + 1); - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA2: // INI - RegWZ = (ushort)(RegBC + 1); - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA3: // OUTI - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // LDD - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA9: // CPD - RegWZ = (ushort)(RegWZ - 1); - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAA: // IND - RegWZ = (ushort)(RegBC - 1); - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAB: // OUTD - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // LDIR - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB1: // CPIR - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB2: // INIR - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB3: // OTIR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // LDDR - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB9: // CPDR - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBA: // INDR - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBB: // OTDR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xED: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - } - break; - case 0xEE: // XOR n - RegAF.Word = TableALU[5, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xEF: // RST $28 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x28; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF0: // RET P - if (!RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF1: // POP AF - RegAF.Low = ReadMemoryWrapper(RegSP.Word++); RegAF.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF2: // JP P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF3: // DI - IFF1 = IFF2 = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // CALL P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xF5: // PUSH AF - WriteMemoryWrapper(--RegSP.Word, RegAF.High); WriteMemoryWrapper(--RegSP.Word, RegAF.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF6: // OR n - RegAF.Word = TableALU[6, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xF7: // RST $30 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x30; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF8: // RET M - if (RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF9: // LD SP, HL - RegSP.Word = RegHL.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0xFA: // JP M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xFB: // EI - EI_pending = 2; - Interruptable = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // CALL M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xFD: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // LD BC, nn - RegBC.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x02: // LD (BC), A - RegWZ.Low = (byte)((RegBC.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegBC.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x03: // INC BC - ++RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x04: // INC B - RegAF.Low = (byte)(TableInc[++RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // DEC B - RegAF.Low = (byte)(TableDec[--RegBC.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // LD B, n - RegBC.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x07: // RLCA - RegAF.Word = TableRotShift[0, 0, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // EX AF, AF' - TUS = RegAF.Word; RegAF.Word = RegAltAF.Word; RegAltAF.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // ADD IY, BC - RegWZ = (ushort)(RegIY + 1); - TI1 = (short)RegIY.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIY.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x0A: // LD A, (BC) - RegAF.High = ReadMemoryWrapper(RegBC.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegBC.Word + 1); - break; - case 0x0B: // DEC BC - --RegBC.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x0C: // INC C - RegAF.Low = (byte)(TableInc[++RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // DEC C - RegAF.Low = (byte)(TableDec[--RegBC.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // LD C, n - RegBC.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x0F: // RRCA - RegAF.Word = TableRotShift[0, 1, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // DJNZ d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (--RegBC.High != 0) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 13; pendingCycles -= 13; - } - else - { - totalExecutedCycles += 8; pendingCycles -= 8; - } - break; - case 0x11: // LD DE, nn - RegDE.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x12: // LD (DE), A - RegWZ.Low = (byte)((RegDE.Word + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(RegDE.Word, RegAF.High); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x13: // INC DE - ++RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x14: // INC D - RegAF.Low = (byte)(TableInc[++RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // DEC D - RegAF.Low = (byte)(TableDec[--RegDE.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // LD D, n - RegDE.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x17: // RLA - RegAF.Word = TableRotShift[0, 2, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // JR d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x19: // ADD IY, DE - RegWZ = (ushort)(RegIY + 1); - TI1 = (short)RegIY.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIY.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x1A: // LD A, (DE) - RegAF.High = ReadMemoryWrapper(RegDE.Word); - totalExecutedCycles += 7; pendingCycles -= 7; - RegWZ = (ushort)(RegDE.Word + 1); - break; - case 0x1B: // DEC DE - --RegDE.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x1C: // INC E - RegAF.Low = (byte)(TableInc[++RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // DEC E - RegAF.Low = (byte)(TableDec[--RegDE.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // LD E, n - RegDE.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x1F: // RRA - RegAF.Word = TableRotShift[0, 3, RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // JR NZ, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x21: // LD IY, nn - RegIY.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x22: // LD (nn), IY - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegIY.Low); - WriteMemoryWrapper(TUS, RegIY.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x23: // INC IY - ++RegIY.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x24: // INC IYH - RegAF.Low = (byte)(TableInc[++RegIY.High] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x25: // DEC IYH - RegAF.Low = (byte)(TableDec[--RegIY.High] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x26: // LD IYH, n - RegIY.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x27: // DAA - RegAF.Word = TableDaa[RegAF.Word]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // JR Z, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagZ) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x29: // ADD IY, IY - RegWZ = (ushort)(RegIY + 1); - TI1 = (short)RegIY.Word; TI2 = (short)RegIY.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIY.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x2A: // LD IY, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegIY.Low = ReadMemoryWrapper(TUS++); RegIY.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x2B: // DEC IY - --RegIY.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x2C: // INC IYL - RegAF.Low = (byte)(TableInc[++RegIY.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2D: // DEC IYL - RegAF.Low = (byte)(TableDec[--RegIY.Low] | (RegAF.Low & 1)); - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x2E: // LD IYL, n - RegIY.Low = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0x2F: // CPL - RegAF.High ^= 0xFF; RegFlagH = true; RegFlagN = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // JR NC, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (!RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x31: // LD SP, nn - RegSP.Word = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0x32: // LD (nn), A - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ.Low = (byte)((temp_WZ + 1) & 0xFF); - RegWZ.High = RegAF.High; - WriteMemoryWrapper(temp_WZ, RegAF.High); - totalExecutedCycles += 13; pendingCycles -= 13; - break; - case 0x33: // INC SP - ++RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x34: // INC (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - TB = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); RegAF.Low = (byte)(TableInc[++TB] | (RegAF.Low & 1)); WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), TB); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x35: // DEC (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - TB = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); RegAF.Low = (byte)(TableDec[--TB] | (RegAF.Low & 1)); WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), TB); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x36: // LD (IY+d), n - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x37: // SCF - RegFlagH = false; RegFlagN = false; RegFlagC = true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // JR C, d - TSB = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegPC.Word + TSB); - if (RegFlagC) - { - RegPC.Word = (ushort)(RegPC.Word + TSB); - totalExecutedCycles += 12; pendingCycles -= 12; - } - else - { - totalExecutedCycles += 7; pendingCycles -= 7; - } - break; - case 0x39: // ADD IY, SP - RegWZ = (ushort)(RegIY + 1); - TI1 = (short)RegIY.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegIY.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x3A: // LD A, (nn) - temp_WZ = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegAF.High = ReadMemoryWrapper(temp_WZ); - totalExecutedCycles += 13; pendingCycles -= 13; - RegWZ = (ushort)(temp_WZ + 1); - break; - case 0x3B: // DEC SP - --RegSP.Word; - totalExecutedCycles += 6; pendingCycles -= 6; - break; - case 0x3C: // INC A - RegAF.Low = (byte)(TableInc[++RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // DEC A - RegAF.Low = (byte)(TableDec[--RegAF.High] | (RegAF.Low & 1)); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // LD A, n - RegAF.High = FetchMemoryWrapper(RegPC.Word++); - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0x3F: // CCF - RegFlagH = RegFlagC; RegFlagN = false; RegFlagC ^= true; RegFlag3 = (RegAF.High & 0x08) != 0; RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // LD B, B - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x41: // LD B, C - RegBC.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x42: // LD B, D - RegBC.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x43: // LD B, E - RegBC.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x44: // LD B, IYH - RegBC.High = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // LD B, IYL - RegBC.High = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x46: // LD B, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegBC.High = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x47: // LD B, A - RegBC.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x48: // LD C, B - RegBC.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x49: // LD C, C - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4A: // LD C, D - RegBC.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4B: // LD C, E - RegBC.Low = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x4C: // LD C, IYH - RegBC.Low = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // LD C, IYL - RegBC.Low = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4E: // LD C, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegBC.Low = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x4F: // LD C, A - RegBC.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x50: // LD D, B - RegDE.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x51: // LD D, C - RegDE.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x52: // LD D, D - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x53: // LD D, E - RegDE.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x54: // LD D, IYH - RegDE.High = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // LD D, IYL - RegDE.High = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x56: // LD D, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegDE.High = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x57: // LD D, A - RegDE.High = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x58: // LD E, B - RegDE.Low = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x59: // LD E, C - RegDE.Low = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5A: // LD E, D - RegDE.Low = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5B: // LD E, E - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x5C: // LD E, IYH - RegDE.Low = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // LD E, IYL - RegDE.Low = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5E: // LD E, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegDE.Low = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x5F: // LD E, A - RegDE.Low = RegAF.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x60: // LD IYH, B - RegIY.High = RegBC.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x61: // LD IYH, C - RegIY.High = RegBC.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x62: // LD IYH, D - RegIY.High = RegDE.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x63: // LD IYH, E - RegIY.High = RegDE.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x64: // LD IYH, IYH - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // LD IYH, IYL - RegIY.High = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x66: // LD H, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegHL.High = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x67: // LD IYH, A - RegIY.High = RegAF.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x68: // LD IYL, B - RegIY.Low = RegBC.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x69: // LD IYL, C - RegIY.Low = RegBC.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6A: // LD IYL, D - RegIY.Low = RegDE.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6B: // LD IYL, E - RegIY.Low = RegDE.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6C: // LD IYL, IYH - RegIY.Low = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // LD IYL, IYL - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6E: // LD L, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegHL.Low = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x6F: // LD IYL, A - RegIY.Low = RegAF.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x70: // LD (IY+d), B - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegBC.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x71: // LD (IY+d), C - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegBC.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x72: // LD (IY+d), D - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegDE.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x73: // LD (IY+d), E - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegDE.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x74: // LD (IY+d), H - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegHL.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x75: // LD (IY+d), L - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegHL.Low); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x76: // HALT - Halt(); - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x77: // LD (IY+d), A - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), RegAF.High); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x78: // LD A, B - RegAF.High = RegBC.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x79: // LD A, C - RegAF.High = RegBC.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7A: // LD A, D - RegAF.High = RegDE.High; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7B: // LD A, E - RegAF.High = RegDE.Low; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x7C: // LD A, IYH - RegAF.High = RegIY.High; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // LD A, IYL - RegAF.High = RegIY.Low; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7E: // LD A, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.High = ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x7F: // LD A, A - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // ADD A, B - RegAF.Word = TableALU[0, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // ADD A, C - RegAF.Word = TableALU[0, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // ADD A, D - RegAF.Word = TableALU[0, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // ADD A, E - RegAF.Word = TableALU[0, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // ADD A, IYH - RegAF.Word = TableALU[0, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x85: // ADD A, IYL - RegAF.Word = TableALU[0, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x86: // ADD A, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[0, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x87: // ADD A, A - RegAF.Word = TableALU[0, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // ADC A, B - RegAF.Word = TableALU[1, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // ADC A, C - RegAF.Word = TableALU[1, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // ADC A, D - RegAF.Word = TableALU[1, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // ADC A, E - RegAF.Word = TableALU[1, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // ADC A, IYH - RegAF.Word = TableALU[1, RegAF.High, RegIY.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8D: // ADC A, IYL - RegAF.Word = TableALU[1, RegAF.High, RegIY.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x8E: // ADC A, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[1, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), RegFlagC ? 1 : 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x8F: // ADC A, A - RegAF.Word = TableALU[1, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // SUB B - RegAF.Word = TableALU[2, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // SUB C - RegAF.Word = TableALU[2, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // SUB D - RegAF.Word = TableALU[2, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // SUB E - RegAF.Word = TableALU[2, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // SUB IYH - RegAF.Word = TableALU[2, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x95: // SUB IYL - RegAF.Word = TableALU[2, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x96: // SUB (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[2, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x97: // SUB A, A - RegAF.Word = TableALU[2, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // SBC A, B - RegAF.Word = TableALU[3, RegAF.High, RegBC.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // SBC A, C - RegAF.Word = TableALU[3, RegAF.High, RegBC.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // SBC A, D - RegAF.Word = TableALU[3, RegAF.High, RegDE.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // SBC A, E - RegAF.Word = TableALU[3, RegAF.High, RegDE.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // SBC A, IYH - RegAF.Word = TableALU[3, RegAF.High, RegIY.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9D: // SBC A, IYL - RegAF.Word = TableALU[3, RegAF.High, RegIY.Low, RegFlagC ? 1 : 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x9E: // SBC A, (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[3, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), RegFlagC ? 1 : 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0x9F: // SBC A, A - RegAF.Word = TableALU[3, RegAF.High, RegAF.High, RegFlagC ? 1 : 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // AND B - RegAF.Word = TableALU[4, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA1: // AND C - RegAF.Word = TableALU[4, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA2: // AND D - RegAF.Word = TableALU[4, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA3: // AND E - RegAF.Word = TableALU[4, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA4: // AND IYH - RegAF.Word = TableALU[4, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA5: // AND IYL - RegAF.Word = TableALU[4, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xA6: // AND (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[4, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xA7: // AND A - RegAF.Word = TableALU[4, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // XOR B - RegAF.Word = TableALU[5, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA9: // XOR C - RegAF.Word = TableALU[5, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAA: // XOR D - RegAF.Word = TableALU[5, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAB: // XOR E - RegAF.Word = TableALU[5, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAC: // XOR IYH - RegAF.Word = TableALU[5, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAD: // XOR IYL - RegAF.Word = TableALU[5, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xAE: // XOR (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[5, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xAF: // XOR A - RegAF.Word = TableALU[5, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // OR B - RegAF.Word = TableALU[6, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB1: // OR C - RegAF.Word = TableALU[6, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB2: // OR D - RegAF.Word = TableALU[6, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB3: // OR E - RegAF.Word = TableALU[6, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB4: // OR IYH - RegAF.Word = TableALU[6, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB5: // OR IYL - RegAF.Word = TableALU[6, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xB6: // OR (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[6, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xB7: // OR A - RegAF.Word = TableALU[6, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // CP B - RegAF.Word = TableALU[7, RegAF.High, RegBC.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB9: // CP C - RegAF.Word = TableALU[7, RegAF.High, RegBC.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBA: // CP D - RegAF.Word = TableALU[7, RegAF.High, RegDE.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBB: // CP E - RegAF.Word = TableALU[7, RegAF.High, RegDE.Low, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBC: // CP IYH - RegAF.Word = TableALU[7, RegAF.High, RegIY.High, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBD: // CP IYL - RegAF.Word = TableALU[7, RegAF.High, RegIY.Low, 0]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xBE: // CP (IY+d) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - RegAF.Word = TableALU[7, RegAF.High, ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)), 0]; - totalExecutedCycles += 19; pendingCycles -= 19; - break; - case 0xBF: // CP A - RegAF.Word = TableALU[7, RegAF.High, RegAF.High, 0]; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // RET NZ - if (!RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC1: // POP BC - RegBC.Low = ReadMemoryWrapper(RegSP.Word++); RegBC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC2: // JP NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC3: // JP nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - RegPC.Word = TUS; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xC4: // CALL NZ, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xC5: // PUSH BC - WriteMemoryWrapper(--RegSP.Word, RegBC.High); WriteMemoryWrapper(--RegSP.Word, RegBC.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC6: // ADD A, n - RegAF.Word = TableALU[0, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xC7: // RST $00 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x00; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xC8: // RET Z - if (RegFlagZ) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xC9: // RET - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCA: // JP Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xCB: // (Prefix) - Displacement = (sbyte)FetchMemoryWrapper(RegPC.Word++); - RegWZ = (ushort)(RegIY.Word + Displacement); - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // RLC (IY+d) - RegWZ = (ushort)(RegIY.Word + Displacement); - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x01: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x02: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x03: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x04: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x05: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x06: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x07: // RLC (IY+d) - TUS = TableRotShift[1, 0, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x08: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x09: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0A: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0B: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0C: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0D: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0E: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x0F: // RRC (IY+d) - TUS = TableRotShift[1, 1, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x10: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x11: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x12: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x13: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x14: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x15: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x16: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x17: // RL (IY+d) - TUS = TableRotShift[1, 2, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x18: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x19: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1A: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1B: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1C: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1D: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1E: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x1F: // RR (IY+d) - TUS = TableRotShift[1, 3, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x20: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x21: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x22: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x23: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x24: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x25: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x26: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x27: // SLA (IY+d) - TUS = TableRotShift[1, 4, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x28: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x29: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2A: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2B: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2C: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2D: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2E: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x2F: // SRA (IY+d) - TUS = TableRotShift[1, 5, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x30: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x31: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x32: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x33: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x34: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x35: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x36: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x37: // SL1 (IY+d) - TUS = TableRotShift[1, 6, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x38: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x39: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3A: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3B: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3C: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3D: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3E: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x3F: // SRL (IY+d) - TUS = TableRotShift[1, 7, RegAF.Low + 256 * ReadMemoryWrapper((ushort)(RegIY.Word + Displacement))]; - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(TUS >> 8)); - RegAF.Low = (byte)TUS; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x40: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x41: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x42: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x43: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x44: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x45: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x46: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x47: // BIT 0, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x01) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x48: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x49: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4A: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4B: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4C: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4D: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4E: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4F: // BIT 1, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x02) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x50: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x51: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x52: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x53: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x54: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x55: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x56: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x57: // BIT 2, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x04) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x58: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x59: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5A: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5B: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5C: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5D: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5E: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5F: // BIT 3, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x08) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x60: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x61: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x62: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x63: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x64: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x65: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x66: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x67: // BIT 4, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x10) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x68: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x69: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6A: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6B: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6C: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6D: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6E: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x6F: // BIT 5, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x20) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x70: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x71: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x72: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x73: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x74: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x75: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x76: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x77: // BIT 6, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x40) == 0; - RegFlagP = RegFlagZ; - RegFlagS = false; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x78: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x79: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7A: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7B: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7C: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7D: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7E: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7F: // BIT 7, (IY+d) - RegFlagZ = (ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & 0x80) == 0; - RegFlagP = RegFlagZ; - RegFlagS = !RegFlagZ; - RegFlag3 = RegWZ.High.Bit(3); - RegFlag5 = RegWZ.High.Bit(5); - RegFlagH = true; - RegFlagN = false; - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x80: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x81: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x82: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x83: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x84: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x85: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x86: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x87: // RES 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x88: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x89: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8A: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8B: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8C: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8D: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8E: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x8F: // RES 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x90: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x91: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x92: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x93: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x94: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x95: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x96: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x97: // RES 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x98: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x99: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9A: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9B: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9C: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9D: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9E: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0x9F: // RES 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA0: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA1: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA2: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA3: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA4: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA5: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA6: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA7: // RES 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA8: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xA9: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAA: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAB: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAC: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAD: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAE: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xAF: // RES 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB0: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB1: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB2: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB3: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB4: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB5: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB6: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB7: // RES 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB8: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xB9: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBA: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBB: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBC: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBD: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBE: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xBF: // RES 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) & unchecked((byte)~0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC0: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC1: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC2: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC3: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC4: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC5: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC6: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC7: // SET 0, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x01))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC8: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xC9: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCA: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCB: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCC: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCD: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCE: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xCF: // SET 1, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x02))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD0: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD1: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD2: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD3: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD4: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD5: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD6: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD7: // SET 2, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x04))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD8: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xD9: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDA: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDB: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDC: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDD: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDE: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xDF: // SET 3, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x08))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE0: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE1: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE2: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE3: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE4: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE5: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE6: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE7: // SET 4, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x10))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE8: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE9: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEA: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEB: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEC: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xED: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEE: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xEF: // SET 5, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x20))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF0: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF1: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF2: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF3: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF4: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF5: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF6: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF7: // SET 6, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x40))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF8: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xF9: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFA: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFB: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFC: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFD: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFE: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xFF: // SET 7, (IY+d) - WriteMemoryWrapper((ushort)(RegIY.Word + Displacement), (byte)(ReadMemoryWrapper((ushort)(RegIY.Word + Displacement)) | unchecked((byte)0x80))); - totalExecutedCycles += 23; pendingCycles -= 23; - break; - } - break; - case 0xCC: // CALL Z, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagZ) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xCD: // CALL nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - break; - case 0xCE: // ADC A, n - RegAF.Word = TableALU[1, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xCF: // RST $08 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x08; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD0: // RET NC - if (!RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD1: // POP DE - RegDE.Low = ReadMemoryWrapper(RegSP.Word++); RegDE.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD2: // JP NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xD3: // OUT n, A - WriteHardware(FetchMemoryWrapper(RegPC.Word++), RegAF.High); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD4: // CALL NC, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xD5: // PUSH DE - WriteMemoryWrapper(--RegSP.Word, RegDE.High); WriteMemoryWrapper(--RegSP.Word, RegDE.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD6: // SUB n - RegAF.Word = TableALU[2, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xD7: // RST $10 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x10; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xD8: // RET C - if (RegFlagC) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xD9: // EXX - TUS = RegBC.Word; RegBC.Word = RegAltBC.Word; RegAltBC.Word = TUS; - TUS = RegDE.Word; RegDE.Word = RegAltDE.Word; RegAltDE.Word = TUS; - TUS = RegHL.Word; RegHL.Word = RegAltHL.Word; RegAltHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // JP C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xDB: // IN A, n - RegAF.High = ReadHardware((ushort)FetchMemoryWrapper(RegPC.Word++)); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xDC: // CALL C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xDD: // <- - // Invalid sequence. - totalExecutedCycles += 1337; pendingCycles -= 1337; - break; - case 0xDE: // SBC A, n - RegAF.Word = TableALU[3, RegAF.High, FetchMemoryWrapper(RegPC.Word++), RegFlagC ? 1 : 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xDF: // RST $18 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x18; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE0: // RET PO - if (!RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE1: // POP IY - RegIY.Low = ReadMemoryWrapper(RegSP.Word++); RegIY.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0xE2: // JP PO, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xE3: // EX (SP), IY - TUS = RegSP.Word; TBL = ReadMemoryWrapper(TUS++); TBH = ReadMemoryWrapper(TUS--); - WriteMemoryWrapper(TUS++, RegIY.Low); WriteMemoryWrapper(TUS, RegIY.High); - RegIY.Low = TBL; RegIY.High = TBH; - RegWZ = RegIY; - totalExecutedCycles += 23; pendingCycles -= 23; - break; - case 0xE4: // CALL C, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagC) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xE5: // PUSH IY - WriteMemoryWrapper(--RegSP.Word, RegIY.High); WriteMemoryWrapper(--RegSP.Word, RegIY.Low); - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0xE6: // AND n - RegAF.Word = TableALU[4, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xE7: // RST $20 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x20; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xE8: // RET PE - if (RegFlagP) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xE9: // JP IY - RegWZ = RegIY; - RegPC.Word = RegIY.Word; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0xEA: // JP PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xEB: // EX DE, HL - TUS = RegDE.Word; RegDE.Word = RegHL.Word; RegHL.Word = TUS; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // CALL PE, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagP) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xED: // (Prefix) - ++RegR; - switch (FetchMemoryWrapper(RegPC.Word++)) - { - case 0x00: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x01: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x02: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x03: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x04: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x05: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x06: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x07: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x08: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x09: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x0F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x10: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x11: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x12: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x13: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x14: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x15: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x16: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x17: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x18: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x19: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x1F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x20: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x21: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x22: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x23: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x24: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x25: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x26: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x27: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x28: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x29: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x2F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x30: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x31: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x32: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x33: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x34: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x35: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x36: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x37: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x38: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x39: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x3F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x40: // IN B, C - RegBC.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.High > 127; - RegFlagZ = RegBC.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x41: // OUT C, B - WriteHardware(RegBC.Low, RegBC.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x42: // SBC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegBC.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegBC.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x43: // LD (nn), BC - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegBC.Low); - WriteMemoryWrapper(TUS, RegBC.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x44: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x45: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x46: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x47: // LD I, A - RegI = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x48: // IN C, C - RegBC.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegBC.Low > 127; - RegFlagZ = RegBC.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegBC.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x49: // OUT C, C - WriteHardware(RegBC.Low, RegBC.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x4A: // ADC HL, BC - TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x4B: // LD BC, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegBC.Low = ReadMemoryWrapper(TUS++); RegBC.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x4C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x4E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x4F: // LD R, A - RegR = RegAF.High; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x50: // IN D, C - RegDE.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.High > 127; - RegFlagZ = RegDE.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x51: // OUT C, D - WriteHardware(RegBC.Low, RegDE.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x52: // SBC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegDE.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegDE.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x53: // LD (nn), DE - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegDE.Low); - WriteMemoryWrapper(TUS, RegDE.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x54: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x55: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x56: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x57: // LD A, I - RegAF.High = RegI; - RegFlagS = RegI > 127; - RegFlagZ = RegI == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x58: // IN E, C - RegDE.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegDE.Low > 127; - RegFlagZ = RegDE.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegDE.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x59: // OUT C, E - WriteHardware(RegBC.Low, RegDE.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x5A: // ADC HL, DE - TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x5B: // LD DE, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegDE.Low = ReadMemoryWrapper(TUS++); RegDE.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x5C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x5E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x5F: // LD A, R - RegAF.High = (byte)(RegR & 0x7F); - RegFlagS = (byte)(RegR & 0x7F) > 127; - RegFlagZ = (byte)(RegR & 0x7F) == 0; - RegFlagH = false; - RegFlagN = false; - RegFlagP = IFF2; - totalExecutedCycles += 9; pendingCycles -= 9; - break; - case 0x60: // IN H, C - RegHL.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.High > 127; - RegFlagZ = RegHL.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x61: // OUT C, H - WriteHardware(RegBC.Low, RegHL.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x62: // SBC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegHL.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegHL.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x63: // LD (nn), HL - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegHL.Low); - WriteMemoryWrapper(TUS, RegHL.High); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x64: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x65: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x66: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x67: // RRD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB2 >> 4) + (TB1 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 & 0x0F)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x68: // IN L, C - RegHL.Low = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegHL.Low > 127; - RegFlagZ = RegHL.Low == 0; - RegFlagH = false; - RegFlagP = TableParity[RegHL.Low]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x69: // OUT C, L - WriteHardware(RegBC.Low, RegHL.Low); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x6A: // ADC HL, HL - TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x6B: // LD HL, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegHL.Low = ReadMemoryWrapper(TUS++); RegHL.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0x6C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x6E: // IM $0 - interruptMode = 0; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x6F: // RLD - RegWZ = (ushort)(RegHL + 1); - TB1 = RegAF.High; TB2 = ReadMemoryWrapper(RegHL.Word); - WriteMemoryWrapper(RegHL.Word, (byte)((TB1 & 0x0F) + (TB2 << 4))); - RegAF.High = (byte)((TB1 & 0xF0) + (TB2 >> 4)); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - RegFlag3 = (RegAF.High & 0x08) != 0; - RegFlag5 = (RegAF.High & 0x20) != 0; - totalExecutedCycles += 18; pendingCycles -= 18; - break; - case 0x70: // IN 0, C - TB = ReadHardware((ushort)RegBC.Low); - RegFlagS = TB > 127; - RegFlagZ = TB == 0; - RegFlagH = false; - RegFlagP = TableParity[TB]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x71: // OUT C, 0 - WriteHardware(RegBC.Low, 0); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x72: // SBC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 - TI2; - if (RegFlagC) { --TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((RegHL.Word ^ RegSP.Word ^ TUS) & 0x1000) != 0; - RegFlagN = true; - RegFlagC = (((int)RegHL.Word - (int)RegSP.Word - (RegFlagC ? 1 : 0)) & 0x10000) != 0; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x73: // LD (nn), SP - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - WriteMemoryWrapper(TUS++, RegSP.Low); - WriteMemoryWrapper(TUS, RegSP.High); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x74: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x75: // RETN - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - IFF1 = IFF2; - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x76: // IM $1 - interruptMode = 1; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x77: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x78: // IN A, C - RegAF.High = ReadHardware((ushort)RegBC.Low); - RegFlagS = RegAF.High > 127; - RegFlagZ = RegAF.High == 0; - RegFlagH = false; - RegFlagP = TableParity[RegAF.High]; - RegFlagN = false; - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x79: // OUT C, A - WriteHardware(RegBC.Low, RegAF.High); - totalExecutedCycles += 12; pendingCycles -= 12; - break; - case 0x7A: // ADC HL, SP - TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2; - if (RegFlagC) { ++TIR; ++TI2; } - TUS = (ushort)TIR; - RegFlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF; - RegFlagN = false; - RegFlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF; - RegFlagP = TIR > 32767 || TIR < -32768; - RegFlagS = TUS > 32767; - RegFlagZ = TUS == 0; - RegHL.Word = TUS; - RegFlag3 = (TUS & 0x0800) != 0; - RegFlag5 = (TUS & 0x2000) != 0; - totalExecutedCycles += 15; pendingCycles -= 15; - break; - case 0x7B: // LD SP, (nn) - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = (ushort)(TUS + 1); - RegSP.Low = ReadMemoryWrapper(TUS++); RegSP.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 20; pendingCycles -= 20; - break; - case 0x7C: // NEG - RegAF.Word = TableNeg[RegAF.Word]; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7D: // RETI - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 14; pendingCycles -= 14; - break; - case 0x7E: // IM $2 - interruptMode = 2; - totalExecutedCycles += 8; pendingCycles -= 8; - break; - case 0x7F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x80: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x81: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x82: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x83: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x84: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x85: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x86: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x87: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x88: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x89: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x8F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x90: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x91: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x92: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x93: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x94: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x95: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x96: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x97: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x98: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x99: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9A: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9B: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9C: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9D: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9E: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0x9F: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA0: // LDI - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA1: // CPI - RegWZ = (ushort)(RegWZ + 1); - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA2: // INI - RegWZ = (ushort)(RegBC + 1); - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA3: // OUTI - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xA8: // LDD - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xA9: // CPD - RegWZ = (ushort)(RegWZ - 1); - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAA: // IND - RegWZ = (ushort)(RegBC - 1); - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAB: // OUTD - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - totalExecutedCycles += 16; pendingCycles -= 16; - break; - case 0xAC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xAF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB0: // LDIR - WriteMemoryWrapper(RegDE.Word++, TB1 = ReadMemoryWrapper(RegHL.Word++)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB1: // CPIR - TB1 = ReadMemoryWrapper(RegHL.Word++); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB2: // INIR - WriteMemoryWrapper(RegHL.Word++, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB3: // OTIR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word++)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xB8: // LDDR - WriteMemoryWrapper(RegDE.Word--, TB1 = ReadMemoryWrapper(RegHL.Word--)); - TB1 += RegAF.High; RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - RegFlagH = false; - RegFlagN = false; - if (RegBC.Word != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xB9: // CPDR - TB1 = ReadMemoryWrapper(RegHL.Word--); TB2 = (byte)(RegAF.High - TB1); - RegFlagN = true; - RegFlagH = TableHalfBorrow[RegAF.High, TB1]; - RegFlagZ = TB2 == 0; - RegFlagS = TB2 > 127; - TB1 = (byte)(RegAF.High - TB1 - (RegFlagH ? 1 : 0)); RegFlag5 = (TB1 & 0x02) != 0; RegFlag3 = (TB1 & 0x08) != 0; - --RegBC.Word; - RegFlagP = RegBC.Word != 0; - if (RegBC.Word != 0 && !RegFlagZ) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBA: // INDR - WriteMemoryWrapper(RegHL.Word--, ReadHardware(RegBC.Word)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBB: // OTDR - WriteHardware(RegBC.Word, ReadMemoryWrapper(RegHL.Word--)); - --RegBC.High; - RegFlagZ = RegBC.High == 0; - RegFlagN = true; - if (RegBC.High != 0) - { - RegPC.Word -= 2; - totalExecutedCycles += 21; pendingCycles -= 21; - } - else - { - totalExecutedCycles += 16; pendingCycles -= 16; - } - break; - case 0xBC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xBF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xC9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xCF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xD9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xDF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xE9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xED: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xEF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF0: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF1: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF2: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF3: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF5: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF6: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF7: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF8: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF9: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFA: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFB: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFD: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFE: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFF: // NOP - totalExecutedCycles += 4; pendingCycles -= 4; - break; - } - break; - case 0xEE: // XOR n - RegAF.Word = TableALU[5, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xEF: // RST $28 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x28; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF0: // RET P - if (!RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF1: // POP AF - RegAF.Low = ReadMemoryWrapper(RegSP.Word++); RegAF.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF2: // JP P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xF3: // DI - IFF1 = IFF2 = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xF4: // CALL P, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (!RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xF5: // PUSH AF - WriteMemoryWrapper(--RegSP.Word, RegAF.High); WriteMemoryWrapper(--RegSP.Word, RegAF.Low); - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF6: // OR n - RegAF.Word = TableALU[6, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xF7: // RST $30 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x30; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - case 0xF8: // RET M - if (RegFlagS) - { - RegPC.Low = ReadMemoryWrapper(RegSP.Word++); RegPC.High = ReadMemoryWrapper(RegSP.Word++); - totalExecutedCycles += 11; pendingCycles -= 11; - } - else - { - totalExecutedCycles += 5; pendingCycles -= 5; - } - break; - case 0xF9: // LD SP, IY - RegSP.Word = RegIY.Word; - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xFA: // JP M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - RegPC.Word = TUS; - } - totalExecutedCycles += 10; pendingCycles -= 10; - break; - case 0xFB: // EI - EI_pending = 2; - Interruptable = false; - totalExecutedCycles += 4; pendingCycles -= 4; - break; - case 0xFC: // CALL M, nn - TUS = (ushort)(FetchMemoryWrapper(RegPC.Word++) + FetchMemoryWrapper(RegPC.Word++) * 256); - RegWZ = TUS; - if (RegFlagS) - { - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = TUS; - totalExecutedCycles += 17; pendingCycles -= 17; - } - else - { - totalExecutedCycles += 10; pendingCycles -= 10; - } - break; - case 0xFD: // <- - // Invalid sequence. - totalExecutedCycles += 1337; pendingCycles -= 1337; - break; - case 0xFE: // CP n - RegAF.Word = TableALU[7, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xFF: // RST $38 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x38; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - } - break; - case 0xFE: // CP n - RegAF.Word = TableALU[7, RegAF.High, FetchMemoryWrapper(RegPC.Word++), 0]; - totalExecutedCycles += 7; pendingCycles -= 7; - break; - case 0xFF: // RST $38 - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x38; - totalExecutedCycles += 11; pendingCycles -= 11; - break; - } - - } - - //EI (enable interrupts) actually takes effect after the NEXT instruction - if (EI_pending > 0) - { - EI_pending--; - if (EI_pending == 0) - { - IFF1 = IFF2 = true; - } - } - - // Process interrupt requests. - if (nonMaskableInterruptPending) - { - halted = false; - - totalExecutedCycles += 11; pendingCycles -= 11; - nonMaskableInterruptPending = false; - - iff2 = iff1; - iff1 = false; - - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x66; - NMICallback(); - - } - else if (iff1 && interrupt && Interruptable) - { - Halted = false; - - iff1 = iff2 = false; - - switch (interruptMode) - { - case 0: - totalExecutedCycles += 13; pendingCycles -= 13; - break; - case 1: - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Word = 0x38; - totalExecutedCycles += 13; pendingCycles -= 13; - break; - case 2: - TUS = (ushort)(RegI * 256 + 0); - WriteMemoryWrapper(--RegSP.Word, RegPC.High); WriteMemoryWrapper(--RegSP.Word, RegPC.Low); - RegPC.Low = ReadMemoryWrapper(TUS++); RegPC.High = ReadMemoryWrapper(TUS); - totalExecutedCycles += 19; pendingCycles -= 19; - break; - } - IRQCallback(); - } - - - } - } - - // TODO, not super thrilled with the existing Z80 disassembler, lets see if we can find something decent to replace it with - Disassembler Disassembler = new Disassembler(); - - public string TraceHeader - { - get { return "Z80: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; } - } - - public TraceInfo State() - { - ushort tempPC = RegPC.Word; - - return new TraceInfo - { - Disassembly = string.Format( - "{0:X4}: {1:X2} {2}", - RegPC.Word, - FetchMemoryWrapper(RegPC.Word), - Disassembler.Disassemble(() => ReadMemoryWrapper(tempPC++))).PadRight(26), - RegisterInfo = string.Format( - "AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7} {8}{9}{10}{11}{12}{13}{14}{15}", - RegAF.Word, - RegBC.Word, - RegDE.Word, - RegHL.Word, - RegIX.Word, - RegIY.Word, - RegSP.Word, - TotalExecutedCycles, - RegFlagC ? "C" : "c", - RegFlagN ? "N" : "n", - RegFlagP ? "P" : "p", - RegFlag3 ? "3" : "-", - RegFlagH ? "H" : "h", - RegFlag5 ? "5" : "-", - RegFlagZ ? "Z" : "z", - RegFlagS ? "S" : "s" - ) - }; - } - } -} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Interrupts.cs deleted file mode 100644 index 738f1dad74..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Interrupts.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; - -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public partial class Z80A - { - private bool iff1; - public bool IFF1 { get { return iff1; } set { iff1 = value; } } - - private bool iff2; - public bool IFF2 { get { return iff2; } set { iff2 = value; } } - - private bool interrupt; - public bool Interrupt { get { return interrupt; } set { interrupt = value; } } - - private bool nonMaskableInterrupt; - public bool NonMaskableInterrupt - { - get { return nonMaskableInterrupt; } - set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; } - } - - private bool nonMaskableInterruptPending; - public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } } - - private int interruptMode; - public int InterruptMode - { - get { return interruptMode; } - set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; } - } - - private bool halted; - public bool Halted { get { return halted; } set { halted = value; } } - - public Action IRQCallback = delegate() { }; - public Action NMICallback = delegate() { }; - - private void ResetInterrupts() - { - IFF1 = false; - IFF2 = false; - Interrupt = false; - NonMaskableInterrupt = false; - NonMaskableInterruptPending = false; - InterruptMode = 1; - Halted = false; - } - - private void Halt() - { - Halted = true; - } - } -} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Registers.cs deleted file mode 100644 index bd5fe98cbc..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Registers.cs +++ /dev/null @@ -1,270 +0,0 @@ -using System.Runtime.InteropServices; -using System; - -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public partial class Z80A - { - [StructLayout(LayoutKind.Explicit)] - [Serializable()] - public struct RegisterPair - { - [FieldOffset(0)] - public ushort Word; - - [FieldOffset(0)] - public byte Low; - - [FieldOffset(1)] - public byte High; - - public RegisterPair(ushort value) - { - Word = value; - Low = (byte)(Word); - High = (byte)(Word >> 8); - } - - public static implicit operator ushort(RegisterPair rp) - { - return rp.Word; - } - - public static implicit operator RegisterPair(ushort value) - { - return new RegisterPair(value); - } - } - - private bool RegFlagC - { - get { return (RegAF.Low & 0x01) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x01) | (value ? 0x01 : 0x00)); } - } - - private bool RegFlagN - { - get { return (RegAF.Low & 0x02) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x02) | (value ? 0x02 : 0x00)); } - } - - private bool RegFlagP - { - get { return (RegAF.Low & 0x04) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x04) | (value ? 0x04 : 0x00)); } - } - - private bool RegFlag3 - { - get { return (RegAF.Low & 0x08) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x08) | (value ? 0x08 : 0x00)); } - } - - private bool RegFlagH - { - get { return (RegAF.Low & 0x10) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x10) | (value ? 0x10 : 0x00)); } - } - - private bool RegFlag5 - { - get { return (RegAF.Low & 0x20) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x20) | (value ? 0x20 : 0x00)); } - } - - private bool RegFlagZ - { - get { return (RegAF.Low & 0x40) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x40) | (value ? 0x40 : 0x00)); } - } - - private bool RegFlagS - { - get { return (RegAF.Low & 0x80) != 0; } - set { RegAF.Low = (byte)((RegAF.Low & ~0x80) | (value ? 0x80 : 0x00)); } - } - - private RegisterPair RegAF; - private RegisterPair RegBC; - private RegisterPair RegDE; - private RegisterPair RegHL; - private RegisterPair RegWZ; - - private RegisterPair RegAltAF; // Shadow for A and F - private RegisterPair RegAltBC; // Shadow for B and C - private RegisterPair RegAltDE; // Shadow for D and E - private RegisterPair RegAltHL; // Shadow for H and L - // NOTE: There is no AltWZ register (despite it being shown on various block diagrams) - - private byte RegI; // I (interrupt vector) - private byte RegR; // R (memory refresh) - - private RegisterPair RegIX; // IX (index register x) - private RegisterPair RegIY; // IY (index register y) - - private RegisterPair RegSP; // SP (stack pointer) - private RegisterPair RegPC; // PC (program counter) - - private void ResetRegisters() - { - // Clear main registers - RegAF = 0; RegBC = 0; RegDE = 0; RegHL = 0; RegWZ = 0; - // Clear alternate registers - RegAltAF = 0; RegAltBC = 0; RegAltDE = 0; RegAltHL = 0; - // Clear special purpose registers - RegI = 0; RegR = 0; - RegIX.Word = 0; RegIY.Word = 0; - RegSP.Word = 0; RegPC.Word = 0; - } - - public byte RegisterA - { - get { return RegAF.High; } - set { RegAF.High = value; } - } - - public byte RegisterF - { - get { return RegAF.Low; } - set { RegAF.Low = value; } - } - - public ushort RegisterAF - { - get { return RegAF.Word; } - set { RegAF.Word = value; } - } - - public byte RegisterB - { - get { return RegBC.High; } - set { RegBC.High = value; } - } - - public byte RegisterC - { - get { return RegBC.Low; } - set { RegBC.Low = value; } - } - - public ushort RegisterBC - { - get { return RegBC.Word; } - set { RegBC.Word = value; } - } - - public byte RegisterD - { - get { return RegDE.High; } - set { RegDE.High = value; } - } - - public byte RegisterE - { - get { return RegDE.Low; } - set { RegDE.Low = value; } - } - - public ushort RegisterDE - { - get { return RegDE.Word; } - set { RegDE.Word = value; } - } - - public byte RegisterH - { - get { return RegHL.High; } - set { RegHL.High = value; } - } - - public byte RegisterL - { - get { return RegHL.Low; } - set { RegHL.Low = value; } - } - - public ushort RegisterHL - { - get { return RegHL.Word; } - set { RegHL.Word = value; } - } - - public byte RegisterW - { - get { return RegWZ.High; } - set { RegWZ.High = value; } - } - - public byte RegisterZ - { - get { return RegWZ.Low; } - set { RegWZ.Low = value; } - } - - public ushort RegisterWZ - { - get { return RegWZ.Word; } - set { RegWZ.Word = value; } - } - - public ushort RegisterPC - { - get { return RegPC.Word; } - set { RegPC.Word = value; } - } - - public ushort RegisterSP - { - get { return RegSP.Word; } - set { RegSP.Word = value; } - } - - public ushort RegisterIX - { - get { return RegIX.Word; } - set { RegIX.Word = value; } - } - - public ushort RegisterIY - { - get { return RegIY.Word; } - set { RegIY.Word = value; } - } - - public byte RegisterI - { - get { return RegI; } - set { RegI = value; } - } - - public byte RegisterR - { - get { return RegR; } - set { RegR = value; } - } - - public ushort RegisterShadowAF - { - get { return RegAltAF.Word; } - set { RegAltAF.Word = value; } - } - - public ushort RegisterShadowBC - { - get { return RegAltBC.Word; } - set { RegAltBC.Word = value; } - } - - public ushort RegisterShadowDE - { - get { return RegAltDE.Word; } - set { RegAltDE.Word = value; } - } - - public ushort RegisterShadowHL - { - get { return RegAltHL.Word; } - set { RegAltHL.Word = value; } - } - } -} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Tables.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Tables.cs deleted file mode 100644 index a50e9a1aeb..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Tables.cs +++ /dev/null @@ -1,331 +0,0 @@ -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public partial class Z80A - { - private void InitialiseTables() - { - InitTableInc(); - InitTableDec(); - InitTableParity(); - InitTableALU(); - InitTableRotShift(); - InitTableHalfBorrow(); - InitTableHalfCarry(); - InitTableNeg(); - InitTableDaa(); - } - - private byte[] TableInc; - private void InitTableInc() - { - TableInc = new byte[256]; - for (int i = 0; i < 256; ++i) - TableInc[i] = FlagByte(false, false, i == 0x80, UndocumentedX(i), (i & 0xF) == 0x0, UndocumentedY(i), i == 0, i > 127); - } - - private byte[] TableDec; - private void InitTableDec() - { - TableDec = new byte[256]; - for (int i = 0; i < 256; ++i) - TableDec[i] = FlagByte(false, true, i == 0x7F, UndocumentedX(i), (i & 0xF) == 0xF, UndocumentedY(i), i == 0, i > 127); - } - - private bool[] TableParity; - private void InitTableParity() - { - TableParity = new bool[256]; - for (int i = 0; i < 256; ++i) - { - int Bits = 0; - for (int j = 0; j < 8; ++j) - { - Bits += (i >> j) & 1; - } - TableParity[i] = (Bits & 1) == 0; - } - } - - private ushort[, , ,] TableALU; - private void InitTableALU() - { - TableALU = new ushort[8, 256, 256, 2]; // Class, OP1, OP2, Carry - - for (int i = 0; i < 8; ++i) - { - for (int op1 = 0; op1 < 256; ++op1) - { - for (int op2 = 0; op2 < 256; ++op2) - { - for (int c = 0; c < 2; ++c) - { - - int ac = (i == 1 || i == 3) ? c : 0; - - bool S = false; - bool Z = false; - bool C = false; - bool H = false; - bool N = false; - bool P = false; - - byte result_b = 0; - int result_si = 0; - int result_ui = 0; - - // Fetch result - switch (i) - { - case 0: - case 1: - result_si = (sbyte)op1 + (sbyte)op2 + ac; - result_ui = op1 + op2 + ac; - break; - case 2: - case 3: - case 7: - result_si = (sbyte)op1 - (sbyte)op2 - ac; - result_ui = op1 - op2 - ac; - break; - case 4: - result_si = op1 & op2; - break; - case 5: - result_si = op1 ^ op2; - break; - case 6: - result_si = op1 | op2; - break; - } - - result_b = (byte)result_si; - - // Parity/Carry - - switch (i) - { - case 0: - case 1: - case 2: - case 3: - case 7: - P = result_si < -128 || result_si > 127; - C = result_ui < 0 || result_ui > 255; - break; - case 4: - case 5: - case 6: - P = TableParity[result_b]; - C = false; - break; - } - - // Subtraction - N = i == 2 || i == 3 || i == 7; - - // Half carry - switch (i) - { - case 0: - case 1: - H = ((op1 & 0xF) + (op2 & 0xF) + (ac & 0xF)) > 0xF; - break; - case 2: - case 3: - case 7: - H = ((op1 & 0xF) - (op2 & 0xF) - (ac & 0xF)) < 0x0; - break; - case 4: - H = true; - break; - case 5: - case 6: - H = false; - break; - } - - // Undocumented - byte UndocumentedFlags = (byte)(result_b & 0x28); - if (i == 7) UndocumentedFlags = (byte)(op2 & 0x28); - - S = result_b > 127; - Z = result_b == 0; - - if (i == 7) result_b = (byte)op1; - - TableALU[i, op1, op2, c] = (ushort)( - result_b * 256 + - ((C ? 0x01 : 0) + (N ? 0x02 : 0) + (P ? 0x04 : 0) + (H ? 0x10 : 0) + (Z ? 0x40 : 0) + (S ? 0x80 : 0)) + - (UndocumentedFlags)); - - } - } - } - } - } - - private bool[,] TableHalfBorrow; - private void InitTableHalfBorrow() - { - TableHalfBorrow = new bool[256, 256]; - for (int i = 0; i < 256; i++) - { - for (int j = 0; j < 256; j++) - { - TableHalfBorrow[i, j] = ((i & 0xF) - (j & 0xF)) < 0; - } - } - } - - private bool[,] TableHalfCarry; - private void InitTableHalfCarry() - { - TableHalfCarry = new bool[256, 256]; - for (int i = 0; i < 256; i++) - { - for (int j = 0; j < 256; j++) - { - TableHalfCarry[i, j] = ((i & 0xF) + (j & 0xF)) > 0xF; - } - } - } - - private ushort[, ,] TableRotShift; - private void InitTableRotShift() - { - TableRotShift = new ushort[2, 8, 65536]; // All, operation, AF - for (int all = 0; all < 2; all++) - { - for (int y = 0; y < 8; ++y) - { - for (int af = 0; af < 65536; af++) - { - byte Old = (byte)(af >> 8); - bool OldCarry = (af & 0x01) != 0; - - ushort newAf = (ushort)(af & ~(0x13)); // Clear HALF-CARRY, SUBTRACT and CARRY flags - - byte New = Old; - if ((y & 1) == 0) - { - if ((Old & 0x80) != 0) ++newAf; - - New <<= 1; - - if ((y & 0x04) == 0) - { - if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x01; - } - else - { - if ((y & 0x02) != 0) New |= 0x01; - } - - } - else - { - - if ((Old & 0x01) != 0) ++newAf; - - New >>= 1; - - if ((y & 0x04) == 0) - { - if (((y & 0x02) == 0) ? ((newAf & 0x01) != 0) : OldCarry) New |= 0x80; - } - else - { - if ((y & 0x02) == 0) New |= (byte)(Old & 0x80); - } - } - - newAf &= 0xFF; - newAf |= (ushort)(New * 256); - - if (all == 1) - { - newAf &= unchecked((ushort)~0xC4); // Clear S, Z, P - if (New > 127) newAf |= 0x80; - if (New == 0) newAf |= 0x40; - if (TableParity[New]) newAf |= 0x04; - } - - TableRotShift[all, y, af] = (ushort)((newAf & ~0x28) | ((newAf >> 8) & 0x28)); - } - } - } - } - - private ushort[] TableNeg; - private void InitTableNeg() - { - TableNeg = new ushort[65536]; - for (int af = 0; af < 65536; af++) - { - ushort raf = 0; - byte b = (byte)(af >> 8); - byte a = (byte)-b; - raf |= (ushort)(a * 256); - raf |= FlagByte(b != 0x00, true, b == 0x80, UndocumentedX(a), TableHalfCarry[a, b], UndocumentedY(a), a == 0, a > 127); - TableNeg[af] = raf; - } - } - - private ushort[] TableDaa; - private void InitTableDaa() - { - TableDaa = new ushort[65536]; - for (int af = 0; af < 65536; ++af) - { - byte a = (byte)(af >> 8); - byte tmp = a; - - if (IsN(af)) - { - if (IsH(af) || ((a & 0x0F) > 0x09)) tmp -= 0x06; - if (IsC(af) || a > 0x99) tmp -= 0x60; - } - else - { - if (IsH(af) || ((a & 0x0F) > 0x09)) tmp += 0x06; - if (IsC(af) || a > 0x99) tmp += 0x60; - } - - TableDaa[af] = (ushort)((tmp * 256) + FlagByte(IsC(af) || a > 0x99, IsN(af), TableParity[tmp], UndocumentedX(tmp), ((a ^ tmp) & 0x10) != 0, UndocumentedY(tmp), tmp == 0, tmp > 127)); - } - } - - private byte FlagByte(bool C, bool N, bool P, bool X, bool H, bool Y, bool Z, bool S) - { - return (byte)( - (C ? 0x01 : 0) + - (N ? 0x02 : 0) + - (P ? 0x04 : 0) + - (X ? 0x08 : 0) + - (H ? 0x10 : 0) + - (Y ? 0x20 : 0) + - (Z ? 0x40 : 0) + - (S ? 0x80 : 0) - ); - } - - private bool UndocumentedX(int value) - { - return (value & 0x08) != 0; - } - - private bool UndocumentedY(int value) - { - return (value & 0x20) != 0; - } - - private bool IsC(int value) { return (value & 0x01) != 0; } - private bool IsN(int value) { return (value & 0x02) != 0; } - private bool IsP(int value) { return (value & 0x04) != 0; } - private bool IsX(int value) { return (value & 0x08) != 0; } - private bool IsH(int value) { return (value & 0x10) != 0; } - private bool IsY(int value) { return (value & 0x20) != 0; } - private bool IsZ(int value) { return (value & 0x40) != 0; } - private bool IsS(int value) { return (value & 0x80) != 0; } - } -} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Z80A.cs deleted file mode 100644 index 35b7d7038c..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Z80A.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System; -using System.Globalization; -using System.IO; - -using BizHawk.Common; -using BizHawk.Emulation.Common; - -// This Z80 emulator is a modified version of Ben Ryves 'Brazil' emulator. -// It is MIT licensed. - -// for WZ register details, see: http://www.grimware.org/lib/exe/fetch.php/documentations/devices/z80/z80.memptr.eng.txt - -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public sealed partial class Z80A - { - public Z80A() - { - InitialiseTables(); - Reset(); - } - - public void Reset() - { - ResetRegisters(); - ResetInterrupts(); - PendingCycles = 0; - ExpectedExecutedCycles = 0; - TotalExecutedCycles = 0; - } - - public void SoftReset() - { - ResetRegisters(); - ResetInterrupts(); - } - - // Memory Access - - public Func FetchMemory; - public Func ReadMemory; - public Action WriteMemory; - - public byte ReadMemoryWrapper(ushort addr) - { - if (MemoryCallbacks != null) - { - MemoryCallbacks.CallReads(addr); - } - - return ReadMemory(addr); - } - - public byte FetchFirstMemoryWrapper(ushort addr) - { - if (MemoryCallbacks != null) - { - MemoryCallbacks.CallReads(addr); - } - - if (FetchMemory != null) - { - return FetchMemory(addr, true); - } - - return ReadMemory(addr); - } - - public byte FetchMemoryWrapper(ushort addr) - { - if (MemoryCallbacks != null) - { - MemoryCallbacks.CallReads(addr); - } - - if (FetchMemory != null) - { - return FetchMemory(addr, false); - } - - return ReadMemory(addr); - } - - public void WriteMemoryWrapper(ushort addr, byte value) - { - if (MemoryCallbacks != null) - { - MemoryCallbacks.CallWrites(addr); - } - - WriteMemory(addr, value); - } - - public IMemoryCallbackSystem MemoryCallbacks { get; set; } - - // Utility function, not used by core - public ushort ReadWord(ushort addr) - { - ushort value = ReadMemory(addr++); - value |= (ushort)(ReadMemory(addr) << 8); - return value; - } - - // Hardware I/O Port Access - - public Func ReadHardware; - public Action WriteHardware; - - // State Save/Load - - public void SyncState(Serializer ser) - { - ser.BeginSection("Z80"); - ser.Sync("AF", ref RegAF.Word); - ser.Sync("BC", ref RegBC.Word); - ser.Sync("DE", ref RegDE.Word); - ser.Sync("HL", ref RegHL.Word); - ser.Sync("WZ", ref RegWZ.Word); - ser.Sync("ShadowAF", ref RegAltAF.Word); - ser.Sync("ShadowBC", ref RegAltBC.Word); - ser.Sync("ShadowDE", ref RegAltDE.Word); - ser.Sync("ShadowHL", ref RegAltHL.Word); - ser.Sync("I", ref RegI); - ser.Sync("R", ref RegR); - ser.Sync("IX", ref RegIX.Word); - ser.Sync("IY", ref RegIY.Word); - ser.Sync("SP", ref RegSP.Word); - ser.Sync("PC", ref RegPC.Word); - ser.Sync("IRQ", ref interrupt); - ser.Sync("NMI", ref nonMaskableInterrupt); - ser.Sync("NMIPending", ref nonMaskableInterruptPending); - ser.Sync("IM", ref interruptMode); - ser.Sync("IFF1", ref iff1); - ser.Sync("IFF2", ref iff2); - ser.Sync("Halted", ref halted); - ser.Sync("ExecutedCycles", ref totalExecutedCycles); - ser.Sync("PendingCycles", ref pendingCycles); - ser.Sync("EI_pending", ref EI_pending); - ser.EndSection(); - } - } -} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs new file mode 100644 index 0000000000..c70e4aa503 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -0,0 +1,1468 @@ +using System; + +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + private int totalExecutedCycles; + public int TotalExecutedCycles { get { return totalExecutedCycles; } set { totalExecutedCycles = value; } } + + private int EI_pending; + + public const ushort CBpre = 0; + public const ushort EXTDpre = 1; + public const ushort IXpre = 2; + public const ushort IYpre = 3; + public const ushort IXCBpre = 4; + public const ushort IYCBpre = 5; + public const ushort IXYprefetch = 6; + + // variables for executing instructions + public int instr_pntr = 0; + public ushort[] cur_instr; + public int opcode; + public bool NO_prefix, CB_prefix, IX_prefix, EXTD_prefix, IY_prefix, IXCB_prefix, IYCB_prefix; + public bool IXCB_prefetch, IYCB_prefetch; // value is fetched before opcode + public bool halted; + public ushort PF; + + public void FetchInstruction(byte opcode) + { + if (NO_prefix) + { + switch (opcode) + { + case 0x00: NOP_(); break; // NOP + case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn + case 0x02: LD_8_IND(C, B, A); break; // LD (BC), A + case 0x03: INC_16(C, B); break; // INC BC + case 0x04: INT_OP(INC8, B); break; // INC B + case 0x05: INT_OP(DEC8, B); break; // DEC B + case 0x06: LD_IND_8_INC(B, PCl, PCh); break; // LD B, n + case 0x07: INT_OP(RLC, Aim); break; // RLCA + case 0x08: EXCH_(); break; // EXCH AF, AF' + case 0x09: ADD_16(L, H, C, B); break; // ADD HL, BC + case 0x0A: REG_OP_IND(TR, A, C, B); break; // LD A, (BC) + case 0x0B: DEC_16(C, B); break; // DEC BC + case 0x0C: INT_OP(INC8, C); break; // INC C + case 0x0D: INT_OP(DEC8, C); break; // DEC C + case 0x0E: LD_IND_8_INC(C, PCl, PCh); break; // LD C, n + case 0x0F: INT_OP(RRC, Aim); break; // RRCA + case 0x10: DJNZ_(); break; // DJNZ B + case 0x11: LD_IND_16(E, D, PCl, PCh); break; // LD DE, nn + case 0x12: LD_8_IND(E, D, A); break; // LD (DE), A + case 0x13: INC_16(E, D); break; // INC DE + case 0x14: INT_OP(INC8, D); break; // INC D + case 0x15: INT_OP(DEC8, D); break; // DEC D + case 0x16: LD_IND_8_INC(D, PCl, PCh); break; // LD D, n + case 0x17: INT_OP(RL, Aim); break; // RLA + case 0x18: JR_COND(true); break; // JR, r8 + case 0x19: ADD_16(L, H, E, D); break; // ADD HL, DE + case 0x1A: REG_OP_IND(TR, A, E, D); break; // LD A, (DE) + case 0x1B: DEC_16(E, D); break; // DEC DE + case 0x1C: INT_OP(INC8, E); break; // INC E + case 0x1D: INT_OP(DEC8, E); break; // DEC E + case 0x1E: LD_IND_8_INC(E, PCl, PCh); break; // LD E, n + case 0x1F: INT_OP(RR, Aim); break; // RRA + case 0x20: JR_COND(!FlagZ); break; // JR NZ, r8 + case 0x21: LD_IND_16(L, H, PCl, PCh); break; // LD HL, nn + case 0x22: LD_16_IND_nn(L, H); break; // LD (nn), HL + case 0x23: INC_16(L, H); break; // INC HL + case 0x24: INT_OP(INC8, H); break; // INC H + case 0x25: INT_OP(DEC8, H); break; // DEC H + case 0x26: LD_IND_8_INC(H, PCl, PCh); break; // LD H, n + case 0x27: INT_OP(DA, A); break; // DAA + case 0x28: JR_COND(FlagZ); break; // JR Z, r8 + case 0x29: ADD_16(L, H, L, H); break; // ADD HL, HL + case 0x2A: LD_IND_16_nn(L, H); break; // LD HL, (nn) + case 0x2B: DEC_16(L, H); break; // DEC HL + case 0x2C: INT_OP(INC8, L); break; // INC L + case 0x2D: INT_OP(DEC8, L); break; // DEC L + case 0x2E: LD_IND_8_INC(L, PCl, PCh); break; // LD L, n + case 0x2F: INT_OP(CPL, A); break; // CPL + case 0x30: JR_COND(!FlagC); break; // JR NC, r8 + case 0x31: LD_IND_16(SPl, SPh, PCl, PCh); break; // LD SP, nn + case 0x32: LD_8_IND_nn(A); break; // LD (nn), A + case 0x33: INC_16(SPl, SPh); break; // INC SP + case 0x34: INC_8_IND(L, H); break; // INC (HL) + case 0x35: DEC_8_IND(L, H); break; // DEC (HL) + case 0x36: LD_8_IND_IND(L, H, PCl, PCh); break; // LD (HL), n + case 0x37: INT_OP(SCF, A); break; // SCF + case 0x38: JR_COND(FlagC); break; // JR C, r8 + case 0x39: ADD_16(L, H, SPl, SPh); break; // ADD HL, SP + case 0x3A: LD_IND_8_nn(A); break; // LD A, (nn) + case 0x3B: DEC_16(SPl, SPh); break; // DEC SP + case 0x3C: INT_OP(INC8, A); break; // INC A + case 0x3D: INT_OP(DEC8, A); break; // DEC A + case 0x3E: LD_IND_8_INC(A, PCl, PCh); break; // LD A, n + case 0x3F: INT_OP(CCF, A); break; // CCF + case 0x40: REG_OP(TR, B, B); break; // LD B, B + case 0x41: REG_OP(TR, B, C); break; // LD B, C + case 0x42: REG_OP(TR, B, D); break; // LD B, D + case 0x43: REG_OP(TR, B, E); break; // LD B, E + case 0x44: REG_OP(TR, B, H); break; // LD B, H + case 0x45: REG_OP(TR, B, L); break; // LD B, L + case 0x46: REG_OP_IND(TR, B, L, H); break; // LD B, (HL) + case 0x47: REG_OP(TR, B, A); break; // LD B, A + case 0x48: REG_OP(TR, C, B); break; // LD C, B + case 0x49: REG_OP(TR, C, C); break; // LD C, C + case 0x4A: REG_OP(TR, C, D); break; // LD C, D + case 0x4B: REG_OP(TR, C, E); break; // LD C, E + case 0x4C: REG_OP(TR, C, H); break; // LD C, H + case 0x4D: REG_OP(TR, C, L); break; // LD C, L + case 0x4E: REG_OP_IND(TR, C, L, H); break; // LD C, (HL) + case 0x4F: REG_OP(TR, C, A); break; // LD C, A + case 0x50: REG_OP(TR, D, B); break; // LD D, B + case 0x51: REG_OP(TR, D, C); break; // LD D, C + case 0x52: REG_OP(TR, D, D); break; // LD D, D + case 0x53: REG_OP(TR, D, E); break; // LD D, E + case 0x54: REG_OP(TR, D, H); break; // LD D, H + case 0x55: REG_OP(TR, D, L); break; // LD D, L + case 0x56: REG_OP_IND(TR, D, L, H); break; // LD D, (HL) + case 0x57: REG_OP(TR, D, A); break; // LD D, A + case 0x58: REG_OP(TR, E, B); break; // LD E, B + case 0x59: REG_OP(TR, E, C); break; // LD E, C + case 0x5A: REG_OP(TR, E, D); break; // LD E, D + case 0x5B: REG_OP(TR, E, E); break; // LD E, E + case 0x5C: REG_OP(TR, E, H); break; // LD E, H + case 0x5D: REG_OP(TR, E, L); break; // LD E, L + case 0x5E: REG_OP_IND(TR, E, L, H); break; // LD E, (HL) + case 0x5F: REG_OP(TR, E, A); break; // LD E, A + case 0x60: REG_OP(TR, H, B); break; // LD H, B + case 0x61: REG_OP(TR, H, C); break; // LD H, C + case 0x62: REG_OP(TR, H, D); break; // LD H, D + case 0x63: REG_OP(TR, H, E); break; // LD H, E + case 0x64: REG_OP(TR, H, H); break; // LD H, H + case 0x65: REG_OP(TR, H, L); break; // LD H, L + case 0x66: REG_OP_IND(TR, H, L, H); break; // LD H, (HL) + case 0x67: REG_OP(TR, H, A); break; // LD H, A + case 0x68: REG_OP(TR, L, B); break; // LD L, B + case 0x69: REG_OP(TR, L, C); break; // LD L, C + case 0x6A: REG_OP(TR, L, D); break; // LD L, D + case 0x6B: REG_OP(TR, L, E); break; // LD L, E + case 0x6C: REG_OP(TR, L, H); break; // LD L, H + case 0x6D: REG_OP(TR, L, L); break; // LD L, L + case 0x6E: REG_OP_IND(TR, L, L, H); break; // LD L, (HL) + case 0x6F: REG_OP(TR, L, A); break; // LD L, A + case 0x70: LD_8_IND(L, H, B); break; // LD (HL), B + case 0x71: LD_8_IND(L, H, C); break; // LD (HL), C + case 0x72: LD_8_IND(L, H, D); break; // LD (HL), D + case 0x73: LD_8_IND(L, H, E); break; // LD (HL), E + case 0x74: LD_8_IND(L, H, H); break; // LD (HL), H + case 0x75: LD_8_IND(L, H, L); break; // LD (HL), L + case 0x76: HALT_(); break; // HALT + case 0x77: LD_8_IND(L, H, A); break; // LD (HL), A + case 0x78: REG_OP(TR, A, B); break; // LD A, B + case 0x79: REG_OP(TR, A, C); break; // LD A, C + case 0x7A: REG_OP(TR, A, D); break; // LD A, D + case 0x7B: REG_OP(TR, A, E); break; // LD A, E + case 0x7C: REG_OP(TR, A, H); break; // LD A, H + case 0x7D: REG_OP(TR, A, L); break; // LD A, L + case 0x7E: REG_OP_IND(TR, A, L, H); break; // LD A, (HL) + case 0x7F: REG_OP(TR, A, A); break; // LD A, A + case 0x80: REG_OP(ADD8, A, B); break; // ADD A, B + case 0x81: REG_OP(ADD8, A, C); break; // ADD A, C + case 0x82: REG_OP(ADD8, A, D); break; // ADD A, D + case 0x83: REG_OP(ADD8, A, E); break; // ADD A, E + case 0x84: REG_OP(ADD8, A, H); break; // ADD A, H + case 0x85: REG_OP(ADD8, A, L); break; // ADD A, L + case 0x86: REG_OP_IND(ADD8, A, L, H); break; // ADD A, (HL) + case 0x87: REG_OP(ADD8, A, A); break; // ADD A, A + case 0x88: REG_OP(ADC8, A, B); break; // ADC A, B + case 0x89: REG_OP(ADC8, A, C); break; // ADC A, C + case 0x8A: REG_OP(ADC8, A, D); break; // ADC A, D + case 0x8B: REG_OP(ADC8, A, E); break; // ADC A, E + case 0x8C: REG_OP(ADC8, A, H); break; // ADC A, H + case 0x8D: REG_OP(ADC8, A, L); break; // ADC A, L + case 0x8E: REG_OP_IND(ADC8, A, L, H); break; // ADC A, (HL) + case 0x8F: REG_OP(ADC8, A, A); break; // ADC A, A + case 0x90: REG_OP(SUB8, A, B); break; // SUB A, B + case 0x91: REG_OP(SUB8, A, C); break; // SUB A, C + case 0x92: REG_OP(SUB8, A, D); break; // SUB A, D + case 0x93: REG_OP(SUB8, A, E); break; // SUB A, E + case 0x94: REG_OP(SUB8, A, H); break; // SUB A, H + case 0x95: REG_OP(SUB8, A, L); break; // SUB A, L + case 0x96: REG_OP_IND(SUB8, A, L, H); break; // SUB A, (HL) + case 0x97: REG_OP(SUB8, A, A); break; // SUB A, A + case 0x98: REG_OP(SBC8, A, B); break; // SBC A, B + case 0x99: REG_OP(SBC8, A, C); break; // SBC A, C + case 0x9A: REG_OP(SBC8, A, D); break; // SBC A, D + case 0x9B: REG_OP(SBC8, A, E); break; // SBC A, E + case 0x9C: REG_OP(SBC8, A, H); break; // SBC A, H + case 0x9D: REG_OP(SBC8, A, L); break; // SBC A, L + case 0x9E: REG_OP_IND(SBC8, A, L, H); break; // SBC A, (HL) + case 0x9F: REG_OP(SBC8, A, A); break; // SBC A, A + case 0xA0: REG_OP(AND8, A, B); break; // AND A, B + case 0xA1: REG_OP(AND8, A, C); break; // AND A, C + case 0xA2: REG_OP(AND8, A, D); break; // AND A, D + case 0xA3: REG_OP(AND8, A, E); break; // AND A, E + case 0xA4: REG_OP(AND8, A, H); break; // AND A, H + case 0xA5: REG_OP(AND8, A, L); break; // AND A, L + case 0xA6: REG_OP_IND(AND8, A, L, H); break; // AND A, (HL) + case 0xA7: REG_OP(AND8, A, A); break; // AND A, A + case 0xA8: REG_OP(XOR8, A, B); break; // XOR A, B + case 0xA9: REG_OP(XOR8, A, C); break; // XOR A, C + case 0xAA: REG_OP(XOR8, A, D); break; // XOR A, D + case 0xAB: REG_OP(XOR8, A, E); break; // XOR A, E + case 0xAC: REG_OP(XOR8, A, H); break; // XOR A, H + case 0xAD: REG_OP(XOR8, A, L); break; // XOR A, L + case 0xAE: REG_OP_IND(XOR8, A, L, H); break; // XOR A, (HL) + case 0xAF: REG_OP(XOR8, A, A); break; // XOR A, A + case 0xB0: REG_OP(OR8, A, B); break; // OR A, B + case 0xB1: REG_OP(OR8, A, C); break; // OR A, C + case 0xB2: REG_OP(OR8, A, D); break; // OR A, D + case 0xB3: REG_OP(OR8, A, E); break; // OR A, E + case 0xB4: REG_OP(OR8, A, H); break; // OR A, H + case 0xB5: REG_OP(OR8, A, L); break; // OR A, L + case 0xB6: REG_OP_IND(OR8, A, L, H); break; // OR A, (HL) + case 0xB7: REG_OP(OR8, A, A); break; // OR A, A + case 0xB8: REG_OP(CP8, A, B); break; // CP A, B + case 0xB9: REG_OP(CP8, A, C); break; // CP A, C + case 0xBA: REG_OP(CP8, A, D); break; // CP A, D + case 0xBB: REG_OP(CP8, A, E); break; // CP A, E + case 0xBC: REG_OP(CP8, A, H); break; // CP A, H + case 0xBD: REG_OP(CP8, A, L); break; // CP A, L + case 0xBE: REG_OP_IND(CP8, A, L, H); break; // CP A, (HL) + case 0xBF: REG_OP(CP8, A, A); break; // CP A, A + case 0xC0: RET_COND(!FlagZ); break; // Ret NZ + case 0xC1: POP_(C, B); break; // POP BC + case 0xC2: JP_COND(!FlagZ); break; // JP NZ + case 0xC3: JP_COND(true); break; // JP + case 0xC4: CALL_COND(!FlagZ); break; // CALL NZ + case 0xC5: PUSH_(C, B); break; // PUSH BC + case 0xC6: REG_OP_IND_INC(ADD8, A, PCl, PCh); break; // ADD A, n + case 0xC7: RST_(0); break; // RST 0 + case 0xC8: RET_COND(FlagZ); break; // RET Z + case 0xC9: RET_(); break; // RET + case 0xCA: JP_COND(FlagZ); break; // JP Z + case 0xCB: PREFIX_(CBpre); break; // PREFIX CB + case 0xCC: CALL_COND(FlagZ); break; // CALL Z + case 0xCD: CALL_COND(true); break; // CALL + case 0xCE: REG_OP_IND_INC(ADC8, A, PCl, PCh); break; // ADC A, n + case 0xCF: RST_(0x08); break; // RST 0x08 + case 0xD0: RET_COND(!FlagC); break; // Ret NC + case 0xD1: POP_(E, D); break; // POP DE + case 0xD2: JP_COND(!FlagC); break; // JP NC + case 0xD3: OUT_(); break; // OUT A + case 0xD4: CALL_COND(!FlagC); break; // CALL NC + case 0xD5: PUSH_(E, D); break; // PUSH DE + case 0xD6: REG_OP_IND_INC(SUB8, A, PCl, PCh); break; // SUB A, n + case 0xD7: RST_(0x10); break; // RST 0x10 + case 0xD8: RET_COND(FlagC); break; // RET C + case 0xD9: EXX_(); break; // EXX + case 0xDA: JP_COND(FlagC); break; // JP C + case 0xDB: IN_(); break; // IN A + case 0xDC: CALL_COND(FlagC); break; // CALL C + case 0xDD: PREFIX_(IXpre); break; // PREFIX IX + case 0xDE: REG_OP_IND_INC(SBC8, A, PCl, PCh); break; // SBC A, n + case 0xDF: RST_(0x18); break; // RST 0x18 + case 0xE0: RET_COND(!FlagP); break; // RET Po + case 0xE1: POP_(L, H); break; // POP HL + case 0xE2: JP_COND(!FlagP); break; // JP Po + case 0xE3: EXCH_16_IND_(SPl, SPh, L, H); break; // ex (SP), HL + case 0xE4: CALL_COND(!FlagP); break; // CALL Po + case 0xE5: PUSH_(L, H); break; // PUSH HL + case 0xE6: REG_OP_IND_INC(AND8, A, PCl, PCh); break; // AND A, n + case 0xE7: RST_(0x20); break; // RST 0x20 + case 0xE8: RET_COND(FlagP); break; // RET Pe + case 0xE9: JP_16(L, H); break; // JP (HL) + case 0xEA: JP_COND(FlagP); break; // JP Pe + case 0xEB: EXCH_16_(E,D, L, H); break; // ex DE, HL + case 0xEC: CALL_COND(FlagP); break; // CALL Pe + case 0xED: PREFIX_(EXTDpre); break; // PREFIX EXTD + case 0xEE: REG_OP_IND_INC(XOR8, A, PCl, PCh); break; // XOR A, n + case 0xEF: RST_(0x28); break; // RST 0x28 + case 0xF0: RET_COND(!FlagS); break; // RET p + case 0xF1: POP_(F, A); break; // POP AF + case 0xF2: JP_COND(!FlagS); break; // JP p + case 0xF3: DI_(); break; // DI + case 0xF4: CALL_COND(!FlagS); break; // CALL p + case 0xF5: PUSH_(F, A); break; // PUSH AF + case 0xF6: REG_OP_IND_INC(OR8, A, PCl, PCh); break; // OR A, n + case 0xF7: RST_(0x30); break; // RST 0x30 + case 0xF8: RET_COND(FlagS); break; // RET M + case 0xF9: LD_SP_16(L, H); break; // LD SP, HL + case 0xFA: JP_COND(FlagS); break; // JP M + case 0xFB: EI_(); break; // EI + case 0xFC: CALL_COND(FlagS); break; // CALL M + case 0xFD: PREFIX_(IYpre); break; // PREFIX IY + case 0xFE: REG_OP_IND_INC(CP8, A, PCl, PCh); break; // CP A, n + case 0xFF: RST_(0x38); break; // RST 0x38 + } + } + else if (CB_prefix) + { + CB_prefix = false; + NO_prefix = true; + switch (opcode) + { + case 0x00: INT_OP(RLC, B); break; // RLC B + case 0x01: INT_OP(RLC, C); break; // RLC C + case 0x02: INT_OP(RLC, D); break; // RLC D + case 0x03: INT_OP(RLC, E); break; // RLC E + case 0x04: INT_OP(RLC, H); break; // RLC H + case 0x05: INT_OP(RLC, L); break; // RLC L + case 0x06: INT_OP_IND(RLC, L, H); break; // RLC (HL) + case 0x07: INT_OP(RLC, A); break; // RLC A + case 0x08: INT_OP(RRC, B); break; // RRC B + case 0x09: INT_OP(RRC, C); break; // RRC C + case 0x0A: INT_OP(RRC, D); break; // RRC D + case 0x0B: INT_OP(RRC, E); break; // RRC E + case 0x0C: INT_OP(RRC, H); break; // RRC H + case 0x0D: INT_OP(RRC, L); break; // RRC L + case 0x0E: INT_OP_IND(RRC, L, H); break; // RRC (HL) + case 0x0F: INT_OP(RRC, A); break; // RRC A + case 0x10: INT_OP(RL, B); break; // RL B + case 0x11: INT_OP(RL, C); break; // RL C + case 0x12: INT_OP(RL, D); break; // RL D + case 0x13: INT_OP(RL, E); break; // RL E + case 0x14: INT_OP(RL, H); break; // RL H + case 0x15: INT_OP(RL, L); break; // RL L + case 0x16: INT_OP_IND(RL, L, H); break; // RL (HL) + case 0x17: INT_OP(RL, A); break; // RL A + case 0x18: INT_OP(RR, B); break; // RR B + case 0x19: INT_OP(RR, C); break; // RR C + case 0x1A: INT_OP(RR, D); break; // RR D + case 0x1B: INT_OP(RR, E); break; // RR E + case 0x1C: INT_OP(RR, H); break; // RR H + case 0x1D: INT_OP(RR, L); break; // RR L + case 0x1E: INT_OP_IND(RR, L, H); break; // RR (HL) + case 0x1F: INT_OP(RR, A); break; // RR A + case 0x20: INT_OP(SLA, B); break; // SLA B + case 0x21: INT_OP(SLA, C); break; // SLA C + case 0x22: INT_OP(SLA, D); break; // SLA D + case 0x23: INT_OP(SLA, E); break; // SLA E + case 0x24: INT_OP(SLA, H); break; // SLA H + case 0x25: INT_OP(SLA, L); break; // SLA L + case 0x26: INT_OP_IND(SLA, L, H); break; // SLA (HL) + case 0x27: INT_OP(SLA, A); break; // SLA A + case 0x28: INT_OP(SRA, B); break; // SRA B + case 0x29: INT_OP(SRA, C); break; // SRA C + case 0x2A: INT_OP(SRA, D); break; // SRA D + case 0x2B: INT_OP(SRA, E); break; // SRA E + case 0x2C: INT_OP(SRA, H); break; // SRA H + case 0x2D: INT_OP(SRA, L); break; // SRA L + case 0x2E: INT_OP_IND(SRA, L, H); break; // SRA (HL) + case 0x2F: INT_OP(SRA, A); break; // SRA A + case 0x30: INT_OP(SLL, B); break; // SLL B + case 0x31: INT_OP(SLL, C); break; // SLL C + case 0x32: INT_OP(SLL, D); break; // SLL D + case 0x33: INT_OP(SLL, E); break; // SLL E + case 0x34: INT_OP(SLL, H); break; // SLL H + case 0x35: INT_OP(SLL, L); break; // SLL L + case 0x36: INT_OP_IND(SLL, L, H); break; // SLL (HL) + case 0x37: INT_OP(SLL, A); break; // SLL A + case 0x38: INT_OP(SRL, B); break; // SRL B + case 0x39: INT_OP(SRL, C); break; // SRL C + case 0x3A: INT_OP(SRL, D); break; // SRL D + case 0x3B: INT_OP(SRL, E); break; // SRL E + case 0x3C: INT_OP(SRL, H); break; // SRL H + case 0x3D: INT_OP(SRL, L); break; // SRL L + case 0x3E: INT_OP_IND(SRL, L, H); break; // SRL (HL) + case 0x3F: INT_OP(SRL, A); break; // SRL A + case 0x40: BIT_OP(BIT, 0, B); break; // BIT 0, B + case 0x41: BIT_OP(BIT, 0, C); break; // BIT 0, C + case 0x42: BIT_OP(BIT, 0, D); break; // BIT 0, D + case 0x43: BIT_OP(BIT, 0, E); break; // BIT 0, E + case 0x44: BIT_OP(BIT, 0, H); break; // BIT 0, H + case 0x45: BIT_OP(BIT, 0, L); break; // BIT 0, L + case 0x46: BIT_TE_IND(BIT, 0, L, H); break; // BIT 0, (HL) + case 0x47: BIT_OP(BIT, 0, A); break; // BIT 0, A + case 0x48: BIT_OP(BIT, 1, B); break; // BIT 1, B + case 0x49: BIT_OP(BIT, 1, C); break; // BIT 1, C + case 0x4A: BIT_OP(BIT, 1, D); break; // BIT 1, D + case 0x4B: BIT_OP(BIT, 1, E); break; // BIT 1, E + case 0x4C: BIT_OP(BIT, 1, H); break; // BIT 1, H + case 0x4D: BIT_OP(BIT, 1, L); break; // BIT 1, L + case 0x4E: BIT_TE_IND(BIT, 1, L, H); break; // BIT 1, (HL) + case 0x4F: BIT_OP(BIT, 1, A); break; // BIT 1, A + case 0x50: BIT_OP(BIT, 2, B); break; // BIT 2, B + case 0x51: BIT_OP(BIT, 2, C); break; // BIT 2, C + case 0x52: BIT_OP(BIT, 2, D); break; // BIT 2, D + case 0x53: BIT_OP(BIT, 2, E); break; // BIT 2, E + case 0x54: BIT_OP(BIT, 2, H); break; // BIT 2, H + case 0x55: BIT_OP(BIT, 2, L); break; // BIT 2, L + case 0x56: BIT_TE_IND(BIT, 2, L, H); break; // BIT 2, (HL) + case 0x57: BIT_OP(BIT, 2, A); break; // BIT 2, A + case 0x58: BIT_OP(BIT, 3, B); break; // BIT 3, B + case 0x59: BIT_OP(BIT, 3, C); break; // BIT 3, C + case 0x5A: BIT_OP(BIT, 3, D); break; // BIT 3, D + case 0x5B: BIT_OP(BIT, 3, E); break; // BIT 3, E + case 0x5C: BIT_OP(BIT, 3, H); break; // BIT 3, H + case 0x5D: BIT_OP(BIT, 3, L); break; // BIT 3, L + case 0x5E: BIT_TE_IND(BIT, 3, L, H); break; // BIT 3, (HL) + case 0x5F: BIT_OP(BIT, 3, A); break; // BIT 3, A + case 0x60: BIT_OP(BIT, 4, B); break; // BIT 4, B + case 0x61: BIT_OP(BIT, 4, C); break; // BIT 4, C + case 0x62: BIT_OP(BIT, 4, D); break; // BIT 4, D + case 0x63: BIT_OP(BIT, 4, E); break; // BIT 4, E + case 0x64: BIT_OP(BIT, 4, H); break; // BIT 4, H + case 0x65: BIT_OP(BIT, 4, L); break; // BIT 4, L + case 0x66: BIT_TE_IND(BIT, 4, L, H); break; // BIT 4, (HL) + case 0x67: BIT_OP(BIT, 4, A); break; // BIT 4, A + case 0x68: BIT_OP(BIT, 5, B); break; // BIT 5, B + case 0x69: BIT_OP(BIT, 5, C); break; // BIT 5, C + case 0x6A: BIT_OP(BIT, 5, D); break; // BIT 5, D + case 0x6B: BIT_OP(BIT, 5, E); break; // BIT 5, E + case 0x6C: BIT_OP(BIT, 5, H); break; // BIT 5, H + case 0x6D: BIT_OP(BIT, 5, L); break; // BIT 5, L + case 0x6E: BIT_TE_IND(BIT, 5, L, H); break; // BIT 5, (HL) + case 0x6F: BIT_OP(BIT, 5, A); break; // BIT 5, A + case 0x70: BIT_OP(BIT, 6, B); break; // BIT 6, B + case 0x71: BIT_OP(BIT, 6, C); break; // BIT 6, C + case 0x72: BIT_OP(BIT, 6, D); break; // BIT 6, D + case 0x73: BIT_OP(BIT, 6, E); break; // BIT 6, E + case 0x74: BIT_OP(BIT, 6, H); break; // BIT 6, H + case 0x75: BIT_OP(BIT, 6, L); break; // BIT 6, L + case 0x76: BIT_TE_IND(BIT, 6, L, H); break; // BIT 6, (HL) + case 0x77: BIT_OP(BIT, 6, A); break; // BIT 6, A + case 0x78: BIT_OP(BIT, 7, B); break; // BIT 7, B + case 0x79: BIT_OP(BIT, 7, C); break; // BIT 7, C + case 0x7A: BIT_OP(BIT, 7, D); break; // BIT 7, D + case 0x7B: BIT_OP(BIT, 7, E); break; // BIT 7, E + case 0x7C: BIT_OP(BIT, 7, H); break; // BIT 7, H + case 0x7D: BIT_OP(BIT, 7, L); break; // BIT 7, L + case 0x7E: BIT_TE_IND(BIT, 7, L, H); break; // BIT 7, (HL) + case 0x7F: BIT_OP(BIT, 7, A); break; // BIT 7, A + case 0x80: BIT_OP(RES, 0, B); break; // RES 0, B + case 0x81: BIT_OP(RES, 0, C); break; // RES 0, C + case 0x82: BIT_OP(RES, 0, D); break; // RES 0, D + case 0x83: BIT_OP(RES, 0, E); break; // RES 0, E + case 0x84: BIT_OP(RES, 0, H); break; // RES 0, H + case 0x85: BIT_OP(RES, 0, L); break; // RES 0, L + case 0x86: BIT_OP_IND(RES, 0, L, H); break; // RES 0, (HL) + case 0x87: BIT_OP(RES, 0, A); break; // RES 0, A + case 0x88: BIT_OP(RES, 1, B); break; // RES 1, B + case 0x89: BIT_OP(RES, 1, C); break; // RES 1, C + case 0x8A: BIT_OP(RES, 1, D); break; // RES 1, D + case 0x8B: BIT_OP(RES, 1, E); break; // RES 1, E + case 0x8C: BIT_OP(RES, 1, H); break; // RES 1, H + case 0x8D: BIT_OP(RES, 1, L); break; // RES 1, L + case 0x8E: BIT_OP_IND(RES, 1, L, H); break; // RES 1, (HL) + case 0x8F: BIT_OP(RES, 1, A); break; // RES 1, A + case 0x90: BIT_OP(RES, 2, B); break; // RES 2, B + case 0x91: BIT_OP(RES, 2, C); break; // RES 2, C + case 0x92: BIT_OP(RES, 2, D); break; // RES 2, D + case 0x93: BIT_OP(RES, 2, E); break; // RES 2, E + case 0x94: BIT_OP(RES, 2, H); break; // RES 2, H + case 0x95: BIT_OP(RES, 2, L); break; // RES 2, L + case 0x96: BIT_OP_IND(RES, 2, L, H); break; // RES 2, (HL) + case 0x97: BIT_OP(RES, 2, A); break; // RES 2, A + case 0x98: BIT_OP(RES, 3, B); break; // RES 3, B + case 0x99: BIT_OP(RES, 3, C); break; // RES 3, C + case 0x9A: BIT_OP(RES, 3, D); break; // RES 3, D + case 0x9B: BIT_OP(RES, 3, E); break; // RES 3, E + case 0x9C: BIT_OP(RES, 3, H); break; // RES 3, H + case 0x9D: BIT_OP(RES, 3, L); break; // RES 3, L + case 0x9E: BIT_OP_IND(RES, 3, L, H); break; // RES 3, (HL) + case 0x9F: BIT_OP(RES, 3, A); break; // RES 3, A + case 0xA0: BIT_OP(RES, 4, B); break; // RES 4, B + case 0xA1: BIT_OP(RES, 4, C); break; // RES 4, C + case 0xA2: BIT_OP(RES, 4, D); break; // RES 4, D + case 0xA3: BIT_OP(RES, 4, E); break; // RES 4, E + case 0xA4: BIT_OP(RES, 4, H); break; // RES 4, H + case 0xA5: BIT_OP(RES, 4, L); break; // RES 4, L + case 0xA6: BIT_OP_IND(RES, 4, L, H); break; // RES 4, (HL) + case 0xA7: BIT_OP(RES, 4, A); break; // RES 4, A + case 0xA8: BIT_OP(RES, 5, B); break; // RES 5, B + case 0xA9: BIT_OP(RES, 5, C); break; // RES 5, C + case 0xAA: BIT_OP(RES, 5, D); break; // RES 5, D + case 0xAB: BIT_OP(RES, 5, E); break; // RES 5, E + case 0xAC: BIT_OP(RES, 5, H); break; // RES 5, H + case 0xAD: BIT_OP(RES, 5, L); break; // RES 5, L + case 0xAE: BIT_OP_IND(RES, 5, L, H); break; // RES 5, (HL) + case 0xAF: BIT_OP(RES, 5, A); break; // RES 5, A + case 0xB0: BIT_OP(RES, 6, B); break; // RES 6, B + case 0xB1: BIT_OP(RES, 6, C); break; // RES 6, C + case 0xB2: BIT_OP(RES, 6, D); break; // RES 6, D + case 0xB3: BIT_OP(RES, 6, E); break; // RES 6, E + case 0xB4: BIT_OP(RES, 6, H); break; // RES 6, H + case 0xB5: BIT_OP(RES, 6, L); break; // RES 6, L + case 0xB6: BIT_OP_IND(RES, 6, L, H); break; // RES 6, (HL) + case 0xB7: BIT_OP(RES, 6, A); break; // RES 6, A + case 0xB8: BIT_OP(RES, 7, B); break; // RES 7, B + case 0xB9: BIT_OP(RES, 7, C); break; // RES 7, C + case 0xBA: BIT_OP(RES, 7, D); break; // RES 7, D + case 0xBB: BIT_OP(RES, 7, E); break; // RES 7, E + case 0xBC: BIT_OP(RES, 7, H); break; // RES 7, H + case 0xBD: BIT_OP(RES, 7, L); break; // RES 7, L + case 0xBE: BIT_OP_IND(RES, 7, L, H); break; // RES 7, (HL) + case 0xBF: BIT_OP(RES, 7, A); break; // RES 7, A + case 0xC0: BIT_OP(SET, 0, B); break; // SET 0, B + case 0xC1: BIT_OP(SET, 0, C); break; // SET 0, C + case 0xC2: BIT_OP(SET, 0, D); break; // SET 0, D + case 0xC3: BIT_OP(SET, 0, E); break; // SET 0, E + case 0xC4: BIT_OP(SET, 0, H); break; // SET 0, H + case 0xC5: BIT_OP(SET, 0, L); break; // SET 0, L + case 0xC6: BIT_OP_IND(SET, 0, L, H); break; // SET 0, (HL) + case 0xC7: BIT_OP(SET, 0, A); break; // SET 0, A + case 0xC8: BIT_OP(SET, 1, B); break; // SET 1, B + case 0xC9: BIT_OP(SET, 1, C); break; // SET 1, C + case 0xCA: BIT_OP(SET, 1, D); break; // SET 1, D + case 0xCB: BIT_OP(SET, 1, E); break; // SET 1, E + case 0xCC: BIT_OP(SET, 1, H); break; // SET 1, H + case 0xCD: BIT_OP(SET, 1, L); break; // SET 1, L + case 0xCE: BIT_OP_IND(SET, 1, L, H); break; // SET 1, (HL) + case 0xCF: BIT_OP(SET, 1, A); break; // SET 1, A + case 0xD0: BIT_OP(SET, 2, B); break; // SET 2, B + case 0xD1: BIT_OP(SET, 2, C); break; // SET 2, C + case 0xD2: BIT_OP(SET, 2, D); break; // SET 2, D + case 0xD3: BIT_OP(SET, 2, E); break; // SET 2, E + case 0xD4: BIT_OP(SET, 2, H); break; // SET 2, H + case 0xD5: BIT_OP(SET, 2, L); break; // SET 2, L + case 0xD6: BIT_OP_IND(SET, 2, L, H); break; // SET 2, (HL) + case 0xD7: BIT_OP(SET, 2, A); break; // SET 2, A + case 0xD8: BIT_OP(SET, 3, B); break; // SET 3, B + case 0xD9: BIT_OP(SET, 3, C); break; // SET 3, C + case 0xDA: BIT_OP(SET, 3, D); break; // SET 3, D + case 0xDB: BIT_OP(SET, 3, E); break; // SET 3, E + case 0xDC: BIT_OP(SET, 3, H); break; // SET 3, H + case 0xDD: BIT_OP(SET, 3, L); break; // SET 3, L + case 0xDE: BIT_OP_IND(SET, 3, L, H); break; // SET 3, (HL) + case 0xDF: BIT_OP(SET, 3, A); break; // SET 3, A + case 0xE0: BIT_OP(SET, 4, B); break; // SET 4, B + case 0xE1: BIT_OP(SET, 4, C); break; // SET 4, C + case 0xE2: BIT_OP(SET, 4, D); break; // SET 4, D + case 0xE3: BIT_OP(SET, 4, E); break; // SET 4, E + case 0xE4: BIT_OP(SET, 4, H); break; // SET 4, H + case 0xE5: BIT_OP(SET, 4, L); break; // SET 4, L + case 0xE6: BIT_OP_IND(SET, 4, L, H); break; // SET 4, (HL) + case 0xE7: BIT_OP(SET, 4, A); break; // SET 4, A + case 0xE8: BIT_OP(SET, 5, B); break; // SET 5, B + case 0xE9: BIT_OP(SET, 5, C); break; // SET 5, C + case 0xEA: BIT_OP(SET, 5, D); break; // SET 5, D + case 0xEB: BIT_OP(SET, 5, E); break; // SET 5, E + case 0xEC: BIT_OP(SET, 5, H); break; // SET 5, H + case 0xED: BIT_OP(SET, 5, L); break; // SET 5, L + case 0xEE: BIT_OP_IND(SET, 5, L, H); break; // SET 5, (HL) + case 0xEF: BIT_OP(SET, 5, A); break; // SET 5, A + case 0xF0: BIT_OP(SET, 6, B); break; // SET 6, B + case 0xF1: BIT_OP(SET, 6, C); break; // SET 6, C + case 0xF2: BIT_OP(SET, 6, D); break; // SET 6, D + case 0xF3: BIT_OP(SET, 6, E); break; // SET 6, E + case 0xF4: BIT_OP(SET, 6, H); break; // SET 6, H + case 0xF5: BIT_OP(SET, 6, L); break; // SET 6, L + case 0xF6: BIT_OP_IND(SET, 6, L, H); break; // SET 6, (HL) + case 0xF7: BIT_OP(SET, 6, A); break; // SET 6, A + case 0xF8: BIT_OP(SET, 7, B); break; // SET 7, B + case 0xF9: BIT_OP(SET, 7, C); break; // SET 7, C + case 0xFA: BIT_OP(SET, 7, D); break; // SET 7, D + case 0xFB: BIT_OP(SET, 7, E); break; // SET 7, E + case 0xFC: BIT_OP(SET, 7, H); break; // SET 7, H + case 0xFD: BIT_OP(SET, 7, L); break; // SET 7, L + case 0xFE: BIT_OP_IND(SET, 7, L, H); break; // SET 7, (HL) + case 0xFF: BIT_OP(SET, 7, A); break; // SET 7, A + } + } + else if (EXTD_prefix) + { + // NOTE: Much of EXTD is empty + EXTD_prefix = false; + NO_prefix = true; + + switch (opcode) + { + case 0x40: IN_REG_(B, C); break; // IN B, (C) + case 0x41: OUT_REG_(C, B); break; // OUT (C), B + case 0x42: REG_OP_16_(SBC16, L, H, C, B); break; // SBC HL, BC + case 0x43: LD_16_IND_nn(C, B); break; // LD (nn), BC + case 0x44: INT_OP(NEG, A); break; // NEG + case 0x45: RETN_(); break; // RETN + case 0x46: INT_MODE_(0); break; // IM $0 + case 0x47: REG_OP_IR(TR, I, A); break; // LD I, A + case 0x48: IN_REG_(C, C); break; // IN C, (C) + case 0x49: OUT_REG_(C, C); break; // OUT (C), C + case 0x4A: REG_OP_16_(ADC16, L, H, C, B); break; // ADC HL, BC + case 0x4B: LD_IND_16_nn(C, B); break; // LD BC, (nn) + case 0x4C: INT_OP(NEG, A); break; // NEG + case 0x4D: RETI_(); break; // RETI + case 0x4E: INT_MODE_(0); break; // IM $0 + case 0x4F: REG_OP_IR(TR, R, A); break; // LD R, A + case 0x50: IN_REG_(D, C); break; // IN D, (C) + case 0x51: OUT_REG_(C, D); break; // OUT (C), D + case 0x52: REG_OP_16_(SBC16, L, H, E, D); break; // SBC HL, DE + case 0x53: LD_16_IND_nn(E, D); break; // LD (nn), DE + case 0x54: INT_OP(NEG, A); break; // NEG + case 0x55: RETN_(); break; // RETN + case 0x56: INT_MODE_(1); break; // IM $1 + case 0x57: REG_OP_IR(TR, A, I); break; // LD A, I + case 0x58: IN_REG_(E, C); break; // IN E, (C) + case 0x59: OUT_REG_(C, E); break; // OUT (C), E + case 0x5A: REG_OP_16_(ADC16, L, H, E, D); break; // ADC HL, DE + case 0x5B: LD_IND_16_nn(E, D); break; // LD DE, (nn) + case 0x5C: INT_OP(NEG, A); break; // NEG + case 0x5D: RETN_(); break; // RETI + case 0x5E: INT_MODE_(2); break; // IM $0 + case 0x5F: REG_OP_IR(TR, A, R); break; // LD A, R + case 0x60: IN_REG_(H, C); break; // IN H, (C) + case 0x61: OUT_REG_(C, H); break; // OUT (C), H + case 0x62: REG_OP_16_(SBC16, L, H, L, H); break; // SBC HL, HL + case 0x63: LD_16_IND_nn(L, H); break; // LD (nn), HL + case 0x64: INT_OP(NEG, A); break; // NEG + case 0x65: RETN_(); break; // RETN + case 0x66: INT_MODE_(0); break; // IM $0 + case 0x67: RRD_(); break; // RRD + case 0x68: IN_REG_(L, C); break; // IN L, (C) + case 0x69: OUT_REG_(C, L); break; // OUT (C), L + case 0x6A: REG_OP_16_(ADC16, L, H, L, H); break; // ADC HL, HL + case 0x6B: LD_IND_16_nn(L, H); break; // LD HL, (nn) + case 0x6C: INT_OP(NEG, A); break; // NEG + case 0x6D: RETN_(); break; // RETI + case 0x6E: INT_MODE_(0); break; // IM $0 + case 0x6F: RLD_(); break; // LD R, A + case 0x70: IN_REG_(ALU, C); break; // IN 0, (C) + case 0x71: OUT_REG_(C, ZERO); break; // OUT (C), 0 + case 0x72: REG_OP_16_(SBC16, L, H, SPl, SPh); break; // SBC HL, SP + case 0x73: LD_16_IND_nn(SPl, SPh); break; // LD (nn), SP + case 0x74: INT_OP(NEG, A); break; // NEG + case 0x75: RETN_(); break; // RETN + case 0x76: INT_MODE_(1); break; // IM $1 + case 0x77: NOP_(); break; // NOP + case 0x78: IN_REG_(A, C); break; // IN A, (C) + case 0x79: OUT_REG_(C, A); break; // OUT (C), A + case 0x7A: REG_OP_16_(ADC16, L, H, SPl, SPh); break; // ADC HL, SP + case 0x7B: LD_IND_16_nn(SPl, SPh); break; // LD SP, (nn) + case 0x7C: INT_OP(NEG, A); break; // NEG + case 0x7D: RETN_(); break; // RETI + case 0x7E: INT_MODE_(2); break; // IM $2 + case 0x7F: NOP_(); break; // NOP + case 0xA0: LD_OP_R(INC16, 0); break; // LDI + case 0xA1: CP_OP_R(INC16, 0); break; // CPI + case 0xA2: IN_OP_R(INC16, 0); break; // INI + case 0xA3: OUT_OP_R(INC16, 0); break; // OUTI + case 0xA8: LD_OP_R(DEC16, 0); break; // LDD + case 0xA9: CP_OP_R(DEC16, 0); break; // CPD + case 0xAA: IN_OP_R(DEC16, 0); break; // IND + case 0xAB: OUT_OP_R(DEC16, 0); break; // OUTD + case 0xB0: LD_OP_R(INC16, 1); break; // LDIR + case 0xB1: CP_OP_R(INC16, 1); break; // CPIR + case 0xB2: IN_OP_R(INC16, 1); break; // INIR + case 0xB3: OUT_OP_R(INC16, 1); break; // OTIR + case 0xB8: LD_OP_R(DEC16, 1); break; // LDDR + case 0xB9: CP_OP_R(DEC16, 1); break; // CPDR + case 0xBA: IN_OP_R(DEC16, 1); break; // INDR + case 0xBB: OUT_OP_R(DEC16, 1); break; // OTDR + default: NOP_(); break; // NOP + + } + } + else if (IX_prefix) + { + IX_prefix = false; + NO_prefix = true; + + switch (opcode) + { + case 0x00: NOP_(); break; // NOP + case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn + case 0x02: LD_8_IND(C, B, A); break; // LD (BC), A + case 0x03: INC_16(C, B); break; // INC BC + case 0x04: INT_OP(INC8, B); break; // INC B + case 0x05: INT_OP(DEC8, B); break; // DEC B + case 0x06: LD_IND_8_INC(B, PCl, PCh); break; // LD B, n + case 0x07: INT_OP(RLC, Aim); break; // RLCA + case 0x08: EXCH_(); break; // EXCH AF, AF' + case 0x09: ADD_16(Ixl, Ixh, C, B); break; // ADD Ix, BC + case 0x0A: REG_OP_IND(TR, A, C, B); break; // LD A, (BC) + case 0x0B: DEC_16(C, B); break; // DEC BC + case 0x0C: INT_OP(INC8, C); break; // INC C + case 0x0D: INT_OP(DEC8, C); break; // DEC C + case 0x0E: LD_IND_8_INC(C, PCl, PCh); break; // LD C, n + case 0x0F: INT_OP(RRC, Aim); break; // RRCA + case 0x10: DJNZ_(); break; // DJNZ B + case 0x11: LD_IND_16(E, D, PCl, PCh); break; // LD DE, nn + case 0x12: LD_8_IND(E, D, A); break; // LD (DE), A + case 0x13: INC_16(E, D); break; // INC DE + case 0x14: INT_OP(INC8, D); break; // INC D + case 0x15: INT_OP(DEC8, D); break; // DEC D + case 0x16: LD_IND_8_INC(D, PCl, PCh); break; // LD D, n + case 0x17: INT_OP(RL, Aim); break; // RLA + case 0x18: JR_COND(true); break; // JR, r8 + case 0x19: ADD_16(Ixl, Ixh, E, D); break; // ADD Ix, DE + case 0x1A: REG_OP_IND(TR, A, E, D); break; // LD A, (DE) + case 0x1B: DEC_16(E, D); break; // DEC DE + case 0x1C: INT_OP(INC8, E); break; // INC E + case 0x1D: INT_OP(DEC8, E); break; // DEC E + case 0x1E: LD_IND_8_INC(E, PCl, PCh); break; // LD E, n + case 0x1F: INT_OP(RR, Aim); break; // RRA + case 0x20: JR_COND(!FlagZ); break; // JR NZ, r8 + case 0x21: LD_IND_16(Ixl, Ixh, PCl, PCh); break; // LD Ix, nn + case 0x22: LD_16_IND_nn(Ixl, Ixh); break; // LD (nn), Ix + case 0x23: INC_16(Ixl, Ixh); break; // INC Ix + case 0x24: INT_OP(INC8, Ixh); break; // INC Ixh + case 0x25: INT_OP(DEC8, Ixh); break; // DEC Ixh + case 0x26: LD_IND_8_INC(Ixh, PCl, PCh); break; // LD Ixh, n + case 0x27: INT_OP(DA, A); break; // DAA + case 0x28: JR_COND(FlagZ); break; // JR Z, r8 + case 0x29: ADD_16(Ixl, Ixh, Ixl, Ixh); break; // ADD Ix, Ix + case 0x2A: LD_IND_16_nn(Ixl, Ixh); break; // LD Ix, (nn) + case 0x2B: DEC_16(Ixl, Ixh); break; // DEC Ix + case 0x2C: INT_OP(INC8, Ixl); break; // INC Ixl + case 0x2D: INT_OP(DEC8, Ixl); break; // DEC Ixl + case 0x2E: LD_IND_8_INC(Ixl, PCl, PCh); break; // LD Ixl, n + case 0x2F: INT_OP(CPL, A); break; // CPL + case 0x30: JR_COND(!FlagC); break; // JR NC, r8 + case 0x31: LD_IND_16(SPl, SPh, PCl, PCh); break; // LD SP, nn + case 0x32: LD_8_IND_nn(A); break; // LD (nn), A + case 0x33: INC_16(SPl, SPh); break; // INC SP + case 0x34: I_OP_n(INC8, Ixl, Ixh); break; // INC (Ix + n) + case 0x35: I_OP_n(DEC8, Ixl, Ixh); break; // DEC (Ix + n) + case 0x36: I_OP_n_n(Ixl, Ixh); break; // LD (Ix + n), n + case 0x37: INT_OP(SCF, A); break; // SCF + case 0x38: JR_COND(FlagC); break; // JR C, r8 + case 0x39: ADD_16(Ixl, Ixh, SPl, SPh); break; // ADD Ix, SP + case 0x3A: LD_IND_8_nn(A); break; // LD A, (nn) + case 0x3B: DEC_16(SPl, SPh); break; // DEC SP + case 0x3C: INT_OP(INC8, A); break; // INC A + case 0x3D: INT_OP(DEC8, A); break; // DEC A + case 0x3E: LD_IND_8_INC(A, PCl, PCh); break; // LD A, n + case 0x3F: INT_OP(CCF, A); break; // CCF + case 0x40: REG_OP(TR, B, B); break; // LD B, B + case 0x41: REG_OP(TR, B, C); break; // LD B, C + case 0x42: REG_OP(TR, B, D); break; // LD B, D + case 0x43: REG_OP(TR, B, E); break; // LD B, E + case 0x44: REG_OP(TR, B, Ixh); break; // LD B, Ixh + case 0x45: REG_OP(TR, B, Ixl); break; // LD B, Ixl + case 0x46: I_REG_OP_IND_n(TR, B, Ixl, Ixh); break; // LD B, (Ix + n) + case 0x47: REG_OP(TR, B, A); break; // LD B, A + case 0x48: REG_OP(TR, C, B); break; // LD C, B + case 0x49: REG_OP(TR, C, C); break; // LD C, C + case 0x4A: REG_OP(TR, C, D); break; // LD C, D + case 0x4B: REG_OP(TR, C, E); break; // LD C, E + case 0x4C: REG_OP(TR, C, Ixh); break; // LD C, Ixh + case 0x4D: REG_OP(TR, C, Ixl); break; // LD C, Ixl + case 0x4E: I_REG_OP_IND_n(TR, C, Ixl, Ixh); break; // LD C, (Ix + n) + case 0x4F: REG_OP(TR, C, A); break; // LD C, A + case 0x50: REG_OP(TR, D, B); break; // LD D, B + case 0x51: REG_OP(TR, D, C); break; // LD D, C + case 0x52: REG_OP(TR, D, D); break; // LD D, D + case 0x53: REG_OP(TR, D, E); break; // LD D, E + case 0x54: REG_OP(TR, D, Ixh); break; // LD D, Ixh + case 0x55: REG_OP(TR, D, Ixl); break; // LD D, Ixl + case 0x56: I_REG_OP_IND_n(TR, D, Ixl, Ixh); break; // LD D, (Ix + n) + case 0x57: REG_OP(TR, D, A); break; // LD D, A + case 0x58: REG_OP(TR, E, B); break; // LD E, B + case 0x59: REG_OP(TR, E, C); break; // LD E, C + case 0x5A: REG_OP(TR, E, D); break; // LD E, D + case 0x5B: REG_OP(TR, E, E); break; // LD E, E + case 0x5C: REG_OP(TR, E, Ixh); break; // LD E, Ixh + case 0x5D: REG_OP(TR, E, Ixl); break; // LD E, Ixl + case 0x5E: I_REG_OP_IND_n(TR, E, Ixl, Ixh); break; // LD E, (Ix + n) + case 0x5F: REG_OP(TR, E, A); break; // LD E, A + case 0x60: REG_OP(TR, Ixh, B); break; // LD Ixh, B + case 0x61: REG_OP(TR, Ixh, C); break; // LD Ixh, C + case 0x62: REG_OP(TR, Ixh, D); break; // LD Ixh, D + case 0x63: REG_OP(TR, Ixh, E); break; // LD Ixh, E + case 0x64: REG_OP(TR, Ixh, Ixh); break; // LD Ixh, Ixh + case 0x65: REG_OP(TR, Ixh, Ixl); break; // LD Ixh, Ixl + case 0x66: I_REG_OP_IND_n(TR, H, Ixl, Ixh); break; // LD H, (Ix + n) + case 0x67: REG_OP(TR, Ixh, A); break; // LD Ixh, A + case 0x68: REG_OP(TR, Ixl, B); break; // LD Ixl, B + case 0x69: REG_OP(TR, Ixl, C); break; // LD Ixl, C + case 0x6A: REG_OP(TR, Ixl, D); break; // LD Ixl, D + case 0x6B: REG_OP(TR, Ixl, E); break; // LD Ixl, E + case 0x6C: REG_OP(TR, Ixl, Ixh); break; // LD Ixl, Ixh + case 0x6D: REG_OP(TR, Ixl, Ixl); break; // LD Ixl, Ixl + case 0x6E: I_REG_OP_IND_n(TR, L, Ixl, Ixh); break; // LD L, (Ix + n) + case 0x6F: REG_OP(TR, Ixl, A); break; // LD Ixl, A + case 0x70: I_LD_8_IND_n(Ixl, Ixh, B); break; // LD (Ix + n), B + case 0x71: I_LD_8_IND_n(Ixl, Ixh, C); break; // LD (Ix + n), C + case 0x72: I_LD_8_IND_n(Ixl, Ixh, D); break; // LD (Ix + n), D + case 0x73: I_LD_8_IND_n(Ixl, Ixh, E); break; // LD (Ix + n), E + case 0x74: I_LD_8_IND_n(Ixl, Ixh, H); break; // LD (Ix + n), H + case 0x75: I_LD_8_IND_n(Ixl, Ixh, L); break; // LD (Ix + n), L + case 0x76: HALT_(); break; // HALT + case 0x77: I_LD_8_IND_n(Ixl, Ixh, A); break; // LD (Ix + n), A + case 0x78: REG_OP(TR, A, B); break; // LD A, B + case 0x79: REG_OP(TR, A, C); break; // LD A, C + case 0x7A: REG_OP(TR, A, D); break; // LD A, D + case 0x7B: REG_OP(TR, A, E); break; // LD A, E + case 0x7C: REG_OP(TR, A, Ixh); break; // LD A, Ixh + case 0x7D: REG_OP(TR, A, Ixl); break; // LD A, Ixl + case 0x7E: I_REG_OP_IND_n(TR, A, Ixl, Ixh); break; // LD A, (Ix + n) + case 0x7F: REG_OP(TR, A, A); break; // LD A, A + case 0x80: REG_OP(ADD8, A, B); break; // ADD A, B + case 0x81: REG_OP(ADD8, A, C); break; // ADD A, C + case 0x82: REG_OP(ADD8, A, D); break; // ADD A, D + case 0x83: REG_OP(ADD8, A, E); break; // ADD A, E + case 0x84: REG_OP(ADD8, A, Ixh); break; // ADD A, Ixh + case 0x85: REG_OP(ADD8, A, Ixl); break; // ADD A, Ixl + case 0x86: I_REG_OP_IND_n(ADD8, A, Ixl, Ixh); break; // ADD A, (Ix + n) + case 0x87: REG_OP(ADD8, A, A); break; // ADD A, A + case 0x88: REG_OP(ADC8, A, B); break; // ADC A, B + case 0x89: REG_OP(ADC8, A, C); break; // ADC A, C + case 0x8A: REG_OP(ADC8, A, D); break; // ADC A, D + case 0x8B: REG_OP(ADC8, A, E); break; // ADC A, E + case 0x8C: REG_OP(ADC8, A, Ixh); break; // ADC A, Ixh + case 0x8D: REG_OP(ADC8, A, Ixl); break; // ADC A, Ixl + case 0x8E: I_REG_OP_IND_n(ADC8, A, Ixl, Ixh); break; // ADC A, (Ix + n) + case 0x8F: REG_OP(ADC8, A, A); break; // ADC A, A + case 0x90: REG_OP(SUB8, A, B); break; // SUB A, B + case 0x91: REG_OP(SUB8, A, C); break; // SUB A, C + case 0x92: REG_OP(SUB8, A, D); break; // SUB A, D + case 0x93: REG_OP(SUB8, A, E); break; // SUB A, E + case 0x94: REG_OP(SUB8, A, Ixh); break; // SUB A, Ixh + case 0x95: REG_OP(SUB8, A, Ixl); break; // SUB A, Ixl + case 0x96: I_REG_OP_IND_n(SUB8, A, Ixl, Ixh); break; // SUB A, (Ix + n) + case 0x97: REG_OP(SUB8, A, A); break; // SUB A, A + case 0x98: REG_OP(SBC8, A, B); break; // SBC A, B + case 0x99: REG_OP(SBC8, A, C); break; // SBC A, C + case 0x9A: REG_OP(SBC8, A, D); break; // SBC A, D + case 0x9B: REG_OP(SBC8, A, E); break; // SBC A, E + case 0x9C: REG_OP(SBC8, A, Ixh); break; // SBC A, Ixh + case 0x9D: REG_OP(SBC8, A, Ixl); break; // SBC A, Ixl + case 0x9E: I_REG_OP_IND_n(SBC8, A, Ixl, Ixh); break; // SBC A, (Ix + n) + case 0x9F: REG_OP(SBC8, A, A); break; // SBC A, A + case 0xA0: REG_OP(AND8, A, B); break; // AND A, B + case 0xA1: REG_OP(AND8, A, C); break; // AND A, C + case 0xA2: REG_OP(AND8, A, D); break; // AND A, D + case 0xA3: REG_OP(AND8, A, E); break; // AND A, E + case 0xA4: REG_OP(AND8, A, Ixh); break; // AND A, Ixh + case 0xA5: REG_OP(AND8, A, Ixl); break; // AND A, Ixl + case 0xA6: I_REG_OP_IND_n(AND8, A, Ixl, Ixh); break; // AND A, (Ix + n) + case 0xA7: REG_OP(AND8, A, A); break; // AND A, A + case 0xA8: REG_OP(XOR8, A, B); break; // XOR A, B + case 0xA9: REG_OP(XOR8, A, C); break; // XOR A, C + case 0xAA: REG_OP(XOR8, A, D); break; // XOR A, D + case 0xAB: REG_OP(XOR8, A, E); break; // XOR A, E + case 0xAC: REG_OP(XOR8, A, Ixh); break; // XOR A, Ixh + case 0xAD: REG_OP(XOR8, A, Ixl); break; // XOR A, Ixl + case 0xAE: I_REG_OP_IND_n(XOR8, A, Ixl, Ixh); break; // XOR A, (Ix + n) + case 0xAF: REG_OP(XOR8, A, A); break; // XOR A, A + case 0xB0: REG_OP(OR8, A, B); break; // OR A, B + case 0xB1: REG_OP(OR8, A, C); break; // OR A, C + case 0xB2: REG_OP(OR8, A, D); break; // OR A, D + case 0xB3: REG_OP(OR8, A, E); break; // OR A, E + case 0xB4: REG_OP(OR8, A, Ixh); break; // OR A, Ixh + case 0xB5: REG_OP(OR8, A, Ixl); break; // OR A, Ixl + case 0xB6: I_REG_OP_IND_n(OR8, A, Ixl, Ixh); break; // OR A, (Ix + n) + case 0xB7: REG_OP(OR8, A, A); break; // OR A, A + case 0xB8: REG_OP(CP8, A, B); break; // CP A, B + case 0xB9: REG_OP(CP8, A, C); break; // CP A, C + case 0xBA: REG_OP(CP8, A, D); break; // CP A, D + case 0xBB: REG_OP(CP8, A, E); break; // CP A, E + case 0xBC: REG_OP(CP8, A, Ixh); break; // CP A, Ixh + case 0xBD: REG_OP(CP8, A, Ixl); break; // CP A, Ixl + case 0xBE: I_REG_OP_IND_n(CP8, A, Ixl, Ixh); break; // CP A, (Ix + n) + case 0xBF: REG_OP(CP8, A, A); break; // CP A, A + case 0xC0: RET_COND(!FlagZ); break; // Ret NZ + case 0xC1: POP_(C, B); break; // POP BC + case 0xC2: JP_COND(!FlagZ); break; // JP NZ + case 0xC3: JP_COND(true); break; // JP + case 0xC4: CALL_COND(!FlagZ); break; // CALL NZ + case 0xC5: PUSH_(C, B); break; // PUSH BC + case 0xC6: REG_OP_IND_INC(ADD8, A, PCl, PCh); break; // ADD A, n + case 0xC7: RST_(0); break; // RST 0 + case 0xC8: RET_COND(FlagZ); break; // RET Z + case 0xC9: RET_(); break; // RET + case 0xCA: JP_COND(FlagZ); break; // JP Z + case 0xCB: PREFIX_(IXCBpre); break; // PREFIX IXCB + case 0xCC: CALL_COND(FlagZ); break; // CALL Z + case 0xCD: CALL_COND(true); break; // CALL + case 0xCE: REG_OP_IND_INC(ADC8, A, PCl, PCh); break; // ADC A, n + case 0xCF: RST_(0x08); break; // RST 0x08 + case 0xD0: RET_COND(!FlagC); break; // Ret NC + case 0xD1: POP_(E, D); break; // POP DE + case 0xD2: JP_COND(!FlagC); break; // JP NC + case 0xD3: OUT_(); break; // OUT A + case 0xD4: CALL_COND(!FlagC); break; // CALL NC + case 0xD5: PUSH_(E, D); break; // PUSH DE + case 0xD6: REG_OP_IND_INC(SUB8, A, PCl, PCh); break; // SUB A, n + case 0xD7: RST_(0x10); break; // RST 0x10 + case 0xD8: RET_COND(FlagC); break; // RET C + case 0xD9: EXX_(); break; // EXX + case 0xDA: JP_COND(FlagC); break; // JP C + case 0xDB: IN_(); break; // IN A + case 0xDC: CALL_COND(FlagC); break; // CALL C + case 0xDD: PREFIX_(IXpre); break; // IX Prefix + case 0xDE: REG_OP_IND_INC(SBC8, A, PCl, PCh); break; // SBC A, n + case 0xDF: RST_(0x18); break; // RST 0x18 + case 0xE0: RET_COND(!FlagP); break; // RET Po + case 0xE1: POP_(Ixl, Ixh); break; // POP Ix + case 0xE2: JP_COND(!FlagP); break; // JP Po + case 0xE3: EXCH_16_IND_(SPl, SPh, Ixl, Ixh); break; // ex (SP), Ix + case 0xE4: CALL_COND(!FlagP); break; // CALL Po + case 0xE5: PUSH_(Ixl, Ixh); break; // PUSH Ix + case 0xE6: REG_OP_IND_INC(AND8, A, PCl, PCh); break; // AND A, n + case 0xE7: RST_(0x20); break; // RST 0x20 + case 0xE8: RET_COND(FlagP); break; // RET Pe + case 0xE9: JP_16(Ixl, Ixh); break; // JP (Ix) + case 0xEA: JP_COND(FlagP); break; // JP Pe + case 0xEB: EXCH_16_(E, D, L, H); break; // ex DE, HL + case 0xEC: CALL_COND(FlagP); break; // CALL Pe + case 0xED: PREFIX_(EXTDpre); break; // EXTD Prefix + case 0xEE: REG_OP_IND_INC(XOR8, A, PCl, PCh); break; // XOR A, n + case 0xEF: RST_(0x28); break; // RST 0x28 + case 0xF0: RET_COND(!FlagS); break; // RET p + case 0xF1: POP_(F, A); break; // POP AF + case 0xF2: JP_COND(!FlagS); break; // JP p + case 0xF3: DI_(); break; // DI + case 0xF4: CALL_COND(!FlagS); break; // CALL p + case 0xF5: PUSH_(F, A); break; // PUSH AF + case 0xF6: REG_OP_IND_INC(OR8, A, PCl, PCh); break; // OR A, n + case 0xF7: RST_(0x30); break; // RST 0x30 + case 0xF8: RET_COND(FlagS); break; // RET M + case 0xF9: LD_SP_16(Ixl, Ixh); break; // LD SP, Ix + case 0xFA: JP_COND(FlagS); break; // JP M + case 0xFB: EI_(); break; // EI + case 0xFC: CALL_COND(FlagS); break; // CALL M + case 0xFD: PREFIX_(IYpre); break; // IY Prefix + case 0xFE: REG_OP_IND_INC(CP8, A, PCl, PCh); break; // CP A, n + case 0xFF: RST_(0x38); break; // RST $38 + } + } + else if (IY_prefix) + { + IY_prefix = false; + NO_prefix = true; + + switch (opcode) + { + case 0x00: NOP_(); break; // NOP + case 0x01: LD_IND_16(C, B, PCl, PCh); break; // LD BC, nn + case 0x02: LD_8_IND(C, B, A); break; // LD (BC), A + case 0x03: INC_16(C, B); break; // INC BC + case 0x04: INT_OP(INC8, B); break; // INC B + case 0x05: INT_OP(DEC8, B); break; // DEC B + case 0x06: LD_IND_8_INC(B, PCl, PCh); break; // LD B, n + case 0x07: INT_OP(RLC, Aim); break; // RLCA + case 0x08: EXCH_(); break; // EXCH AF, AF' + case 0x09: ADD_16(Iyl, Iyh, C, B); break; // ADD Iy, BC + case 0x0A: REG_OP_IND(TR, A, C, B); break; // LD A, (BC) + case 0x0B: DEC_16(C, B); break; // DEC BC + case 0x0C: INT_OP(INC8, C); break; // INC C + case 0x0D: INT_OP(DEC8, C); break; // DEC C + case 0x0E: LD_IND_8_INC(C, PCl, PCh); break; // LD C, n + case 0x0F: INT_OP(RRC, Aim); break; // RRCA + case 0x10: DJNZ_(); break; // DJNZ B + case 0x11: LD_IND_16(E, D, PCl, PCh); break; // LD DE, nn + case 0x12: LD_8_IND(E, D, A); break; // LD (DE), A + case 0x13: INC_16(E, D); break; // INC DE + case 0x14: INT_OP(INC8, D); break; // INC D + case 0x15: INT_OP(DEC8, D); break; // DEC D + case 0x16: LD_IND_8_INC(D, PCl, PCh); break; // LD D, n + case 0x17: INT_OP(RL, Aim); break; // RLA + case 0x18: JR_COND(true); break; // JR, r8 + case 0x19: ADD_16(Iyl, Iyh, E, D); break; // ADD Iy, DE + case 0x1A: REG_OP_IND(TR, A, E, D); break; // LD A, (DE) + case 0x1B: DEC_16(E, D); break; // DEC DE + case 0x1C: INT_OP(INC8, E); break; // INC E + case 0x1D: INT_OP(DEC8, E); break; // DEC E + case 0x1E: LD_IND_8_INC(E, PCl, PCh); break; // LD E, n + case 0x1F: INT_OP(RR, Aim); break; // RRA + case 0x20: JR_COND(!FlagZ); break; // JR NZ, r8 + case 0x21: LD_IND_16(Iyl, Iyh, PCl, PCh); break; // LD Iy, nn + case 0x22: LD_16_IND_nn(Iyl, Iyh); break; // LD (nn), Iy + case 0x23: INC_16(Iyl, Iyh); break; // INC Iy + case 0x24: INT_OP(INC8, Iyh); break; // INC Iyh + case 0x25: INT_OP(DEC8, Iyh); break; // DEC Iyh + case 0x26: LD_IND_8_INC(Iyh, PCl, PCh); break; // LD Iyh, n + case 0x27: INT_OP(DA, A); break; // DAA + case 0x28: JR_COND(FlagZ); break; // JR Z, r8 + case 0x29: ADD_16(Iyl, Iyh, Iyl, Iyh); break; // ADD Iy, Iy + case 0x2A: LD_IND_16_nn(Iyl, Iyh); break; // LD Iy, (nn) + case 0x2B: DEC_16(Iyl, Iyh); break; // DEC Iy + case 0x2C: INT_OP(INC8, Iyl); break; // INC Iyl + case 0x2D: INT_OP(DEC8, Iyl); break; // DEC Iyl + case 0x2E: LD_IND_8_INC(Iyl, PCl, PCh); break; // LD Iyl, n + case 0x2F: INT_OP(CPL, A); break; // CPL + case 0x30: JR_COND(!FlagC); break; // JR NC, r8 + case 0x31: LD_IND_16(SPl, SPh, PCl, PCh); break; // LD SP, nn + case 0x32: LD_8_IND_nn(A); break; // LD (nn), A + case 0x33: INC_16(SPl, SPh); break; // INC SP + case 0x34: I_OP_n(INC8, Iyl, Iyh); break; // INC (Iy + n) + case 0x35: I_OP_n(DEC8, Iyl, Iyh); break; // DEC (Iy + n) + case 0x36: I_OP_n_n(Iyl, Iyh); break; // LD (Iy + n), n + case 0x37: INT_OP(SCF, A); break; // SCF + case 0x38: JR_COND(FlagC); break; // JR C, r8 + case 0x39: ADD_16(Iyl, Iyh, SPl, SPh); break; // ADD Iy, SP + case 0x3A: LD_IND_8_nn(A); break; // LD A, (nn) + case 0x3B: DEC_16(SPl, SPh); break; // DEC SP + case 0x3C: INT_OP(INC8, A); break; // INC A + case 0x3D: INT_OP(DEC8, A); break; // DEC A + case 0x3E: LD_IND_8_INC(A, PCl, PCh); break; // LD A, n + case 0x3F: INT_OP(CCF, A); break; // CCF + case 0x40: REG_OP(TR, B, B); break; // LD B, B + case 0x41: REG_OP(TR, B, C); break; // LD B, C + case 0x42: REG_OP(TR, B, D); break; // LD B, D + case 0x43: REG_OP(TR, B, E); break; // LD B, E + case 0x44: REG_OP(TR, B, Iyh); break; // LD B, Iyh + case 0x45: REG_OP(TR, B, Iyl); break; // LD B, Iyl + case 0x46: I_REG_OP_IND_n(TR, B, Iyl, Iyh); break; // LD B, (Iy + n) + case 0x47: REG_OP(TR, B, A); break; // LD B, A + case 0x48: REG_OP(TR, C, B); break; // LD C, B + case 0x49: REG_OP(TR, C, C); break; // LD C, C + case 0x4A: REG_OP(TR, C, D); break; // LD C, D + case 0x4B: REG_OP(TR, C, E); break; // LD C, E + case 0x4C: REG_OP(TR, C, Iyh); break; // LD C, Iyh + case 0x4D: REG_OP(TR, C, Iyl); break; // LD C, Iyl + case 0x4E: I_REG_OP_IND_n(TR, C, Iyl, Iyh); break; // LD C, (Iy + n) + case 0x4F: REG_OP(TR, C, A); break; // LD C, A + case 0x50: REG_OP(TR, D, B); break; // LD D, B + case 0x51: REG_OP(TR, D, C); break; // LD D, C + case 0x52: REG_OP(TR, D, D); break; // LD D, D + case 0x53: REG_OP(TR, D, E); break; // LD D, E + case 0x54: REG_OP(TR, D, Iyh); break; // LD D, Iyh + case 0x55: REG_OP(TR, D, Iyl); break; // LD D, Iyl + case 0x56: I_REG_OP_IND_n(TR, D, Iyl, Iyh); break; // LD D, (Iy + n) + case 0x57: REG_OP(TR, D, A); break; // LD D, A + case 0x58: REG_OP(TR, E, B); break; // LD E, B + case 0x59: REG_OP(TR, E, C); break; // LD E, C + case 0x5A: REG_OP(TR, E, D); break; // LD E, D + case 0x5B: REG_OP(TR, E, E); break; // LD E, E + case 0x5C: REG_OP(TR, E, Iyh); break; // LD E, Iyh + case 0x5D: REG_OP(TR, E, Iyl); break; // LD E, Iyl + case 0x5E: I_REG_OP_IND_n(TR, E, Iyl, Iyh); break; // LD E, (Iy + n) + case 0x5F: REG_OP(TR, E, A); break; // LD E, A + case 0x60: REG_OP(TR, Iyh, B); break; // LD Iyh, B + case 0x61: REG_OP(TR, Iyh, C); break; // LD Iyh, C + case 0x62: REG_OP(TR, Iyh, D); break; // LD Iyh, D + case 0x63: REG_OP(TR, Iyh, E); break; // LD Iyh, E + case 0x64: REG_OP(TR, Iyh, Iyh); break; // LD Iyh, Iyh + case 0x65: REG_OP(TR, Iyh, Iyl); break; // LD Iyh, Iyl + case 0x66: I_REG_OP_IND_n(TR, H, Iyl, Iyh); break; // LD H, (Iy + n) + case 0x67: REG_OP(TR, Iyh, A); break; // LD Iyh, A + case 0x68: REG_OP(TR, Iyl, B); break; // LD Iyl, B + case 0x69: REG_OP(TR, Iyl, C); break; // LD Iyl, C + case 0x6A: REG_OP(TR, Iyl, D); break; // LD Iyl, D + case 0x6B: REG_OP(TR, Iyl, E); break; // LD Iyl, E + case 0x6C: REG_OP(TR, Iyl, Iyh); break; // LD Iyl, Iyh + case 0x6D: REG_OP(TR, Iyl, Iyl); break; // LD Iyl, Iyl + case 0x6E: I_REG_OP_IND_n(TR, L, Iyl, Iyh); break; // LD L, (Iy + n) + case 0x6F: REG_OP(TR, Iyl, A); break; // LD Iyl, A + case 0x70: I_LD_8_IND_n(Iyl, Iyh, B); break; // LD (Iy + n), B + case 0x71: I_LD_8_IND_n(Iyl, Iyh, C); break; // LD (Iy + n), C + case 0x72: I_LD_8_IND_n(Iyl, Iyh, D); break; // LD (Iy + n), D + case 0x73: I_LD_8_IND_n(Iyl, Iyh, E); break; // LD (Iy + n), E + case 0x74: I_LD_8_IND_n(Iyl, Iyh, H); break; // LD (Iy + n), H + case 0x75: I_LD_8_IND_n(Iyl, Iyh, L); break; // LD (Iy + n), L + case 0x76: HALT_(); break; // HALT + case 0x77: I_LD_8_IND_n(Iyl, Iyh, A); break; // LD (Iy + n), A + case 0x78: REG_OP(TR, A, B); break; // LD A, B + case 0x79: REG_OP(TR, A, C); break; // LD A, C + case 0x7A: REG_OP(TR, A, D); break; // LD A, D + case 0x7B: REG_OP(TR, A, E); break; // LD A, E + case 0x7C: REG_OP(TR, A, Iyh); break; // LD A, Iyh + case 0x7D: REG_OP(TR, A, Iyl); break; // LD A, Iyl + case 0x7E: I_REG_OP_IND_n(TR, A, Iyl, Iyh); break; // LD A, (Iy + n) + case 0x7F: REG_OP(TR, A, A); break; // LD A, A + case 0x80: REG_OP(ADD8, A, B); break; // ADD A, B + case 0x81: REG_OP(ADD8, A, C); break; // ADD A, C + case 0x82: REG_OP(ADD8, A, D); break; // ADD A, D + case 0x83: REG_OP(ADD8, A, E); break; // ADD A, E + case 0x84: REG_OP(ADD8, A, Iyh); break; // ADD A, Iyh + case 0x85: REG_OP(ADD8, A, Iyl); break; // ADD A, Iyl + case 0x86: I_REG_OP_IND_n(ADD8, A, Iyl, Iyh); break; // ADD A, (Iy + n) + case 0x87: REG_OP(ADD8, A, A); break; // ADD A, A + case 0x88: REG_OP(ADC8, A, B); break; // ADC A, B + case 0x89: REG_OP(ADC8, A, C); break; // ADC A, C + case 0x8A: REG_OP(ADC8, A, D); break; // ADC A, D + case 0x8B: REG_OP(ADC8, A, E); break; // ADC A, E + case 0x8C: REG_OP(ADC8, A, Iyh); break; // ADC A, Iyh + case 0x8D: REG_OP(ADC8, A, Iyl); break; // ADC A, Iyl + case 0x8E: I_REG_OP_IND_n(ADC8, A, Iyl, Iyh); break; // ADC A, (Iy + n) + case 0x8F: REG_OP(ADC8, A, A); break; // ADC A, A + case 0x90: REG_OP(SUB8, A, B); break; // SUB A, B + case 0x91: REG_OP(SUB8, A, C); break; // SUB A, C + case 0x92: REG_OP(SUB8, A, D); break; // SUB A, D + case 0x93: REG_OP(SUB8, A, E); break; // SUB A, E + case 0x94: REG_OP(SUB8, A, Iyh); break; // SUB A, Iyh + case 0x95: REG_OP(SUB8, A, Iyl); break; // SUB A, Iyl + case 0x96: I_REG_OP_IND_n(SUB8, A, Iyl, Iyh); break; // SUB A, (Iy + n) + case 0x97: REG_OP(SUB8, A, A); break; // SUB A, A + case 0x98: REG_OP(SBC8, A, B); break; // SBC A, B + case 0x99: REG_OP(SBC8, A, C); break; // SBC A, C + case 0x9A: REG_OP(SBC8, A, D); break; // SBC A, D + case 0x9B: REG_OP(SBC8, A, E); break; // SBC A, E + case 0x9C: REG_OP(SBC8, A, Iyh); break; // SBC A, Iyh + case 0x9D: REG_OP(SBC8, A, Iyl); break; // SBC A, Iyl + case 0x9E: I_REG_OP_IND_n(SBC8, A, Iyl, Iyh); break; // SBC A, (Iy + n) + case 0x9F: REG_OP(SBC8, A, A); break; // SBC A, A + case 0xA0: REG_OP(AND8, A, B); break; // AND A, B + case 0xA1: REG_OP(AND8, A, C); break; // AND A, C + case 0xA2: REG_OP(AND8, A, D); break; // AND A, D + case 0xA3: REG_OP(AND8, A, E); break; // AND A, E + case 0xA4: REG_OP(AND8, A, Iyh); break; // AND A, Iyh + case 0xA5: REG_OP(AND8, A, Iyl); break; // AND A, Iyl + case 0xA6: I_REG_OP_IND_n(AND8, A, Iyl, Iyh); break; // AND A, (Iy + n) + case 0xA7: REG_OP(AND8, A, A); break; // AND A, A + case 0xA8: REG_OP(XOR8, A, B); break; // XOR A, B + case 0xA9: REG_OP(XOR8, A, C); break; // XOR A, C + case 0xAA: REG_OP(XOR8, A, D); break; // XOR A, D + case 0xAB: REG_OP(XOR8, A, E); break; // XOR A, E + case 0xAC: REG_OP(XOR8, A, Iyh); break; // XOR A, Iyh + case 0xAD: REG_OP(XOR8, A, Iyl); break; // XOR A, Iyl + case 0xAE: I_REG_OP_IND_n(XOR8, A, Iyl, Iyh); break; // XOR A, (Iy + n) + case 0xAF: REG_OP(XOR8, A, A); break; // XOR A, A + case 0xB0: REG_OP(OR8, A, B); break; // OR A, B + case 0xB1: REG_OP(OR8, A, C); break; // OR A, C + case 0xB2: REG_OP(OR8, A, D); break; // OR A, D + case 0xB3: REG_OP(OR8, A, E); break; // OR A, E + case 0xB4: REG_OP(OR8, A, Iyh); break; // OR A, Iyh + case 0xB5: REG_OP(OR8, A, Iyl); break; // OR A, Iyl + case 0xB6: I_REG_OP_IND_n(OR8, A, Iyl, Iyh); break; // OR A, (Iy + n) + case 0xB7: REG_OP(OR8, A, A); break; // OR A, A + case 0xB8: REG_OP(CP8, A, B); break; // CP A, B + case 0xB9: REG_OP(CP8, A, C); break; // CP A, C + case 0xBA: REG_OP(CP8, A, D); break; // CP A, D + case 0xBB: REG_OP(CP8, A, E); break; // CP A, E + case 0xBC: REG_OP(CP8, A, Iyh); break; // CP A, Iyh + case 0xBD: REG_OP(CP8, A, Iyl); break; // CP A, Iyl + case 0xBE: I_REG_OP_IND_n(CP8, A, Iyl, Iyh); break; // CP A, (Iy + n) + case 0xBF: REG_OP(CP8, A, A); break; // CP A, A + case 0xC0: RET_COND(!FlagZ); break; // Ret NZ + case 0xC1: POP_(C, B); break; // POP BC + case 0xC2: JP_COND(!FlagZ); break; // JP NZ + case 0xC3: JP_COND(true); break; // JP + case 0xC4: CALL_COND(!FlagZ); break; // CALL NZ + case 0xC5: PUSH_(C, B); break; // PUSH BC + case 0xC6: REG_OP_IND_INC(ADD8, A, PCl, PCh); break; // ADD A, n + case 0xC7: RST_(0); break; // RST 0 + case 0xC8: RET_COND(FlagZ); break; // RET Z + case 0xC9: RET_(); break; // RET + case 0xCA: JP_COND(FlagZ); break; // JP Z + case 0xCB: PREFIX_(IYCBpre); break; // PREFIy IyCB + case 0xCC: CALL_COND(FlagZ); break; // CALL Z + case 0xCD: CALL_COND(true); break; // CALL + case 0xCE: REG_OP_IND_INC(ADC8, A, PCl, PCh); break; // ADC A, n + case 0xCF: RST_(0x08); break; // RST 0x08 + case 0xD0: RET_COND(!FlagC); break; // Ret NC + case 0xD1: POP_(E, D); break; // POP DE + case 0xD2: JP_COND(!FlagC); break; // JP NC + case 0xD3: OUT_(); break; // OUT A + case 0xD4: CALL_COND(!FlagC); break; // CALL NC + case 0xD5: PUSH_(E, D); break; // PUSH DE + case 0xD6: REG_OP_IND_INC(SUB8, A, PCl, PCh); break; // SUB A, n + case 0xD7: RST_(0x10); break; // RST 0x10 + case 0xD8: RET_COND(FlagC); break; // RET C + case 0xD9: EXX_(); break; // EXX + case 0xDA: JP_COND(FlagC); break; // JP C + case 0xDB: IN_(); break; // IN A + case 0xDC: CALL_COND(FlagC); break; // CALL C + case 0xDD: PREFIX_(IXpre); break; // IX Prefix + case 0xDE: REG_OP_IND_INC(SBC8, A, PCl, PCh); break; // SBC A, n + case 0xDF: RST_(0x18); break; // RST 0x18 + case 0xE0: RET_COND(!FlagP); break; // RET Po + case 0xE1: POP_(Iyl, Iyh); break; // POP Iy + case 0xE2: JP_COND(!FlagP); break; // JP Po + case 0xE3: EXCH_16_IND_(SPl, SPh, Iyl, Iyh); break; // ex (SP), Iy + case 0xE4: CALL_COND(!FlagP); break; // CALL Po + case 0xE5: PUSH_(Iyl, Iyh); break; // PUSH Iy + case 0xE6: REG_OP_IND_INC(AND8, A, PCl, PCh); break; // AND A, n + case 0xE7: RST_(0x20); break; // RST 0x20 + case 0xE8: RET_COND(FlagP); break; // RET Pe + case 0xE9: JP_16(Iyl, Iyh); break; // JP (Iy) + case 0xEA: JP_COND(FlagP); break; // JP Pe + case 0xEB: EXCH_16_(E, D, L, H); break; // ex DE, HL + case 0xEC: CALL_COND(FlagP); break; // CALL Pe + case 0xED: PREFIX_(EXTDpre); break; // EXTD Prefix + case 0xEE: REG_OP_IND_INC(XOR8, A, PCl, PCh); break; // XOR A, n + case 0xEF: RST_(0x28); break; // RST 0x28 + case 0xF0: RET_COND(!FlagS); break; // RET p + case 0xF1: POP_(F, A); break; // POP AF + case 0xF2: JP_COND(!FlagS); break; // JP p + case 0xF3: DI_(); break; // DI + case 0xF4: CALL_COND(!FlagS); break; // CALL p + case 0xF5: PUSH_(F, A); break; // PUSH AF + case 0xF6: REG_OP_IND_INC(OR8, A, PCl, PCh); break; // OR A, n + case 0xF7: RST_(0x30); break; // RST 0x30 + case 0xF8: RET_COND(FlagS); break; // RET M + case 0xF9: LD_SP_16(Iyl, Iyh); break; // LD SP, Iy + case 0xFA: JP_COND(FlagS); break; // JP M + case 0xFB: EI_(); break; // EI + case 0xFC: CALL_COND(FlagS); break; // CALL M + case 0xFD: PREFIX_(IYpre); break; // IY Prefix + case 0xFE: REG_OP_IND_INC(CP8, A, PCl, PCh); break; // CP A, n + case 0xFF: RST_(0x38); break; // RST $38 + } + } + else if (IXCB_prefix || IYCB_prefix) + { + // the first byte fetched is the prefetch value to use with the instruction + // we pick Ix or Iy here, the indexed value is stored in WZ + // In this way, we don't need to pass them as an argument to the I_Funcs. + if (IXCB_prefetch) + { + IXCB_prefetch = false; + PF = opcode; + Regs[ALU] = PF; + PREFETCH_(Ixl, Ixh); + return; + } + + if (IYCB_prefetch) + { + IYCB_prefetch = false; + PF = opcode; + Regs[ALU] = PF; + PREFETCH_(Iyl, Iyh); + return; + } + + IXCB_prefix = false; + IYCB_prefix = false; + NO_prefix = true; + + switch (opcode) + { + case 0x00: I_INT_OP(RLC, B); break; // RLC (I* + n) -> B + case 0x01: I_INT_OP(RLC, C); break; // RLC (I* + n) -> C + case 0x02: I_INT_OP(RLC, D); break; // RLC (I* + n) -> D + case 0x03: I_INT_OP(RLC, E); break; // RLC (I* + n) -> E + case 0x04: I_INT_OP(RLC, H); break; // RLC (I* + n) -> H + case 0x05: I_INT_OP(RLC, L); break; // RLC (I* + n) -> L + case 0x06: I_INT_OP(RLC, ALU); break; // RLC (I* + n) + case 0x07: I_INT_OP(RLC, A); break; // RLC (I* + n) -> A + case 0x08: I_INT_OP(RRC, B); break; // RRC (I* + n) -> B + case 0x09: I_INT_OP(RRC, C); break; // RRC (I* + n) -> C + case 0x0A: I_INT_OP(RRC, D); break; // RRC (I* + n) -> D + case 0x0B: I_INT_OP(RRC, E); break; // RRC (I* + n) -> E + case 0x0C: I_INT_OP(RRC, H); break; // RRC (I* + n) -> H + case 0x0D: I_INT_OP(RRC, L); break; // RRC (I* + n) -> L + case 0x0E: I_INT_OP(RRC, ALU); break; // RRC (I* + n) + case 0x0F: I_INT_OP(RRC, A); break; // RRC (I* + n) -> A + case 0x10: I_INT_OP(RL, B); break; // RL (I* + n) -> B + case 0x11: I_INT_OP(RL, C); break; // RL (I* + n) -> C + case 0x12: I_INT_OP(RL, D); break; // RL (I* + n) -> D + case 0x13: I_INT_OP(RL, E); break; // RL (I* + n) -> E + case 0x14: I_INT_OP(RL, H); break; // RL (I* + n) -> H + case 0x15: I_INT_OP(RL, L); break; // RL (I* + n) -> L + case 0x16: I_INT_OP(RL, ALU); break; // RL (I* + n) + case 0x17: I_INT_OP(RL, A); break; // RL (I* + n) -> A + case 0x18: I_INT_OP(RR, B); break; // RR (I* + n) -> B + case 0x19: I_INT_OP(RR, C); break; // RR (I* + n) -> C + case 0x1A: I_INT_OP(RR, D); break; // RR (I* + n) -> D + case 0x1B: I_INT_OP(RR, E); break; // RR (I* + n) -> E + case 0x1C: I_INT_OP(RR, H); break; // RR (I* + n) -> H + case 0x1D: I_INT_OP(RR, L); break; // RR (I* + n) -> L + case 0x1E: I_INT_OP(RR, ALU); break; // RR (I* + n) + case 0x1F: I_INT_OP(RR, A); break; // RR (I* + n) -> A + case 0x20: I_INT_OP(SLA, B); break; // SLA (I* + n) -> B + case 0x21: I_INT_OP(SLA, C); break; // SLA (I* + n) -> C + case 0x22: I_INT_OP(SLA, D); break; // SLA (I* + n) -> D + case 0x23: I_INT_OP(SLA, E); break; // SLA (I* + n) -> E + case 0x24: I_INT_OP(SLA, H); break; // SLA (I* + n) -> H + case 0x25: I_INT_OP(SLA, L); break; // SLA (I* + n) -> L + case 0x26: I_INT_OP(SLA, ALU); break; // SLA (I* + n) + case 0x27: I_INT_OP(SLA, A); break; // SLA (I* + n) -> A + case 0x28: I_INT_OP(SRA, B); break; // SRA (I* + n) -> B + case 0x29: I_INT_OP(SRA, C); break; // SRA (I* + n) -> C + case 0x2A: I_INT_OP(SRA, D); break; // SRA (I* + n) -> D + case 0x2B: I_INT_OP(SRA, E); break; // SRA (I* + n) -> E + case 0x2C: I_INT_OP(SRA, H); break; // SRA (I* + n) -> H + case 0x2D: I_INT_OP(SRA, L); break; // SRA (I* + n) -> L + case 0x2E: I_INT_OP(SRA, ALU); break; // SRA (I* + n) + case 0x2F: I_INT_OP(SRA, A); break; // SRA (I* + n) -> A + case 0x30: I_INT_OP(SLL, B); break; // SLL (I* + n) -> B + case 0x31: I_INT_OP(SLL, C); break; // SLL (I* + n) -> C + case 0x32: I_INT_OP(SLL, D); break; // SLL (I* + n) -> D + case 0x33: I_INT_OP(SLL, E); break; // SLL (I* + n) -> E + case 0x34: I_INT_OP(SLL, H); break; // SLL (I* + n) -> H + case 0x35: I_INT_OP(SLL, L); break; // SLL (I* + n) -> L + case 0x36: I_INT_OP(SLL, ALU); break; // SLL (I* + n) + case 0x37: I_INT_OP(SLL, A); break; // SLL (I* + n) -> A + case 0x38: I_INT_OP(SRL, B); break; // SRL (I* + n) -> B + case 0x39: I_INT_OP(SRL, C); break; // SRL (I* + n) -> C + case 0x3A: I_INT_OP(SRL, D); break; // SRL (I* + n) -> D + case 0x3B: I_INT_OP(SRL, E); break; // SRL (I* + n) -> E + case 0x3C: I_INT_OP(SRL, H); break; // SRL (I* + n) -> H + case 0x3D: I_INT_OP(SRL, L); break; // SRL (I* + n) -> L + case 0x3E: I_INT_OP(SRL, ALU); break; // SRL (I* + n) + case 0x3F: I_INT_OP(SRL, A); break; // SRL (I* + n) -> A + case 0x40: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x41: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x42: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x43: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x44: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x45: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x46: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x47: I_BIT_TE(0); break; // BIT 0, (I* + n) + case 0x48: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x49: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4A: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4B: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4C: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4D: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4E: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x4F: I_BIT_TE(1); break; // BIT 1, (I* + n) + case 0x50: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x51: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x52: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x53: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x54: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x55: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x56: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x57: I_BIT_TE(2); break; // BIT 2, (I* + n) + case 0x58: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x59: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5A: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5B: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5C: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5D: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5E: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x5F: I_BIT_TE(3); break; // BIT 3, (I* + n) + case 0x60: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x61: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x62: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x63: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x64: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x65: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x66: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x67: I_BIT_TE(4); break; // BIT 4, (I* + n) + case 0x68: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x69: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6A: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6B: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6C: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6D: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6E: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x6F: I_BIT_TE(5); break; // BIT 5, (I* + n) + case 0x70: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x71: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x72: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x73: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x74: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x75: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x76: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x77: I_BIT_TE(6); break; // BIT 6, (I* + n) + case 0x78: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x79: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7A: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7B: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7C: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7D: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7E: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x7F: I_BIT_TE(7); break; // BIT 7, (I* + n) + case 0x80: I_BIT_OP(RES, 0, B); break; // RES 0, (I* + n) -> B + case 0x81: I_BIT_OP(RES, 0, C); break; // RES 0, (I* + n) -> C + case 0x82: I_BIT_OP(RES, 0, D); break; // RES 0, (I* + n) -> D + case 0x83: I_BIT_OP(RES, 0, E); break; // RES 0, (I* + n) -> E + case 0x84: I_BIT_OP(RES, 0, H); break; // RES 0, (I* + n) -> H + case 0x85: I_BIT_OP(RES, 0, L); break; // RES 0, (I* + n) -> L + case 0x86: I_BIT_OP(RES, 0, ALU); break; // RES 0, (I* + n) + case 0x87: I_BIT_OP(RES, 0, A); break; // RES 0, (I* + n) -> A + case 0x88: I_BIT_OP(RES, 1, B); break; // RES 1, (I* + n) -> B + case 0x89: I_BIT_OP(RES, 1, C); break; // RES 1, (I* + n) -> C + case 0x8A: I_BIT_OP(RES, 1, D); break; // RES 1, (I* + n) -> D + case 0x8B: I_BIT_OP(RES, 1, E); break; // RES 1, (I* + n) -> E + case 0x8C: I_BIT_OP(RES, 1, H); break; // RES 1, (I* + n) -> H + case 0x8D: I_BIT_OP(RES, 1, L); break; // RES 1, (I* + n) -> L + case 0x8E: I_BIT_OP(RES, 1, ALU); break; // RES 1, (I* + n) + case 0x8F: I_BIT_OP(RES, 1, A); break; // RES 1, (I* + n) -> A + case 0x90: I_BIT_OP(RES, 2, B); break; // RES 2, (I* + n) -> B + case 0x91: I_BIT_OP(RES, 2, C); break; // RES 2, (I* + n) -> C + case 0x92: I_BIT_OP(RES, 2, D); break; // RES 2, (I* + n) -> D + case 0x93: I_BIT_OP(RES, 2, E); break; // RES 2, (I* + n) -> E + case 0x94: I_BIT_OP(RES, 2, H); break; // RES 2, (I* + n) -> H + case 0x95: I_BIT_OP(RES, 2, L); break; // RES 2, (I* + n) -> L + case 0x96: I_BIT_OP(RES, 2, ALU); break; // RES 2, (I* + n) + case 0x97: I_BIT_OP(RES, 2, A); break; // RES 2, (I* + n) -> A + case 0x98: I_BIT_OP(RES, 3, B); break; // RES 3, (I* + n) -> B + case 0x99: I_BIT_OP(RES, 3, C); break; // RES 3, (I* + n) -> C + case 0x9A: I_BIT_OP(RES, 3, D); break; // RES 3, (I* + n) -> D + case 0x9B: I_BIT_OP(RES, 3, E); break; // RES 3, (I* + n) -> E + case 0x9C: I_BIT_OP(RES, 3, H); break; // RES 3, (I* + n) -> H + case 0x9D: I_BIT_OP(RES, 3, L); break; // RES 3, (I* + n) -> L + case 0x9E: I_BIT_OP(RES, 3, ALU); break; // RES 3, (I* + n) + case 0x9F: I_BIT_OP(RES, 3, A); break; // RES 3, (I* + n) -> A + case 0xA0: I_BIT_OP(RES, 4, B); break; // RES 4, (I* + n) -> B + case 0xA1: I_BIT_OP(RES, 4, C); break; // RES 4, (I* + n) -> C + case 0xA2: I_BIT_OP(RES, 4, D); break; // RES 4, (I* + n) -> D + case 0xA3: I_BIT_OP(RES, 4, E); break; // RES 4, (I* + n) -> E + case 0xA4: I_BIT_OP(RES, 4, H); break; // RES 4, (I* + n) -> H + case 0xA5: I_BIT_OP(RES, 4, L); break; // RES 4, (I* + n) -> L + case 0xA6: I_BIT_OP(RES, 4, ALU); break; // RES 4, (I* + n) + case 0xA7: I_BIT_OP(RES, 4, A); break; // RES 4, (I* + n) -> A + case 0xA8: I_BIT_OP(RES, 5, B); break; // RES 5, (I* + n) -> B + case 0xA9: I_BIT_OP(RES, 5, C); break; // RES 5, (I* + n) -> C + case 0xAA: I_BIT_OP(RES, 5, D); break; // RES 5, (I* + n) -> D + case 0xAB: I_BIT_OP(RES, 5, E); break; // RES 5, (I* + n) -> E + case 0xAC: I_BIT_OP(RES, 5, H); break; // RES 5, (I* + n) -> H + case 0xAD: I_BIT_OP(RES, 5, L); break; // RES 5, (I* + n) -> L + case 0xAE: I_BIT_OP(RES, 5, ALU); break; // RES 5, (I* + n) + case 0xAF: I_BIT_OP(RES, 5, A); break; // RES 5, (I* + n) -> A + case 0xB0: I_BIT_OP(RES, 6, B); break; // RES 6, (I* + n) -> B + case 0xB1: I_BIT_OP(RES, 6, C); break; // RES 6, (I* + n) -> C + case 0xB2: I_BIT_OP(RES, 6, D); break; // RES 6, (I* + n) -> D + case 0xB3: I_BIT_OP(RES, 6, E); break; // RES 6, (I* + n) -> E + case 0xB4: I_BIT_OP(RES, 6, H); break; // RES 6, (I* + n) -> H + case 0xB5: I_BIT_OP(RES, 6, L); break; // RES 6, (I* + n) -> L + case 0xB6: I_BIT_OP(RES, 6, ALU); break; // RES 6, (I* + n) + case 0xB7: I_BIT_OP(RES, 6, A); break; // RES 6, (I* + n) -> A + case 0xB8: I_BIT_OP(RES, 7, B); break; // RES 7, (I* + n) -> B + case 0xB9: I_BIT_OP(RES, 7, C); break; // RES 7, (I* + n) -> C + case 0xBA: I_BIT_OP(RES, 7, D); break; // RES 7, (I* + n) -> D + case 0xBB: I_BIT_OP(RES, 7, E); break; // RES 7, (I* + n) -> E + case 0xBC: I_BIT_OP(RES, 7, H); break; // RES 7, (I* + n) -> H + case 0xBD: I_BIT_OP(RES, 7, L); break; // RES 7, (I* + n) -> L + case 0xBE: I_BIT_OP(RES, 7, ALU); break; // RES 7, (I* + n) + case 0xBF: I_BIT_OP(RES, 7, A); break; // RES 7, (I* + n) -> A + case 0xC0: I_BIT_OP(SET, 0, B); break; // SET 0, (I* + n) -> B + case 0xC1: I_BIT_OP(SET, 0, C); break; // SET 0, (I* + n) -> C + case 0xC2: I_BIT_OP(SET, 0, D); break; // SET 0, (I* + n) -> D + case 0xC3: I_BIT_OP(SET, 0, E); break; // SET 0, (I* + n) -> E + case 0xC4: I_BIT_OP(SET, 0, H); break; // SET 0, (I* + n) -> H + case 0xC5: I_BIT_OP(SET, 0, L); break; // SET 0, (I* + n) -> L + case 0xC6: I_BIT_OP(SET, 0, ALU); break; // SET 0, (I* + n) + case 0xC7: I_BIT_OP(SET, 0, A); break; // SET 0, (I* + n) -> A + case 0xC8: I_BIT_OP(SET, 1, B); break; // SET 1, (I* + n) -> B + case 0xC9: I_BIT_OP(SET, 1, C); break; // SET 1, (I* + n) -> C + case 0xCA: I_BIT_OP(SET, 1, D); break; // SET 1, (I* + n) -> D + case 0xCB: I_BIT_OP(SET, 1, E); break; // SET 1, (I* + n) -> E + case 0xCC: I_BIT_OP(SET, 1, H); break; // SET 1, (I* + n) -> H + case 0xCD: I_BIT_OP(SET, 1, L); break; // SET 1, (I* + n) -> L + case 0xCE: I_BIT_OP(SET, 1, ALU); break; // SET 1, (I* + n) + case 0xCF: I_BIT_OP(SET, 1, A); break; // SET 1, (I* + n) -> A + case 0xD0: I_BIT_OP(SET, 2, B); break; // SET 2, (I* + n) -> B + case 0xD1: I_BIT_OP(SET, 2, C); break; // SET 2, (I* + n) -> C + case 0xD2: I_BIT_OP(SET, 2, D); break; // SET 2, (I* + n) -> D + case 0xD3: I_BIT_OP(SET, 2, E); break; // SET 2, (I* + n) -> E + case 0xD4: I_BIT_OP(SET, 2, H); break; // SET 2, (I* + n) -> H + case 0xD5: I_BIT_OP(SET, 2, L); break; // SET 2, (I* + n) -> L + case 0xD6: I_BIT_OP(SET, 2, ALU); break; // SET 2, (I* + n) + case 0xD7: I_BIT_OP(SET, 2, A); break; // SET 2, (I* + n) -> A + case 0xD8: I_BIT_OP(SET, 3, B); break; // SET 3, (I* + n) -> B + case 0xD9: I_BIT_OP(SET, 3, C); break; // SET 3, (I* + n) -> C + case 0xDA: I_BIT_OP(SET, 3, D); break; // SET 3, (I* + n) -> D + case 0xDB: I_BIT_OP(SET, 3, E); break; // SET 3, (I* + n) -> E + case 0xDC: I_BIT_OP(SET, 3, H); break; // SET 3, (I* + n) -> H + case 0xDD: I_BIT_OP(SET, 3, L); break; // SET 3, (I* + n) -> L + case 0xDE: I_BIT_OP(SET, 3, ALU); break; // SET 3, (I* + n) + case 0xDF: I_BIT_OP(SET, 3, A); break; // SET 3, (I* + n) -> A + case 0xE0: I_BIT_OP(SET, 4, B); break; // SET 4, (I* + n) -> B + case 0xE1: I_BIT_OP(SET, 4, C); break; // SET 4, (I* + n) -> C + case 0xE2: I_BIT_OP(SET, 4, D); break; // SET 4, (I* + n) -> D + case 0xE3: I_BIT_OP(SET, 4, E); break; // SET 4, (I* + n) -> E + case 0xE4: I_BIT_OP(SET, 4, H); break; // SET 4, (I* + n) -> H + case 0xE5: I_BIT_OP(SET, 4, L); break; // SET 4, (I* + n) -> L + case 0xE6: I_BIT_OP(SET, 4, ALU); break; // SET 4, (I* + n) + case 0xE7: I_BIT_OP(SET, 4, A); break; // SET 4, (I* + n) -> A + case 0xE8: I_BIT_OP(SET, 5, B); break; // SET 5, (I* + n) -> B + case 0xE9: I_BIT_OP(SET, 5, C); break; // SET 5, (I* + n) -> C + case 0xEA: I_BIT_OP(SET, 5, D); break; // SET 5, (I* + n) -> D + case 0xEB: I_BIT_OP(SET, 5, E); break; // SET 5, (I* + n) -> E + case 0xEC: I_BIT_OP(SET, 5, H); break; // SET 5, (I* + n) -> H + case 0xED: I_BIT_OP(SET, 5, L); break; // SET 5, (I* + n) -> L + case 0xEE: I_BIT_OP(SET, 5, ALU); break; // SET 5, (I* + n) + case 0xEF: I_BIT_OP(SET, 5, A); break; // SET 5, (I* + n) -> A + case 0xF0: I_BIT_OP(SET, 6, B); break; // SET 6, (I* + n) -> B + case 0xF1: I_BIT_OP(SET, 6, C); break; // SET 6, (I* + n) -> C + case 0xF2: I_BIT_OP(SET, 6, D); break; // SET 6, (I* + n) -> D + case 0xF3: I_BIT_OP(SET, 6, E); break; // SET 6, (I* + n) -> E + case 0xF4: I_BIT_OP(SET, 6, H); break; // SET 6, (I* + n) -> H + case 0xF5: I_BIT_OP(SET, 6, L); break; // SET 6, (I* + n) -> L + case 0xF6: I_BIT_OP(SET, 6, ALU); break; // SET 6, (I* + n) + case 0xF7: I_BIT_OP(SET, 6, A); break; // SET 6, (I* + n) -> A + case 0xF8: I_BIT_OP(SET, 7, B); break; // SET 7, (I* + n) -> B + case 0xF9: I_BIT_OP(SET, 7, C); break; // SET 7, (I* + n) -> C + case 0xFA: I_BIT_OP(SET, 7, D); break; // SET 7, (I* + n) -> D + case 0xFB: I_BIT_OP(SET, 7, E); break; // SET 7, (I* + n) -> E + case 0xFC: I_BIT_OP(SET, 7, H); break; // SET 7, (I* + n) -> H + case 0xFD: I_BIT_OP(SET, 7, L); break; // SET 7, (I* + n) -> L + case 0xFE: I_BIT_OP(SET, 7, ALU); break; // SET 7, (I* + n) + case 0xFF: I_BIT_OP(SET, 7, A); break; // SET 7, (I* + n) -> A + } + } + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs new file mode 100644 index 0000000000..8dc1cd24ce --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs @@ -0,0 +1,123 @@ +using System; + +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + private bool iff1; + public bool IFF1 { get { return iff1; } set { iff1 = value; } } + + private bool iff2; + public bool IFF2 { get { return iff2; } set { iff2 = value; } } + + private bool nonMaskableInterrupt; + public bool NonMaskableInterrupt + { + get { return nonMaskableInterrupt; } + set { if (value && !nonMaskableInterrupt) NonMaskableInterruptPending = true; nonMaskableInterrupt = value; } + } + + private bool nonMaskableInterruptPending; + public bool NonMaskableInterruptPending { get { return nonMaskableInterruptPending; } set { nonMaskableInterruptPending = value; } } + + private int interruptMode; + public int InterruptMode + { + get { return interruptMode; } + set { if (value < 0 || value > 2) throw new ArgumentOutOfRangeException(); interruptMode = value; } + } + + public Action IRQCallback = delegate () { }; + public Action NMICallback = delegate () { }; + + private void NMI_() + { + cur_instr = new ushort[] + {IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCh, + IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCl, + IDLE, + ASGN, PCl, 0x66, + ASGN, PCh, 0, + IDLE, + OP }; + } + + // Mode 0 interrupts only take effect if a CALL or RST is on the data bus + // Otherwise operation just continues as normal + // For now assume a NOP is on the data bus, in which case no stack operations occur + + //NOTE: TODO: When a CALL is present on the data bus, adjust WZ accordingly + private void INTERRUPT_0(ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + OP }; + } + + // Just jump to $0038 + private void INTERRUPT_1() + { + cur_instr = new ushort[] + {DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, PCh, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, PCl, + IDLE, + ASGN, PCl, 0x38, + IDLE, + ASGN, PCh, 0, + IDLE, + OP }; + } + + // Interrupt mode 2 uses the I vector combined with a byte on the data bus + // Again for now we assume only a 0 on the data bus and jump to (0xI00) + private void INTERRUPT_2(ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCh, + IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCl, + IDLE, + ASGN, PCl, 0, + TR, PCh, I, + IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + TR16, PCl, PCh, Z, W, + OP }; + } + + private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60}; + + private void ResetInterrupts() + { + IFF1 = false; + IFF2 = false; + NonMaskableInterrupt = false; + NonMaskableInterruptPending = false; + FlagI = false; + InterruptMode = 1; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs similarity index 89% rename from BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs rename to BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index d5b9c2c4e1..596e0ff66d 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -1,114 +1,27 @@ -//http://www.zophar.net/fileuploads/2/10819kouzv/z80undoc.html - -//TODO: ex. (IX+00h) could be turned into (IX) - -//usage: -//VgMuseum.Z80.Disassembler disasm = new Disassembler(); -//ushort pc = RegPC.Word; -//string str = disasm.Disassemble(() => ReadMemory(pc++)); -//Console.WriteLine(str); - -//please note that however much youre tempted to, timings can't be put in a table here because they depend on how the instruction executes at runtime - -using System; +using System; using System.Collections.Generic; using BizHawk.Emulation.Common; -namespace BizHawk.Emulation.Cores.Components.Z80 +namespace BizHawk.Emulation.Cores.Components.Z80A { - public class Disassembler : IDisassemblable + public sealed partial class Z80A : IDisassemblable { - readonly static sbyte[,] opcodeSizes = new sbyte[7, 256]; - - public static void GenerateOpcodeSizes() - { - Disassembler disasm = new Disassembler(); - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[0, i] = (sbyte)pc; - } - - opcodeSizes[0, 0xCB] = -1; - opcodeSizes[0, 0xED] = -2; - opcodeSizes[0, 0xDD] = -3; - opcodeSizes[0, 0xFD] = -4; - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xCB, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[1, i] = (sbyte)pc; - } - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xED, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[2, i] = (sbyte)pc; - } - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xDD, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[3, i] = (sbyte)pc; - } - - opcodeSizes[3, 0xCB] = -5; - opcodeSizes[3, 0xED] = -2; - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xFD, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[4, i] = (sbyte)pc; - } - - opcodeSizes[3, 0xCB] = -6; - opcodeSizes[3, 0xED] = -2; - - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xDD, 0xCB, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[5, i] = (sbyte)pc; - } - - for (int i = 0; i < 256; i++) - { - int pc = 0; - byte[] opcode = { 0xFD, 0xCB, (byte)i, 0, 0, 0 }; - disasm.Disassemble(() => opcode[pc++]); - opcodeSizes[6, i] = (sbyte)pc; - } - } - - static string Result(string format, Func read) + static string Result(string format, Func read, ref ushort addr) { //d immediately succeeds the opcode //n immediate succeeds the opcode and the displacement (if present) //nn immediately succeeds the opcode and the displacement (if present) if (format.IndexOf("nn") != -1) { - byte B = read(); - byte C = read(); + byte B = read(addr++); + byte C = read(addr++); format = format.Replace("nn", string.Format("{0:X4}h", B + C * 256)); } if (format.IndexOf("n") != -1) { - byte B = read(); + byte B = read(addr++); format = format.Replace("n", string.Format("{0:X2}h", B)); } @@ -116,7 +29,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80 if (format.IndexOf("d") != -1) { - byte B = read(); + byte B = read(addr++); bool neg = ((B & 0x80) != 0); char sign = neg ? '-' : '+'; int val = neg ? 256 - B : B; @@ -480,46 +393,49 @@ namespace BizHawk.Emulation.Cores.Components.Z80 "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100 }; - string DisassembleInternal(Func read) + public string Disassemble(ushort addr, Func read, out ushort size) { - byte A = read(); + ushort start_addr = addr; + ushort extra_inc = 0; + byte A = read(addr++); string format; switch (A) { case 0xCB: - A = read(); + A = read(addr++); format = mnemonicsCB[A]; break; case 0xDD: - A = read(); + A = read(addr++); switch (A) { - case 0xCB: format = mnemonicsDDCB[A]; break; + case 0xCB: format = mnemonicsDDCB[A]; extra_inc = 1; break; case 0xED: format = mnemonicsED[A]; break; default: format = mnemonicsDD[A]; break; } break; case 0xED: - A = read(); + A = read(addr++); format = mnemonicsED[A]; break; case 0xFD: - A = read(); + A = read(addr++); switch (A) { - case 0xCB: format = mnemonicsFDCB[A]; break; + case 0xCB: format = mnemonicsFDCB[A]; extra_inc = 1; break; case 0xED: format = mnemonicsED[A]; break; default: format = mnemonicsFD[A]; break; } break; default: format = mnemonics[A]; break; } - return format; - } + + string temp = Result(format, read, ref addr); - public string Disassemble(Func read) - { - return Result(DisassembleInternal(read), read); + addr += extra_inc; + + size = (ushort)(addr - start_addr); + return temp; } #region IDisassemblable @@ -543,7 +459,8 @@ namespace BizHawk.Emulation.Cores.Components.Z80 public string Disassemble(MemoryDomain m, uint addr, out int length) { int loc = (int)addr; - string ret = Disassemble(() => m.PeekByte(loc++)); + ushort unused = 0; + string ret = Disassemble((ushort) addr, a => m.PeekByte(a), out unused); length = loc - (int)addr; return ret; } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs new file mode 100644 index 0000000000..cfaf517ec7 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs @@ -0,0 +1,742 @@ +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + public void Read_Func(ushort dest, ushort src_l, ushort src_h) + { + Regs[dest] = ReadMemory((ushort)(Regs[src_l] | (Regs[src_h]) << 8)); + } + + public void I_Read_Func(ushort dest, ushort src_l, ushort src_h, ushort inc) + { + Regs[dest] = ReadMemory((ushort)((Regs[src_l] | (Regs[src_h] << 8)) + inc)); + } + + public void Write_Func(ushort dest_l, ushort dest_h, ushort src) + { + WriteMemory((ushort)(Regs[dest_l] | (Regs[dest_h] << 8)), (byte)Regs[src]); + } + + public void I_Write_Func(ushort dest_l, ushort dest_h, ushort inc, ushort src) + { + WriteMemory((ushort)((Regs[dest_l] | (Regs[dest_h] << 8)) + inc), (byte)Regs[src]); + } + + public void OUT_Func(ushort dest, ushort src) + { + WriteHardware(Regs[dest], (byte)(Regs[src])); + } + + public void IN_Func(ushort dest, ushort src) + { + Regs[dest] = ReadHardware(Regs[src]); + } + + public void TR_Func(ushort dest, ushort src) + { + Regs[dest] = Regs[src]; + } + + public void TR16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + Regs[dest_l] = Regs[src_l]; + Regs[dest_h] = Regs[src_h]; + } + + public void ADD16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8); + int Reg16_s = Regs[src_l] | (Regs[src_h] << 8); + int temp = Reg16_d + Reg16_s; + + FlagC = temp.Bit(16); + FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF)) > 0xFFF; + FlagN = false; + Flag3 = (temp & 0x0800) != 0; + Flag5 = (temp & 0x2000) != 0; + + Regs[dest_l] = (ushort)(temp & 0xFF); + Regs[dest_h] = (ushort)((temp & 0xFF00) >> 8); + } + + public void ADD8_Func(ushort dest, ushort src) + { + int Reg16_d = Regs[dest]; + Reg16_d += Regs[src]; + + FlagC = Reg16_d.Bit(8); + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[dest] & 0xF; + Reg16_d += (Regs[src] & 0xF); + + FlagH = Reg16_d.Bit(4); + FlagN = false; + Flag3 = (ans & 0x08) != 0; + Flag5 = (ans & 0x20) != 0; + FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7)); + FlagS = ans > 127; + + Regs[dest] = ans; + } + + public void SUB8_Func(ushort dest, ushort src) + { + int Reg16_d = Regs[dest]; + Reg16_d -= Regs[src]; + + FlagC = Reg16_d.Bit(8); + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[dest] & 0xF; + Reg16_d -= (Regs[src] & 0xF); + + FlagH = Reg16_d.Bit(4); + FlagN = true; + Flag3 = (ans & 0x08) != 0; + Flag5 = (ans & 0x20) != 0; + FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7)); + FlagS = ans > 127; + + Regs[dest] = ans; + } + + public void BIT_Func(ushort bit, ushort src) + { + FlagZ = !Regs[src].Bit(bit); + FlagP = FlagZ; // special case + FlagH = true; + FlagN = false; + FlagS = ((bit == 7) && Regs[src].Bit(bit)); + Flag5 = Regs[src].Bit(5); + Flag3 = Regs[src].Bit(3); + } + + // When doing I* + n bit tests, flags 3 and 5 come from I* + n + // This cooresponds to the high byte of WZ + // This is the same for the (HL) bit tests, except that WZ were not assigned to before the test occurs + public void I_BIT_Func(ushort bit, ushort src) + { + FlagZ = !Regs[src].Bit(bit); + FlagP = FlagZ; // special case + FlagH = true; + FlagN = false; + FlagS = ((bit == 7) && Regs[src].Bit(bit)); + Flag5 = Regs[W].Bit(5); + Flag3 = Regs[W].Bit(3); + } + + public void SET_Func(ushort bit, ushort src) + { + Regs[src] |= (ushort)(1 << bit); + } + + public void RES_Func(ushort bit, ushort src) + { + Regs[src] &= (ushort)(0xFF - (1 << bit)); + } + + public void ASGN_Func(ushort src, ushort val) + { + Regs[src] = val; + } + + public void SLL_Func(ushort src) + { + FlagC = Regs[src].Bit(7); + + Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | 0x1); + + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void SLA_Func(ushort src) + { + FlagC = Regs[src].Bit(7); + + Regs[src] = (ushort)((Regs[src] << 1) & 0xFF); + + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void SRA_Func(ushort src) + { + FlagC = Regs[src].Bit(0); + + ushort temp = (ushort)(Regs[src] & 0x80); // MSB doesn't change in this operation + + Regs[src] = (ushort)((Regs[src] >> 1) | temp); + + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void SRL_Func(ushort src) + { + FlagC = Regs[src].Bit(0) ? true : false; + + Regs[src] = (ushort)(Regs[src] >> 1); + + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void CPL_Func(ushort src) + { + Regs[src] = (ushort)((~Regs[src]) & 0xFF); + + FlagH = true; + FlagN = true; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + } + + public void CCF_Func(ushort src) + { + FlagH = FlagC; + FlagC = !FlagC; + FlagN = false; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + } + + public void SCF_Func(ushort src) + { + FlagC = true; + FlagH = false; + FlagN = false; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + } + + public void AND8_Func(ushort dest, ushort src) + { + Regs[dest] = (ushort)(Regs[dest] & Regs[src]); + + FlagZ = Regs[dest] == 0; + FlagC = false; + FlagH = true; + FlagN = false; + Flag3 = (Regs[dest] & 0x08) != 0; + Flag5 = (Regs[dest] & 0x20) != 0; + FlagS = Regs[dest] > 127; + FlagP = TableParity[Regs[dest]]; + } + + public void OR8_Func(ushort dest, ushort src) + { + Regs[dest] = (ushort)(Regs[dest] | Regs[src]); + + FlagZ = Regs[dest] == 0; + FlagC = false; + FlagH = false; + FlagN = false; + Flag3 = (Regs[dest] & 0x08) != 0; + Flag5 = (Regs[dest] & 0x20) != 0; + FlagS = Regs[dest] > 127; + FlagP = TableParity[Regs[dest]]; + } + + public void XOR8_Func(ushort dest, ushort src) + { + Regs[dest] = (ushort)((Regs[dest] ^ Regs[src])); + + FlagZ = Regs[dest] == 0; + FlagC = false; + FlagH = false; + FlagN = false; + Flag3 = (Regs[dest] & 0x08) != 0; + Flag5 = (Regs[dest] & 0x20) != 0; + FlagS = Regs[dest] > 127; + FlagP = TableParity[Regs[dest]]; + } + + public void CP8_Func(ushort dest, ushort src) + { + int Reg16_d = Regs[dest]; + Reg16_d -= Regs[src]; + + FlagC = Reg16_d.Bit(8); + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[dest] & 0xF; + Reg16_d -= (Regs[src] & 0xF); + + FlagH = Reg16_d.Bit(4); + FlagN = true; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7)); + FlagS = ans > 127; + } + + public void RRC_Func(ushort src) + { + bool imm = src == Aim; + if (imm) { src = A; } + + FlagC = Regs[src].Bit(0); + + Regs[src] = (ushort)((FlagC ? 0x80 : 0) | (Regs[src] >> 1)); + + if (!imm) + { + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + } + + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void RR_Func(ushort src) + { + bool imm = src == Aim; + if (imm) { src = A; } + + ushort c = (ushort)(FlagC ? 0x80 : 0); + + FlagC = Regs[src].Bit(0); + + Regs[src] = (ushort)(c | (Regs[src] >> 1)); + + if (!imm) + { + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + } + + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void RLC_Func(ushort src) + { + bool imm = src == Aim; + if (imm) { src = A; } + + ushort c = (ushort)(Regs[src].Bit(7) ? 1 : 0); + FlagC = Regs[src].Bit(7); + + Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c); + + if (!imm) + { + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + } + + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void RL_Func(ushort src) + { + bool imm = src == Aim; + if (imm) { src = A; } + + ushort c = (ushort)(FlagC ? 1 : 0); + FlagC = Regs[src].Bit(7); + + Regs[src] = (ushort)(((Regs[src] << 1) & 0xFF) | c); + + if (!imm) + { + FlagS = Regs[src].Bit(7); + FlagZ = Regs[src] == 0; + FlagP = TableParity[Regs[src]]; + } + + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + FlagH = false; + FlagN = false; + } + + public void INC8_Func(ushort src) + { + int Reg16_d = Regs[src]; + Reg16_d += 1; + + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[src] & 0xF; + Reg16_d += 1; + + FlagH = Reg16_d.Bit(4); + FlagN = false; + + Regs[src] = ans; + + FlagS = Regs[src].Bit(7); + FlagP = Regs[src] == 0x80; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + } + + public void DEC8_Func(ushort src) + { + int Reg16_d = Regs[src]; + Reg16_d -= 1; + + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[src] & 0xF; + Reg16_d -= 1; + + FlagH = Reg16_d.Bit(4); + FlagN = true; + + Regs[src] = ans; + + FlagS = Regs[src].Bit(7); + FlagP = Regs[src] == 0x7F; + Flag3 = (Regs[src] & 0x08) != 0; + Flag5 = (Regs[src] & 0x20) != 0; + } + + public void INC16_Func(ushort src_l, ushort src_h) + { + int Reg16_d = Regs[src_l] | (Regs[src_h] << 8); + + Reg16_d += 1; + + Regs[src_l] = (ushort)(Reg16_d & 0xFF); + Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8); + } + + public void DEC16_Func(ushort src_l, ushort src_h) + { + int Reg16_d = Regs[src_l] | (Regs[src_h] << 8); + + Reg16_d -= 1; + + Regs[src_l] = (ushort)(Reg16_d & 0xFF); + Regs[src_h] = (ushort)((Reg16_d & 0xFF00) >> 8); + } + + public void ADC8_Func(ushort dest, ushort src) + { + int Reg16_d = Regs[dest]; + int c = FlagC ? 1 : 0; + + Reg16_d += (Regs[src] + c); + + FlagC = Reg16_d.Bit(8); + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[dest] & 0xF; + Reg16_d += ((Regs[src] & 0xF) + c); + + FlagH = Reg16_d.Bit(4); + FlagN = false; + Flag3 = (ans & 0x08) != 0; + Flag5 = (ans & 0x20) != 0; + FlagP = (Regs[dest].Bit(7) == Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7)); + FlagS = ans > 127; + + Regs[dest] = ans; + } + + public void SBC8_Func(ushort dest, ushort src) + { + int Reg16_d = Regs[dest]; + int c = FlagC ? 1 : 0; + + Reg16_d -= (Regs[src] + c); + + FlagC = Reg16_d.Bit(8); + FlagZ = (Reg16_d & 0xFF) == 0; + + ushort ans = (ushort)(Reg16_d & 0xFF); + + // redo for half carry flag + Reg16_d = Regs[dest] & 0xF; + Reg16_d -= ((Regs[src] & 0xF) + c); + + FlagH = Reg16_d.Bit(4); + FlagN = true; + Flag3 = (ans & 0x08) != 0; + Flag5 = (ans & 0x20) != 0; + FlagP = (Regs[dest].Bit(7) != Regs[src].Bit(7)) && (Regs[dest].Bit(7) != ans.Bit(7)); + FlagS = ans > 127; + + Regs[dest] = ans; + } + + public void DA_Func(ushort src) + { + byte a = (byte)Regs[src]; + byte temp = a; + + if (FlagN) + { + if (FlagH || ((a & 0x0F) > 0x09)) { temp -= 0x06; } + if (FlagC || a > 0x99) { temp -= 0x60; } + } + else + { + if (FlagH || ((a & 0x0F) > 0x09)) { temp += 0x06; } + if (FlagC || a > 0x99) { temp += 0x60; } + } + + temp &= 0xFF; + + FlagC = FlagC || a > 0x99; + FlagZ = temp == 0; + FlagH = ((a ^ temp) & 0x10) != 0; + FlagP = TableParity[temp]; + FlagS = temp > 127; + Flag3 = (temp & 0x08) != 0; + Flag5 = (temp & 0x20) != 0; + + Regs[src] = temp; + } + + // used for signed operations + public void ADDS_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + int Reg16_d = Regs[dest_l]; + int Reg16_s = Regs[src_l]; + + Reg16_d += Reg16_s; + + ushort temp = 0; + + // since this is signed addition, calculate the high byte carry appropriately + // note that flags are unaffected by this operation + if (Reg16_s.Bit(7)) + { + if (((Reg16_d & 0xFF) >= Regs[dest_l])) + { + temp = 0xFF; + } + else + { + temp = 0; + } + } + else + { + temp = (ushort)(Reg16_d.Bit(8) ? 1 : 0); + } + + ushort ans_l = (ushort)(Reg16_d & 0xFF); + + Regs[dest_l] = ans_l; + Regs[dest_h] += temp; + Regs[dest_h] &= 0xFF; + + } + + public void EXCH_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + ushort temp = Regs[dest_l]; + Regs[dest_l] = Regs[src_l]; + Regs[src_l] = temp; + + temp = Regs[dest_h]; + Regs[dest_h] = Regs[src_h]; + Regs[src_h] = temp; + } + + public void SBC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8); + int Reg16_s = Regs[src_l] | (Regs[src_h] << 8); + int c = FlagC ? 1 : 0; + + int ans = Reg16_d - Reg16_s - c; + + FlagN = true; + FlagC = ans.Bit(16); + FlagP = (Reg16_d.Bit(15) != Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15)); + FlagS = (ushort)(ans & 0xFFFF) > 32767; + FlagZ = (ans & 0xFFFF) == 0; + Flag3 = (ans & 0x0800) != 0; + Flag5 = (ans & 0x2000) != 0; + + // redo for half carry flag + Reg16_d &= 0xFFF; + Reg16_d -= ((Reg16_s & 0xFFF) + c); + + FlagH = Reg16_d.Bit(12); + + Regs[dest_l] = (ushort)(ans & 0xFF); + Regs[dest_h] = (ushort)((ans >> 8) & 0xFF); + } + + public void ADC_16_Func(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + int Reg16_d = Regs[dest_l] | (Regs[dest_h] << 8); + int Reg16_s = Regs[src_l] | (Regs[src_h] << 8); + + int ans = Reg16_d + Reg16_s + (FlagC ? 1 : 0); + + FlagH = ((Reg16_d & 0xFFF) + (Reg16_s & 0xFFF) + (FlagC ? 1 : 0)) > 0xFFF; + FlagN = false; + FlagC = ans.Bit(16); + FlagP = (Reg16_d.Bit(15) == Reg16_s.Bit(15)) && (Reg16_d.Bit(15) != ans.Bit(15)); + FlagS = (ans & 0xFFFF) > 32767; + FlagZ = (ans & 0xFFFF) == 0; + Flag3 = (ans & 0x0800) != 0; + Flag5 = (ans & 0x2000) != 0; + + Regs[dest_l] = (ushort)(ans & 0xFF); + Regs[dest_h] = (ushort)((ans >> 8) & 0xFF); + } + + public void NEG_8_Func(ushort src) + { + int Reg16_d = 0; + Reg16_d -= Regs[src]; + + FlagC = Regs[src] != 0x0; + FlagZ = (Reg16_d & 0xFF) == 0; + FlagP = Regs[src] == 0x80; + FlagS = (Reg16_d & 0xFF) > 127; + + ushort ans = (ushort)(Reg16_d & 0xFF); + // redo for half carry flag + Reg16_d = 0; + Reg16_d -= (Regs[src] & 0xF); + FlagH = Reg16_d.Bit(4); + Regs[src] = ans; + FlagN = true; + Flag3 = (ans & 0x08) != 0; + Flag5 = (ans & 0x20) != 0; + } + + public void RRD_Func(ushort dest, ushort src) + { + ushort temp1 = Regs[src]; + ushort temp2 = Regs[dest]; + Regs[dest] = (ushort)(((temp1 & 0x0F) << 4) + ((temp2 & 0xF0) >> 4)); + Regs[src] = (ushort)((temp1 & 0xF0) + (temp2 & 0x0F)); + + temp1 = Regs[src]; + FlagS = temp1 > 127; + FlagZ = temp1 == 0; + FlagH = false; + FlagP = TableParity[temp1]; + FlagN = false; + Flag3 = (temp1 & 0x08) != 0; + Flag5 = (temp1 & 0x20) != 0; + } + + public void RLD_Func(ushort dest, ushort src) + { + ushort temp1 = Regs[src]; + ushort temp2 = Regs[dest]; + Regs[dest] = (ushort)((temp1 & 0x0F) + ((temp2 & 0x0F) << 4)); + Regs[src] = (ushort)((temp1 & 0xF0) + ((temp2 & 0xF0) >> 4)); + + temp1 = Regs[src]; + FlagS = temp1 > 127; + FlagZ = temp1 == 0; + FlagH = false; + FlagP = TableParity[temp1]; + FlagN = false; + Flag3 = (temp1 & 0x08) != 0; + Flag5 = (temp1 & 0x20) != 0; + } + + // sets flags for LD/R + public void SET_FL_LD_Func() + { + FlagP = (Regs[C] | (Regs[B] << 8)) != 0; + FlagH = false; + FlagN = false; + Flag5 = ((Regs[ALU] + Regs[A]) & 0x02) != 0; + Flag3 = ((Regs[ALU] + Regs[A]) & 0x08) != 0; + } + + // set flags for CP/R + public void SET_FL_CP_Func() + { + int Reg8_d = Regs[A]; + int Reg8_s = Regs[ALU]; + + // get half carry flag + byte temp = (byte)((Reg8_d & 0xF) - (Reg8_s & 0xF)); + FlagH = temp.Bit(4); + + temp = (byte)(Reg8_d - Reg8_s); + FlagN = true; + FlagZ = temp == 0; + FlagS = temp > 127; + FlagP = (Regs[C] | (Regs[B] << 8)) != 0; + + temp = (byte)(Reg8_d - Reg8_s - (FlagH ? 1 : 0)); + Flag5 = (temp & 0x02) != 0; + Flag3 = (temp & 0x08) != 0; + } + + // set flags for LD A, I/R + public void SET_FL_IR_Func(ushort dest) + { + if (dest == A) + { + FlagN = false; + FlagH = false; + FlagZ = Regs[A] == 0; + FlagS = Regs[A] > 127; + FlagP = iff2; + Flag5 = (Regs[A] & 0x02) != 0; + Flag3 = (Regs[A] & 0x08) != 0; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/ReadMe.txt b/BizHawk.Emulation.Cores/CPUs/Z80A/ReadMe.txt new file mode 100644 index 0000000000..d11f79b637 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/ReadMe.txt @@ -0,0 +1,8 @@ +TODO: + +Mode 0 and 2 interrupts +Check T-cycle level memory access timing +Check R register +new tests for WZ Registers +Memory refresh - IR is pushed onto the address bus at instruction start, does anything need this? +Data Bus - For mode zero and 2 interrupts, need a system that uses it to test diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs new file mode 100644 index 0000000000..628243c19e --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs @@ -0,0 +1,132 @@ +using System.Runtime.InteropServices; +using System; + +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + // registers + // note these are not constants. When shadows are used, they will be changed accordingly + public ushort PCl = 0; + public ushort PCh = 1; + public ushort SPl = 2; + public ushort SPh = 3; + public ushort A = 4; + public ushort F = 5; + public ushort B = 6; + public ushort C = 7; + public ushort D = 8; + public ushort E = 9; + public ushort H = 10; + public ushort L = 11; + public ushort W = 12; + public ushort Z = 13; + public ushort Aim = 14; // use this indicator for RLCA etc., since the Z flag is reset on those + public ushort Ixl = 15; + public ushort Ixh = 16; + public ushort Iyl = 17; + public ushort Iyh = 18; + public ushort Int = 19; + public ushort R = 20; + public ushort I = 21; + public ushort ZERO = 22; // it is convenient to have a register that is always zero, to reuse instructions + public ushort ALU = 23; // This will be temporary arthimatic storage + // shadow registers + public ushort A_s = 24; + public ushort F_s = 25; + public ushort B_s = 26; + public ushort C_s = 27; + public ushort D_s = 28; + public ushort E_s = 29; + public ushort H_s = 30; + public ushort L_s = 31; + + public ushort[] Regs = new ushort[36]; + + public bool FlagI; + + public bool FlagC + { + get { return (Regs[5] & 0x01) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x01) | (value ? 0x01 : 0x00)); } + } + + public bool FlagN + { + get { return (Regs[5] & 0x02) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x02) | (value ? 0x02 : 0x00)); } + } + + public bool FlagP + { + get { return (Regs[5] & 0x04) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x04) | (value ? 0x04 : 0x00)); } + } + + public bool Flag3 + { + get { return (Regs[5] & 0x08) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x08) | (value ? 0x08 : 0x00)); } + } + + public bool FlagH + { + get { return (Regs[5] & 0x10) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x10) | (value ? 0x10 : 0x00)); } + } + + public bool Flag5 + { + get { return (Regs[5] & 0x20) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x20) | (value ? 0x20 : 0x00)); } + } + + public bool FlagZ + { + get { return (Regs[5] & 0x40) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x40) | (value ? 0x40 : 0x00)); } + } + + public bool FlagS + { + get { return (Regs[5] & 0x80) != 0; } + set { Regs[5] = (ushort)((Regs[5] & ~0x80) | (value ? 0x80 : 0x00)); } + } + + public ushort RegPC + { + get { return (ushort)(Regs[0] | (Regs[1] << 8)); } + set + { + Regs[0] = (ushort)(value & 0xFF); + Regs[1] = (ushort)((value >> 8) & 0xFF); + } + } + + private void ResetRegisters() + { + for (int i=0; i < 36; i++) + { + Regs[i] = 0; + } + } + + private bool[] TableParity; + private void InitTableParity() + { + TableParity = new bool[256]; + for (int i = 0; i < 256; ++i) + { + int Bits = 0; + for (int j = 0; j < 8; ++j) + { + Bits += (i >> j) & 1; + } + TableParity[i] = (Bits & 1) == 0; + } + } + + + + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs new file mode 100644 index 0000000000..71b39d6018 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -0,0 +1,572 @@ +using System; + +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + // this contains the vectors of instrcution operations + // NOTE: This list is NOT confirmed accurate for each individual cycle + + private void NOP_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + OP }; + } + + // NOTE: In a real Z80, this operation just flips a switch to choose between 2 registers + // but it's simpler to emulate just by exchanging the register with it's shadow + private void EXCH_() + { + cur_instr = new ushort[] + {EXCH, + IDLE, + IDLE, + OP }; + } + + private void EXX_() + { + cur_instr = new ushort[] + {EXX, + IDLE, + IDLE, + OP }; + } + + // this exchanges 2 16 bit registers + private void EXCH_16_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {EXCH_16, dest_l, dest_h, src_l, src_h, + IDLE, + IDLE, + OP }; + } + + private void INC_16(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + INC16, src_l, src_h, + IDLE, + OP }; + } + + + private void DEC_16(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + DEC16, src_l, src_h, + IDLE, + IDLE, + OP }; + } + + // this is done in two steps technically, but the flags don't work out using existing funcitons + // so let's use a different function since it's an internal operation anyway + private void ADD_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + TR16, Z, W, dest_l, dest_h, + INC16, Z, W, + IDLE, + IDLE, + ADD16, dest_l, dest_h, src_l, src_h, + IDLE, + IDLE, + OP }; + } + + private void REG_OP(ushort operation, ushort dest, ushort src) + { + cur_instr = new ushort[] + {operation, dest, src, + IDLE, + IDLE, + OP }; + } + + // Operations using the I and R registers take one T-cycle longer + private void REG_OP_IR(ushort operation, ushort dest, ushort src) + { + cur_instr = new ushort[] + {operation, dest, src, + IDLE, + IDLE, + SET_FL_IR, dest, + OP }; + } + + // note: do not use DEC here since no flags are affected by this operation + private void DJNZ_() + { + if ((Regs[B] - 1) != 0) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + ASGN, B, (ushort)((Regs[B] - 1) & 0xFF), + IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + ASGN, W, 0, + IDLE, + ADDS, PCl, PCh, Z, W, + TR16, Z, W, PCl, PCh, + OP }; + } + else + { + cur_instr = new ushort[] + {IDLE, + ASGN, B, (ushort)((Regs[B] - 1) & 0xFF), + IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + OP }; + } + } + + private void HALT_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + HALT }; + } + + private void JR_COND(bool cond) + { + if (cond) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + IDLE, + IDLE, + ASGN, W, 0, + IDLE, + ADDS, PCl, PCh, Z, W, + TR16, Z, W, PCl, PCh, + IDLE, + OP }; + } + else + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + OP }; + } + } + + private void JP_COND(bool cond) + { + if (cond) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + TR16, PCl, PCh, Z, W, + IDLE, + OP }; + } + else + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + INC16, PCl, PCh, + IDLE, + IDLE, + OP }; + } + } + + private void RET_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, SPl, SPh, + INC16, SPl, SPh, + IDLE, + IDLE, + RD, W, SPl, SPh, + INC16, SPl, SPh, + TR16, PCl, PCh, Z, W, + OP }; + } + + private void RETI_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, SPl, SPh, + INC16, SPl, SPh, + IDLE, + IDLE, + RD, W, SPl, SPh, + INC16, SPl, SPh, + TR16, PCl, PCh, Z, W, + OP }; + } + + private void RETN_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, SPl, SPh, + INC16, SPl, SPh, + IDLE, + RD, W, SPl, SPh, + INC16, SPl, SPh, + EI_RETN, + TR16, PCl, PCh, Z, W, + OP }; + } + + + private void RET_COND(bool cond) + { + if (cond) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, SPl, SPh, + INC16, SPl, SPh, + IDLE, + IDLE, + RD, W, SPl, SPh, + INC16, SPl, SPh, + IDLE, + TR16, PCl, PCh, Z, W, + OP }; + } + else + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + IDLE, + OP }; + } + } + + private void CALL_COND(bool cond) + { + if (cond) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + INC16, PCl, PCh, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, PCh, + DEC16, SPl, SPh, + WR, SPl, SPh, PCl, + IDLE, + TR, PCl, Z, + TR, PCh, W, + OP }; + } + else + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + OP }; + } + } + + private void INT_OP(ushort operation, ushort src) + { + cur_instr = new ushort[] + {operation, src, + IDLE, + IDLE, + OP }; + } + + private void BIT_OP(ushort operation, ushort bit, ushort src) + { + cur_instr = new ushort[] + {operation, bit, src, + IDLE, + IDLE, + OP }; + } + + private void PUSH_(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, src_h, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, src_l, + IDLE, + OP }; + } + + + private void POP_(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + RD, src_l, SPl, SPh, + IDLE, + INC16, SPl, SPh, + IDLE, + RD, src_h, SPl, SPh, + IDLE, + INC16, SPl, SPh, + IDLE, + OP }; + } + + private void RST_(ushort n) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + DEC16, SPl, SPh, + WR, SPl, SPh, PCh, + DEC16, SPl, SPh, + WR, SPl, SPh, PCl, + IDLE, + ASGN, Z, n, + ASGN, W, 0, + TR16, PCl, PCh, Z, W, + OP }; + } + + private void PREFIX_(ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + PREFIX, src}; + } + + private void PREFETCH_(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {TR16, Z, W, src_l, src_h, + ADDS, Z, W, ALU, ZERO, + IDLE, + PREFIX, IXYprefetch }; + } + + private void DI_() + { + cur_instr = new ushort[] + {DI, + IDLE, + IDLE, + OP }; + } + + private void EI_() + { + cur_instr = new ushort[] + {EI, + IDLE, + IDLE, + OP }; + } + + private void JP_16(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {TR, PCl, src_l, + IDLE, + TR, PCh, src_h, + OP }; + } + + private void LD_SP_16(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + TR, SPl, src_l, + TR, SPh, src_h, + IDLE, + OP }; + } + + private void OUT_() + { + cur_instr = new ushort[] + {IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + TR, W, A, + OUT, ALU, A, + TR, Z, ALU, + INC16, Z, ALU, + IDLE, + IDLE, + OP}; + } + + private void OUT_REG_(ushort dest, ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + OUT, dest, src, + IDLE, + TR16, Z, W, C, B, + INC16, Z, W, + IDLE, + OP}; + } + + private void IN_() + { + cur_instr = new ushort[] + {IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + TR, W, A, + IN, A, ALU, + TR, Z, ALU, + INC16, Z, W, + IDLE, + IDLE, + OP}; + } + + private void IN_REG_(ushort dest, ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IN, dest, src, + IDLE, + TR16, Z, W, C, B, + INC16, Z, W, + IDLE, + OP}; + } + + private void REG_OP_16_(ushort op, ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + TR16, Z, W, dest_l, dest_h, + INC16, Z, W, + IDLE, + IDLE, + op, dest_l, dest_h, src_l, src_h, + IDLE, + IDLE, + OP}; + } + + private void INT_MODE_(ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + INT_MODE, src, + OP }; + } + + private void RRD_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + TR16, Z, W, L, H, + IDLE, + RD, ALU, Z, W, + IDLE, + RRD, ALU, A, + IDLE, + WR, Z, W, ALU, + IDLE, + INC16, Z, W, + IDLE, + IDLE, + OP }; + } + + private void RLD_() + { + cur_instr = new ushort[] + {IDLE, + IDLE, + TR16, Z, W, L, H, + IDLE, + RD, ALU, Z, W, + IDLE, + RLD, ALU, A, + IDLE, + WR, Z, W, ALU, + IDLE, + INC16, Z, W, + IDLE, + IDLE, + OP }; + } + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs new file mode 100644 index 0000000000..4a1c46cc03 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs @@ -0,0 +1,478 @@ +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public partial class Z80A + { + private void INT_OP_IND(ushort operation, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + operation, ALU, + IDLE, + WR, src_l, src_h, ALU, + IDLE, + IDLE, + OP }; + } + + private void BIT_OP_IND(ushort operation, ushort bit, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + operation, bit, ALU, + IDLE, + WR, src_l, src_h, ALU, + IDLE, + IDLE, + OP }; + } + + // Note that this operation uses I_BIT, same as indexed BIT. + // This is where the strange behaviour in Flag bits 3 and 5 come from. + // normally WZ contain I* + n when doing I_BIT ops, but here we use that code path + // even though WZ is not assigned to, letting it's value from other operations show through + private void BIT_TE_IND(ushort operation, ushort bit, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + I_BIT, bit, ALU, + IDLE, + OP }; + } + + private void REG_OP_IND_INC(ushort operation, ushort dest, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + operation, dest, ALU, + INC16, src_l, src_h, + OP }; + } + + private void REG_OP_IND(ushort operation, ushort dest, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + TR16, Z, W, src_l, src_h, + RD, ALU, Z, W, + INC16, Z, W, + operation, dest, ALU, + OP }; + } + + private void LD_16_IND_nn(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + WR, Z, W, src_l, + IDLE, + INC16, Z, W, + IDLE, + WR, Z, W, src_h, + IDLE, + OP }; + } + + private void LD_IND_16_nn(ushort dest_l, ushort dest_h) + { + cur_instr = new ushort[] + {IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, dest_l, Z, W, + IDLE, + INC16, Z, W, + IDLE, + RD, dest_h, Z, W, + IDLE, + OP }; + } + + private void LD_8_IND_nn(ushort src) + { + cur_instr = new ushort[] + {IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + WR, Z, W, src, + INC16, Z, W, + TR, W, A, + OP }; + } + + private void LD_IND_8_nn(ushort dest) + { + cur_instr = new ushort[] + {IDLE, + RD, Z, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + RD, dest, Z, W, + IDLE, + INC16, Z, W, + OP }; + } + + private void LD_8_IND(ushort dest_l, ushort dest_h, ushort src) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + TR16, Z, W, dest_l, dest_h, + WR, Z, W, src, + INC16, Z, W, + TR, W, A, + OP }; + } + + private void LD_8_IND_IND(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + INC16, src_l, src_h, + IDLE, + WR, dest_l, dest_h, ALU, + IDLE, + OP }; + } + + private void LD_IND_8_INC(ushort dest, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, dest, src_l, src_h, + IDLE, + INC16, src_l, src_h, + OP }; + } + + private void LD_IND_8_DEC(ushort dest, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, dest, src_l, src_h, + IDLE, + DEC16, src_l, src_h, + IDLE, + OP }; + } + + private void LD_IND_16(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, dest_l, src_l, src_h, + IDLE, + INC16, src_l, src_h, + RD, dest_h, src_l, src_h, + IDLE, + INC16, src_l, src_h, + OP }; + } + + private void INC_8_IND(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + INC8, ALU, + IDLE, + WR, src_l, src_h, ALU, + IDLE, + IDLE, + OP }; + } + + private void DEC_8_IND(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, src_l, src_h, + IDLE, + DEC8, ALU, + IDLE, + WR, src_l, src_h, ALU, + IDLE, + IDLE, + OP }; + } + + // NOTE: WZ implied for the wollowing 3 functions + private void I_INT_OP(ushort operation, ushort dest) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, Z, W, + IDLE, + operation, ALU, + IDLE, + WR, Z, W, ALU, + IDLE, + TR, dest, ALU, + IDLE, + OP }; + } + + private void I_BIT_OP(ushort operation, ushort bit, ushort dest) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, Z, W, + IDLE, + operation, bit, ALU, + IDLE, + WR, Z, W, ALU, + IDLE, + TR, dest, ALU, + IDLE, + OP }; + } + + private void I_BIT_TE(ushort bit) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + RD, ALU, Z, W, + IDLE, + I_BIT, bit, ALU, + IDLE, + OP }; + } + + private void I_OP_n(ushort operation, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, PCl, PCh, + INC16, PCl, PCh, + IDLE, + TR16, Z, W, src_l, src_h, + IDLE, + ADDS, Z, W, ALU, ZERO, + IDLE, + RD, ALU, Z, W, + IDLE, + IDLE, + operation, ALU, + IDLE, + IDLE, + IDLE, + WR, Z, W, ALU, + IDLE, + OP }; + } + + private void I_OP_n_n(ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, PCl, PCh, + INC16, PCl, PCh, + IDLE, + TR16, Z, W, src_l, src_h, + IDLE, + ADDS, Z, W, ALU, ZERO, + IDLE, + RD, ALU, PCl, PCh, + INC16, PCl, PCh, + IDLE, + WR, Z, W, ALU, + IDLE, + OP }; + } + + private void I_REG_OP_IND_n(ushort operation, ushort dest, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + TR16, Z, W, src_l, src_h, + IDLE, + ADDS, Z, W, ALU, ZERO, + IDLE, + RD, ALU, Z, W, + IDLE, + operation, dest, ALU, + IDLE, + OP }; + } + + private void I_LD_8_IND_n(ushort dest_l, ushort dest_h, ushort src) + { + cur_instr = new ushort[] + {IDLE, + RD, ALU, PCl, PCh, + IDLE, + INC16, PCl, PCh, + IDLE, + TR16, Z, W, dest_l, dest_h, + IDLE, + ADDS, Z, W, ALU, ZERO, + IDLE, + WR, Z, W, src, + IDLE, + IDLE, + IDLE, + IDLE, + OP }; + } + + private void LD_OP_R(ushort operation, ushort repeat_instr) + { + cur_instr = new ushort[] + {RD, ALU, L, H, + IDLE, + WR, E, D, ALU, + IDLE, + operation, L, H, + IDLE, + operation, E, D, + IDLE, + DEC16, C, B, + SET_FL_LD, + IDLE, + OP_R, 0, operation, repeat_instr }; + } + + private void CP_OP_R(ushort operation, ushort repeat_instr) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, ALU, L, H, + operation, L, H, + IDLE, + IDLE, + DEC16, C, B, + SET_FL_CP, + IDLE, + operation, Z, W, + IDLE, + OP_R, 1, operation, repeat_instr }; + } + + private void IN_OP_R(ushort operation, ushort repeat_instr) + { + cur_instr = new ushort[] + {IN, ALU, C, + IDLE, + WR, L, H, ALU, + IDLE, + operation, L, H, + IDLE, + TR16, Z, W, C, B, + operation, Z, W, + IDLE, + DEC8, B, + IDLE, + OP_R, 2, operation, repeat_instr }; + } + + private void OUT_OP_R(ushort operation, ushort repeat_instr) + { + cur_instr = new ushort[] + {RD, ALU, L, H, + IDLE, + OUT, C, ALU, + IDLE, + IDLE, + operation, L, H, + DEC8, B, + IDLE, + TR16, Z, W, C, B, + operation, Z, W, + IDLE, + OP_R, 3, operation, repeat_instr }; + } + + // this is an indirect change of a a 16 bit register with memory + private void EXCH_16_IND_(ushort dest_l, ushort dest_h, ushort src_l, ushort src_h) + { + cur_instr = new ushort[] + {IDLE, + IDLE, + RD, Z, dest_l, dest_h, + IDLE, + IDLE, + I_RD, W, dest_l, dest_h, 1, + IDLE, + IDLE, + WR, dest_l, dest_h, src_l, + IDLE, + IDLE, + I_WR, dest_l, dest_h, 1, src_h, + IDLE, + IDLE, + TR16, src_l, src_h, Z, W, + IDLE, + IDLE, + IDLE, + OP }; + } + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs new file mode 100644 index 0000000000..2f13b0e6c7 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -0,0 +1,687 @@ +using System; +using System.Globalization; +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Common.NumberExtensions; + +// Z80A CPU +namespace BizHawk.Emulation.Cores.Components.Z80A +{ + public sealed partial class Z80A + { + // operations that can take place in an instruction + public const ushort IDLE = 0; + public const ushort OP = 1; + public const ushort OP_R = 2; // used for repeating operations + public const ushort HALT = 3; + public const ushort RD = 4; + public const ushort WR = 5; + public const ushort I_RD = 6; + public const ushort I_WR = 7; + public const ushort TR = 8; + public const ushort TR16 = 9; + public const ushort ADD16 = 10; + public const ushort ADD8 = 11; + public const ushort SUB8 = 12; + public const ushort ADC8 = 13; + public const ushort SBC8 = 14; + public const ushort SBC16 = 15; + public const ushort ADC16 = 16; + public const ushort INC16 = 17; + public const ushort INC8 = 18; + public const ushort DEC16 = 19; + public const ushort DEC8 = 20; + public const ushort RLC = 21; + public const ushort RL = 22; + public const ushort RRC = 23; + public const ushort RR = 24; + public const ushort CPL = 25; + public const ushort DA = 26; + public const ushort SCF = 27; + public const ushort CCF = 28; + public const ushort AND8 = 29; + public const ushort XOR8 = 30; + public const ushort OR8 = 31; + public const ushort CP8 = 32; + public const ushort SLA = 33; + public const ushort SRA = 34; + public const ushort SRL = 35; + public const ushort SLL = 36; + public const ushort BIT = 37; + public const ushort RES = 38; + public const ushort SET = 39; + public const ushort EI = 40; + public const ushort DI = 41; + public const ushort EXCH = 42; + public const ushort EXX = 43; + public const ushort EXCH_16 = 44; + public const ushort PREFIX = 45; + public const ushort PREFETCH = 46; + public const ushort ASGN = 47; + public const ushort ADDS = 48; // signed 16 bit operation used in 2 instructions + public const ushort INT_MODE = 49; + public const ushort EI_RETN = 50; + public const ushort EI_RETI = 51; // reti has no delay in interrupt enable + public const ushort OUT = 52; + public const ushort IN = 53; + public const ushort NEG = 54; + public const ushort RRD = 55; + public const ushort RLD = 56; + public const ushort SET_FL_LD = 57; + public const ushort SET_FL_CP = 58; + public const ushort SET_FL_IR = 59; + public const ushort I_BIT = 60; + public const ushort HL_BIT = 61; + + public byte temp_R; + + public Z80A() + { + Reset(); + InitTableParity(); + } + + public void Reset() + { + ResetRegisters(); + ResetInterrupts(); + TotalExecutedCycles = 0; + cur_instr = new ushort[] { OP }; + NO_prefix = true; + } + + public IMemoryCallbackSystem MemoryCallbacks { get; set; } + + // Memory Access + public Func FetchMemory; + public Func ReadMemory; + public Action WriteMemory; + public Func PeekMemory; + public Func DummyReadMemory; + + // Hardware I/O Port Access + public Func ReadHardware; + public Action WriteHardware; + + //this only calls when the first byte of an instruction is fetched. + public Action OnExecFetch; + + public void UnregisterMemoryMapper() + { + ReadMemory = null; + WriteMemory = null; + PeekMemory = null; + DummyReadMemory = null; + ReadHardware = null; + WriteHardware = null; + } + + public void SetCallbacks + ( + Func ReadMemory, + Func DummyReadMemory, + Func PeekMemory, + Action WriteMemory, + Func ReadHardware, + Action WriteHardware + ) + { + this.ReadMemory = ReadMemory; + this.DummyReadMemory = DummyReadMemory; + this.PeekMemory = PeekMemory; + this.WriteMemory = WriteMemory; + this.ReadHardware = ReadHardware; + this.WriteHardware = WriteHardware; + } + + // Execute instructions + public void ExecuteOne() + { + if (Regs[A] > 255) { Console.WriteLine(RegPC); } + switch (cur_instr[instr_pntr++]) + { + case IDLE: + // do nothing + break; + case OP: + // Read the opcode of the next instruction + if (EI_pending > 0) + { + EI_pending--; + if (EI_pending == 0) { IFF1 = IFF2 = true; } + } + + // Process interrupt requests. + if (nonMaskableInterruptPending) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + } + else if (iff1 && FlagI) + { + iff1 = iff2 = false; + EI_pending = 0; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); + } + + switch (interruptMode) + { + case 0: + // Requires something to be pushed onto the data bus + // we'll assume it's a zero for now + INTERRUPT_0(0); + break; + case 1: + INTERRUPT_1(); + break; + case 2: + // Low byte of interrupt vector comes from data bus + // We'll assume it's zero for now + INTERRUPT_2(0); + break; + } + IRQCallback(); + } + else + { + if (OnExecFetch != null) OnExecFetch(RegPC); + if (TraceCallback != null) TraceCallback(State()); + FetchInstruction(ReadMemory(RegPC++)); + } + instr_pntr = 0; + + temp_R = (byte)(Regs[R] & 0x7F); + temp_R++; + temp_R &= 0x7F; + Regs[R] = (byte)((Regs[R] & 0x80) | temp_R); + break; + case OP_R: + // determine if we repeat based on what operation we are doing + // single execution versions also come here, but never repeat + ushort temp1 = cur_instr[instr_pntr++]; + ushort temp2 = cur_instr[instr_pntr++]; + ushort temp3 = cur_instr[instr_pntr++]; + + bool repeat = false; + int Reg16_d = Regs[C] | (Regs[B] << 8); + switch (temp1) + { + case 0: + repeat = Reg16_d != 0; + break; + case 1: + repeat = (Reg16_d != 0) && !FlagZ; + break; + case 2: + repeat = Regs[B] != 0; + break; + case 3: + repeat = Regs[B] != 0; + break; + } + + // if we repeat, we do a 5 cycle refresh which decrements PC by 2 + // if we don't repeat, continue on as a normal opcode fetch + if (repeat && temp3 > 0) + { + cur_instr = new ushort[] + {IDLE, + DEC16, PCl, PCh, + IDLE, + DEC16, PCl, PCh, + OP }; + + // adjust WZ register accordingly + switch (temp1) + { + case 0: + // TEST: PC before or after the instruction? + Regs[Z] = Regs[PCl]; + Regs[W] = Regs[PCh]; + INC16_Func(Z, W); + break; + case 1: + // TEST: PC before or after the instruction? + Regs[Z] = Regs[PCl]; + Regs[W] = Regs[PCh]; + INC16_Func(Z, W); + break; + case 2: + // Nothing + break; + case 3: + // Nothing + break; + } + } + else + { + // Interrupts can occur at this point, so process them accordingly + // Read the opcode of the next instruction + if (EI_pending > 0) + { + EI_pending--; + if (EI_pending == 0) { IFF1 = IFF2 = true; } + } + + // Process interrupt requests. + if (nonMaskableInterruptPending) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + } + else if (iff1 && FlagI) + { + iff1 = iff2 = false; + EI_pending = 0; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); + } + + switch (interruptMode) + { + case 0: + // Requires something to be pushed onto the data bus + // we'll assume it's a zero for now + INTERRUPT_0(0); + break; + case 1: + INTERRUPT_1(); + break; + case 2: + // Low byte of interrupt vector comes from data bus + // We'll assume it's zero for now + INTERRUPT_2(0); + break; + } + IRQCallback(); + } + else + { + if (OnExecFetch != null) OnExecFetch(RegPC); + if (TraceCallback != null) TraceCallback(State()); + FetchInstruction(ReadMemory(RegPC++)); + } + + temp_R = (byte)(Regs[R] & 0x7F); + temp_R++; + temp_R &= 0x7F; + Regs[R] = (byte)((Regs[R] & 0x80) | temp_R); + } + instr_pntr = 0; + break; + + case HALT: + halted = true; + if (EI_pending > 0) + { + EI_pending--; + if (EI_pending == 0) { IFF1 = IFF2 = true; } + } + + // Process interrupt requests. + if (nonMaskableInterruptPending) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + halted = false; + } + else if (iff1 && FlagI) + { + iff1 = iff2 = false; + EI_pending = 0; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); + } + + switch (interruptMode) + { + case 0: + // Requires something to be pushed onto the data bus + // we'll assume it's a zero for now + INTERRUPT_0(0); + break; + case 1: + INTERRUPT_1(); + break; + case 2: + // Low byte of interrupt vector comes from data bus + // We'll assume it's zero for now + INTERRUPT_2(0); + break; + } + IRQCallback(); + halted = false; + } + else + { + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + HALT }; + } + temp_R = (byte)(Regs[R] & 0x7F); + temp_R++; + temp_R &= 0x7F; + Regs[R] = (byte)((Regs[R] & 0x80) | temp_R); + + instr_pntr = 0; + break; + case RD: + Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case WR: + Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case I_RD: + I_Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case I_WR: + I_Write_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case TR: + TR_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case TR16: + TR16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case ADD16: + ADD16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case ADD8: + ADD8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SUB8: + SUB8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case ADC8: + ADC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case ADC16: + ADC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SBC8: + SBC8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SBC16: + SBC_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case INC16: + INC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case INC8: + INC8_Func(cur_instr[instr_pntr++]); + break; + case DEC16: + DEC16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case DEC8: + DEC8_Func(cur_instr[instr_pntr++]); + break; + case RLC: + RLC_Func(cur_instr[instr_pntr++]); + break; + case RL: + RL_Func(cur_instr[instr_pntr++]); + break; + case RRC: + RRC_Func(cur_instr[instr_pntr++]); + break; + case RR: + RR_Func(cur_instr[instr_pntr++]); + break; + case CPL: + CPL_Func(cur_instr[instr_pntr++]); + break; + case DA: + DA_Func(cur_instr[instr_pntr++]); + break; + case SCF: + SCF_Func(cur_instr[instr_pntr++]); + break; + case CCF: + CCF_Func(cur_instr[instr_pntr++]); + break; + case AND8: + AND8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case XOR8: + XOR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case OR8: + OR8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case CP8: + CP8_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SLA: + SLA_Func(cur_instr[instr_pntr++]); + break; + case SRA: + SRA_Func(cur_instr[instr_pntr++]); + break; + case SRL: + SRL_Func(cur_instr[instr_pntr++]); + break; + case SLL: + SLL_Func(cur_instr[instr_pntr++]); + break; + case BIT: + BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case I_BIT: + I_BIT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case RES: + RES_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SET: + SET_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case EI: + EI_pending = 2; + break; + case DI: + IFF1 = IFF2 = false; + break; + case EXCH: + EXCH_16_Func(F_s, A_s, F, A); + break; + case EXX: + EXCH_16_Func(C_s, B_s, C, B); + EXCH_16_Func(E_s, D_s, E, D); + EXCH_16_Func(L_s, H_s, L, H); + break; + case EXCH_16: + EXCH_16_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case PREFIX: + ushort prefix_src = cur_instr[instr_pntr++]; + NO_prefix = false; + if (prefix_src == CBpre) { CB_prefix = true; } + if (prefix_src == EXTDpre) { EXTD_prefix = true; } + if (prefix_src == IXpre) { IX_prefix = true; } + if (prefix_src == IYpre) { IY_prefix = true; } + if (prefix_src == IXCBpre) { IXCB_prefix = true; IXCB_prefetch = true; } + if (prefix_src == IYCBpre) { IYCB_prefix = true; IYCB_prefetch = true; } + + FetchInstruction(ReadMemory(RegPC++)); + instr_pntr = 0; + // only the first prefix in a double prefix increases R, although I don't know how / why + if (prefix_src < 4) + { + temp_R = (byte)(Regs[R] & 0x7F); + temp_R++; + temp_R &= 0x7F; + Regs[R] = (byte)((Regs[R] & 0x80) | temp_R); + } + break; + case ASGN: + ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case ADDS: + ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case EI_RETI: + // NOTE: This is needed for systems using multiple interrupt sources, it triggers the next interrupt + // Not currently implemented here + iff1 = iff2; + break; + case EI_RETN: + iff1 = iff2; + break; + case OUT: + OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case IN: + IN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case NEG: + NEG_8_Func(cur_instr[instr_pntr++]); + break; + case INT_MODE: + interruptMode = cur_instr[instr_pntr++]; + break; + case RRD: + RRD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case RLD: + RLD_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); + break; + case SET_FL_LD: + SET_FL_LD_Func(); + break; + case SET_FL_CP: + SET_FL_CP_Func(); + break; + case SET_FL_IR: + SET_FL_IR_Func(cur_instr[instr_pntr++]); + break; + } + totalExecutedCycles++; + } + + // tracer stuff + public Action TraceCallback; + + public string TraceHeader + { + get { return "Z80A: PC, machine code, mnemonic, operands, registers (AF, BC, DE, HL, IX, IY, SP, Cy), flags (CNP3H5ZS)"; } + } + + public TraceInfo State(bool disassemble = true) + { + ushort bytes_read = 0; + + string disasm = disassemble ? Disassemble(RegPC, ReadMemory, out bytes_read) : "---"; + string byte_code = null; + + for (ushort i = 0; i < bytes_read; i++) + { + byte_code += ReadMemory((ushort)(RegPC + i)).ToHexString(2); + if (i < (bytes_read - 1)) + { + byte_code += " "; + } + } + + return new TraceInfo + { + Disassembly = string.Format( + "{0:X4}: {1} {2}", + RegPC, + byte_code.PadRight(12), + disasm.PadRight(26)), + RegisterInfo = string.Format( + "AF:{0:X4} BC:{1:X4} DE:{2:X4} HL:{3:X4} IX:{4:X4} IY:{5:X4} SP:{6:X4} Cy:{7} {8}{9}{10}{11}{12}{13}{14}{15}{16}", + (Regs[A] << 8) + Regs[F], + (Regs[B] << 8) + Regs[C], + (Regs[D] << 8) + Regs[E], + (Regs[H] << 8) + Regs[L], + (Regs[Ixh] << 8) + Regs[Ixl], + (Regs[Iyh] << 8) + Regs[Iyl], + Regs[SPl] | (Regs[SPh] << 8), + TotalExecutedCycles, + FlagC ? "C" : "c", + FlagN ? "N" : "n", + FlagP ? "P" : "p", + Flag3 ? "3" : "-", + FlagH ? "H" : "h", + Flag5 ? "5" : "-", + FlagZ ? "Z" : "z", + FlagS ? "S" : "s", + FlagI ? "E" : "e") + }; + } + // State Save/Load + + public void SyncState(Serializer ser) + { + ser.BeginSection("Z80A"); + ser.Sync("Regs", ref Regs, false); + ser.Sync("NMI", ref nonMaskableInterrupt); + ser.Sync("NMIPending", ref nonMaskableInterruptPending); + ser.Sync("IM", ref interruptMode); + ser.Sync("IFF1", ref iff1); + ser.Sync("IFF2", ref iff2); + ser.Sync("Halted", ref halted); + ser.Sync("ExecutedCycles", ref totalExecutedCycles); + ser.Sync("EI_pending", ref EI_pending); + + ser.Sync("instruction_pointer", ref instr_pntr); + ser.Sync("current instruction", ref cur_instr, false); + ser.Sync("opcode", ref opcode); + ser.Sync("FlagI", ref FlagI); + + ser.Sync("NO Preifx", ref NO_prefix); + ser.Sync("CB Preifx", ref CB_prefix); + ser.Sync("IX_prefix", ref IX_prefix); + ser.Sync("IY_prefix", ref IY_prefix); + ser.Sync("IXCB_prefix", ref IXCB_prefix); + ser.Sync("IYCB_prefix", ref IYCB_prefix); + ser.Sync("EXTD_prefix", ref EXTD_prefix); + ser.Sync("IXCB_prefetch", ref IXCB_prefetch); + ser.Sync("IYCB_prefetch", ref IYCB_prefetch); + ser.Sync("PF", ref PF); + + ser.EndSection(); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IDebuggable.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IDebuggable.cs index ab88799f79..9fc34a0121 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IDebuggable.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IDebuggable.cs @@ -12,36 +12,36 @@ namespace BizHawk.Emulation.Cores.Calculators { return new Dictionary { - ["A"] = _cpu.RegisterA, - ["AF"] = _cpu.RegisterAF, - ["B"] = _cpu.RegisterB, - ["BC"] = _cpu.RegisterBC, - ["C"] = _cpu.RegisterC, - ["D"] = _cpu.RegisterD, - ["DE"] = _cpu.RegisterDE, - ["E"] = _cpu.RegisterE, - ["F"] = _cpu.RegisterF, - ["H"] = _cpu.RegisterH, - ["HL"] = _cpu.RegisterHL, - ["I"] = _cpu.RegisterI, - ["IX"] = _cpu.RegisterIX, - ["IY"] = _cpu.RegisterIY, - ["L"] = _cpu.RegisterL, - ["PC"] = _cpu.RegisterPC, - ["R"] = _cpu.RegisterR, - ["Shadow AF"] = _cpu.RegisterShadowAF, - ["Shadow BC"] = _cpu.RegisterShadowBC, - ["Shadow DE"] = _cpu.RegisterShadowDE, - ["Shadow HL"] = _cpu.RegisterShadowHL, - ["SP"] = _cpu.RegisterSP, - ["Flag C"] = _cpu.RegisterF.Bit(0), - ["Flag N"] = _cpu.RegisterF.Bit(1), - ["Flag P/V"] = _cpu.RegisterF.Bit(2), - ["Flag 3rd"] = _cpu.RegisterF.Bit(3), - ["Flag H"] = _cpu.RegisterF.Bit(4), - ["Flag 5th"] = _cpu.RegisterF.Bit(5), - ["Flag Z"] = _cpu.RegisterF.Bit(6), - ["Flag S"] = _cpu.RegisterF.Bit(7) + ["A"] = _cpu.Regs[_cpu.A], + ["AF"] = _cpu.Regs[_cpu.F] + (_cpu.Regs[_cpu.A] << 8), + ["B"] = _cpu.Regs[_cpu.B], + ["BC"] = _cpu.Regs[_cpu.C] + (_cpu.Regs[_cpu.B] << 8), + ["C"] = _cpu.Regs[_cpu.C], + ["D"] = _cpu.Regs[_cpu.D], + ["DE"] = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8), + ["E"] = _cpu.Regs[_cpu.E], + ["F"] = _cpu.Regs[_cpu.F], + ["H"] = _cpu.Regs[_cpu.H], + ["HL"] = _cpu.Regs[_cpu.L] + (_cpu.Regs[_cpu.H] << 8), + ["I"] = _cpu.Regs[_cpu.I], + ["IX"] = _cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8), + ["IY"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8), + ["L"] = _cpu.Regs[_cpu.L], + ["PC"] = _cpu.Regs[_cpu.PCl] + (_cpu.Regs[_cpu.PCh] << 8), + ["R"] = _cpu.Regs[_cpu.R], + ["Shadow AF"] = _cpu.Regs[_cpu.F_s] + (_cpu.Regs[_cpu.A_s] << 8), + ["Shadow BC"] = _cpu.Regs[_cpu.C_s] + (_cpu.Regs[_cpu.B_s] << 8), + ["Shadow DE"] = _cpu.Regs[_cpu.E_s] + (_cpu.Regs[_cpu.D_s] << 8), + ["Shadow HL"] = _cpu.Regs[_cpu.L_s] + (_cpu.Regs[_cpu.H_s] << 8), + ["SP"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8), + ["Flag C"] = _cpu.FlagC, + ["Flag N"] = _cpu.FlagN, + ["Flag P/V"] = _cpu.FlagP, + ["Flag 3rd"] = _cpu.Flag3, + ["Flag H"] = _cpu.FlagH, + ["Flag 5th"] = _cpu.Flag5, + ["Flag Z"] = _cpu.FlagZ, + ["Flag S"] = _cpu.FlagS }; } @@ -49,73 +49,85 @@ namespace BizHawk.Emulation.Cores.Calculators { switch (register) { - default: - throw new InvalidOperationException(); - case "A": - _cpu.RegisterA = (byte)value; - break; - case "AF": - _cpu.RegisterAF = (byte)value; - break; - case "B": - _cpu.RegisterB = (byte)value; - break; - case "BC": - _cpu.RegisterBC = (byte)value; - break; - case "C": - _cpu.RegisterC = (byte)value; - break; - case "D": - _cpu.RegisterD = (byte)value; - break; - case "DE": - _cpu.RegisterDE = (byte)value; - break; - case "E": - _cpu.RegisterE = (byte)value; - break; - case "F": - _cpu.RegisterF = (byte)value; - break; - case "H": - _cpu.RegisterH = (byte)value; - break; - case "HL": - _cpu.RegisterHL = (byte)value; - break; - case "I": - _cpu.RegisterI = (byte)value; - break; - case "IX": - _cpu.RegisterIX = (byte)value; - break; - case "IY": - _cpu.RegisterIY = (byte)value; - break; - case "L": - _cpu.RegisterL = (byte)value; - break; - case "PC": - _cpu.RegisterPC = (ushort)value; - break; - case "R": - _cpu.RegisterR = (byte)value; - break; - case "Shadow AF": - _cpu.RegisterShadowAF = (byte)value; - break; - case "Shadow BC": - _cpu.RegisterShadowBC = (byte)value; - break; - case "Shadow DE": - _cpu.RegisterShadowDE = (byte)value; - break; - case "Shadow HL": - _cpu.RegisterShadowHL = (byte)value; - break; - case "SP": - _cpu.RegisterSP = (byte)value; + default: + throw new InvalidOperationException(); + case "A": + _cpu.Regs[_cpu.A] = (ushort)value; + break; + case "AF": + _cpu.Regs[_cpu.F] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.A] = (ushort)(value & 0xFF00); + break; + case "B": + _cpu.Regs[_cpu.B] = (ushort)value; + break; + case "BC": + _cpu.Regs[_cpu.C] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.B] = (ushort)(value & 0xFF00); + break; + case "C": + _cpu.Regs[_cpu.C] = (ushort)value; + break; + case "D": + _cpu.Regs[_cpu.D] = (ushort)value; + break; + case "DE": + _cpu.Regs[_cpu.E] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.D] = (ushort)(value & 0xFF00); + break; + case "E": + _cpu.Regs[_cpu.E] = (ushort)value; + break; + case "F": + _cpu.Regs[_cpu.F] = (ushort)value; + break; + case "H": + _cpu.Regs[_cpu.H] = (ushort)value; + break; + case "HL": + _cpu.Regs[_cpu.L] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.H] = (ushort)(value & 0xFF00); + break; + case "I": + _cpu.Regs[_cpu.I] = (ushort)value; + break; + case "IX": + _cpu.Regs[_cpu.Ixl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.Ixh] = (ushort)(value & 0xFF00); + break; + case "IY": + _cpu.Regs[_cpu.Iyl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.Iyh] = (ushort)(value & 0xFF00); + break; + case "L": + _cpu.Regs[_cpu.L] = (ushort)value; + break; + case "PC": + _cpu.Regs[_cpu.PCl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.PCh] = (ushort)(value & 0xFF00); + break; + case "R": + _cpu.Regs[_cpu.R] = (ushort)value; + break; + case "Shadow AF": + _cpu.Regs[_cpu.F_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.A_s] = (ushort)(value & 0xFF00); + break; + case "Shadow BC": + _cpu.Regs[_cpu.C_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.B_s] = (ushort)(value & 0xFF00); + break; + case "Shadow DE": + _cpu.Regs[_cpu.E_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.D_s] = (ushort)(value & 0xFF00); + break; + case "Shadow HL": + _cpu.Regs[_cpu.L_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.H_s] = (ushort)(value & 0xFF00); + break; + case "SP": + _cpu.Regs[_cpu.SPl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.SPh] = (ushort)(value & 0xFF00); break; } } diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs index f1de9171dd..622664bcc7 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs @@ -13,21 +13,42 @@ namespace BizHawk.Emulation.Cores.Calculators _controller = controller; _lagged = true; - _cpu.Debug = _tracer.Enabled; - - if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first + if (_tracer.Enabled) { - _cpu.Logger = s => _tracer.Put(s); + _cpu.TraceCallback = s => _tracer.Put(s); + } + else + { + _cpu.TraceCallback = null; } - // I eyeballed this speed - for (int i = 0; i < 5; i++) - { - _onPressed = controller.IsPressed("ON"); + _onPressed = controller.IsPressed("ON"); - // and this was derived from other emus - _cpu.ExecuteCycles(10000); - _cpu.Interrupt = true; + if (_onPressed && ON_key_int_EN && !ON_key_int) + { + ON_key_int = true; + _cpu.FlagI = true; + } + + // see: http://wikiti.brandonw.net/index.php?title=83:Ports:04 + // for timer interrupt frequency + + // CPU frequency is 6MHz + for (int i = 0; i < 100000; i++) + { + _cpu.ExecuteOne(); + + TIM_count++; + if (TIM_count >= TIM_hit) + { + TIM_count = 0; + + if (TIM_1_int_EN) + { + TIM_1_int = true; + _cpu.FlagI = true; + } + } } Frame++; diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs index e6927d9962..d2bd9192ca 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs @@ -7,55 +7,52 @@ namespace BizHawk.Emulation.Cores.Calculators { public partial class TI83 : IStatable { - private byte[] _stateBuffer; + public bool BinarySaveStatesPreferred + { + get { return true; } + } - public bool BinarySaveStatesPreferred => false; + public void SaveStateText(TextWriter writer) + { + SyncState(new Serializer(writer)); + } + + public void LoadStateText(TextReader reader) + { + SyncState(new Serializer(reader)); + } public void SaveStateBinary(BinaryWriter bw) { - SyncState(Serializer.CreateBinaryWriter(bw)); + SyncState(new Serializer(bw)); } public void LoadStateBinary(BinaryReader br) { - SyncState(Serializer.CreateBinaryReader(br)); - } - - public void SaveStateText(TextWriter tw) - { - SyncState(Serializer.CreateTextWriter(tw)); - } - - public void LoadStateText(TextReader tr) - { - SyncState(Serializer.CreateTextReader(tr)); + SyncState(new Serializer(br)); } public byte[] SaveStateBinary() { - if (_stateBuffer == null) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - _stateBuffer = stream.ToArray(); - writer.Close(); - return _stateBuffer; - } - else - { - var stream = new MemoryStream(_stateBuffer); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Close(); - return _stateBuffer; - } + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); } private void SyncState(Serializer ser) { - ser.BeginSection("TI83"); + byte[] core = null; + if (ser.IsWriter) + { + var ms = new MemoryStream(); + ms.Close(); + core = ms.ToArray(); + } _cpu.SyncState(ser); + + ser.BeginSection("TI83"); ser.Sync("RAM", ref _ram, false); ser.Sync("romPageLow3Bits", ref _romPageLow3Bits); ser.Sync("romPageHighBit", ref _romPageHighBit); @@ -72,6 +69,15 @@ namespace BizHawk.Emulation.Cores.Calculators ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); ser.Sync("IsLag", ref _isLag); + ser.Sync("ON_key_int", ref ON_key_int); + ser.Sync("ON_key_int_EN", ref ON_key_int_EN); + ser.Sync("TIM_1_int", ref TIM_1_int); + ser.Sync("TIM_1_int_EN", ref TIM_1_int_EN); + ser.Sync("TIM_frq", ref TIM_frq); + ser.Sync("TIM_mult", ref TIM_mult); + ser.Sync("TIM_count", ref TIM_count); + ser.Sync("TIM_hit", ref TIM_hit); + ser.EndSection(); if (ser.IsReader) diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.cs b/BizHawk.Emulation.Cores/Calculator/TI83.cs index 53a69072b6..09b0928449 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.cs @@ -2,7 +2,7 @@ using System; using System.Globalization; using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Components.Z80; +using BizHawk.Emulation.Cores.Components.Z80A; // http://www.ticalc.org/pub/text/calcinfo/ namespace BizHawk.Emulation.Cores.Calculators @@ -34,21 +34,13 @@ namespace BizHawk.Emulation.Cores.Calculators _rom = rom; LinkPort = new TI83LinkPort(this); - // different calculators (different revisions?) have different initPC. we track this in the game database by rom hash - // if( *(unsigned long *)(m_pRom + 0x6ce) == 0x04D3163E ) m_Regs.PC.W = 0x6ce; //KNOWN - // else if( *(unsigned long *)(m_pRom + 0x6f6) == 0x04D3163E ) m_Regs.PC.W = 0x6f6; //UNKNOWN - if (game["initPC"]) - { - _startPC = ushort.Parse(game.OptionValue("initPC"), NumberStyles.HexNumber); - } - HardReset(); SetupMemoryDomains(); _tracer = new TraceBuffer { Header = _cpu.TraceHeader }; ser.Register(_tracer); - ser.Register(new Disassembler()); + ser.Register(_cpu); } private readonly TraceBuffer _tracer; @@ -57,8 +49,6 @@ namespace BizHawk.Emulation.Cores.Calculators private readonly byte[] _rom; // configuration - private readonly ushort _startPC; - private IController _controller; private byte[] _ram; @@ -75,6 +65,10 @@ namespace BizHawk.Emulation.Cores.Calculators private bool _cursorMoved; private int _frame; + public bool ON_key_int, ON_key_int_EN; + public bool TIM_1_int, TIM_1_int_EN; + public int TIM_frq, TIM_mult, TIM_count, TIM_hit; + // Link Cable public TI83LinkPort LinkPort { get; } @@ -151,7 +145,7 @@ namespace BizHawk.Emulation.Cores.Calculators if (LinkActive) { // Prevent rom calls from disturbing link port activity - if (LinkActive && _cpu.RegisterPC < 0x4000) + if (LinkActive && _cpu.RegPC < 0x4000) { return; } @@ -169,7 +163,60 @@ namespace BizHawk.Emulation.Cores.Calculators _romPageLow3Bits = value & 0x7; break; case 3: // PORT_STATUS - _maskOn = (byte)(value & 1); + // controls ON key interrupts + if ((value & 0x1) == 0) + { + ON_key_int = false; + ON_key_int_EN = false; + } + else + { + ON_key_int_EN = true; + } + + // controls first timer interrupts + if ((value & 0x2) == 0) + { + TIM_1_int = false; + TIM_1_int_EN = false; + } + else + { + TIM_1_int_EN = true; + } + + // controls second timer, not yet implemented and unclear how to differentiate + if ((value & 0x4) == 0) + { + } + else + { + } + + // controls low power mode, not yet implemeneted + if ((value & 0x8) == 0) + { + } + else + { + } + break; + case 4: // PORT_INTCTRL + // controls ON key interrupts + TIM_frq = value & 6; + + TIM_mult = ((value & 0x10) == 0x10) ? 1800 : 1620; + + TIM_hit = (int)Math.Floor((double)TIM_mult / (3 + TIM_frq * 2)); + + TIM_hit = (int)Math.Floor((double)6000000 / TIM_hit); + + // Bit 0 is some form of memory mapping + + // Bit 5 controls reset + + // Bit 6-7 controls battery power compare (not implemented, will always return full power) + break; case 16: // PORT_DISPCTRL ////Console.WriteLine("write PORT_DISPCTRL {0}",value); @@ -198,22 +245,23 @@ namespace BizHawk.Emulation.Cores.Calculators { // Console.WriteLine("read PORT_STATUS"); // Bits: - // 0 - Set if ON key is down and ON key is trapped + // 0 - Set if ON key Interrupt generated // 1 - Update things (keyboard etc) // 2 - Unknown, but used // 3 - Set if ON key is up // 4-7 - Unknown - ////if (onPressed && maskOn) ret |= 1; - ////if (!onPressed) ret |= 0x8; - return (byte)((_controller.IsPressed("ON") ? _maskOn : 8) | (LinkActive ? 0 : 2)); + + return (byte)((_controller.IsPressed("ON") ? 0 : 8) | + (TIM_1_int ? 2 : 0) | + (ON_key_int ? 1 : 0)); } case 4: // PORT_INTCTRL - ////Console.WriteLine("read PORT_INTCTRL"); - return 0xFF; + // returns mirror of link port + return (byte)((_romPageHighBit << 4) | (LinkState << 2) | LinkOutput); case 16: // PORT_DISPCTRL - ////Console.WriteLine("read DISPCTRL"); + // Console.WriteLine("read DISPCTRL"); break; case 17: // PORT_DISPDATA @@ -428,13 +476,13 @@ namespace BizHawk.Emulation.Cores.Calculators private void IRQCallback() { - // Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", cpu.RegisterI, cpu.InterruptMode); - _cpu.Interrupt = false; + //Console.WriteLine("IRQ with vec {0} and cpu.InterruptMode {1}", _cpu.Regs[_cpu.I], _cpu.InterruptMode); + _cpu.FlagI = false; } private void NMICallback() { - Console.WriteLine("NMI"); + //Console.WriteLine("NMI"); _cpu.NonMaskableInterrupt = false; } @@ -447,7 +495,7 @@ namespace BizHawk.Emulation.Cores.Calculators _ram[i] = 0xFF; } - _cpu.RegisterPC = _startPC; + _cpu.RegPC = 0; _cpu.IFF1 = false; _cpu.IFF2 = false; diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs index a44baeb679..bf018db6b5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoControllers.cs @@ -38,7 +38,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision public byte Read(IController c, bool left_mode, int wheel) { - return 0; // needs checking + return 0x7F; // needs checking } public ControllerDefinition Definition { get; } diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs index 1c4e048e64..c48bbabf8f 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IDebuggable.cs @@ -12,36 +12,36 @@ namespace BizHawk.Emulation.Cores.ColecoVision { return new Dictionary { - ["A"] = _cpu.RegisterA, - ["AF"] = _cpu.RegisterAF, - ["B"] = _cpu.RegisterB, - ["BC"] = _cpu.RegisterBC, - ["C"] = _cpu.RegisterC, - ["D"] = _cpu.RegisterD, - ["DE"] = _cpu.RegisterDE, - ["E"] = _cpu.RegisterE, - ["F"] = _cpu.RegisterF, - ["H"] = _cpu.RegisterH, - ["HL"] = _cpu.RegisterHL, - ["I"] = _cpu.RegisterI, - ["IX"] = _cpu.RegisterIX, - ["IY"] = _cpu.RegisterIY, - ["L"] = _cpu.RegisterL, - ["PC"] = _cpu.RegisterPC, - ["R"] = _cpu.RegisterR, - ["Shadow AF"] = _cpu.RegisterShadowAF, - ["Shadow BC"] = _cpu.RegisterShadowBC, - ["Shadow DE"] = _cpu.RegisterShadowDE, - ["Shadow HL"] = _cpu.RegisterShadowHL, - ["SP"] = _cpu.RegisterSP, - ["Flag C"] = _cpu.RegisterF.Bit(0), - ["Flag N"] = _cpu.RegisterF.Bit(1), - ["Flag P/V"] = _cpu.RegisterF.Bit(2), - ["Flag 3rd"] = _cpu.RegisterF.Bit(3), - ["Flag H"] = _cpu.RegisterF.Bit(4), - ["Flag 5th"] = _cpu.RegisterF.Bit(5), - ["Flag Z"] = _cpu.RegisterF.Bit(6), - ["Flag S"] = _cpu.RegisterF.Bit(7) + ["A"] = _cpu.Regs[_cpu.A], + ["AF"] = _cpu.Regs[_cpu.F] + (_cpu.Regs[_cpu.A] << 8), + ["B"] = _cpu.Regs[_cpu.B], + ["BC"] = _cpu.Regs[_cpu.C] + (_cpu.Regs[_cpu.B] << 8), + ["C"] = _cpu.Regs[_cpu.C], + ["D"] = _cpu.Regs[_cpu.D], + ["DE"] = _cpu.Regs[_cpu.E] + (_cpu.Regs[_cpu.D] << 8), + ["E"] = _cpu.Regs[_cpu.E], + ["F"] = _cpu.Regs[_cpu.F], + ["H"] = _cpu.Regs[_cpu.H], + ["HL"] = _cpu.Regs[_cpu.L] + (_cpu.Regs[_cpu.H] << 8), + ["I"] = _cpu.Regs[_cpu.I], + ["IX"] = _cpu.Regs[_cpu.Ixl] + (_cpu.Regs[_cpu.Ixh] << 8), + ["IY"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8), + ["L"] = _cpu.Regs[_cpu.L], + ["PC"] = _cpu.Regs[_cpu.PCl] + (_cpu.Regs[_cpu.PCh] << 8), + ["R"] = _cpu.Regs[_cpu.R], + ["Shadow AF"] = _cpu.Regs[_cpu.F_s] + (_cpu.Regs[_cpu.A_s] << 8), + ["Shadow BC"] = _cpu.Regs[_cpu.C_s] + (_cpu.Regs[_cpu.B_s] << 8), + ["Shadow DE"] = _cpu.Regs[_cpu.E_s] + (_cpu.Regs[_cpu.D_s] << 8), + ["Shadow HL"] = _cpu.Regs[_cpu.L_s] + (_cpu.Regs[_cpu.H_s] << 8), + ["SP"] = _cpu.Regs[_cpu.Iyl] + (_cpu.Regs[_cpu.Iyh] << 8), + ["Flag C"] = _cpu.FlagC, + ["Flag N"] = _cpu.FlagN, + ["Flag P/V"] = _cpu.FlagP, + ["Flag 3rd"] = _cpu.Flag3, + ["Flag H"] = _cpu.FlagH, + ["Flag 5th"] = _cpu.Flag5, + ["Flag Z"] = _cpu.FlagZ, + ["Flag S"] = _cpu.FlagS }; } @@ -52,70 +52,82 @@ namespace BizHawk.Emulation.Cores.ColecoVision default: throw new InvalidOperationException(); case "A": - _cpu.RegisterA = (byte)value; + _cpu.Regs[_cpu.A] = (ushort)value; break; case "AF": - _cpu.RegisterAF = (byte)value; + _cpu.Regs[_cpu.F] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.A] = (ushort)(value & 0xFF00); break; case "B": - _cpu.RegisterB = (byte)value; + _cpu.Regs[_cpu.B] = (ushort)value; break; case "BC": - _cpu.RegisterBC = (byte)value; + _cpu.Regs[_cpu.C] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.B] = (ushort)(value & 0xFF00); break; case "C": - _cpu.RegisterC = (byte)value; + _cpu.Regs[_cpu.C] = (ushort)value; break; case "D": - _cpu.RegisterD = (byte)value; + _cpu.Regs[_cpu.D] = (ushort)value; break; case "DE": - _cpu.RegisterDE = (byte)value; + _cpu.Regs[_cpu.E] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.D] = (ushort)(value & 0xFF00); break; case "E": - _cpu.RegisterE = (byte)value; + _cpu.Regs[_cpu.E] = (ushort)value; break; case "F": - _cpu.RegisterF = (byte)value; + _cpu.Regs[_cpu.F] = (ushort)value; break; case "H": - _cpu.RegisterH = (byte)value; + _cpu.Regs[_cpu.H] = (ushort)value; break; case "HL": - _cpu.RegisterHL = (byte)value; + _cpu.Regs[_cpu.L] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.H] = (ushort)(value & 0xFF00); break; case "I": - _cpu.RegisterI = (byte)value; + _cpu.Regs[_cpu.I] = (ushort)value; break; case "IX": - _cpu.RegisterIX = (byte)value; + _cpu.Regs[_cpu.Ixl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.Ixh] = (ushort)(value & 0xFF00); break; case "IY": - _cpu.RegisterIY = (byte)value; + _cpu.Regs[_cpu.Iyl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.Iyh] = (ushort)(value & 0xFF00); break; case "L": - _cpu.RegisterL = (byte)value; + _cpu.Regs[_cpu.L] = (ushort)value; break; case "PC": - _cpu.RegisterPC = (ushort)value; + _cpu.Regs[_cpu.PCl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.PCh] = (ushort)(value & 0xFF00); break; case "R": - _cpu.RegisterR = (byte)value; + _cpu.Regs[_cpu.R] = (ushort)value; break; case "Shadow AF": - _cpu.RegisterShadowAF = (byte)value; + _cpu.Regs[_cpu.F_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.A_s] = (ushort)(value & 0xFF00); break; case "Shadow BC": - _cpu.RegisterShadowBC = (byte)value; + _cpu.Regs[_cpu.C_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.B_s] = (ushort)(value & 0xFF00); break; case "Shadow DE": - _cpu.RegisterShadowDE = (byte)value; + _cpu.Regs[_cpu.E_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.D_s] = (ushort)(value & 0xFF00); break; case "Shadow HL": - _cpu.RegisterShadowHL = (byte)value; + _cpu.Regs[_cpu.L_s] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.H_s] = (ushort)(value & 0xFF00); break; case "SP": - _cpu.RegisterSP = (byte)value; + _cpu.Regs[_cpu.SPl] = (ushort)(value & 0xFF); + _cpu.Regs[_cpu.SPh] = (ushort)(value & 0xFF00); break; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs index a503350386..22e67db446 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IEmulator.cs @@ -24,16 +24,18 @@ namespace BizHawk.Emulation.Cores.ColecoVision SoftReset(); } - _cpu.Debug = _tracer.Enabled; _frame++; _isLag = true; PSG.BeginFrame(_cpu.TotalExecutedCycles); - if (_cpu.Debug && _cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first + if (_tracer.Enabled) { - _cpu.Logger = (s) => _tracer.Put(s); + _cpu.TraceCallback = s => _tracer.Put(s); + } + else + { + _cpu.TraceCallback = null; } - byte tempRet1 = ControllerDeck.ReadPort1(controller, true, true); byte tempRet2 = ControllerDeck.ReadPort2(controller, true, true); diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IStatable.cs index 62b5297675..d079fa50f4 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.IStatable.cs @@ -7,53 +7,52 @@ namespace BizHawk.Emulation.Cores.ColecoVision { public partial class ColecoVision : IStatable { - public bool BinarySaveStatesPreferred => false; + public bool BinarySaveStatesPreferred + { + get { return true; } + } + + public void SaveStateText(TextWriter writer) + { + SyncState(new Serializer(writer)); + } + + public void LoadStateText(TextReader reader) + { + SyncState(new Serializer(reader)); + } public void SaveStateBinary(BinaryWriter bw) { - SyncState(Serializer.CreateBinaryWriter(bw)); + SyncState(new Serializer(bw)); } public void LoadStateBinary(BinaryReader br) { - SyncState(Serializer.CreateBinaryReader(br)); - } - - public void SaveStateText(TextWriter tw) - { - SyncState(Serializer.CreateTextWriter(tw)); - } - - public void LoadStateText(TextReader tr) - { - SyncState(Serializer.CreateTextReader(tr)); + SyncState(new Serializer(br)); } public byte[] SaveStateBinary() { - if (_stateBuffer == null) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - _stateBuffer = stream.ToArray(); - writer.Close(); - return _stateBuffer; - } - else - { - var stream = new MemoryStream(_stateBuffer); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Close(); - return _stateBuffer; - } + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); } private void SyncState(Serializer ser) { - ser.BeginSection("Coleco"); + byte[] core = null; + if (ser.IsWriter) + { + var ms = new MemoryStream(); + ms.Close(); + core = ms.ToArray(); + } _cpu.SyncState(ser); + + ser.BeginSection("Coleco"); _vdp.SyncState(ser); PSG.SyncState(ser); ser.Sync("RAM", ref _ram, false); diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs index 2422f9a36f..83c175ef78 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs @@ -1,6 +1,6 @@ using BizHawk.Emulation.Common; using BizHawk.Emulation.Cores.Components; -using BizHawk.Emulation.Cores.Components.Z80; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.ColecoVision { @@ -53,7 +53,7 @@ namespace BizHawk.Emulation.Cores.ColecoVision SetupMemoryDomains(); _tracer.Header = _cpu.TraceHeader; - ser.Register(new Disassembler()); + ser.Register(_cpu); ser.Register(_tracer); } diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs index 1e5abd1445..c86bd515c1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs +++ b/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs @@ -2,7 +2,7 @@ using BizHawk.Common; using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Components.Z80; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.ColecoVision { @@ -54,14 +54,17 @@ namespace BizHawk.Emulation.Cores.ColecoVision Cpu.NonMaskableInterrupt = true; } - Cpu.ExecuteCycles(228); - - Cpu.Interrupt = false; + for (int i = 0; i < 228; i++) + { + Cpu.ExecuteOne(); + } + + Cpu.FlagI = false; if (Int_pending && scanLine==50) { if (EnableInterrupts) { - Cpu.Interrupt = true; + Cpu.FlagI = true; Int_pending = false; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs index 9f46fdf560..e649c730e5 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/FDS.cs @@ -255,19 +255,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES case 0x0020: timerlatch &= 0xff00; timerlatch |= value; - //timerirq = false; break; case 0x0021: timerlatch &= 0x00ff; timerlatch |= value << 8; - //timerirq = false; break; case 0x0022: - timerreg = (byte)(value & 3); - timervalue = timerlatch; + if (diskenable) + { + timerreg = (byte)(value & 3); + if ((value & 0x02) == 0x02) + { + timervalue = timerlatch; + } + else + { + _timerirq = false; + } + } + break; case 0x0023: diskenable = (value & 1) != 0; + if (!diskenable) { _timerirq = false; } soundenable = (value & 2) != 0; break; case 0x0024: @@ -344,7 +354,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES public override void ClockCPU() { - if ((timerreg & 2) != 0)// && timervalue > 0) + if ((timerreg & 2) != 0 && diskenable) { if (timervalue!=0) { @@ -352,22 +362,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES } if (timervalue == 0) { - - /* - if ((timerreg & 1) != 0) - { - timervalue = timerlatch; - //timervalue = 0xFFFF; - } - else - { - timerreg &= unchecked((byte)~2); - timervalue = 0; - timerlatch = 0; - } - */ timervalue = timerlatch; timerirq = true; + if ((timerreg & 1) == 0) + { + timerreg -= 2; + } } } audio.Clock(); diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs index 4861d49708..9c86f953e7 100644 --- a/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs +++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/NES/FDS/RamAdapter.cs @@ -67,14 +67,17 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES byte[] fileheader = br.ReadBytes(16); if (fileheader[0] != 0x03) { - throw new Exception("Corrupt FDS block 3"); + // Instead of exceptions, display strong warnings + Console.WriteLine("WARNING: INVALID FILE, BLOCK 3 ERROR"); + //throw new Exception("Corrupt FDS block 3"); } int filesize = fileheader[13] + fileheader[14] * 256; byte[] file = br.ReadBytes(filesize + 1); if (file[0] != 0x04) { - throw new Exception("Corrupt FDS block 4"); + Console.WriteLine("WARNING: INVALID FILE, BLOCK 4 ERROR"); + //throw new Exception("Corrupt FDS block 4"); } WriteBlock(ret, fileheader, 122); diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs new file mode 100644 index 0000000000..ec0acddec1 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs @@ -0,0 +1,233 @@ +using System; +using BizHawk.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + class EEPROM93c46 + { + enum EEPROMWriteMode + { + Instruction, + WriteData, + WriteAll, + Read + } + + enum EEPROMReadMode + { + ReadNew, + ReadOld, + Hold + } + + [Flags] + enum EEPROMFlags : byte + { + Ready = 1, + Clock = 2, + ChipSelect = 4 + } + + ushort Address = 0; + ushort Value = 0; + int BitsWritten = 0; + int BitsRead = 0; + bool WriteEnable = false; + EEPROMWriteMode WriteMode = EEPROMWriteMode.Instruction; + EEPROMReadMode ReadMode = EEPROMReadMode.Hold; + EEPROMFlags Flags = 0; + + public byte Read(byte[] saveRAM) + { + switch (ReadMode) + { + case EEPROMReadMode.ReadNew: + // A new value clocking out + + ReadMode = EEPROMReadMode.ReadOld; + byte ret = Read(saveRAM); + + if (++BitsRead == 8) + { + // Increment address + BitsRead = 0; + ++Address; + + if(Address % 2 == 0) + { + WriteMode = EEPROMWriteMode.Instruction; + ReadMode = EEPROMReadMode.Hold; + BitsWritten = 0; + Value = 0; + } + } + + return ret; + case EEPROMReadMode.ReadOld: + // repeat old value + + byte bit = (byte)((saveRAM[Address % saveRAM.Length] >> (7 - BitsRead)) & 1); + + return (byte)((byte)(Flags | EEPROMFlags.Clock) | bit); + default: + // ready/busy flag is always ready in this emulation + return (byte)(Flags | EEPROMFlags.Clock | EEPROMFlags.Ready); + } + } + + public void Write(byte bit, byte[] saveRAM) + { + // new instruction? + if ((bit & 4) == 0) + { + WriteMode = EEPROMWriteMode.Instruction; + ReadMode = EEPROMReadMode.Hold; + BitsWritten = 0; + Value = 0; + + Flags = (EEPROMFlags)bit & ~EEPROMFlags.Ready; + return; + } + + // clock low to high? + if ((bit & (byte)EEPROMFlags.Clock) != 0 && (Flags & EEPROMFlags.Clock) == 0) + { + // all modes shift in a larger value + Value = (ushort)((Value << 1) | (bit & 1)); + ++BitsWritten; + + switch (WriteMode) + { + case EEPROMWriteMode.Instruction: + // Process opcode including start bit + + // check start bit + if ((Value & 0x100) == 0) + return; + + byte op = (byte)Value; + Value = 0; + BitsWritten = 0; + + switch (op & 0xC0) + { + case 0x00: + // non-addressed commands + switch (op & 0xF0) + { + case 0x00: + // EWDS: write disable + WriteEnable = false; + return; + case 0x10: + // WRAL: write to all addresses (silly) + WriteMode = EEPROMWriteMode.WriteAll; + ReadMode = EEPROMReadMode.Hold; + return; + case 0x20: + // ERAL: erase all addresses + if (WriteEnable) + { + for (int i = 0; i < saveRAM.Length; ++i) + { + saveRAM[i] = 0xFF; + } + } + ReadMode = EEPROMReadMode.Hold; + return; + case 0x30: + // EWEN: write enable + WriteEnable = true; + return; + default: + // impossible + return; + } + case 0x40: + // WRITE + Address = (ushort)((op & 0x3F) << 1); + WriteMode = EEPROMWriteMode.WriteData; + ReadMode = EEPROMReadMode.Hold; + return; + case 0x80: + // READ + Address = (ushort)((op & 0x3F) << 1); + ReadMode = EEPROMReadMode.Hold; + WriteMode = EEPROMWriteMode.Read; + BitsRead = 0; + return; + case 0xC0: + // ERASE + Address = (ushort)((op & 0x3F) << 1); + if (WriteEnable) + { + saveRAM[Address % saveRAM.Length] = 0xFF; + saveRAM[(Address + 1) % saveRAM.Length] = 0xFF; + } + ReadMode = EEPROMReadMode.Hold; + return; + default: + // impossible + return; + } + case EEPROMWriteMode.WriteData: + // Write bits + + if (BitsWritten < 16) + return; + + if (WriteEnable) + { + saveRAM[Address % saveRAM.Length] = (byte)(Value >> 8); + saveRAM[(Address + 1) % saveRAM.Length] = (byte)Value; + } + WriteMode = EEPROMWriteMode.Instruction; + + Value = 0; + BitsWritten = 0; + return; + case EEPROMWriteMode.WriteAll: + // write to ALL addresses + + if (BitsWritten < 16) + return; + + Value = 0; + BitsWritten = 0; + + if (WriteEnable) + { + for (int i = 0; i < saveRAM.Length; i += 2) + { + saveRAM[i % saveRAM.Length] = (byte)Value; + saveRAM[(i + 1) % saveRAM.Length] = (byte)(Value >> 8); + } + } + WriteMode = EEPROMWriteMode.Instruction; + return; + case EEPROMWriteMode.Read: + // Clock a new value out + ReadMode = EEPROMReadMode.ReadNew; + + return; + } + } + + Flags = (EEPROMFlags)bit & ~EEPROMFlags.Ready; + } + + public void SyncState(Serializer ser) + { + ser.BeginSection("93c46"); + ser.Sync("Address", ref Address); + ser.Sync("Value", ref Value); + ser.Sync("BitsWritten", ref BitsWritten); + ser.Sync("BitsRead", ref BitsRead); + ser.Sync("WriteEnable", ref WriteEnable); + ser.SyncEnum("WriteMode", ref WriteMode); + ser.SyncEnum("ReadMode", ref ReadMode); + ser.SyncEnum("Flags", ref Flags); + ser.EndSection(); + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs new file mode 100644 index 0000000000..2e5c544c11 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs @@ -0,0 +1,136 @@ +using System; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public partial class SMS + { + // The 93c46-connected mapper is assumed to be equivalent to the Sega mapper except for $8000-.. + // The Sega memory mapper layout looks like so: + // $0000-$03FF - ROM (unpaged) + // $0400-$3FFF - ROM mapper slot 0 + // $4000-$7FFF - ROM mapper slot 1 + // $8000-$BFFF - ROM mapper slot 2 - OR - EEPROM + // $C000-$DFFF - System RAM + // $E000-$FFFF - System RAM (mirror) + // $FFFC - SaveRAM mapper control + // $FFFD - Mapper slot 0 control + // $FFFE - Mapper slot 1 control + // $FFFF - Mapper slot 2 control + + EEPROM93c46 EEPROM; + + byte ReadMemoryEEPROM(ushort address) + { + byte ret = 0xFF; + + if (address < 0xC000) + { + if ((Port3E & 0x48) == 0x48) // cart and bios disabled, return empty bus + ret = 0xFF; + else if (BiosMapped && BiosRom != null) + ret = BiosRom[address & 0x1FFF]; + else if (address < 1024) + ret = RomData[address]; + else if (address < 0x4000) + ret = RomData[(RomBank0 * BankSize) + address]; + else if (address < 0x8000) + ret = RomData[(RomBank1 * BankSize) + (address & BankSizeMask)]; + else + { + switch (SaveRamBank) + { + case 0: ret = RomData[(RomBank2 * BankSize) + (address & BankSizeMask)]; break; + case 1: if (SaveRAM != null && EEPROM != null) ret = EEPROM.Read(SaveRAM); break; + default: + ret = SystemRam[address & RamSizeMask]; + break; + } + } + } + else + { + ret = SystemRam[address & RamSizeMask]; + } + + return ret; + } + + CDLog_MapResults MapMemoryEEPROM(ushort address, bool write) + { + if (address < 0xC000) + { + if ((Port3E & 0x48) == 0x48) // cart and bios disabled, return empty bus + return new CDLog_MapResults(); + else if (BiosMapped && BiosRom != null) + return new CDLog_MapResults(); //bios tracking of CDL is not supported + else if (address < 1024) + return new CDLog_MapResults() { Type = CDLog_AddrType.ROM, Address = address }; + else if (address < 0x4000) + return new CDLog_MapResults() { Type = CDLog_AddrType.ROM, Address = (RomBank0 * BankSize) + address }; + else if (address < 0x8000) + return new CDLog_MapResults() { Type = CDLog_AddrType.ROM, Address = (RomBank1 * BankSize) + (address & BankSizeMask) }; + else + { + switch (SaveRamBank) + { + case 0: return new CDLog_MapResults() { Type = CDLog_AddrType.ROM, Address = (RomBank2 * BankSize) + (address & BankSizeMask) }; + case 1: return new CDLog_MapResults(); // a serial IO port + case 2: return new CDLog_MapResults(); // a serial IO port + default: + return new CDLog_MapResults() { Type = CDLog_AddrType.MainRAM, Address = address & RamSizeMask }; + } + } + } + else + { + return new CDLog_MapResults() { Type = CDLog_AddrType.MainRAM, Address = address & RamSizeMask }; + } + } + + void WriteMemoryEEPROM(ushort address, byte value) + { + if (address >= 0xC000) + SystemRam[address & RamSizeMask] = value; + + else if (address >= 0x8000) + { + if (SaveRAM != null) + { + SaveRamModified = true; + EEPROM.Write(value, SaveRAM); + return; + } + else System.Console.WriteLine("Game attempt to use SRAM but SRAM not present"); + } + + if (address >= 0xFFFC) + { + if (address == 0xFFFC) + { + if ((value & 8) != 0) + SaveRamBank = (byte)((value & 4) == 0 ? 1 : 2); // SaveRAM selected + else + SaveRamBank = 0; // ROM bank selected + + } + else if (address == 0xFFFD) RomBank0 = (byte)(value % RomBanks); + else if (address == 0xFFFE) RomBank1 = (byte)(value % RomBanks); + else if (address == 0xFFFF) RomBank2 = (byte)(value % RomBanks); + return; + } + } + + void InitEEPROMMapper() + { + ReadMemory = ReadMemoryEEPROM; + WriteMemory = WriteMemoryEEPROM; + MapMemory = MapMemoryEEPROM; + WriteMemoryEEPROM(0xFFFC, 0); + WriteMemoryEEPROM(0xFFFD, 0); + WriteMemoryEEPROM(0xFFFE, 1); + WriteMemoryEEPROM(0xFFFF, 2); + + EEPROM = new EEPROM93c46(); + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs index 973f3e78b7..009cd5fd4c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IDebuggable.cs @@ -12,36 +12,36 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { return new Dictionary { - ["A"] = Cpu.RegisterA, - ["AF"] = Cpu.RegisterAF, - ["B"] = Cpu.RegisterB, - ["BC"] = Cpu.RegisterBC, - ["C"] = Cpu.RegisterC, - ["D"] = Cpu.RegisterD, - ["DE"] = Cpu.RegisterDE, - ["E"] = Cpu.RegisterE, - ["F"] = Cpu.RegisterF, - ["H"] = Cpu.RegisterH, - ["HL"] = Cpu.RegisterHL, - ["I"] = Cpu.RegisterI, - ["IX"] = Cpu.RegisterIX, - ["IY"] = Cpu.RegisterIY, - ["L"] = Cpu.RegisterL, - ["PC"] = Cpu.RegisterPC, - ["R"] = Cpu.RegisterR, - ["Shadow AF"] = Cpu.RegisterShadowAF, - ["Shadow BC"] = Cpu.RegisterShadowBC, - ["Shadow DE"] = Cpu.RegisterShadowDE, - ["Shadow HL"] = Cpu.RegisterShadowHL, - ["SP"] = Cpu.RegisterSP, - ["Flag C"] = Cpu.RegisterF.Bit(0), - ["Flag N"] = Cpu.RegisterF.Bit(1), - ["Flag P/V"] = Cpu.RegisterF.Bit(2), - ["Flag 3rd"] = Cpu.RegisterF.Bit(3), - ["Flag H"] = Cpu.RegisterF.Bit(4), - ["Flag 5th"] = Cpu.RegisterF.Bit(5), - ["Flag Z"] = Cpu.RegisterF.Bit(6), - ["Flag S"] = Cpu.RegisterF.Bit(7) + ["A"] = Cpu.Regs[Cpu.A], + ["AF"] = Cpu.Regs[Cpu.F] + (Cpu.Regs[Cpu.A] << 8), + ["B"] = Cpu.Regs[Cpu.B], + ["BC"] = Cpu.Regs[Cpu.C] + (Cpu.Regs[Cpu.B] << 8), + ["C"] = Cpu.Regs[Cpu.C], + ["D"] = Cpu.Regs[Cpu.D], + ["DE"] = Cpu.Regs[Cpu.E] + (Cpu.Regs[Cpu.D] << 8), + ["E"] = Cpu.Regs[Cpu.E], + ["F"] = Cpu.Regs[Cpu.F], + ["H"] = Cpu.Regs[Cpu.H], + ["HL"] = Cpu.Regs[Cpu.L] + (Cpu.Regs[Cpu.H] << 8), + ["I"] = Cpu.Regs[Cpu.I], + ["IX"] = Cpu.Regs[Cpu.Ixl] + (Cpu.Regs[Cpu.Ixh] << 8), + ["IY"] = Cpu.Regs[Cpu.Iyl] + (Cpu.Regs[Cpu.Iyh] << 8), + ["L"] = Cpu.Regs[Cpu.L], + ["PC"] = Cpu.Regs[Cpu.PCl] + (Cpu.Regs[Cpu.PCh] << 8), + ["R"] = Cpu.Regs[Cpu.R], + ["Shadow AF"] = Cpu.Regs[Cpu.F_s] + (Cpu.Regs[Cpu.A_s] << 8), + ["Shadow BC"] = Cpu.Regs[Cpu.C_s] + (Cpu.Regs[Cpu.B_s] << 8), + ["Shadow DE"] = Cpu.Regs[Cpu.E_s] + (Cpu.Regs[Cpu.D_s] << 8), + ["Shadow HL"] = Cpu.Regs[Cpu.L_s] + (Cpu.Regs[Cpu.H_s] << 8), + ["SP"] = Cpu.Regs[Cpu.Iyl] + (Cpu.Regs[Cpu.Iyh] << 8), + ["Flag C"] = Cpu.FlagC, + ["Flag N"] = Cpu.FlagN, + ["Flag P/V"] = Cpu.FlagP, + ["Flag 3rd"] = Cpu.Flag3, + ["Flag H"] = Cpu.FlagH, + ["Flag 5th"] = Cpu.Flag5, + ["Flag Z"] = Cpu.FlagZ, + ["Flag S"] = Cpu.FlagS }; } @@ -52,70 +52,82 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem default: throw new InvalidOperationException(); case "A": - Cpu.RegisterA = (byte)value; + Cpu.Regs[Cpu.A] = (ushort)value; break; case "AF": - Cpu.RegisterAF = (byte)value; + Cpu.Regs[Cpu.F] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.A] = (ushort)(value & 0xFF00); break; case "B": - Cpu.RegisterB = (byte)value; + Cpu.Regs[Cpu.B] = (ushort)value; break; case "BC": - Cpu.RegisterBC = (byte)value; + Cpu.Regs[Cpu.C] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.B] = (ushort)(value & 0xFF00); break; case "C": - Cpu.RegisterC = (byte)value; + Cpu.Regs[Cpu.C] = (ushort)value; break; case "D": - Cpu.RegisterD = (byte)value; + Cpu.Regs[Cpu.D] = (ushort)value; break; case "DE": - Cpu.RegisterDE = (byte)value; + Cpu.Regs[Cpu.E] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.D] = (ushort)(value & 0xFF00); break; case "E": - Cpu.RegisterE = (byte)value; + Cpu.Regs[Cpu.E] = (ushort)value; break; case "F": - Cpu.RegisterF = (byte)value; + Cpu.Regs[Cpu.F] = (ushort)value; break; case "H": - Cpu.RegisterH = (byte)value; + Cpu.Regs[Cpu.H] = (ushort)value; break; case "HL": - Cpu.RegisterHL = (byte)value; + Cpu.Regs[Cpu.L] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.H] = (ushort)(value & 0xFF00); break; case "I": - Cpu.RegisterI = (byte)value; + Cpu.Regs[Cpu.I] = (ushort)value; break; case "IX": - Cpu.RegisterIX = (byte)value; + Cpu.Regs[Cpu.Ixl] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.Ixh] = (ushort)(value & 0xFF00); break; case "IY": - Cpu.RegisterIY = (byte)value; + Cpu.Regs[Cpu.Iyl] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.Iyh] = (ushort)(value & 0xFF00); break; case "L": - Cpu.RegisterL = (byte)value; + Cpu.Regs[Cpu.L] = (ushort)value; break; case "PC": - Cpu.RegisterPC = (ushort)value; + Cpu.Regs[Cpu.PCl] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.PCh] = (ushort)(value & 0xFF00); break; case "R": - Cpu.RegisterR = (byte)value; + Cpu.Regs[Cpu.R] = (ushort)value; break; case "Shadow AF": - Cpu.RegisterShadowAF = (byte)value; + Cpu.Regs[Cpu.F_s] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.A_s] = (ushort)(value & 0xFF00); break; case "Shadow BC": - Cpu.RegisterShadowBC = (byte)value; + Cpu.Regs[Cpu.C_s] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.B_s] = (ushort)(value & 0xFF00); break; case "Shadow DE": - Cpu.RegisterShadowDE = (byte)value; + Cpu.Regs[Cpu.E_s] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.D_s] = (ushort)(value & 0xFF00); break; case "Shadow HL": - Cpu.RegisterShadowHL = (byte)value; + Cpu.Regs[Cpu.L_s] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.H_s] = (ushort)(value & 0xFF00); break; case "SP": - Cpu.RegisterSP = (byte)value; + Cpu.Regs[Cpu.SPl] = (ushort)(value & 0xFF); + Cpu.Regs[Cpu.SPh] = (ushort)(value & 0xFF00); break; } } diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs index 86582d24ce..fe2a9222a3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -1,95 +1,99 @@ -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Sega.MasterSystem -{ - public sealed partial class SMS : IEmulator - { - public IEmulatorServiceProvider ServiceProvider { get; } - - public ControllerDefinition ControllerDefinition - { - get - { - if (IsGameGear) - { - return GGController; - } - - switch(Settings.ControllerType) - { - case "Paddle": - return SMSPaddleController; - case "Light Phaser": - // scale the vertical to the display mode - SMSLightPhaserController.FloatRanges[1] = new ControllerDefinition.FloatRange(0, Vdp.FrameHeight / 2, Vdp.FrameHeight - 1); - - return SMSLightPhaserController; - default: - return SmsController; - } - } - } - - public void FrameAdvance(IController controller, bool render, bool rendersound) - { - _controller = controller; - _lagged = true; - _frame++; - PSG.BeginFrame(Cpu.TotalExecutedCycles); - Cpu.Debug = Tracer.Enabled; - if (!IsGameGear) - { - PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte)0xFF; - } - - if (Cpu.Debug && Cpu.Logger == null) // TODO, lets not do this on each frame. But lets refactor CoreComm/CoreComm first - { - Cpu.Logger = s => Tracer.Put(s); - } - - if (IsGameGear == false) - { - Cpu.NonMaskableInterrupt = controller.IsPressed("Pause"); - } - - if (IsGame3D && Settings.Fix3D) - { - Vdp.ExecFrame((Frame & 1) == 0); - } - else - { - Vdp.ExecFrame(render); - } - - PSG.EndFrame(Cpu.TotalExecutedCycles); - if (_lagged) - { - _lagCount++; - _isLag = true; - } - else - { - _isLag = false; - } - } - - public int Frame => _frame; - - public string SystemId => "SMS"; - - public bool DeterministicEmulation => true; - - public void ResetCounters() - { - _frame = 0; - _lagCount = 0; - _isLag = false; - } - - public CoreComm CoreComm { get; } - - public void Dispose() - { - } - } -} +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : IEmulator + { + public IEmulatorServiceProvider ServiceProvider { get; } + + public ControllerDefinition ControllerDefinition + { + get + { + if (IsGameGear) + { + return GGController; + } + + switch(Settings.ControllerType) + { + case "Paddle": + return SMSPaddleController; + case "Light Phaser": + // scale the vertical to the display mode + SMSLightPhaserController.FloatRanges[1] = new ControllerDefinition.FloatRange(0, Vdp.FrameHeight / 2, Vdp.FrameHeight - 1); + + return SMSLightPhaserController; + default: + return SmsController; + } + } + } + + public void FrameAdvance(IController controller, bool render, bool rendersound) + { + _controller = controller; + _lagged = true; + _frame++; + PSG.BeginFrame(Cpu.TotalExecutedCycles); + + if (!IsGameGear) + { + PSG.StereoPanning = Settings.ForceStereoSeparation ? ForceStereoByte : (byte)0xFF; + } + + if (Tracer.Enabled) + { + Cpu.TraceCallback = s => Tracer.Put(s); + } + else + { + Cpu.TraceCallback = null; + } + + if (IsGameGear == false) + { + Cpu.NonMaskableInterrupt = controller.IsPressed("Pause"); + } + + if (IsGame3D && Settings.Fix3D) + { + Vdp.ExecFrame((Frame & 1) == 0); + } + else + { + Vdp.ExecFrame(render); + } + + PSG.EndFrame(Cpu.TotalExecutedCycles); + if (_lagged) + { + _lagCount++; + _isLag = true; + } + else + { + _isLag = false; + } + } + + public int Frame => _frame; + + public string SystemId => "SMS"; + + public bool DeterministicEmulation => true; + + public void ResetCounters() + { + _frame = 0; + _lagCount = 0; + _isLag = false; + } + + public CoreComm CoreComm { get; } + + public void Dispose() + { + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs index 72f703980d..0ba7d4293d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs @@ -1,106 +1,105 @@ -using System.IO; - -using BizHawk.Common; -using BizHawk.Emulation.Common; - - -namespace BizHawk.Emulation.Cores.Sega.MasterSystem -{ - public sealed partial class SMS : IStatable - { - public bool BinarySaveStatesPreferred - { - get { return false; } - } - - public void SaveStateBinary(BinaryWriter bw) - { - SyncState(Serializer.CreateBinaryWriter(bw)); - } - - public void LoadStateBinary(BinaryReader br) - { - SyncState(Serializer.CreateBinaryReader(br)); - } - - public void SaveStateText(TextWriter tw) - { - SyncState(Serializer.CreateTextWriter(tw)); - } - - public void LoadStateText(TextReader tr) - { - SyncState(Serializer.CreateTextReader(tr)); - } - - public byte[] SaveStateBinary() - { - if (_stateBuffer == null) - { - var stream = new MemoryStream(); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - _stateBuffer = stream.ToArray(); - writer.Close(); - return _stateBuffer; - } - else - { - var stream = new MemoryStream(_stateBuffer); - var writer = new BinaryWriter(stream); - SaveStateBinary(writer); - writer.Close(); - return _stateBuffer; - } - } - - private byte[] _stateBuffer; - - private void SyncState(Serializer ser) - { - ser.BeginSection("SMS"); - Cpu.SyncState(ser); - Vdp.SyncState(ser); - PSG.SyncState(ser); - ser.Sync("RAM", ref SystemRam, false); - ser.Sync("RomBank0", ref RomBank0); - ser.Sync("RomBank1", ref RomBank1); - ser.Sync("RomBank2", ref RomBank2); - ser.Sync("RomBank3", ref RomBank3); - ser.Sync("Port01", ref Port01); - ser.Sync("Port02", ref Port02); - ser.Sync("Port3E", ref Port3E); - ser.Sync("Port3F", ref Port3F); - ser.Sync("Paddle1High", ref Paddle1High); - ser.Sync("Paddle2High", ref Paddle2High); - ser.Sync("LatchLightPhaser", ref LatchLightPhaser); - - if (SaveRAM != null) - { - ser.Sync("SaveRAM", ref SaveRAM, false); - ser.Sync("SaveRamBank", ref SaveRamBank); - } - - if (ExtRam != null) - { - ser.Sync("ExtRAM", ref ExtRam, true); - } - - if (HasYM2413) - { - YM2413.SyncState(ser); - } - - ser.Sync("Frame", ref _frame); - ser.Sync("LagCount", ref _lagCount); - ser.Sync("IsLag", ref _isLag); - - ser.EndSection(); - - if (ser.IsReader) - { - SyncAllByteArrayDomains(); - } - } - } -} +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; + + +namespace BizHawk.Emulation.Cores.Sega.MasterSystem +{ + public sealed partial class SMS : IStatable + { + public bool BinarySaveStatesPreferred + { + get { return true; } + } + + public void SaveStateText(TextWriter writer) + { + SyncState(new Serializer(writer)); + } + + public void LoadStateText(TextReader reader) + { + SyncState(new Serializer(reader)); + } + + public void SaveStateBinary(BinaryWriter bw) + { + SyncState(new Serializer(bw)); + } + + public void LoadStateBinary(BinaryReader br) + { + SyncState(new Serializer(br)); + } + + public byte[] SaveStateBinary() + { + MemoryStream ms = new MemoryStream(); + BinaryWriter bw = new BinaryWriter(ms); + SaveStateBinary(bw); + bw.Flush(); + return ms.ToArray(); + } + + private void SyncState(Serializer ser) + { + byte[] core = null; + if (ser.IsWriter) + { + var ms = new MemoryStream(); + ms.Close(); + core = ms.ToArray(); + } + Cpu.SyncState(ser); + + ser.BeginSection("SMS"); + Vdp.SyncState(ser); + PSG.SyncState(ser); + ser.Sync("RAM", ref SystemRam, false); + ser.Sync("RomBank0", ref RomBank0); + ser.Sync("RomBank1", ref RomBank1); + ser.Sync("RomBank2", ref RomBank2); + ser.Sync("RomBank3", ref RomBank3); + ser.Sync("Port01", ref Port01); + ser.Sync("Port02", ref Port02); + ser.Sync("Port3E", ref Port3E); + ser.Sync("Port3F", ref Port3F); + ser.Sync("Paddle1High", ref Paddle1High); + ser.Sync("Paddle2High", ref Paddle2High); + ser.Sync("LatchLightPhaser", ref LatchLightPhaser); + + if (SaveRAM != null) + { + ser.Sync("SaveRAM", ref SaveRAM, false); + ser.Sync("SaveRamBank", ref SaveRamBank); + } + + if (ExtRam != null) + { + ser.Sync("ExtRAM", ref ExtRam, true); + } + + if (HasYM2413) + { + YM2413.SyncState(ser); + } + + if (EEPROM != null) + { + EEPROM.SyncState(ser); + } + + ser.Sync("Frame", ref _frame); + ser.Sync("LagCount", ref _lagCount); + ser.Sync("IsLag", ref _isLag); + + ser.EndSection(); + + if (ser.IsReader) + { + SyncAllByteArrayDomains(); + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index b3f51ba047..423b11b965 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -4,7 +4,7 @@ using BizHawk.Common.StringExtensions; using BizHawk.Emulation.Common; using BizHawk.Emulation.Common.Components; using BizHawk.Emulation.Cores.Components; -using BizHawk.Emulation.Cores.Components.Z80; +using BizHawk.Emulation.Cores.Components.Z80A; /***************************************************** TODO: @@ -75,11 +75,12 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem HasYM2413 = true; } - Cpu = new Z80A + Cpu = new Z80A() { - RegisterSP = 0xDFF0, ReadHardware = ReadPort, WriteHardware = WritePort, + ReadMemory = ReadMemory, + WriteMemory = WriteMemory, MemoryCallbacks = MemoryCallbacks }; @@ -113,6 +114,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem InitNemesisMapper(); else if (game["TerebiOekaki"]) InitTerebiOekaki(); + else if (game["EEPROM"]) + InitEEPROMMapper(); else InitSegaMapper(); @@ -160,7 +163,10 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem } if (game["SRAM"]) + { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; + Console.WriteLine(SaveRAM.Length); + } else if (game.NotInDatabase) SaveRAM = new byte[0x8000]; @@ -175,8 +181,11 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register(Tracer); - serviceProvider.Register(new Disassembler()); + serviceProvider.Register(Cpu); Vdp.ProcessOverscan(); + + Cpu.ReadMemory = ReadMemory; + Cpu.WriteMemory = WriteMemory; } // Constants diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs index 7dcf21971b..adccda7fd3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs @@ -4,7 +4,7 @@ using System.IO; using BizHawk.Common; using BizHawk.Emulation.Common; -using BizHawk.Emulation.Cores.Components.Z80; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.Sega.MasterSystem @@ -113,7 +113,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem StatusByte &= 0x1F; HIntPending = false; VIntPending = false; - Cpu.Interrupt = false; + Cpu.FlagI = false; return returnValue; } @@ -291,13 +291,13 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { case 0: // Mode Control Register 1 CheckVideoMode(); - Cpu.Interrupt = (EnableLineInterrupts && HIntPending); - Cpu.Interrupt |= (EnableFrameInterrupts && VIntPending); + Cpu.FlagI = (EnableLineInterrupts && HIntPending); + Cpu.FlagI |= (EnableFrameInterrupts && VIntPending); break; case 1: // Mode Control Register 2 CheckVideoMode(); - Cpu.Interrupt = (EnableFrameInterrupts && VIntPending); - Cpu.Interrupt |= (EnableLineInterrupts && HIntPending); + Cpu.FlagI = (EnableFrameInterrupts && VIntPending); + Cpu.FlagI |= (EnableLineInterrupts && HIntPending); break; case 2: // Name Table Base Address NameTableBase = CalcNameTableBase(); @@ -347,7 +347,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem if (VIntPending && EnableFrameInterrupts) { - Cpu.Interrupt = true; + Cpu.FlagI = true; } } @@ -361,7 +361,7 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem HIntPending = true; if (EnableLineInterrupts) {; - Cpu.Interrupt = true; + Cpu.FlagI = true; } lineIntLinesRemaining = Registers[0x0A]; } @@ -383,7 +383,14 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem ProcessLineInterrupt(); Sms.ProcessLineControls(); - Cpu.ExecuteCycles(IPeriod); + //Console.Write(Cpu.cur_instr.Length); + //Console.Write(" "); + //Console.WriteLine(Cpu.instr_pntr); + for (int j = 0; j < IPeriod; j++) + { + Cpu.ExecuteOne(); + } + if (ScanLine == scanlinesPerFrame - 1) { diff --git a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj index 4f34ffd071..9ad6e73985 100644 --- a/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj +++ b/BizHawk.Emulation.DiscSystem/BizHawk.Emulation.DiscSystem.csproj @@ -70,6 +70,7 @@ + diff --git a/BizHawk.Emulation.DiscSystem/CDFS/EndianBitConverter.cs b/BizHawk.Emulation.DiscSystem/CDFS/EndianBitConverter.cs index 382cd7c39a..3ecee543b6 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/EndianBitConverter.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/EndianBitConverter.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace BizHawk.Emulation.DiscSystem @@ -114,5 +115,49 @@ namespace BizHawk.Emulation.DiscSystem } #endregion + + // (asni 20171013) - Some methods I wrote that have been shoehorned in from another project to speed up development time + // If these are offensive in any way, tell me I suck and that I need to do more work with existing methods + #region Misc + + /// + /// Returns a byte array of any length + /// Not really anything endian going on, but I struggled to find a better place for it + /// + /// + /// + /// + /// + public byte[] ReadBytes(byte[] buffer, int offset, int length) + { + return buffer.Skip(offset).Take(length).ToArray(); + } + + /// + /// Returns an int32 value from any size byte array + /// (careful, data may/will be truncated) + /// + /// + /// + /// + /// + public int ReadIntValue(byte[] buffer, int offset, int length) + { + var bytes = buffer.Skip(offset).Take(length).ToArray(); + + if (swap) + Array.Reverse(bytes); + + if (length == 1) + return bytes.FirstOrDefault(); + + if (length == 2) + return BitConverter.ToInt16(bytes, 0); + + int result = BitConverter.ToInt32(bytes, 0); + return result; + } + + #endregion } } diff --git a/BizHawk.Emulation.DiscSystem/CDFS/ISODirectoryNode.cs b/BizHawk.Emulation.DiscSystem/CDFS/ISODirectoryNode.cs index 53cd7f09b1..2b40ebb9a0 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/ISODirectoryNode.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/ISODirectoryNode.cs @@ -48,21 +48,24 @@ namespace BizHawk.Emulation.DiscSystem s.Seek(this.Offset * ISOFile.SECTOR_SIZE, SeekOrigin.Begin); List records = new List(); - - // Read the directory entries - while (s.Position < ((this.Offset * ISOFile.SECTOR_SIZE) + this.Length)) + + // Read the directory entries + while (s.Position < ((this.Offset * ISOFile.SECTOR_SIZE) + this.Length)) { ISONode node; ISONodeRecord record; - + // Read the record record = new ISONodeRecord(); - record.Parse(s); + if (ISOFile.Format == ISOFile.ISOFormat.CDInteractive) + record.ParseCDInteractive(s); + if (ISOFile.Format == ISOFile.ISOFormat.ISO9660) + record.ParseISO9660(s); - //zero 24-jun-2013 - improved validity checks - //theres nothing here! - if (record.Length == 0) + //zero 24-jun-2013 - improved validity checks + //theres nothing here! + if (record.Length == 0) { break; } @@ -95,7 +98,8 @@ namespace BizHawk.Emulation.DiscSystem } // Add the node as a child - this.Children.Add(record.Name, node); + if (!this.Children.ContainsKey(record.Name)) + this.Children.Add(record.Name, node); } } diff --git a/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs b/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs index fb848fa2fe..e81d6316a4 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs @@ -2,27 +2,51 @@ using System.Collections.Generic; using System.Text; using System.IO; +using System.Linq; namespace BizHawk.Emulation.DiscSystem { - /// - /// This class is meant to parse disk images as specified by ISO9660. - /// Specifically, it should work for most disk images that are created - /// by the stanard disk imaging software. This class is by no means - /// robust to all variations of ISO9660. - /// Also, this class does not currently support the UDF file system. - /// - /// TODO: Add functions to enumerate a directory or visit a file... - /// - /// The information for building class came from three primary sources: - /// 1. The ISO9660 wikipedia article: - /// http://en.wikipedia.org/wiki/ISO_9660 - /// 2. ISO9660 Simplified for DOS/Windows - /// http://alumnus.caltech.edu/~pje/iso9660.html - /// 3. The ISO 9660 File System - /// http://users.telenet.be/it3.consultants.bvba/handouts/ISO9960.html - /// - public class ISOFile + /// + /// This class is meant to parse disk images as specified by: + /// + /// ISO9660 + /// ------- + /// It should work for most disk images that are created + /// by the stanard disk imaging software. This class is by no means + /// robust to all variations of ISO9660. + /// Also, this class does not currently support the UDF file system. + /// + /// The information for building class came from three primary sources: + /// 1. The ISO9660 wikipedia article: + /// http://en.wikipedia.org/wiki/ISO_9660 + /// 2. ISO9660 Simplified for DOS/Windows + /// http://alumnus.caltech.edu/~pje/iso9660.html + /// 3. The ISO 9660 File System + /// http://users.telenet.be/it3.consultants.bvba/handouts/ISO9960.html + /// + /// + /// CD-I + /// ---- + /// (asni - 20171013) - Class modified to be able to detect and consume Green + /// Book disc images. + /// + /// The implemtation of CD-I in this class adds some (but not all) additional + /// properties to the class structures that CD-I brings. This means that + /// the same ISO class structures can be returned for both standards. + /// These small additions are readily found in ISOVolumeDescriptor.cs + /// + /// ISOFile.cs also now contains a public 'ISOFormat' enum that is set + /// during disc parsing. + /// + /// The main reference source for this implementation: + /// 1. The CD-I Full Functional Specification (aka Green Book) + /// https://www.lscdweb.com/data/downloadables/2/8/cdi_may94_r2.pdf + /// + /// + /// TODO: Add functions to enumerate a directory or visit a file... + /// + /// + public class ISOFile { #region Constants @@ -31,21 +55,37 @@ namespace BizHawk.Emulation.DiscSystem /// public const int SECTOR_SIZE = 2048; - #endregion + #endregion - #region Public Members + #region Static Members - /// - /// This is a list of all the volume descriptors in the disk image. - /// NOTE: The first entry should be the primary volume. - /// - public List VolumeDescriptors; + /// + /// Making this a static for now. Every other way I tried was fairly ineligant (asni) + /// + public static ISOFormat Format; + + public static List CDIPathTable; + + #endregion + + #region Public Members + + /// + /// This is a list of all the volume descriptors in the disk image. + /// NOTE: The first entry should be the primary volume. + /// + public List VolumeDescriptors; /// /// The Directory that is the root of this file system /// public ISODirectoryNode Root; + /// + /// The type of CDFS format detected + /// + public ISOFormat CDFSType; + #endregion #region Construction @@ -77,9 +117,9 @@ namespace BizHawk.Emulation.DiscSystem // Seek through the first volume descriptor s.Seek(startPosition + (SECTOR_SIZE * startSector), SeekOrigin.Begin); - - // Read one of more volume descriptors - do + + // Read one of more volume descriptors + do { //zero 24-jun-2013 - improved validity checks @@ -87,6 +127,8 @@ namespace BizHawk.Emulation.DiscSystem bool isValid = desc.Parse(s); if (!isValid) return false; + this.CDFSType = Format; + if (desc.IsTerminator()) break; else if (desc.Type < 4) @@ -98,16 +140,17 @@ namespace BizHawk.Emulation.DiscSystem } while (true); - //zero 24-jun-2013 - well, my very first test iso had 2 volume descriptors. - // Check to make sure we only read one volume descriptor - // Finding more could be an error with the disk. - //if (this.VolumeDescriptors.Count != 1) { - // Console.WriteLine("Strange ISO format..."); - // return; - //} + //zero 24-jun-2013 - well, my very first test iso had 2 volume descriptors. + // Check to make sure we only read one volume descriptor + // Finding more could be an error with the disk. + //if (this.VolumeDescriptors.Count != 1) { + // Console.WriteLine("Strange ISO format..."); + // return; + //} - //zero 24-jun-2013 - if theres no volume descriptors, we're gonna call this not a cdfs - if (VolumeDescriptors.Count == 0) return false; + + //zero 24-jun-2013 - if theres no volume descriptors, we're gonna call this not a cdfs + if (VolumeDescriptors.Count == 0) return false; // Visit all the directories and get the offset of each directory/file @@ -116,12 +159,68 @@ namespace BizHawk.Emulation.DiscSystem // Create (and visit) the root node this.Root = new ISODirectoryNode(this.VolumeDescriptors[0].RootDirectoryRecord); - visitedNodes.Add(this.Root.Offset, this.Root); - this.Root.Parse(s, visitedNodes); + + visitedNodes.Add(this.Root.Offset, this.Root); + this.Root.Parse(s, visitedNodes); return true; } + + private List> fileNodes; + private List dirsParsed; + + /// + /// Returns a flat list of all recursed files + /// + /// + public List> EnumerateAllFilesRecursively() + { + fileNodes = new List>(); + dirsParsed = new List(); + + if (Root.Children == null) + return fileNodes; + + // get all folders + List> dirs = (from a in Root.Children + where a.Value.GetType() == typeof(ISODirectoryNode) + select a).ToList(); + // iterate through each folder + foreach (var d in dirs) + { + // process all files in this directory (and recursively process files in sub folders + ISODirectoryNode idn = d.Value as ISODirectoryNode; + if (dirsParsed.Where(a => a == idn).Count() > 0) + continue; + + dirsParsed.Add(idn); + ProcessDirectoryFiles(idn.Children); + } + + return fileNodes.Distinct().ToList(); + } + + private void ProcessDirectoryFiles(Dictionary idn) + { + foreach (var n in idn) + { + if (n.Value.GetType() == typeof(ISODirectoryNode)) + { + if (dirsParsed.Where(a => a == n.Value).Count() > 0) + continue; + + dirsParsed.Add(n.Value as ISODirectoryNode); + ProcessDirectoryFiles((n.Value as ISODirectoryNode).Children); + } + else + { + KeyValuePair f = new KeyValuePair(n.Key, n.Value as ISOFileNode); + fileNodes.Add(f); + } + } + } + #endregion #region Printing @@ -135,6 +234,17 @@ namespace BizHawk.Emulation.DiscSystem this.Root.Print(0); } - #endregion - } + #endregion + + #region Misc + + public enum ISOFormat + { + Unknown, + ISO9660, + CDInteractive + } + + #endregion + } } diff --git a/BizHawk.Emulation.DiscSystem/CDFS/ISONodeRecord.cs b/BizHawk.Emulation.DiscSystem/CDFS/ISONodeRecord.cs index 1913f3d897..72bb82cfff 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/ISONodeRecord.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/ISONodeRecord.cs @@ -31,10 +31,16 @@ namespace BizHawk.Emulation.DiscSystem /// public byte Length; - /// - /// The file offset of the data for this file/directory (in sectors). - /// - public long OffsetOfData; + /// + /// This is the number of blocks at the beginning of the file reserved for extended attribute information + /// The format of the extended attribute record is not defined and is reserved for application use + /// + public byte ExtendedAttribRecordLength; + + /// + /// The file offset of the data for this file/directory (in sectors). + /// + public long OffsetOfData; /// /// The length of the data for this file/directory (in bytes). /// @@ -148,14 +154,19 @@ namespace BizHawk.Emulation.DiscSystem // Put the array into a memory stream and pass to the main parsing function MemoryStream s = new MemoryStream(data); s.Seek(cursor, SeekOrigin.Begin); - this.Parse(s); + + if (ISOFile.Format == ISOFile.ISOFormat.ISO9660) + this.ParseISO9660(s); + + if (ISOFile.Format == ISOFile.ISOFormat.CDInteractive) + this.ParseCDInteractive(s); } /// - /// Parse the node record from the given stream. + /// Parse the node record from the given ISO9660 stream. /// /// The stream to parse from. - public void Parse(Stream s) + public void ParseISO9660(Stream s) { EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); long startPosition = s.Position; @@ -212,6 +223,100 @@ namespace BizHawk.Emulation.DiscSystem s.Seek(startPosition + this.Length, SeekOrigin.Begin); } - #endregion - } + /// + /// Parse the node record from the given CD-I stream. + /// + /// The stream to parse from. + public void ParseCDInteractive(Stream s) + { + /* + BP Size in bytes Description + 1 1 Record length + 2 1 Extended Attribute record length + 3 4 Reserved + 7 4 File beginning LBN + 11 4 Reserved + 15 4 File size + 19 6 Creation date + 25 1 Reserved + 26 1 File flags + 27 2 Interleave + 29 2 Reserved + 31 2 Album Set Sequence number + 33 1 File name size + 34 (n) File name + 34+n 4 Owner ID + 38+n 2 Attributes + 40+n 2 Reserved + 42+n 1 File number + 43+n 1 Reserved + 43+n Total + */ + + EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); + EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); + long startPosition = s.Position; + byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; + + // Read the entire structure + s.Read(buffer, 0, ISOFile.SECTOR_SIZE); + s.Position -= ISOFile.SECTOR_SIZE; + + // Get the record length + this.Length = buffer[0]; + + // extended attribute record length + this.ExtendedAttribRecordLength = buffer[1]; + + // Read Data Offset + this.OffsetOfData = bcBig.ReadIntValue(buffer, 6, 4); + + // Read Data Length + this.LengthOfData = bcBig.ReadIntValue(buffer, 14, 4); + + // Read the time + var ti = bc.ReadBytes(buffer, 18, 6); + this.Year = ti[0]; + this.Month = ti[1]; + this.Day = ti[2]; + this.Hour = ti[3]; + this.Minute = ti[4]; + this.Second = ti[5]; + + // read interleave - still to do + + // read album (volume) set sequence number (we are ignoring this) + + // Read the name length + this.NameLength = buffer[32]; + + // Read the file/directory name + var name = bc.ReadBytes(buffer, 33, this.NameLength); + if (this.NameLength == 1 && (name[0] == 0 || name[0] == 1)) + { + if (name[0] == 0) + this.Name = ISONodeRecord.CURRENT_DIRECTORY; + else + this.Name = ISONodeRecord.PARENT_DIRECTORY; + } + else + { + this.Name = ASCIIEncoding.ASCII.GetString(name, 0, this.NameLength); + } + + // skip ownerID for now + + // read the flags - only really interested in the directory attribute (bit 15) + // (confusingly these are called 'attributes' in CD-I. the CD-I 'File Flags' entry is something else entirely) + this.Flags = buffer[37 + this.NameLength]; + + // skip filenumber + //this.FileNumber = buffer[41 + this.NameLength]; + + // Seek to end + s.Seek(startPosition + this.Length, SeekOrigin.Begin); + } + + #endregion + } } diff --git a/BizHawk.Emulation.DiscSystem/CDFS/ISOVolumeDescriptor.cs b/BizHawk.Emulation.DiscSystem/CDFS/ISOVolumeDescriptor.cs index 4dda3f59e4..e8b271e10f 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/ISOVolumeDescriptor.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/ISOVolumeDescriptor.cs @@ -25,14 +25,21 @@ namespace BizHawk.Emulation.DiscSystem private const int LENGTH_TIME = 17; private const int LENGTH_RESERVED = 512; - #endregion + #endregion - #region Public Properties + #region Private Properties - /// - /// The type of this volume description, only 1 and 255 are supported - /// - public byte Type; + private EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); + private EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); + + #endregion + + #region Public Properties + + /// + /// The type of this volume description, only 1 and 255 are supported + /// + public byte Type; /// /// The system identifier @@ -66,21 +73,21 @@ namespace BizHawk.Emulation.DiscSystem /// public int PathTableSize; /// - /// Sector offset of the first path table + /// (ISO9660 only) Sector offset of the first path table /// public int OffsetOfFirstLittleEndianPathTable; - /// - /// Sector offset of the second path table - /// - public int OffsetOfSecondLittleEndianPathTable; - /// - /// Sector offset of the first path table - /// - public int OffsetOfFirstBigEndianPathTable; - /// - /// Sector offset of the second path table - /// - public int OffsetOfSecondBigEndianPathTable; + /// + /// (ISO9660 only) Sector offset of the second path table + /// + public int OffsetOfSecondLittleEndianPathTable; + /// + /// (ISO9660 only) Sector offset of the first path table + /// + public int OffsetOfFirstBigEndianPathTable; + /// + /// (ISO9660 only) Sector offset of the second path table + /// + public int OffsetOfSecondBigEndianPathTable; /// /// The root directory record @@ -134,19 +141,43 @@ namespace BizHawk.Emulation.DiscSystem /// public byte[] EffectiveDateTime; - /// - /// Extra reserved data - /// - public byte[] Reserved; + /// + /// (ISO9660 only) Extra reserved data + /// + public byte[] Reserved; - #endregion - #region Construction + // CD-Interactive only + + /// + /// The bits of this field are numbered from 0 to 7 starting with the least significant bit + /// BitPosition 0: A value of 0 = the coded character set identifier field specifies only an escape sequence registered according to ISO 2375 + /// A value of 1 = the coded character set identifier field specifies only an escape sequence NOT registered according to ISO 2375 + /// BitPostion 1-7: All bits are 0 (reserved for future standardization) + /// + public byte VolumeFlags; + /// + /// This field specifies one escape sequence according to the International Register of Coded Character Sets to be used with escape + /// sequence standards for recording.The ESC character, which is the first character of all sequences, shall be omitted when recording this field + /// + public byte[] CodedCharSetIdent; + /// + /// The block address of the first block of the system Path Table is kept in this field + /// + public int AddressOfPathTable; + /// + /// This number is used to indicate the revision number of the file structure standard to which the + /// directory search files conform. It is set to one + /// - /// - /// Constructor. - /// - public ISOVolumeDescriptor() + #endregion + + #region Construction + + /// + /// Constructor. + /// + public ISOVolumeDescriptor() { // Set everything to the default value this.Type = 0; @@ -183,6 +214,11 @@ namespace BizHawk.Emulation.DiscSystem this.EffectiveDateTime = new byte[LENGTH_TIME]; this.Reserved = new byte[LENGTH_RESERVED]; + + // CD-I specific + this.VolumeFlags = 0; + this.CodedCharSetIdent = new byte[LENGTH_SHORT_IDENTIFIER]; + this.AddressOfPathTable = 0; } #endregion @@ -190,137 +226,391 @@ namespace BizHawk.Emulation.DiscSystem #region Parsing /// - /// Parse the volume descriptor header. + /// Start parsing the volume descriptor header. /// /// The stream to parse from. public bool Parse(Stream s) { - EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); - EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); long startPosition = s.Position; byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; // Read the entire structure s.Read(buffer, 0, ISOFile.SECTOR_SIZE); - // Get the type - this.Type = buffer[0]; + // Parse based on format + byte[] header = bc.ReadBytes(buffer, 0, ISOFile.SECTOR_SIZE); + if (GetISO9660(header)) + { + ParseISO9660(s); + return true; + } + if (GetCDI(header)) + { + ParseCDInteractive(s); + return true; + } - //zero 24-jun-2013 - validate - // "CD001" + 0x01 - if (buffer[1] == 'C' && buffer[2] == 'D' && buffer[3] == '0' && buffer[4] == '0' && buffer[5] == '1' && buffer[6] == 0x01) - { - //it seems to be a valid volume descriptor - } - else - { - return false; - } - - // Handle the primary volume information - if (this.Type == 1) - { - int cursor = 8; - // Get the system identifier - Array.Copy(buffer, cursor, - this.SystemIdentifier, 0, LENGTH_SHORT_IDENTIFIER); - cursor += LENGTH_SHORT_IDENTIFIER; - - // Get the volume identifier - Array.Copy(buffer, cursor, - this.VolumeIdentifier, 0, LENGTH_SHORT_IDENTIFIER); - cursor += LENGTH_SHORT_IDENTIFIER; - - cursor += 8; - - // Get the total number of sectors - this.NumberOfSectors = bc.ToInt32(buffer, cursor); - cursor += 8; - - cursor += 32; - - this.VolumeSetSize = bc.ToInt16(buffer, cursor); - cursor += 4; - this.VolumeSequenceNumber = bc.ToInt16(buffer, cursor); - cursor += 4; - this.SectorSize = bc.ToInt16(buffer, cursor); - cursor += 4; - - this.PathTableSize = bc.ToInt32(buffer, cursor); - cursor += 8; - this.OffsetOfFirstLittleEndianPathTable = bc.ToInt32(buffer, cursor); - cursor += 4; - this.OffsetOfSecondLittleEndianPathTable = bc.ToInt32(buffer, cursor); - cursor += 4; - this.OffsetOfFirstLittleEndianPathTable = bcBig.ToInt32(buffer, cursor); - cursor += 4; - this.OffsetOfSecondLittleEndianPathTable = bcBig.ToInt32(buffer, cursor); - cursor += 4; - - this.RootDirectoryRecord.Parse(buffer, cursor); - cursor += LENGTH_ROOT_DIRECTORY_RECORD; - - Array.Copy(buffer, cursor, - this.VolumeSetIdentifier, 0, LENGTH_LONG_IDENTIFIER); - cursor += LENGTH_LONG_IDENTIFIER; - Array.Copy(buffer, cursor, - this.PublisherIdentifier, 0, LENGTH_LONG_IDENTIFIER); - cursor += LENGTH_LONG_IDENTIFIER; - Array.Copy(buffer, cursor, - this.DataPreparerIdentifier, 0, LENGTH_LONG_IDENTIFIER); - cursor += LENGTH_LONG_IDENTIFIER; - Array.Copy(buffer, cursor, - this.ApplicationIdentifier, 0, LENGTH_LONG_IDENTIFIER); - cursor += LENGTH_LONG_IDENTIFIER; - - Array.Copy(buffer, cursor, - this.CopyrightFileIdentifier, 0, LENGTH_IDENTIFIER); - cursor += LENGTH_IDENTIFIER; - Array.Copy(buffer, cursor, - this.AbstractFileIdentifier, 0, LENGTH_IDENTIFIER); - cursor += LENGTH_IDENTIFIER; - Array.Copy(buffer, cursor, - this.BibliographicalFileIdentifier, 0, LENGTH_IDENTIFIER); - cursor += LENGTH_IDENTIFIER; - - Array.Copy(buffer, cursor, - this.VolumeCreationDateTime, 0, LENGTH_TIME); - cursor += LENGTH_TIME; - Array.Copy(buffer, cursor, - this.LastModifiedDateTime, 0, LENGTH_TIME); - cursor += LENGTH_TIME; - Array.Copy(buffer, cursor, - this.ExpirationDateTime, 0, LENGTH_TIME); - cursor += LENGTH_TIME; - Array.Copy(buffer, cursor, - this.EffectiveDateTime, 0, LENGTH_TIME); - cursor += LENGTH_TIME; - - cursor += 1; - - cursor += 1; - - Array.Copy(buffer, cursor, - this.Reserved, 0, LENGTH_RESERVED); - cursor += LENGTH_RESERVED; - } - - return true; + return false; } - #endregion + public void ParseISO9660(Stream s) + { + long startPosition = s.Position; + byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; + s.Position = startPosition - ISOFile.SECTOR_SIZE; - #region Type Information + // Read the entire structure + s.Read(buffer, 0, ISOFile.SECTOR_SIZE); - /// - /// Returns true if this is the terminator volume descriptor. - /// - /// True if the terminator. - public bool IsTerminator() + // Get the type + this.Type = buffer[0]; + + // Handle the primary volume information + if (this.Type == 1) + { + int cursor = 8; + // Get the system identifier + Array.Copy(buffer, cursor, + this.SystemIdentifier, 0, LENGTH_SHORT_IDENTIFIER); + cursor += LENGTH_SHORT_IDENTIFIER; + + // Get the volume identifier + Array.Copy(buffer, cursor, + this.VolumeIdentifier, 0, LENGTH_SHORT_IDENTIFIER); + cursor += LENGTH_SHORT_IDENTIFIER; + + cursor += 8; + + // Get the total number of sectors + this.NumberOfSectors = bc.ToInt32(buffer, cursor); + cursor += 8; + + cursor += 32; + + this.VolumeSetSize = bc.ToInt16(buffer, cursor); + cursor += 4; + this.VolumeSequenceNumber = bc.ToInt16(buffer, cursor); + cursor += 4; + this.SectorSize = bc.ToInt16(buffer, cursor); + cursor += 4; + + this.PathTableSize = bc.ToInt32(buffer, cursor); + cursor += 8; + this.OffsetOfFirstLittleEndianPathTable = bc.ToInt32(buffer, cursor); + cursor += 4; + this.OffsetOfSecondLittleEndianPathTable = bc.ToInt32(buffer, cursor); + cursor += 4; + this.OffsetOfFirstLittleEndianPathTable = bcBig.ToInt32(buffer, cursor); + cursor += 4; + this.OffsetOfSecondLittleEndianPathTable = bcBig.ToInt32(buffer, cursor); + cursor += 4; + + this.RootDirectoryRecord.Parse(buffer, cursor); + cursor += LENGTH_ROOT_DIRECTORY_RECORD; + + Array.Copy(buffer, cursor, + this.VolumeSetIdentifier, 0, LENGTH_LONG_IDENTIFIER); + cursor += LENGTH_LONG_IDENTIFIER; + Array.Copy(buffer, cursor, + this.PublisherIdentifier, 0, LENGTH_LONG_IDENTIFIER); + cursor += LENGTH_LONG_IDENTIFIER; + Array.Copy(buffer, cursor, + this.DataPreparerIdentifier, 0, LENGTH_LONG_IDENTIFIER); + cursor += LENGTH_LONG_IDENTIFIER; + Array.Copy(buffer, cursor, + this.ApplicationIdentifier, 0, LENGTH_LONG_IDENTIFIER); + cursor += LENGTH_LONG_IDENTIFIER; + + Array.Copy(buffer, cursor, + this.CopyrightFileIdentifier, 0, LENGTH_IDENTIFIER); + cursor += LENGTH_IDENTIFIER; + Array.Copy(buffer, cursor, + this.AbstractFileIdentifier, 0, LENGTH_IDENTIFIER); + cursor += LENGTH_IDENTIFIER; + Array.Copy(buffer, cursor, + this.BibliographicalFileIdentifier, 0, LENGTH_IDENTIFIER); + cursor += LENGTH_IDENTIFIER; + + Array.Copy(buffer, cursor, + this.VolumeCreationDateTime, 0, LENGTH_TIME); + cursor += LENGTH_TIME; + Array.Copy(buffer, cursor, + this.LastModifiedDateTime, 0, LENGTH_TIME); + cursor += LENGTH_TIME; + Array.Copy(buffer, cursor, + this.ExpirationDateTime, 0, LENGTH_TIME); + cursor += LENGTH_TIME; + Array.Copy(buffer, cursor, + this.EffectiveDateTime, 0, LENGTH_TIME); + cursor += LENGTH_TIME; + + cursor += 1; + + cursor += 1; + + Array.Copy(buffer, cursor, + this.Reserved, 0, LENGTH_RESERVED); + cursor += LENGTH_RESERVED; + } + } + + public void ParseCDInteractive(Stream s) + { + /* From the Green Book Spec + * BP (byte position) obviously is n+1 + + BP Size in Bytes Description + 1 1 Disc Label Record Type + 2 5 Volume Structure Standard ID + 7 1 Volume Structure Version number + 8 1 Volume flags + 9 32 System identifier + 41 32 Volume identifier + 73 12 Reserved + 85 4 Volume space size + 89 32 Coded Character Set identifier + 121 2 Reserved + 123 2 Number of Volumes in Album + 125 2 Reserved + 127 2 Album Set Sequence number + 129 2 Reserved + 131 2 Logical Block size + 133 4 Reserved + 137 4 Path Table size + 141 8 Reserved + 149 4 Address of Path Table + 153 38 Reserved + 191 128 Album identifier + 319 128 Publisher identifier + 447 128 Data Preparer identifier + 575 128 Application identifier + 703 32 Copyright file name + 735 5 Reserved + 740 32 Abstract file name + 772 5 Reserved + 777 32 Bibliographic file name + 809 5 Reserved + 814 16 Creation date and time + 830 1 Reserved + 831 16 Modification date and time + 847 1 Reserved + 848 16 Expiration date and time + 864 1 Reserved + 865 16 Effective date and time + 881 1 Reserved + 882 1 File Structure Standard Version number + 883 1 Reserved + 884 512 Application use + 1396 653 Reserved */ + + long startPosition = s.Position; + byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; + s.Position = startPosition - ISOFile.SECTOR_SIZE; + + // Read the entire structure + s.Read(buffer, 0, ISOFile.SECTOR_SIZE); + + // Get the type + this.Type = buffer[0]; + + // Handle the primary volume information + if (this.Type == 1) + { + this.VolumeFlags = buffer[7]; + this.SystemIdentifier = bc.ReadBytes(buffer, 8, LENGTH_SHORT_IDENTIFIER); + this.VolumeIdentifier = bc.ReadBytes(buffer, 40, LENGTH_SHORT_IDENTIFIER); + this.NumberOfSectors = bcBig.ReadIntValue(buffer, 84, 4); + this.CodedCharSetIdent = bc.ReadBytes(buffer, 88, LENGTH_SHORT_IDENTIFIER); + this.VolumeSetSize = bcBig.ReadIntValue(buffer, 122, 2); + this.VolumeSequenceNumber = bcBig.ReadIntValue(buffer, 126, 2); + this.SectorSize = bcBig.ReadIntValue(buffer, 130, 2); + this.PathTableSize = bcBig.ReadIntValue(buffer, 136, 4); + this.AddressOfPathTable = bcBig.ReadIntValue(buffer, 148, 4); + + this.VolumeSetIdentifier = bc.ReadBytes(buffer, 190, LENGTH_LONG_IDENTIFIER); + this.PublisherIdentifier = bc.ReadBytes(buffer, 318, LENGTH_LONG_IDENTIFIER); + this.DataPreparerIdentifier = bc.ReadBytes(buffer, 446, LENGTH_LONG_IDENTIFIER); + this.ApplicationIdentifier = bc.ReadBytes(buffer, 574, LENGTH_LONG_IDENTIFIER); + + this.CopyrightFileIdentifier = bc.ReadBytes(buffer, 702, LENGTH_SHORT_IDENTIFIER); + this.AbstractFileIdentifier = bc.ReadBytes(buffer, 739, LENGTH_SHORT_IDENTIFIER); + this.BibliographicalFileIdentifier = bc.ReadBytes(buffer, 776, LENGTH_SHORT_IDENTIFIER); + + this.VolumeCreationDateTime = bc.ReadBytes(buffer, 813, 16); + this.LastModifiedDateTime = bc.ReadBytes(buffer, 830, 16); + this.ExpirationDateTime = bc.ReadBytes(buffer, 847, 16); + this.EffectiveDateTime = bc.ReadBytes(buffer, 864, 16); + + // save current position + long pos = s.Position; + + // get path table records + s.Position = ISOFile.SECTOR_SIZE * this.AddressOfPathTable; + ISOFile.CDIPathTable = CDIPathNode.ParsePathTable(s, this.PathTableSize); + + // read the root dir record + s.Position = ISOFile.SECTOR_SIZE * ISOFile.CDIPathTable[0].DirectoryBlockAddress; + s.Read(buffer, 0, ISOFile.SECTOR_SIZE); + this.RootDirectoryRecord.Parse(buffer, 0); + + // go back to where we were + s.Position = pos; + } + } + + /// + /// Detect ISO9660 + /// + /// + /// + public bool GetISO9660(byte[] buffer) + { + //zero 24-jun-2013 - validate ISO9660 + // "CD001" + 0x01 + if (buffer[1] == 'C' && buffer[2] == 'D' && buffer[3] == '0' && buffer[4] == '0' && buffer[5] == '1' && buffer[6] == 0x01) + { + ISOFile.Format = ISOFile.ISOFormat.ISO9660; + return true; + } + + return false; + } + + /// + /// Detect CD-I + /// + /// + /// + public bool GetCDI(byte[] buffer) + { + // CD-Interactive + if (Encoding.ASCII.GetString(bc.ReadBytes(buffer, 1, 5)).Contains("CD-I")) + { + ISOFile.Format = ISOFile.ISOFormat.CDInteractive; + return true; + } + + return false; + } + + #endregion + + #region Type Information + + /// + /// Returns true if this is the terminator volume descriptor. + /// + /// True if the terminator. + public bool IsTerminator() { return (this.Type == 255); } #endregion } + + /// + /// Represents a Directory Path Table entry on a CD-I disc + /// + public class CDIPathNode + { + #region Public Properties + + /// + /// The length of the directory name. + /// + public byte NameLength; + + /// + /// This is the length of the Extended Attribute record + /// + public byte ExtendedAttribRecordLength; + + /// + /// This field contains the beginning logical block number (LBN) of the directory file on disc + /// + public int DirectoryBlockAddress; + + /// + /// This is the number (relative to the beginning of the Path Table) of this directory's parent + /// + public int ParentDirectoryNumber; + + /// + /// The directory name. + /// This variable length field is used to store the actual text representing the name of the directory. + /// If the length of the file name is odd, a null padding byte is added to make the size of the Path Table record even. + /// The padding byte is not included in the name size field. + /// + public string Name; + + #endregion + + #region Construction + + /// + /// Empty Constructor + /// + public CDIPathNode() + { + + } + + #endregion + + #region Parsing + + /* + BP Size in bytes Description + 1 1 Name size + 2 1 Extended Attribute record length + 3 4 Directory block address + 7 2 Parent Directory number + 9 n Directory file name + */ + + public static List ParsePathTable(Stream s, int PathTableSize) + { + EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); + EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); + + byte[] buffer = new byte[ISOFile.SECTOR_SIZE]; + + // Read the entire structure + s.Read(buffer, 0, ISOFile.SECTOR_SIZE); + + int startCursor = 0; + + List pathNodes = new List(); + + int pad = 0; + + do + { + CDIPathNode node = new CDIPathNode(); + byte[] data = bc.ReadBytes(buffer, startCursor, ISOFile.SECTOR_SIZE - startCursor); + node.NameLength = data[0]; + + node.ExtendedAttribRecordLength = data[1]; + node.DirectoryBlockAddress = bcBig.ReadIntValue(data, 2, 4); + node.ParentDirectoryNumber = bcBig.ReadIntValue(data, 6, 2); + node.Name = Encoding.ASCII.GetString(bc.ReadBytes(data, 8, data[0])); + + // if nameLength is odd a padding byte must be added + + if (node.NameLength % 2 != 0) + pad = 1; + + pathNodes.Add(node); + + startCursor += node.NameLength + 8; + + } while (startCursor < PathTableSize + pad); + + + return pathNodes; + } + + #endregion + } } diff --git a/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs b/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs new file mode 100644 index 0000000000..59ba49d5a5 --- /dev/null +++ b/BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs @@ -0,0 +1,907 @@ +using System; +using System.Text; +using System.IO; +using System.Globalization; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace BizHawk.Emulation.DiscSystem +{ + /// + /// Parsing Alcohol 120% files + /// Info taken from: + /// * http://forum.redump.org/post/41803/#p41803 + /// * Libmirage image-mds parser - https://sourceforge.net/projects/cdemu/files/libmirage/ + /// * DiscImageChef - https://github.com/claunia/DiscImageChef/blob/master/DiscImageChef.DiscImages/Alcohol120.cs + /// + public class MDS_Format + { + /// + /// A loose representation of an Alcohol 120 .mds file (with a few extras) + /// + public class AFile + { + /// + /// Full path to the MDS file + /// + public string MDSPath; + + /// + /// MDS Header + /// + public AHeader Header = new AHeader(); + + /// + /// List of MDS session blocks + /// + public List Sessions = new List(); + + /// + /// List of track blocks + /// + public List Tracks = new List(); + + /// + /// Current parsed session objects + /// + public List ParsedSession = new List(); + + /// + /// Calculated MDS TOC entries (still to be parsed into BizHawk) + /// + public List TOCEntries = new List(); + + } + + public class AHeader + { + /// + /// Standard alcohol 120% signature - usually "MEDIA DESCRIPTOR" + /// + public string Signature; // 16 bytes + + /// + /// Alcohol version? + /// + public byte[] Version; // 2 bytes + + /// + /// The medium type + /// * 0x00 - CD + /// * 0x01 - CD-R + /// * 0x02 - CD-RW + /// * 0x10 - DVD + /// * 0x12 - DVD-R + /// + public int Medium; + + /// + /// Number of sessions + /// + public int SessionCount; + + /// + /// Burst Cutting Area length + /// + public int BCALength; + + /// + /// Burst Cutting Area data offset + /// + public Int64 BCAOffset; + + /// + /// Offset to disc (DVD?) structures + /// + public Int64 StructureOffset; + + /// + /// Offset to the first session block + /// + public Int64 SessionOffset; + + /// + /// Data Position Measurement offset + /// + public Int64 DPMOffset; + + /// + /// Parse mds stream for the header + /// + /// + /// + public AHeader Parse(Stream stream) + { + EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); + EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); + + byte[] header = new byte[88]; + stream.Read(header, 0, 88); + + this.Signature = Encoding.ASCII.GetString(header.Take(16).ToArray()); + this.Version = header.Skip(16).Take(2).ToArray(); + this.Medium = bc.ToInt16(header.Skip(18).Take(2).ToArray()); + this.SessionCount = bc.ToInt16(header.Skip(20).Take(2).ToArray()); + this.BCALength = bc.ToInt16(header.Skip(26).Take(2).ToArray()); + this.BCAOffset = bc.ToInt32(header.Skip(36).Take(4).ToArray()); + this.StructureOffset = bc.ToInt32(header.Skip(64).Take(4).ToArray()); + this.SessionOffset = bc.ToInt32(header.Skip(80).Take(4).ToArray()); + this.DPMOffset = bc.ToInt32(header.Skip(84).Take(4).ToArray()); + + return this; + } + } + + /// + /// MDS session block representation + /// + public class ASession + { + public int SessionStart; /* Session's start address */ + public int SessionEnd; /* Session's end address */ + public int SessionNumber; /* Session number */ + public byte AllBlocks; /* Number of all data blocks. */ + public byte NonTrackBlocks; /* Number of lead-in data blocks */ + public int FirstTrack; /* First track in session */ + public int LastTrack; /* Last track in session */ + public Int64 TrackOffset; /* Offset of lead-in+regular track data blocks. */ + } + + /// + /// Representation of an MDS track block + /// For convenience (and extra confusion) this also holds the track extrablock, filename(footer) block infos + /// as well as the calculated image filepath as specified in the MDS file + /// + public class ATrack + { + /// + /// The specified data mode + /// 0x00 - None (no data) + /// 0x02 - DVD + /// 0xA9 - Audio + /// 0xAA - Mode1 + /// 0xAB - Mode2 + /// 0xAC - Mode2 Form1 + /// 0xAD - Mode2 Form2 + /// + public byte Mode; /* Track mode */ + + /// + /// Subchannel mode for the track (0x00 = None, 0x08 = Interleaved) + /// + public byte SubMode; /* Subchannel mode */ + + /* These are the fields from Sub-channel Q information, which are + also returned in full TOC by READ TOC/PMA/ATIP command */ + public int ADR_Control; /* Adr/Ctl */ + public int TrackNo; /* Track number field */ + public int Point; /* Point field (= track number for track entries) */ + public int AMin; /* Min */ + public int ASec; /* Sec */ + public int AFrame; /* Frame */ + public int Zero; /* Zero */ + public int PMin; /* PMin */ + public int PSec; /* PSec */ + public int PFrame; /* PFrame */ + + public Int64 ExtraOffset; /* Start offset of this track's extra block. */ + public int SectorSize; /* Sector size. */ + public Int64 PLBA; /* Track start sector (PLBA). */ + public ulong StartOffset; /* Track start offset (from beginning of MDS file) */ + public Int64 Files; /* Number of filenames for this track */ + public Int64 FooterOffset; /* Start offset of footer (from beginning of MDS file) */ + + /// + /// Track extra block + /// + public ATrackExtra ExtraBlock = new ATrackExtra(); + + /// + /// List of footer(filename) blocks for this track + /// + public List FooterBlocks = new List(); + + /// + /// List of the calculated full paths to this track's image file + /// The MDS file itself may contain a filename, or just an *.extension + /// + public List ImageFileNamePaths = new List(); + + public int BlobIndex; + } + + /// + /// Extra track block + /// + public class ATrackExtra + { + public Int64 Pregap; /* Number of sectors in pregap. */ + public Int64 Sectors; /* Number of sectors in track. */ + } + + /// + /// Footer (filename) block - potentially one for every track + /// + public class AFooter + { + public Int64 FilenameOffset; /* Start offset of image filename string (from beginning of mds file) */ + public Int64 WideChar; /* Seems to be set to 1 if widechar filename is used */ + } + + /// + /// Represents a parsed MDS TOC entry + /// + public class ATOCEntry + { + public ATOCEntry(int entryNum) + { + EntryNum = entryNum; + } + + /// + /// these should be 0-indexed + /// + public int EntryNum; + + + /// + /// 1-indexed - the session that this entry belongs to + /// + public int Session; + + /// + /// this seems just to be the LBA corresponding to AMIN:ASEC:AFRAME (give or take 150). It's not stored on the disc, and it's redundant. + /// + //public int ALBA; + + /// + /// this seems just to be the LBA corresponding to PMIN:PSEC:PFRAME (give or take 150). + /// + public int PLBA; + + //these correspond pretty directly to values in the Q subchannel fields + //NOTE: they're specified as absolute MSF. That means, they're 2 seconds off from what they should be when viewed as final TOC values + public int ADR_Control; + public int TrackNo; + public int Point; + public int AMin; + public int ASec; + public int AFrame; + public int Zero; + public int PMin; + public int PSec; + public int PFrame; + + + public int SectorSize; + public long TrackOffset; + + /// + /// List of the calculated full paths to this track's image file + /// The MDS file itself may contain a filename, or just an *.extension + /// + public List ImageFileNamePaths = new List(); + + /// + /// Track extra block + /// + public ATrackExtra ExtraBlock = new ATrackExtra(); + + public int BlobIndex; + } + + public AFile Parse(Stream stream) + { + EndianBitConverter bc = EndianBitConverter.CreateForLittleEndian(); + EndianBitConverter bcBig = EndianBitConverter.CreateForBigEndian(); + bool isDvd = false; + + AFile aFile = new AFile(); + + aFile.MDSPath = (stream as FileStream).Name; + + stream.Seek(0, SeekOrigin.Begin); + + // check whether the header in the mds file is long enough + if (stream.Length < 88) throw new MDSParseException("Malformed MDS format: The descriptor file does not appear to be long enough."); + + // parse header + aFile.Header = aFile.Header.Parse(stream); + + // parse sessions + Dictionary aSessions = new Dictionary(); + + stream.Seek(aFile.Header.SessionOffset, SeekOrigin.Begin); + for (int se = 0; se < aFile.Header.SessionCount; se++) + { + byte[] sessionHeader = new byte[24]; + stream.Read(sessionHeader, 0, 24); + //sessionHeader.Reverse().ToArray(); + + ASession session = new ASession(); + + session.SessionStart = bc.ToInt32(sessionHeader.Take(4).ToArray()); + session.SessionEnd = bc.ToInt32(sessionHeader.Skip(4).Take(4).ToArray()); + session.SessionNumber = bc.ToInt16(sessionHeader.Skip(8).Take(2).ToArray()); + session.AllBlocks = sessionHeader[10]; + session.NonTrackBlocks = sessionHeader[11]; + session.FirstTrack = bc.ToInt16(sessionHeader.Skip(12).Take(2).ToArray()); + session.LastTrack = bc.ToInt16(sessionHeader.Skip(14).Take(2).ToArray()); + session.TrackOffset = bc.ToInt32(sessionHeader.Skip(20).Take(4).ToArray()); + + + //mdsf.Sessions.Add(session); + aSessions.Add(session.SessionNumber, session); + } + + long footerOffset = 0; + + // parse track blocks + Dictionary aTracks = new Dictionary(); + + // iterate through each session block + foreach (ASession session in aSessions.Values) + { + stream.Seek(session.TrackOffset, SeekOrigin.Begin); + //Dictionary sessionToc = new Dictionary(); + + // iterate through every block specified in each session + for (int bl = 0; bl < session.AllBlocks; bl++) + { + byte[] trackHeader; + ATrack track = new ATrack(); + + trackHeader = new byte[80]; + + stream.Read(trackHeader, 0, 80); + + track.Mode = trackHeader[0]; + track.SubMode = trackHeader[1]; + track.ADR_Control = trackHeader[2]; + track.TrackNo = trackHeader[3]; + track.Point = trackHeader[4]; + track.AMin = trackHeader[5]; + track.ASec = trackHeader[6]; + track.AFrame = trackHeader[7]; + track.Zero = trackHeader[8]; + track.PMin = trackHeader[9]; + track.PSec = trackHeader[10]; + track.PFrame = trackHeader[11]; + track.ExtraOffset = bc.ToInt32(trackHeader.Skip(12).Take(4).ToArray()); + track.SectorSize = bc.ToInt16(trackHeader.Skip(16).Take(2).ToArray()); + track.PLBA = bc.ToInt32(trackHeader.Skip(36).Take(4).ToArray()); + track.StartOffset = BitConverter.ToUInt64(trackHeader.Skip(40).Take(8).ToArray(), 0); + track.Files = bc.ToInt32(trackHeader.Skip(48).Take(4).ToArray()); + track.FooterOffset = bc.ToInt32(trackHeader.Skip(52).Take(4).ToArray()); + + if (track.Mode == 0x02) + { + isDvd = true; + throw new MDSParseException("DVD Detected. Not currently supported!"); + } + + + // check for track extra block - this can probably be handled in a separate loop, + // but I'll just store the current stream position then seek forward to the extra block for this track + Int64 currPos = stream.Position; + + // Only CDs have extra blocks - for DVDs ExtraOffset = track length + if (track.ExtraOffset > 0 && !isDvd) + { + byte[] extHeader = new byte[8]; + stream.Seek(track.ExtraOffset, SeekOrigin.Begin); + stream.Read(extHeader, 0, 8); + track.ExtraBlock.Pregap = bc.ToInt32(extHeader.Take(4).ToArray()); + track.ExtraBlock.Sectors = bc.ToInt32(extHeader.Skip(4).Take(4).ToArray()); + stream.Seek(currPos, SeekOrigin.Begin); + } + else if (isDvd == true) + { + track.ExtraBlock.Sectors = track.ExtraOffset; + } + + // read the footer/filename block for this track + currPos = stream.Position; + long numOfFilenames = track.Files; + for (long fi = 1; fi <= numOfFilenames; fi++) + { + // skip leadin/out info tracks + if (track.FooterOffset == 0) + continue; + + byte[] foot = new byte[16]; + stream.Seek(track.FooterOffset, SeekOrigin.Begin); + stream.Read(foot, 0, 16); + + AFooter f = new AFooter(); + f.FilenameOffset = bc.ToInt32(foot.Take(4).ToArray()); + f.WideChar = bc.ToInt32(foot.Skip(4).Take(4).ToArray()); + track.FooterBlocks.Add(f); + track.FooterBlocks = track.FooterBlocks.Distinct().ToList(); + + // parse the filename string + string fileName = "*.mdf"; + if (f.FilenameOffset > 0) + { + // filename offset is present + stream.Seek(f.FilenameOffset, SeekOrigin.Begin); + byte[] fname; + + if (numOfFilenames == 1) + { + if (aFile.Header.DPMOffset == 0) + { + // filename is in the remaining space to EOF + fname = new byte[stream.Length - stream.Position]; + } + else + { + // filename is in the remaining space to EOF + dpm offset + fname = new byte[aFile.Header.DPMOffset - stream.Position]; + } + } + + else + { + // looks like each filename string is 6 bytes with a trailing \0 + fname = new byte[6]; + } + + + // read the filename + stream.Read(fname, 0, fname.Length); + + // if widechar is 1 filename is stored using 16-bit, otherwise 8-bit is used + if (f.WideChar == 1) + fileName = Encoding.Unicode.GetString(fname).TrimEnd('\0'); + else + fileName = Encoding.Default.GetString(fname).TrimEnd('\0'); + } + + else + { + // assume an MDF file with the same name as the MDS + } + + string dir = Path.GetDirectoryName(aFile.MDSPath); + + if (f.FilenameOffset == 0 || + string.Compare(fileName, "*.mdf", StringComparison.InvariantCultureIgnoreCase) == 0) + { + fileName = dir + @"\" + Path.GetFileNameWithoutExtension(aFile.MDSPath) + ".mdf"; + } + else + { + fileName = dir + @"\" + fileName; + } + + track.ImageFileNamePaths.Add(fileName); + track.ImageFileNamePaths = track.ImageFileNamePaths.Distinct().ToList(); + } + + stream.Position = currPos; + + + aTracks.Add(track.Point, track); + aFile.Tracks.Add(track); + + if (footerOffset == 0) + footerOffset = track.FooterOffset; + } + } + + + // build custom session object + aFile.ParsedSession = new List(); + foreach (var s in aSessions.Values) + { + Session session = new Session(); + ATrack startTrack; + ATrack endTrack; + + if (!aTracks.TryGetValue(s.FirstTrack, out startTrack)) + { + break; + } + + if (!aTracks.TryGetValue(s.LastTrack, out endTrack)) + { + break; + } + + session.StartSector = startTrack.PLBA; + session.StartTrack = s.FirstTrack; + session.SessionSequence = s.SessionNumber; + session.EndSector = endTrack.PLBA + endTrack.ExtraBlock.Sectors - 1; + session.EndTrack = s.LastTrack; + + aFile.ParsedSession.Add(session); + } + + // now build the TOC object + foreach (var se in aFile.ParsedSession) + { + // get the first and last tracks + int sTrack = se.StartTrack; + int eTrack = se.EndTrack; + + // get list of all tracks from aTracks for this session + var tracks = (from a in aTracks.Values + where a.TrackNo >= sTrack || a.TrackNo <= eTrack + orderby a.TrackNo + select a).ToList(); + + // create the TOC entries + foreach (var t in tracks) + { + ATOCEntry toc = new ATOCEntry(t.Point); + toc.ADR_Control = t.ADR_Control; + toc.AFrame = t.AFrame; + toc.AMin = t.AMin; + toc.ASec = t.ASec; + toc.EntryNum = t.TrackNo; + toc.PFrame = t.PFrame; + toc.PLBA = Convert.ToInt32(t.PLBA); + toc.PMin = t.PMin; + toc.Point = t.Point; + toc.PSec = t.PSec; + toc.SectorSize = t.SectorSize; + toc.Zero = t.Zero; + toc.TrackOffset = Convert.ToInt64(t.StartOffset); + toc.Session = se.SessionSequence; + toc.ImageFileNamePaths = t.ImageFileNamePaths; + toc.ExtraBlock = t.ExtraBlock; + toc.BlobIndex = t.BlobIndex; + aFile.TOCEntries.Add(toc); + } + + } + + return aFile; + } + + /// + /// Custom session object + /// + public class Session + { + public long StartSector; + public int StartTrack; + public int SessionSequence; + public long EndSector; + public int EndTrack; + } + + + public class MDSParseException : Exception + { + public MDSParseException(string message) : base(message) { } + } + + + public class LoadResults + { + public List RawTOCEntries; + public AFile ParsedMDSFile; + public bool Valid; + public Exception FailureException; + public string MdsPath; + } + + public static LoadResults LoadMDSPath(string path) + { + LoadResults ret = new LoadResults(); + ret.MdsPath = path; + //ret.MdfPath = Path.ChangeExtension(path, ".mdf"); + try + { + if (!File.Exists(path)) throw new MDSParseException("Malformed MDS format: nonexistent MDS file!"); + + AFile mdsf; + using (var infMDS = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + mdsf = new MDS_Format().Parse(infMDS); + + ret.ParsedMDSFile = mdsf; + + ret.Valid = true; + } + catch (MDSParseException ex) + { + ret.FailureException = ex; + } + + return ret; + } + + Dictionary MountBlobs(AFile mdsf, Disc disc) + { + Dictionary BlobIndex = new Dictionary(); + + int count = 0; + foreach (var track in mdsf.Tracks) + { + foreach (var file in track.ImageFileNamePaths.Distinct()) + { + if (!File.Exists(file)) + throw new MDSParseException("Malformed MDS format: nonexistent image file: " + file); + + IBlob mdfBlob = null; + long mdfLen = -1; + + //mount the file + if (mdfBlob == null) + { + var mdfFile = new Disc.Blob_RawFile() { PhysicalPath = file }; + mdfLen = mdfFile.Length; + mdfBlob = mdfFile; + } + + bool dupe = false; + foreach (var re in disc.DisposableResources) + { + if (re.ToString() == mdfBlob.ToString()) + dupe = true; + } + + if (!dupe) + { + // wrap in zeropadadapter + disc.DisposableResources.Add(mdfBlob); + BlobIndex[count] = mdfBlob; + } + } + } + + return BlobIndex; + } + + RawTOCEntry EmitRawTOCEntry(ATOCEntry entry) + { + BCD2 tno, ino; + + //this should actually be zero. im not sure if this is stored as BCD2 or not + tno = BCD2.FromDecimal(entry.TrackNo); + + //these are special values.. I think, taken from this: + //http://www.staff.uni-mainz.de/tacke/scsi/SCSI2-14.html + //the CCD will contain Points as decimal values except for these specially converted decimal values which should stay as BCD. + //Why couldn't they all be BCD? I don't know. I guess because BCD is inconvenient, but only A0 and friends have special meaning. It's confusing. + ino = BCD2.FromDecimal(entry.Point); + if (entry.Point == 0xA0) ino.BCDValue = 0xA0; + else if (entry.Point == 0xA1) ino.BCDValue = 0xA1; + else if (entry.Point == 0xA2) ino.BCDValue = 0xA2; + + // get ADR & Control from ADR_Control byte + byte adrc = Convert.ToByte(entry.ADR_Control); + var Control = adrc & 0x0F; + var ADR = adrc >> 4; + + var q = new SubchannelQ + { + q_status = SubchannelQ.ComputeStatus(ADR, (EControlQ)(Control & 0xF)), + q_tno = tno, + q_index = ino, + min = BCD2.FromDecimal(entry.AMin), + sec = BCD2.FromDecimal(entry.ASec), + frame = BCD2.FromDecimal(entry.AFrame), + zero = (byte)entry.Zero, + ap_min = BCD2.FromDecimal(entry.PMin), + ap_sec = BCD2.FromDecimal(entry.PSec), + ap_frame = BCD2.FromDecimal(entry.PFrame), + q_crc = 0, //meaningless + }; + + return new RawTOCEntry { QData = q }; + } + + + /// + /// Loads a MDS at the specified path to a Disc object + /// + public Disc LoadMDSToDisc(string mdsPath, DiscMountPolicy IN_DiscMountPolicy) + { + var loadResults = LoadMDSPath(mdsPath); + if (!loadResults.Valid) + throw loadResults.FailureException; + + Disc disc = new Disc(); + + // load all blobs + Dictionary BlobIndex = MountBlobs(loadResults.ParsedMDSFile, disc); + + var mdsf = loadResults.ParsedMDSFile; + + //generate DiscTOCRaw items from the ones specified in the MDS file + disc.RawTOCEntries = new List(); + foreach (var entry in mdsf.TOCEntries) + { + disc.RawTOCEntries.Add(EmitRawTOCEntry(entry)); + } + + //analyze the RAWTocEntries to figure out what type of track track 1 is + var tocSynth = new Synthesize_DiscTOC_From_RawTOCEntries_Job() { Entries = disc.RawTOCEntries }; + tocSynth.Run(); + + // now build the sectors + int currBlobIndex = 0; + foreach (var session in mdsf.ParsedSession) + { + for (int i = session.StartTrack; i <= session.EndTrack; i++) + { + int relMSF = -1; + + var track = mdsf.TOCEntries.Where(t => t.Point == i).FirstOrDefault(); + if (track == null) + break; + + // ignore the info entries + if (track.Point == 0xA0 || + track.Point == 0xA1 || + track.Point == 0xA2) + { + continue; + } + + // get the blob(s) for this track + // its probably a safe assumption that there will be only one blob per track, + // but i'm still not 100% sure on this + var tr = (from a in mdsf.TOCEntries + where a.Point == i + select a).FirstOrDefault(); + + if (tr == null) + throw new MDSParseException("BLOB Error!"); + + List blobstrings = new List(); + foreach (var t in tr.ImageFileNamePaths) + { + if (!blobstrings.Contains(t)) + blobstrings.Add(t); + } + + var tBlobs = (from a in tr.ImageFileNamePaths + select a).ToList(); + + if (tBlobs.Count < 1) + throw new MDSParseException("BLOB Error!"); + + // is the currBlob valid for this track, or do we need to increment? + string bString = tBlobs.First(); + + IBlob mdfBlob = null; + + // check for track pregap and create if neccessary + // this is specified in the track extras block + if (track.ExtraBlock.Pregap > 0) + { + CUE.CueTrackType pregapTrackType = CUE.CueTrackType.Audio; + if (tocSynth.Result.TOCItems[1].IsData) + { + if (tocSynth.Result.Session1Format == SessionFormat.Type20_CDXA) + pregapTrackType = CUE.CueTrackType.Mode2_2352; + else if (tocSynth.Result.Session1Format == SessionFormat.Type10_CDI) + pregapTrackType = CUE.CueTrackType.CDI_2352; + else if (tocSynth.Result.Session1Format == SessionFormat.Type00_CDROM_CDDA) + pregapTrackType = CUE.CueTrackType.Mode1_2352; + } + for (int pre = 0; pre < track.ExtraBlock.Pregap; pre++) + { + relMSF++; + + var ss_gap = new CUE.SS_Gap() + { + Policy = IN_DiscMountPolicy, + TrackType = pregapTrackType + }; + disc._Sectors.Add(ss_gap); + + int qRelMSF = pre - Convert.ToInt32(track.ExtraBlock.Pregap); + + //tweak relMSF due to ambiguity/contradiction in yellowbook docs + if (!IN_DiscMountPolicy.CUE_PregapContradictionModeA) + qRelMSF++; + + //setup subQ + byte ADR = 1; //absent some kind of policy for how to set it, this is a safe assumption: + ss_gap.sq.SetStatus(ADR, tocSynth.Result.TOCItems[1].Control); + ss_gap.sq.q_tno = BCD2.FromDecimal(1); + ss_gap.sq.q_index = BCD2.FromDecimal(0); + ss_gap.sq.AP_Timestamp = pre; + ss_gap.sq.Timestamp = qRelMSF; + + //setup subP + ss_gap.Pause = true; + } + // pregap processing completed + } + + + + // create track sectors + long currBlobOffset = track.TrackOffset; + for (long sector = session.StartSector; sector <= session.EndSector; sector++) + { + CUE.SS_Base sBase = null; + + // get the current blob from the BlobIndex + Disc.Blob_RawFile currBlob = BlobIndex[currBlobIndex] as Disc.Blob_RawFile; + long currBlobLength = currBlob.Length; + long currBlobPosition = sector; + if (currBlobPosition == currBlobLength) + currBlobIndex++; + mdfBlob = disc.DisposableResources[currBlobIndex] as Disc.Blob_RawFile; + + int userSector = 2048; + switch (track.SectorSize) + { + case 2448: + sBase = new CUE.SS_2352() + { + Policy = IN_DiscMountPolicy + }; + userSector = 2352; + break; + case 2048: + default: + sBase = new CUE.SS_Mode1_2048() + { + Policy = IN_DiscMountPolicy + }; + userSector = 2048; + break; + + //throw new Exception("Not supported: Sector Size " + track.SectorSize); + } + + // configure blob + sBase.Blob = mdfBlob; + sBase.BlobOffset = currBlobOffset; + + currBlobOffset += track.SectorSize; // userSector; + + // add subchannel data + relMSF++; + BCD2 tno, ino; + + //this should actually be zero. im not sure if this is stored as BCD2 or not + tno = BCD2.FromDecimal(track.TrackNo); + + //these are special values.. I think, taken from this: + //http://www.staff.uni-mainz.de/tacke/scsi/SCSI2-14.html + //the CCD will contain Points as decimal values except for these specially converted decimal values which should stay as BCD. + //Why couldn't they all be BCD? I don't know. I guess because BCD is inconvenient, but only A0 and friends have special meaning. It's confusing. + ino = BCD2.FromDecimal(track.Point); + if (track.Point == 0xA0) ino.BCDValue = 0xA0; + else if (track.Point == 0xA1) ino.BCDValue = 0xA1; + else if (track.Point == 0xA2) ino.BCDValue = 0xA2; + + // get ADR & Control from ADR_Control byte + byte adrc = Convert.ToByte(track.ADR_Control); + var Control = adrc & 0x0F; + var ADR = adrc >> 4; + + var q = new SubchannelQ + { + q_status = SubchannelQ.ComputeStatus(ADR, (EControlQ)(Control & 0xF)), + q_tno = BCD2.FromDecimal(track.Point), + q_index = ino, + AP_Timestamp = disc._Sectors.Count, + Timestamp = relMSF - Convert.ToInt32(track.ExtraBlock.Pregap) + }; + + sBase.sq = q; + + disc._Sectors.Add(sBase); + + } + } + } + + return disc; + } + + } //class MDS_Format +} + + diff --git a/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs b/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs index a9add9cf4e..e4fe3c2f74 100644 --- a/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs +++ b/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; //disc type identification logic @@ -8,7 +9,7 @@ namespace BizHawk.Emulation.DiscSystem public enum DiscType { /// - /// Disc contains audio in track 1. Nothing more can readily be determined + /// Disc contains audio in track 1. This may be a PCFX or PCECD game, but if not it is assumed AudioDisc /// AudioDisc, @@ -38,7 +39,7 @@ namespace BizHawk.Emulation.DiscSystem SegaSaturn, /// - /// Its not clear whether we can ever have enough info to ID a turboCD disc (we're using hashes) + /// PC Engine CD /// TurboCD, @@ -50,7 +51,47 @@ namespace BizHawk.Emulation.DiscSystem /// /// By NEC. /// - PCFX + PCFX, + + /// + /// By Panasonic + /// + Panasonic3DO, + + /// + /// Philips + /// + CDi, + + /// + /// Nintendo Gamecube + /// + GameCube, + + /// + /// Nintendo Wii + /// + Wii, + + /// + /// SNK NeoGeo + /// + NeoGeoCD, + + /// + /// Bandai Playdia + /// + Playdia, + + /// + /// Either CDTV or CD32 (I havent found a reliable way of distinguishing between them yet -asni) + /// + Amiga, + + /// + /// Sega Dreamcast + /// + Dreamcast } public class DiscIdentifier @@ -76,24 +117,26 @@ namespace BizHawk.Emulation.DiscSystem /// public DiscType DetectDiscType() { - // not fully tested yet + // PCFX & TurboCD sometimes (if not alltimes) have audio on track 1 - run these before the AudioDisc detection (asni) if (DetectPCFX()) return DiscType.PCFX; - //check track 1's data type. if it's an audio track, further data-track testing is useless - //furthermore, it's probably senseless (no binary data there to read) - //NOTE: PCE-CD detection goes through here (no good way to detect PCE cd) - if (!_disc.TOC.TOCItems[1].IsData) + if (DetectTurboCD()) + return DiscType.TurboCD; + + //check track 1's data type. if it's an audio track, further data-track testing is useless + //furthermore, it's probably senseless (no binary data there to read) + if (!_disc.TOC.TOCItems[1].IsData) return DiscType.AudioDisc; // if (_dsr.ReadLBA_Mode(_disc.TOC.TOCItems[1].LBA) == 0) // return DiscType.AudioDisc; // sega doesnt put anything identifying in the cdfs volume info. but its consistent about putting its own header here in sector 0 + //asni - this isn't strictly true - SystemIdentifier in volume descriptor has been observed on occasion (see below) if (DetectSegaSaturn()) return DiscType.SegaSaturn; - // not fully tested yet if (DetectMegaCD()) return DiscType.MegaCD; @@ -102,31 +145,79 @@ namespace BizHawk.Emulation.DiscSystem if (DetectPSX()) return DiscType.SonyPSX; - //we dont know how to detect TurboCD. - //an emulator frontend will likely just guess TurboCD if the disc is UnknownFormat - //(we can also have a gameDB!) + if (Detect3DO()) + return DiscType.Panasonic3DO; - var discView = EDiscStreamView.DiscStreamView_Mode1_2048; + if (DetectCDi()) + return DiscType.CDi; + + if (DetectGameCube()) + return DiscType.GameCube; + + if (DetectWii()) + return DiscType.Wii; + + var discView = EDiscStreamView.DiscStreamView_Mode1_2048; if (_disc.TOC.Session1Format == SessionFormat.Type20_CDXA) discView = EDiscStreamView.DiscStreamView_Mode2_Form1_2048; var iso = new ISOFile(); bool isIso = iso.Parse(new DiscStream(_disc, discView, 0)); + if (!isIso) + { + // its much quicker to detect dreamcast from ISO data. Only do this if ISO is not detected + if (DetectDreamcast()) + return DiscType.Dreamcast; + } + + //*** asni - 20171011 - Suggestion: move this to the beginning of the DetectDiscType() method before any longer running lookups? + //its a cheap win for a lot of systems, but ONLY if the iso.Parse() method is quick running (might have to time it) if (isIso) { var appId = System.Text.Encoding.ASCII.GetString(iso.VolumeDescriptors[0].ApplicationIdentifier).TrimEnd('\0', ' '); + var sysId = System.Text.Encoding.ASCII.GetString(iso.VolumeDescriptors[0].SystemIdentifier).TrimEnd('\0', ' '); - //for example: PSX magical drop F (JP SLPS_02337) doesn't have the correct iso PVD fields - //but, some PSX games (junky rips) don't have the 'licensed by string' so we'll hope they get caught here - if (appId == "PLAYSTATION") + //for example: PSX magical drop F (JP SLPS_02337) doesn't have the correct iso PVD fields + //but, some PSX games (junky rips) don't have the 'licensed by string' so we'll hope they get caught here + if (appId == "PLAYSTATION") return DiscType.SonyPSX; if (appId == "PSP GAME") return DiscType.SonyPSP; + // in case the appId is not set correctly... + if (iso.Root.Children.Where(a => a.Key == "PSP_GAME").FirstOrDefault().Value as ISODirectoryNode != null) + return DiscType.SonyPSP; - return DiscType.UnknownCDFS; - } + if (sysId == "SEGA SEGASATURN") + return DiscType.SegaSaturn; + + if (sysId.Contains("SEGAKATANA")) + return DiscType.Dreamcast; + + if (sysId == "MEGA_CD") + return DiscType.MegaCD; + + if (sysId == "ASAHI-CDV") + return DiscType.Playdia; + + if (sysId == "CDTV" || sysId == "AMIGA") + return DiscType.Amiga; + foreach (var f in iso.Root.Children) + if (f.Key.ToLower().Contains("cd32")) + return DiscType.Amiga; + + // NeoGeoCD Check + var absTxt = iso.Root.Children.Where(a => a.Key.Contains("ABS.TXT")).ToList(); + if (absTxt.Count > 0) + { + if (SectorContains("abstracted by snk", Convert.ToInt32(absTxt.First().Value.Offset))) + return DiscType.NeoGeoCD; + } + + + return DiscType.UnknownCDFS; + } return DiscType.UnknownFormat; } @@ -165,13 +256,87 @@ namespace BizHawk.Emulation.DiscSystem t++) { var track = _disc.TOC.TOCItems[t]; - if (track.IsData && StringAt("PC-FX:Hu_CD-ROM", 0, track.LBA)) + //asni - this search is less specific - turns out there are discs where 'Hu:' is not present + if (track.IsData && SectorContains("pc-fx", track.LBA)) return true; } return false; } - private byte[] ReadSectorCached(int lba) + //asni 20171011 - this ONLY works if a valid cuefile/ccd is passed into DiscIdentifier. + //if an .iso is presented, the internally manufactured cue data does not work - possibly something to do with + //track 01 being Audio. Not tested, but presumably PCFX has the same issue + bool DetectTurboCD() + { + var toc = _disc.TOC; + for (int t = toc.FirstRecordedTrackNumber; + t <= toc.LastRecordedTrackNumber; + t++) + { + var track = _disc.TOC.TOCItems[t]; + //asni - pcfx games also contain the 'PC Engine' string + if ((track.IsData && SectorContains("pc engine", track.LBA + 1) && !SectorContains("pc-fx", track.LBA + 1))) + return true; + } + return false; + } + + bool Detect3DO() + { + var toc = _disc.TOC; + for (int t = toc.FirstRecordedTrackNumber; + t <= toc.LastRecordedTrackNumber; + t++) + { + var track = _disc.TOC.TOCItems[t]; + if (track.IsData && SectorContains("iamaduckiamaduck", track.LBA)) + return true; + } + return false; + } + + //asni - slightly longer running than the others due to its brute-force nature. Should run later in the method + bool DetectDreamcast() + { + for (int i = 0; i < 1000; i++) + { + if (SectorContains("segakatana", i)) + return true; + } + + return false; + } + + bool DetectCDi() + { + return StringAt("CD-RTOS", 8, 16); + } + + bool DetectGameCube() + { + var data = ReadSectorCached(0); + if (data == null) return false; + byte[] magic = data.Skip(28).Take(4).ToArray(); + string hexString = ""; + foreach (var b in magic) + hexString += b.ToString("X2"); + + return hexString == "C2339F3D"; + } + + bool DetectWii() + { + var data = ReadSectorCached(0); + if (data == null) return false; + byte[] magic = data.Skip(24).Take(4).ToArray(); + string hexString = ""; + foreach (var b in magic) + hexString += b.ToString("X2"); + + return hexString == "5D1C9EA3"; + } + + private byte[] ReadSectorCached(int lba) { //read it if we dont have it cached //we wont be caching very much here, it's no big deal @@ -197,5 +362,12 @@ namespace BizHawk.Emulation.DiscSystem Buffer.BlockCopy(data, n, cmp2, 0, cmp.Length); return System.Linq.Enumerable.SequenceEqual(cmp, cmp2); } + + private bool SectorContains(string s, int lba = 0) + { + var data = ReadSectorCached(lba); + if (data == null) return false; + return System.Text.Encoding.ASCII.GetString(data).ToLower().Contains(s.ToLower()); + } } } \ No newline at end of file diff --git a/BizHawk.Emulation.DiscSystem/DiscMountJob.cs b/BizHawk.Emulation.DiscSystem/DiscMountJob.cs index dab08a7dbf..7282d00f74 100644 --- a/BizHawk.Emulation.DiscSystem/DiscMountJob.cs +++ b/BizHawk.Emulation.DiscSystem/DiscMountJob.cs @@ -187,6 +187,11 @@ namespace BizHawk.Emulation.DiscSystem CCD_Format ccdLoader = new CCD_Format(); OUT_Disc = ccdLoader.LoadCCDToDisc(IN_FromPath, IN_DiscMountPolicy); } + else if (ext == ".mds") + { + MDS_Format mdsLoader = new MDS_Format(); + OUT_Disc = mdsLoader.LoadMDSToDisc(IN_FromPath, IN_DiscMountPolicy); + } DONE: diff --git a/output/dll/octoshock.dll b/output/dll/octoshock.dll index 292d2536eb..3e80c9454e 100644 Binary files a/output/dll/octoshock.dll and b/output/dll/octoshock.dll differ diff --git a/psx/octoshock/psx/input/memcard.cpp b/psx/octoshock/psx/input/memcard.cpp index 814e68d117..b98fa9de58 100644 --- a/psx/octoshock/psx/input/memcard.cpp +++ b/psx/octoshock/psx/input/memcard.cpp @@ -193,7 +193,9 @@ void InputDevice_Memcard::SyncState(bool isReader, EW::NewState *ns) //HOWEVER - we clear the dirty flag. that way, a user wont accidentally `clobber` his savestates when loading a state. //instead, the state will only be dirtied when the game actually modifies the contents NSS(card_data); - dirty_count = 0; + + if(isReader) + dirty_count = 0; } // //int InputDevice_Memcard::StateAction(StateMem* sm, int load, int data_only, const char* section_name)