From 420aec7870b4b4571a0eda9930afdc95160e788a Mon Sep 17 00:00:00 2001 From: Asnivor Date: Wed, 11 Oct 2017 10:57:58 +0100 Subject: [PATCH 01/39] DiscIdentifier - Improved detection of PC-FX. Added detection of lots more systems. --- .../DiscIdentifier.cs | 212 ++++++++++++++++-- 1 file changed, 192 insertions(+), 20 deletions(-) diff --git a/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs b/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs index a9add9cf4e..7db33ef622 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 < 10000; 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 From 688015bde8a409b3d37112f3c4d54281f97aac34 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Wed, 11 Oct 2017 11:20:46 +0100 Subject: [PATCH 02/39] Reduced dreamcast detection time by a factor of 10 --- BizHawk.Emulation.DiscSystem/DiscIdentifier.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs b/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs index 7db33ef622..e4fe3c2f74 100644 --- a/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs +++ b/BizHawk.Emulation.DiscSystem/DiscIdentifier.cs @@ -298,7 +298,7 @@ namespace BizHawk.Emulation.DiscSystem //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 < 10000; i++) + for (int i = 0; i < 1000; i++) { if (SectorContains("segakatana", i)) return true; From ff13009e976ab92bdf47cd4c734ddfe2e5686f61 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 12 Oct 2017 20:19:42 -0400 Subject: [PATCH 03/39] Create ReadMe.txt --- BizHawk.Emulation.Cores/CPUs/Z80A/ReadMe.txt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/ReadMe.txt 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 From 12c46db79054d549e108e3134527666ee2273a8f Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 12 Oct 2017 20:20:13 -0400 Subject: [PATCH 04/39] Add files via upload --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 1469 +++++++++++++++++ .../CPUs/Z80A/Interrupts.cs | 122 ++ .../CPUs/Z80A/NewDisassembler.cs | 467 ++++++ .../CPUs/Z80A/Operations.cs | 727 ++++++++ .../CPUs/Z80A/Registers.cs | 134 ++ .../CPUs/Z80A/Tables_Direct.cs | 590 +++++++ .../CPUs/Z80A/Tables_Indirect.cs | 478 ++++++ BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 697 ++++++++ 8 files changed, 4684 insertions(+) create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs create mode 100644 BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs new file mode 100644 index 0000000000..ce3fb3f729 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -0,0 +1,1469 @@ +using System; + +namespace BizHawk.Emulation.Common.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; + + // 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 bool jammed; + 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 R, A + 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: JAM_(); break; // JAM + 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: JAM_(); break; // JAM + 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: JAM_(); break; // JAM + + } + } + 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: JAM_(); break; // Jam (invalid) + 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: JAM_(); break; // Jam (invalid) + 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: JAM_(); break; // Jam (invalid) + 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: JAM_(); break; // Jam (invalid) + 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: JAM_(); break; // Jam (invalid) + 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: JAM_(); break; // Jam (invalid) + 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..33df2edf55 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs @@ -0,0 +1,122 @@ +using System; + +namespace BizHawk.Emulation.Common.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, + IDLE, + IDLE, + IDLE, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, PCh, + IDLE, + DEC16, SPl, SPh, + IDLE, + WR, SPl, SPh, PCl, + IDLE, + ASGN, PCl, 0, + IDLE, + TR, PCh, I, + IDLE, + OP }; + } + + private static ushort[] INT_vectors = new ushort[] {0x40, 0x48, 0x50, 0x58, 0x60}; + + private void ResetInterrupts() + { + IFF1 = false; + IFF2 = false; + NonMaskableInterrupt = false; + NonMaskableInterruptPending = false; + InterruptMode = 1; + } + } +} \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs new file mode 100644 index 0000000000..62c546ca6e --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -0,0 +1,467 @@ +using System; +using System.Collections.Generic; + +using BizHawk.Emulation.Common; + +namespace BizHawk.Emulation.Common.Components.Z80A +{ + public sealed partial class Z80A : IDisassemblable + { + 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(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(addr++); + format = format.Replace("n", string.Format("{0:X2}h", B)); + } + + if (format.IndexOf("+d") != -1) format = format.Replace("+d", "d"); + + if (format.IndexOf("d") != -1) + { + byte B = read(addr++); + bool neg = ((B & 0x80) != 0); + char sign = neg ? '-' : '+'; + int val = neg ? 256 - B : B; + format = format.Replace("d", string.Format("{0}{1:X2}h", sign, val)); + } + + return format; + } + + readonly static string[] mnemonics = new string[] + { + "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 + "INC B", "DEC B", "LD B, n", "RLCA", //0x08 + "EX AF, AF'", "ADD HL, BC", "LD A, (BC)", "DEC BC", //0x0C + "INC C", "DEC C", "LD C, n", "RRCA", //0x10 + "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 + "INC D", "DEC D", "LD D, n", "RLA", //0x18 + "JR d", "ADD HL, DE", "LD A, (DE)", "DEC DE", //0x1C + "INC E", "DEC E", "LD E, n", "RRA", //0x20 + "JR NZ, d", "LD HL, nn", "LD (nn), HL", "INC HL", //0x24 + "INC H", "DEC H", "LD H, n", "DAA", //0x28 + "JR Z, d", "ADD HL, HL", "LD HL, (nn)", "DEC HL", //0x2C + "INC L", "DEC L", "LD L, n", "CPL", //0x30 + "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 + "INC (HL)", "DEC (HL)", "LD (HL), n", "SCF", //0x38 + "JR C, d", "ADD HL, SP", "LD A, (nn)", "DEC SP", //0x3C + "INC A", "DEC A", "LD A, n", "CCF", //0x40 + "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 + "LD B, H", "LD B, L", "LD B, (HL)", "LD B, A", //0x48 + "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C + "LD C, H", "LD C, L", "LD C, (HL)", "LD C, A", //0x50 + "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 + "LD D, H", "LD D, L", "LD D, (HL)", "LD D, A", //0x58 + "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C + "LD E, H", "LD E, L", "LD E, (HL)", "LD E, A", //0x60 + "LD H, B", "LD H, C", "LD H, D", "LD H, E", //0x64 + "LD H, H", "LD H, L", "LD H, (HL)", "LD H, A", //0x68 + "LD L, B", "LD L, B", "LD L, D", "LD L, E", //0x6C + "LD L, H", "LD L, L", "LD L, (HL)", "LD L, A", //0x70 + "LD (HL), B", "LD (HL), C", "LD (HL), D", "LD (HL), E", //0x74 + "LD (HL), H", "LD (HL), L", "HALT", "LD (HL), A", //0x78 + "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C + "LD A, H", "LD A, L", "LD A, (HL)", "LD A, A", //0x80 + "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 + "ADD A, H", "ADD A, L", "ADD A, (HL)", "ADD A, A", //0x88 + "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C + "ADC A, H", "ADC A, L", "ADC A, (HL)", "ADC A, A", //0x90 + "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 + "SUB A, H", "SUB A, L", "SUB A, (HL)", "SUB A, A", //0x98 + "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C + "SBC A, H", "SBC A, L", "SBC A, (HL)", "SBC A, A", //0xA0 + "AND B", "AND C", "AND D", "AND E", //0xA4 + "AND H", "AND L", "AND (HL)", "AND A", //0xA8 + "XOR B", "XOR C", "XOR D", "XOR E", //0xAC + "XOR H", "XOR L", "XOR (HL)", "XOR A", //0xB0 + "OR B", "OR C", "OR D", "OR E", //0xB4 + "OR H", "OR L", "OR (HL)", "OR A", //0xB8 + "CP B", "CP C", "CP D", "CP E", //0xBC + "CP H", "CP L", "CP (HL)", "CP A", //0xC0 + "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 + "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 + "RET Z", "RET", "JP Z, nn", "[CB]", //0xCC + "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 + "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 + "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 + "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC + "CALL C, nn", "[DD]", "SBC A, n", "RST $18", //0xE0 + "RET PO", "POP HL", "JP PO, nn", "EX (SP), HL", //0xE4 + "CALL C, nn", "PUSH HL", "AND n", "RST $20", //0xE8 + "RET PE", "JP HL", "JP PE, nn", "EX DE, HL", //0xEC + "CALL PE, nn", "[ED]", "XOR n", "RST $28", //0xF0 + "RET P", "POP AF", "JP P, nn", "DI", //0xF4 + "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 + "RET M", "LD SP, HL", "JP M, nn", "EI", //0xFC + "CALL M, nn", "[FD]", "CP n", "RST $38", //0x100 + }; + + readonly static string[] mnemonicsDD = new string[] + { + "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 + "INC B", "DEC B", "LD B, n", "RLCA", //0x08 + "EX AF, AF'", "ADD IX, BC", "LD A, (BC)", "DEC BC", //0x0C + "INC C", "DEC C", "LD C, n", "RRCA", //0x10 + "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 + "INC D", "DEC D", "LD D, n", "RLA", //0x18 + "JR d", "ADD IX, DE", "LD A, (DE)", "DEC DE", //0x1C + "INC E", "DEC E", "LD E, n", "RRA", //0x20 + "JR NZ, d", "LD IX, nn", "LD (nn), IX", "INC IX", //0x24 + "INC IXH", "DEC IXH", "LD IXH, n", "DAA", //0x28 + "JR Z, d", "ADD IX, IX", "LD IX, (nn)", "DEC IX", //0x2C + "INC IXL", "DEC IXL", "LD IXL, n", "CPL", //0x30 + "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 + "INC (IX+d)", "DEC (IX+d)", "LD (IX+d), n", "SCF", //0x38 + "JR C, d", "ADD IX, SP", "LD A, (nn)", "DEC SP", //0x3C + "INC A", "DEC A", "LD A, n", "CCF", //0x40 + "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 + "LD B, IXH", "LD B, IXL", "LD B, (IX+d)", "LD B, A", //0x48 + "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C + "LD C, IXH", "LD C, IXL", "LD C, (IX+d)", "LD C, A", //0x50 + "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 + "LD D, IXH", "LD D, IXL", "LD D, (IX+d)", "LD D, A", //0x58 + "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C + "LD E, IXH", "LD E, IXL", "LD E, (IX+d)", "LD E, A", //0x60 + "LD IXH, B", "LD IXH, C", "LD IXH, D", "LD IXH, E", //0x64 + "LD IXH, IXH", "LD IXH, IXL", "LD H, (IX+d)", "LD IXH, A", //0x68 + "LD IXL, B", "LD IXL, C", "LD IXL, D", "LD IXL, E", //0x6C + "LD IXL, IXH", "LD IXL, IXL", "LD L, (IX+d)", "LD IXL, A", //0x70 + "LD (IX+d), B", "LD (IX+d), C", "LD (IX+d), D", "LD (IX+d), E", //0x74 + "LD (IX+d), H", "LD (IX+d), L", "HALT", "LD (IX+d), A", //0x78 + "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C + "LD A, IXH", "LD A, IXL", "LD A, (IX+d)", "LD A, A", //0x80 + "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 + "ADD A, IXH", "ADD A, IXL", "ADD A, (IX+d)", "ADD A, A", //0x88 + "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C + "ADC A, IXH", "ADC A, IXL", "ADC A, (IX+d)", "ADC A, A", //0x90 + "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 + "SUB A, IXH", "SUB A, IXL", "SUB A, (IX+d)", "SUB A, A", //0x98 + "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C + "SBC A, IXH", "SBC A, IXL", "SBC A, (IX+d)", "SBC A, A", //0xA0 + "AND B", "AND C", "AND D", "AND E", //0xA4 + "AND IXH", "AND IXL", "AND (IX+d)", "AND A", //0xA8 + "XOR B", "XOR C", "XOR D", "XOR E", //0xAC + "XOR IXH", "XOR IXL", "XOR (IX+d)", "XOR A", //0xB0 + "OR B", "OR C", "OR D", "OR E", //0xB4 + "OR IXH", "OR IXL", "OR (IX+d)", "OR A", //0xB8 + "CP B", "CP C", "CP D", "CP E", //0xBC + "CP IXH", "CP IXL", "CP (IX+d)", "CP A", //0xC0 + "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 + "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 + "RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC + "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 + "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 + "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 + "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC + "CALL C, nn", "[!DD DD!]", "SBC A, n", "RST $18", //0xE0 + "RET PO", "POP IX", "JP PO, nn", "EX (SP), IX", //0xE4 + "CALL C, nn", "PUSH IX", "AND n", "RST $20", //0xE8 + "RET PE", "JP IX", "JP PE, nn", "EX DE, HL", //0xEC + "CALL PE, nn", "[DD ED]", "XOR n", "RST $28", //0xF0 + "RET P", "POP AF", "JP P, nn", "DI", //0xF4 + "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 + "RET M", "LD SP, IX", "JP M, nn", "EI", //0xFC + "CALL M, nn", "[!!DD FD!!]", "CP n", "RST $38", //0x100 + }; + + readonly static string[] mnemonicsFD = new string[] + { + "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 + "INC B", "DEC B", "LD B, n", "RLCA", //0x08 + "EX AF, AF'", "ADD IY, BC", "LD A, (BC)", "DEC BC", //0x0C + "INC C", "DEC C", "LD C, n", "RRCA", //0x10 + "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 + "INC D", "DEC D", "LD D, n", "RLA", //0x18 + "JR d", "ADD IY, DE", "LD A, (DE)", "DEC DE", //0x1C + "INC E", "DEC E", "LD E, n", "RRA", //0x20 + "JR NZ, d", "LD IY, nn", "LD (nn), IY", "INC IY", //0x24 + "INC IYH", "DEC IYH", "LD IYH, n", "DAA", //0x28 + "JR Z, d", "ADD IY, IY", "LD IY, (nn)", "DEC IY", //0x2C + "INC IYL", "DEC IYL", "LD IYL, n", "CPL", //0x30 + "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 + "INC (IY+d)", "DEC (IY+d)", "LD (IY+d), n", "SCF", //0x38 + "JR C, d", "ADD IY, SP", "LD A, (nn)", "DEC SP", //0x3C + "INC A", "DEC A", "LD A, n", "CCF", //0x40 + "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 + "LD B, IYH", "LD B, IYL", "LD B, (IY+d)", "LD B, A", //0x48 + "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C + "LD C, IYH", "LD C, IYL", "LD C, (IY+d)", "LD C, A", //0x50 + "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 + "LD D, IYH", "LD D, IYL", "LD D, (IY+d)", "LD D, A", //0x58 + "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C + "LD E, IYH", "LD E, IYL", "LD E, (IY+d)", "LD E, A", //0x60 + "LD IYH, B", "LD IYH, C", "LD IYH, D", "LD IYH, E", //0x64 + "LD IYH, IYH", "LD IYH, IYL", "LD H, (IY+d)", "LD IYH, A", //0x68 + "LD IYL, B", "LD IYL, C", "LD IYL, D", "LD IYL, E", //0x6C + "LD IYL, IYH", "LD IYL, IYL", "LD L, (IY+d)", "LD IYL, A", //0x70 + "LD (IY+d), B", "LD (IY+d), C", "LD (IY+d), D", "LD (IY+d), E", //0x74 + "LD (IY+d), H", "LD (IY+d), L", "HALT", "LD (IY+d), A", //0x78 + "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C + "LD A, IYH", "LD A, IYL", "LD A, (IY+d)", "LD A, A", //0x80 + "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 + "ADD A, IYH", "ADD A, IYL", "ADD A, (IY+d)", "ADD A, A", //0x88 + "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C + "ADC A, IYH", "ADC A, IYL", "ADC A, (IY+d)", "ADC A, A", //0x90 + "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 + "SUB A, IYH", "SUB A, IYL", "SUB A, (IY+d)", "SUB A, A", //0x98 + "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C + "SBC A, IYH", "SBC A, IYL", "SBC A, (IY+d)", "SBC A, A", //0xA0 + "AND B", "AND C", "AND D", "AND E", //0xA4 + "AND IYH", "AND IYL", "AND (IY+d)", "AND A", //0xA8 + "XOR B", "XOR C", "XOR D", "XOR E", //0xAC + "XOR IYH", "XOR IYL", "XOR (IY+d)", "XOR A", //0xB0 + "OR B", "OR C", "OR D", "OR E", //0xB4 + "OR IYH", "OR IYL", "OR (IY+d)", "OR A", //0xB8 + "CP B", "CP C", "CP D", "CP E", //0xBC + "CP IYH", "CP IYL", "CP (IY+d)", "CP A", //0xC0 + "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 + "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 + "RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC + "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 + "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 + "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 + "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC + "CALL C, nn", "[!FD DD!]", "SBC A, n", "RST $18", //0xE0 + "RET PO", "POP IY", "JP PO, nn", "EX (SP), IY", //0xE4 + "CALL C, nn", "PUSH IY", "AND n", "RST $20", //0xE8 + "RET PE", "JP IY", "JP PE, nn", "EX DE, HL", //0xEC + "CALL PE, nn", "[FD ED]", "XOR n", "RST $28", //0xF0 + "RET P", "POP AF", "JP P, nn", "DI", //0xF4 + "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 + "RET M", "LD SP, IY", "JP M, nn", "EI", //0xFC + "CALL M, nn", "[!FD FD!]", "CP n", "RST $38", //0x100 + }; + + readonly static string[] mnemonicsDDCB = new string[] + { + "RLC (IX+d)->B", "RLC (IX+d)->C", "RLC (IX+d)->D", "RLC (IX+d)->E", "RLC (IX+d)->H", "RLC (IX+d)->L", "RLC (IX+d)", "RLC (IX+d)->A", + "RRC (IX+d)->B", "RRC (IX+d)->C", "RRC (IX+d)->D", "RRC (IX+d)->E", "RRC (IX+d)->H", "RRC (IX+d)->L", "RRC (IX+d)", "RRC (IX+d)->A", + "RL (IX+d)->B", "RL (IX+d)->C", "RL (IX+d)->D", "RL (IX+d)->E", "RL (IX+d)->H", "RL (IX+d)->L", "RL (IX+d)", "RL (IX+d)->A", + "RR (IX+d)->B", "RR (IX+d)->C", "RR (IX+d)->D", "RR (IX+d)->E", "RR (IX+d)->H", "RR (IX+d)->L", "RR (IX+d)", "RR (IX+d)->A", + "SLA (IX+d)->B", "SLA (IX+d)->C", "SLA (IX+d)->D", "SLA (IX+d)->E", "SLA (IX+d)->H", "SLA (IX+d)->L", "SLA (IX+d)", "SLA (IX+d)->A", + "SRA (IX+d)->B", "SRA (IX+d)->C", "SRA (IX+d)->D", "SRA (IX+d)->E", "SRA (IX+d)->H", "SRA (IX+d)->L", "SRA (IX+d)", "SRA (IX+d)->A", + "SL1 (IX+d)->B", "SL1 (IX+d)->C", "SL1 (IX+d)->D", "SL1 (IX+d)->E", "SL1 (IX+d)->H", "SL1 (IX+d)->L", "SL1 (IX+d)", "SL1 (IX+d)->A", + "SRL (IX+d)->B", "SRL (IX+d)->C", "SRL (IX+d)->D", "SRL (IX+d)->E", "SRL (IX+d)->H", "SRL (IX+d)->L", "SRL (IX+d)", "SRL (IX+d)->A", + "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", + "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", + "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", + "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", + "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", + "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", + "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", + "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", + "RES 0 (IX+d)->B", "RES 0 (IX+d)->C", "RES 0 (IX+d)->D", "RES 0 (IX+d)->E", "RES 0 (IX+d)->H", "RES 0 (IX+d)->L", "RES 0 (IX+d)", "RES 0 (IX+d)->A", + "RES 1 (IX+d)->B", "RES 1 (IX+d)->C", "RES 1 (IX+d)->D", "RES 1 (IX+d)->E", "RES 1 (IX+d)->H", "RES 1 (IX+d)->L", "RES 1 (IX+d)", "RES 1 (IX+d)->A", + "RES 2 (IX+d)->B", "RES 2 (IX+d)->C", "RES 2 (IX+d)->D", "RES 2 (IX+d)->E", "RES 2 (IX+d)->H", "RES 2 (IX+d)->L", "RES 2 (IX+d)", "RES 2 (IX+d)->A", + "RES 3 (IX+d)->B", "RES 3 (IX+d)->C", "RES 3 (IX+d)->D", "RES 3 (IX+d)->E", "RES 3 (IX+d)->H", "RES 3 (IX+d)->L", "RES 3 (IX+d)", "RES 3 (IX+d)->A", + "RES 4 (IX+d)->B", "RES 4 (IX+d)->C", "RES 4 (IX+d)->D", "RES 4 (IX+d)->E", "RES 4 (IX+d)->H", "RES 4 (IX+d)->L", "RES 4 (IX+d)", "RES 4 (IX+d)->A", + "RES 5 (IX+d)->B", "RES 5 (IX+d)->C", "RES 5 (IX+d)->D", "RES 5 (IX+d)->E", "RES 5 (IX+d)->H", "RES 5 (IX+d)->L", "RES 5 (IX+d)", "RES 5 (IX+d)->A", + "RES 6 (IX+d)->B", "RES 6 (IX+d)->C", "RES 6 (IX+d)->D", "RES 6 (IX+d)->E", "RES 6 (IX+d)->H", "RES 6 (IX+d)->L", "RES 6 (IX+d)", "RES 6 (IX+d)->A", + "RES 7 (IX+d)->B", "RES 7 (IX+d)->C", "RES 7 (IX+d)->D", "RES 7 (IX+d)->E", "RES 7 (IX+d)->H", "RES 7 (IX+d)->L", "RES 7 (IX+d)", "RES 7 (IX+d)->A", + "SET 0 (IX+d)->B", "SET 0 (IX+d)->C", "SET 0 (IX+d)->D", "SET 0 (IX+d)->E", "SET 0 (IX+d)->H", "SET 0 (IX+d)->L", "SET 0 (IX+d)", "SET 0 (IX+d)->A", + "SET 1 (IX+d)->B", "SET 1 (IX+d)->C", "SET 1 (IX+d)->D", "SET 1 (IX+d)->E", "SET 1 (IX+d)->H", "SET 1 (IX+d)->L", "SET 1 (IX+d)", "SET 1 (IX+d)->A", + "SET 2 (IX+d)->B", "SET 2 (IX+d)->C", "SET 2 (IX+d)->D", "SET 2 (IX+d)->E", "SET 2 (IX+d)->H", "SET 2 (IX+d)->L", "SET 2 (IX+d)", "SET 2 (IX+d)->A", + "SET 3 (IX+d)->B", "SET 3 (IX+d)->C", "SET 3 (IX+d)->D", "SET 3 (IX+d)->E", "SET 3 (IX+d)->H", "SET 3 (IX+d)->L", "SET 3 (IX+d)", "SET 3 (IX+d)->A", + "SET 4 (IX+d)->B", "SET 4 (IX+d)->C", "SET 4 (IX+d)->D", "SET 4 (IX+d)->E", "SET 4 (IX+d)->H", "SET 4 (IX+d)->L", "SET 4 (IX+d)", "SET 4 (IX+d)->A", + "SET 5 (IX+d)->B", "SET 5 (IX+d)->C", "SET 5 (IX+d)->D", "SET 5 (IX+d)->E", "SET 5 (IX+d)->H", "SET 5 (IX+d)->L", "SET 5 (IX+d)", "SET 5 (IX+d)->A", + "SET 6 (IX+d)->B", "SET 6 (IX+d)->C", "SET 6 (IX+d)->D", "SET 6 (IX+d)->E", "SET 6 (IX+d)->H", "SET 6 (IX+d)->L", "SET 6 (IX+d)", "SET 6 (IX+d)->A", + "SET 7 (IX+d)->B", "SET 7 (IX+d)->C", "SET 7 (IX+d)->D", "SET 7 (IX+d)->E", "SET 7 (IX+d)->H", "SET 7 (IX+d)->L", "SET 7 (IX+d)", "SET 7 (IX+d)->A", + }; + + readonly static string[] mnemonicsFDCB = new string[] + { + "RLC (IY+d)->B", "RLC (IY+d)->C", "RLC (IY+d)->D", "RLC (IY+d)->E", "RLC (IY+d)->H", "RLC (IY+d)->L", "RLC (IY+d)", "RLC (IY+d)->A", + "RRC (IY+d)->B", "RRC (IY+d)->C", "RRC (IY+d)->D", "RRC (IY+d)->E", "RRC (IY+d)->H", "RRC (IY+d)->L", "RRC (IY+d)", "RRC (IY+d)->A", + "RL (IY+d)->B", "RL (IY+d)->C", "RL (IY+d)->D", "RL (IY+d)->E", "RL (IY+d)->H", "RL (IY+d)->L", "RL (IY+d)", "RL (IY+d)->A", + "RR (IY+d)->B", "RR (IY+d)->C", "RR (IY+d)->D", "RR (IY+d)->E", "RR (IY+d)->H", "RR (IY+d)->L", "RR (IY+d)", "RR (IY+d)->A", + "SLA (IY+d)->B", "SLA (IY+d)->C", "SLA (IY+d)->D", "SLA (IY+d)->E", "SLA (IY+d)->H", "SLA (IY+d)->L", "SLA (IY+d)", "SLA (IY+d)->A", + "SRA (IY+d)->B", "SRA (IY+d)->C", "SRA (IY+d)->D", "SRA (IY+d)->E", "SRA (IY+d)->H", "SRA (IY+d)->L", "SRA (IY+d)", "SRA (IY+d)->A", + "SL1 (IY+d)->B", "SL1 (IY+d)->C", "SL1 (IY+d)->D", "SL1 (IY+d)->E", "SL1 (IY+d)->H", "SL1 (IY+d)->L", "SL1 (IY+d)", "SL1 (IY+d)->A", + "SRL (IY+d)->B", "SRL (IY+d)->C", "SRL (IY+d)->D", "SRL (IY+d)->E", "SRL (IY+d)->H", "SRL (IY+d)->L", "SRL (IY+d)", "SRL (IY+d)->A", + "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", + "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", + "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", + "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", + "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", + "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", + "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", + "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", + "RES 0 (IY+d)->B", "RES 0 (IY+d)->C", "RES 0 (IY+d)->D", "RES 0 (IY+d)->E", "RES 0 (IY+d)->H", "RES 0 (IY+d)->L", "RES 0 (IY+d)", "RES 0 (IY+d)->A", + "RES 1 (IY+d)->B", "RES 1 (IY+d)->C", "RES 1 (IY+d)->D", "RES 1 (IY+d)->E", "RES 1 (IY+d)->H", "RES 1 (IY+d)->L", "RES 1 (IY+d)", "RES 1 (IY+d)->A", + "RES 2 (IY+d)->B", "RES 2 (IY+d)->C", "RES 2 (IY+d)->D", "RES 2 (IY+d)->E", "RES 2 (IY+d)->H", "RES 2 (IY+d)->L", "RES 2 (IY+d)", "RES 2 (IY+d)->A", + "RES 3 (IY+d)->B", "RES 3 (IY+d)->C", "RES 3 (IY+d)->D", "RES 3 (IY+d)->E", "RES 3 (IY+d)->H", "RES 3 (IY+d)->L", "RES 3 (IY+d)", "RES 3 (IY+d)->A", + "RES 4 (IY+d)->B", "RES 4 (IY+d)->C", "RES 4 (IY+d)->D", "RES 4 (IY+d)->E", "RES 4 (IY+d)->H", "RES 4 (IY+d)->L", "RES 4 (IY+d)", "RES 4 (IY+d)->A", + "RES 5 (IY+d)->B", "RES 5 (IY+d)->C", "RES 5 (IY+d)->D", "RES 5 (IY+d)->E", "RES 5 (IY+d)->H", "RES 5 (IY+d)->L", "RES 5 (IY+d)", "RES 5 (IY+d)->A", + "RES 6 (IY+d)->B", "RES 6 (IY+d)->C", "RES 6 (IY+d)->D", "RES 6 (IY+d)->E", "RES 6 (IY+d)->H", "RES 6 (IY+d)->L", "RES 6 (IY+d)", "RES 6 (IY+d)->A", + "RES 7 (IY+d)->B", "RES 7 (IY+d)->C", "RES 7 (IY+d)->D", "RES 7 (IY+d)->E", "RES 7 (IY+d)->H", "RES 7 (IY+d)->L", "RES 7 (IY+d)", "RES 7 (IY+d)->A", + "SET 0 (IY+d)->B", "SET 0 (IY+d)->C", "SET 0 (IY+d)->D", "SET 0 (IY+d)->E", "SET 0 (IY+d)->H", "SET 0 (IY+d)->L", "SET 0 (IY+d)", "SET 0 (IY+d)->A", + "SET 1 (IY+d)->B", "SET 1 (IY+d)->C", "SET 1 (IY+d)->D", "SET 1 (IY+d)->E", "SET 1 (IY+d)->H", "SET 1 (IY+d)->L", "SET 1 (IY+d)", "SET 1 (IY+d)->A", + "SET 2 (IY+d)->B", "SET 2 (IY+d)->C", "SET 2 (IY+d)->D", "SET 2 (IY+d)->E", "SET 2 (IY+d)->H", "SET 2 (IY+d)->L", "SET 2 (IY+d)", "SET 2 (IY+d)->A", + "SET 3 (IY+d)->B", "SET 3 (IY+d)->C", "SET 3 (IY+d)->D", "SET 3 (IY+d)->E", "SET 3 (IY+d)->H", "SET 3 (IY+d)->L", "SET 3 (IY+d)", "SET 3 (IY+d)->A", + "SET 4 (IY+d)->B", "SET 4 (IY+d)->C", "SET 4 (IY+d)->D", "SET 4 (IY+d)->E", "SET 4 (IY+d)->H", "SET 4 (IY+d)->L", "SET 4 (IY+d)", "SET 4 (IY+d)->A", + "SET 5 (IY+d)->B", "SET 5 (IY+d)->C", "SET 5 (IY+d)->D", "SET 5 (IY+d)->E", "SET 5 (IY+d)->H", "SET 5 (IY+d)->L", "SET 5 (IY+d)", "SET 5 (IY+d)->A", + "SET 6 (IY+d)->B", "SET 6 (IY+d)->C", "SET 6 (IY+d)->D", "SET 6 (IY+d)->E", "SET 6 (IY+d)->H", "SET 6 (IY+d)->L", "SET 6 (IY+d)", "SET 6 (IY+d)->A", + "SET 7 (IY+d)->B", "SET 7 (IY+d)->C", "SET 7 (IY+d)->D", "SET 7 (IY+d)->E", "SET 7 (IY+d)->H", "SET 7 (IY+d)->L", "SET 7 (IY+d)", "SET 7 (IY+d)->A", + }; + + readonly static string[] mnemonicsCB = new string[] + { + "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", + "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", + "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", + "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", + "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", + "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", + "SL1 B", "SL1 C", "SL1 D", "SL1 E", "SL1 H", "SL1 L", "SL1 (HL)", "SL1 A", + "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", + "BIT 0, B", "BIT 0, C", "BIT 0, D", "BIT 0, E", "BIT 0, H", "BIT 0, L", "BIT 0, (HL)", "BIT 0, A", + "BIT 1, B", "BIT 1, C", "BIT 1, D", "BIT 1, E", "BIT 1, H", "BIT 1, L", "BIT 1, (HL)", "BIT 1, A", + "BIT 2, B", "BIT 2, C", "BIT 2, D", "BIT 2, E", "BIT 2, H", "BIT 2, L", "BIT 2, (HL)", "BIT 2, A", + "BIT 3, B", "BIT 3, C", "BIT 3, D", "BIT 3, E", "BIT 3, H", "BIT 3, L", "BIT 3, (HL)", "BIT 3, A", + "BIT 4, B", "BIT 4, C", "BIT 4, D", "BIT 4, E", "BIT 4, H", "BIT 4, L", "BIT 4, (HL)", "BIT 4, A", + "BIT 5, B", "BIT 5, C", "BIT 5, D", "BIT 5, E", "BIT 5, H", "BIT 5, L", "BIT 5, (HL)", "BIT 5, A", + "BIT 6, B", "BIT 6, C", "BIT 6, D", "BIT 6, E", "BIT 6, H", "BIT 6, L", "BIT 6, (HL)", "BIT 6, A", + "BIT 7, B", "BIT 7, C", "BIT 7, D", "BIT 7, E", "BIT 7, H", "BIT 7, L", "BIT 7, (HL)", "BIT 7, A", + "RES 0, B", "RES 0, C", "RES 0, D", "RES 0, E", "RES 0, H", "RES 0, L", "RES 0, (HL)", "RES 0, A", + "RES 1, B", "RES 1, C", "RES 1, D", "RES 1, E", "RES 1, H", "RES 1, L", "RES 1, (HL)", "RES 1, A", + "RES 2, B", "RES 2, C", "RES 2, D", "RES 2, E", "RES 2, H", "RES 2, L", "RES 2, (HL)", "RES 2, A", + "RES 3, B", "RES 3, C", "RES 3, D", "RES 3, E", "RES 3, H", "RES 3, L", "RES 3, (HL)", "RES 3, A", + "RES 4, B", "RES 4, C", "RES 4, D", "RES 4, E", "RES 4, H", "RES 4, L", "RES 4, (HL)", "RES 4, A", + "RES 5, B", "RES 5, C", "RES 5, D", "RES 5, E", "RES 5, H", "RES 5, L", "RES 5, (HL)", "RES 5, A", + "RES 6, B", "RES 6, C", "RES 6, D", "RES 6, E", "RES 6, H", "RES 6, L", "RES 6, (HL)", "RES 6, A", + "RES 7, B", "RES 7, C", "RES 7, D", "RES 7, E", "RES 7, H", "RES 7, L", "RES 7, (HL)", "RES 7, A", + "SET 0, B", "SET 0, C", "SET 0, D", "SET 0, E", "SET 0, H", "SET 0, L", "SET 0, (HL)", "SET 0, A", + "SET 1, B", "SET 1, C", "SET 1, D", "SET 1, E", "SET 1, H", "SET 1, L", "SET 1, (HL)", "SET 1, A", + "SET 2, B", "SET 2, C", "SET 2, D", "SET 2, E", "SET 2, H", "SET 2, L", "SET 2, (HL)", "SET 2, A", + "SET 3, B", "SET 3, C", "SET 3, D", "SET 3, E", "SET 3, H", "SET 3, L", "SET 3, (HL)", "SET 3, A", + "SET 4, B", "SET 4, C", "SET 4, D", "SET 4, E", "SET 4, H", "SET 4, L", "SET 4, (HL)", "SET 4, A", + "SET 5, B", "SET 5, C", "SET 5, D", "SET 5, E", "SET 5, H", "SET 5, L", "SET 5, (HL)", "SET 5, A", + "SET 6, B", "SET 6, C", "SET 6, D", "SET 6, E", "SET 6, H", "SET 6, L", "SET 6, (HL)", "SET 6, A", + "SET 7, B", "SET 7, C", "SET 7, D", "SET 7, E", "SET 7, H", "SET 7, L", "SET 7, (HL)", "SET 7, A", + }; + + readonly static string[] mnemonicsED = new string[] + { + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", + + "IN B, C", "OUT C, B", "SBC HL, BC", "LD (nn), BC", //0x44 + "NEG", "RETN", "IM $0", "LD I, A", //0x48 + "IN C, C", "OUT C, C", "ADC HL, BC", "LD BC, (nn)", //0x4C + "NEG", "RETI", "IM $0", "LD R, A", //0x50 + "IN D, C", "OUT C, D", "SBC HL, DE", "LD (nn), DE", //0x54 + "NEG", "RETN", "IM $1", "LD A, I", //0x58 + "IN E, C", "OUT C, E", "ADC HL, DE", "LD DE, (nn)", //0x5C + "NEG", "RETI", "IM $2", "LD A, R", //0x60 + + "IN H, C", "OUT C, H", "SBC HL, HL", "LD (nn), HL", //0x64 + "NEG", "RETN", "IM $0", "RRD", //0x68 + "IN L, C", "OUT C, L", "ADC HL, HL", "LD HL, (nn)", //0x6C + "NEG", "RETI", "IM $0", "RLD", //0x70 + "IN 0, C", "OUT C, 0", "SBC HL, SP", "LD (nn), SP", //0x74 + "NEG", "RETN", "IM $1", "NOP", //0x78 + "IN A, C", "OUT C, A", "ADC HL, SP", "LD SP, (nn)", //0x7C + "NEG", "RETI", "IM $2", "NOP", //0x80 + + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x90 + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xA0 + "LDI", "CPI", "INI", "OUTI", //0xA4 + "NOP", "NOP", "NOP", "NOP", //0xA8 + "LDD", "CPD", "IND", "OUTD", //0xAC + "NOP", "NOP", "NOP", "NOP", //0xB0 + "LDIR", "CPIR", "INIR", "OTIR", //0xB4 + "NOP", "NOP", "NOP", "NOP", //0xB8 + "LDDR", "CPDR", "INDR", "OTDR", //0xBC + "NOP", "NOP", "NOP", "NOP", //0xC0 + + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xD0 + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xE0 + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xF0 + "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100 + }; + + public string Disassemble(ushort addr, Func read, out ushort size) + { + ushort start_addr = addr; + byte A = read(addr++); + string format; + switch (A) + { + case 0xCB: + A = read(addr++); + format = mnemonicsCB[A]; + break; + case 0xDD: + A = read(addr++); + switch (A) + { + case 0xCB: format = mnemonicsDDCB[A]; break; + case 0xED: format = mnemonicsED[A]; break; + default: format = mnemonicsDD[A]; break; + } + break; + case 0xED: + A = read(addr++); + format = mnemonicsED[A]; + break; + case 0xFD: + A = read(addr++); + switch (A) + { + case 0xCB: format = mnemonicsFDCB[A]; break; + case 0xED: format = mnemonicsED[A]; break; + default: format = mnemonicsFD[A]; break; + } + break; + default: format = mnemonics[A]; break; + } + + string temp = Result(format, read, ref addr); + + size = (ushort)(addr - start_addr); + return temp; + } + + #region IDisassemblable + + public string Cpu + { + get { return "Z80"; } + set { } + } + + public string PCRegisterName + { + get { return "PC"; } + } + + public IEnumerable AvailableCpus + { + get { yield return "Z80"; } + } + + public string Disassemble(MemoryDomain m, uint addr, out int length) + { + int loc = (int)addr; + ushort unused = 0; + string ret = Disassemble((ushort) addr, a => m.PeekByte(a), out unused); + length = loc - (int)addr; + return ret; + } + + #endregion + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs new file mode 100644 index 0000000000..64ddc1ae5c --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs @@ -0,0 +1,727 @@ +using BizHawk.Common.NumberExtensions; +using System; + +namespace BizHawk.Emulation.Common.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] + inc)) << 8), (byte)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 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 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; + } + } +} diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs new file mode 100644 index 0000000000..e2095693ec --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs @@ -0,0 +1,134 @@ +using System.Runtime.InteropServices; +using System; + +namespace BizHawk.Emulation.Common.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]; + + // The Z80 also has ports to communicate with external components + + 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 < 14; 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..a3ca05dcb0 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -0,0 +1,590 @@ +using System; + +namespace BizHawk.Emulation.Common.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, + IDLE, + 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[] + {PREFIX, src, + IDLE, + IDLE, + OP }; + } + + 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, + OP }; + } + + 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, + IDLE, + TR, SPl, src_l, + IDLE, + TR, SPh, src_h, + IDLE, + OP }; + } + + private void JAM_() + { + cur_instr = new ushort[] + {JAM, + IDLE, + IDLE, + IDLE }; + } + + 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, + 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, + IDLE, + IDLE, + TR16, Z, W, L, H, + IDLE, + IDLE, + 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, + IDLE, + IDLE, + TR16, Z, W, L, H, + IDLE, + IDLE, + 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..38890f7918 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs @@ -0,0 +1,478 @@ +namespace BizHawk.Emulation.Common.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..0f640eb124 --- /dev/null +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -0,0 +1,697 @@ +using System; +using System.Globalization; +using System.IO; + +using BizHawk.Common; +using BizHawk.Emulation.Common; +using BizHawk.Common.NumberExtensions; + +// Z80A CPU +namespace BizHawk.Emulation.Common.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 JAM = 49; // all undocumented opcodes jam the machine + 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 INT_MODE = 55; + public const ushort RRD = 56; + public const ushort RLD = 57; + public const ushort SET_FL_LD = 58; + public const ushort SET_FL_CP = 59; + public const ushort I_BIT = 60; + public const ushort HL_BIT = 61; + + + 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() + { + switch (cur_instr[instr_pntr++]) + { + case IDLE: + // do nothing + break; + case OP: + // Read the opcode of the next instruction + if (EI_pending > 0 && NO_prefix) + { + EI_pending--; + if (EI_pending == 0) + { + IFF1 = IFF2 = true; + } + } + + // Process interrupt requests. + if (nonMaskableInterruptPending && NO_prefix) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo + { + Disassembly = "====NMI====", + RegisterInfo = "" + }); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + + } + else if (iff1 && FlagI && NO_prefix) + { + iff1 = iff2 = false; + + 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 && NO_prefix) TraceCallback(State()); + FetchInstruction(ReadMemory(RegPC++)); + } + instr_pntr = 0; + Regs[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) + { + instr_pntr = 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 && NO_prefix) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo + { + Disassembly = "====NMI====", + RegisterInfo = "" + }); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + + } + else if (iff1 && FlagI && NO_prefix) + { + iff1 = iff2 = false; + + 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; + Regs[R]++; + } + } + break; + + case HALT: + halted = true; + if (EI_pending > 0 && NO_prefix) + { + EI_pending--; + if (EI_pending == 0) + { + IFF1 = IFF2 = true; + } + } + + // Process interrupt requests. + if (nonMaskableInterruptPending && NO_prefix) + { + nonMaskableInterruptPending = false; + + if (TraceCallback != null) + { + TraceCallback(new TraceInfo + { + Disassembly = "====NMI====", + RegisterInfo = "" + }); + } + + iff2 = iff1; + iff1 = false; + NMI_(); + NMICallback(); + + } + else if (iff1 && FlagI && NO_prefix) + { + iff1 = iff2 = false; + + 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 + { + instr_pntr = 0; + Regs[R]++; + cur_instr = new ushort[] + {IDLE, + IDLE, + IDLE, + HALT }; + } + 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; + EI_pending = 0; + 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; } + Regs[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 JAM: + jammed = true; + 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 + break; + case EI_RETN: + EI_pending = 1; + 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; + } + 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("jammped", ref jammed); + 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 From fc0a251040d8208d68e0378811ea29a238f62e13 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 12 Oct 2017 20:21:32 -0400 Subject: [PATCH 05/39] Add files via upload --- .../Consoles/Sega/SMS/SMS.IDebuggable.cs | 116 +++++----- .../Consoles/Sega/SMS/SMS.IEmulator.cs | 16 +- .../Consoles/Sega/SMS/SMS.IStatable.cs | 206 +++++++++--------- .../Consoles/Sega/SMS/SMS.cs | 15 +- .../Consoles/Sega/SMS/VDP.cs | 25 ++- 5 files changed, 201 insertions(+), 177 deletions(-) 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..d6f398dccd 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -36,15 +36,19 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem _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 (Tracer.Enabled) + { + Cpu.TraceCallback = s => Tracer.Put(s); + } + else + { + Cpu.TraceCallback = null; } if (IsGameGear == false) diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs index 72f703980d..8f29ddaf9c 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs @@ -1,106 +1,100 @@ -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); + } + + 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..1e9b39381d 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.Common.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 }; @@ -160,7 +161,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 +179,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..f079d04608 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.Common.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) { From 73dfcf00bd7b6631009c3768c4e0fe2fc90350a7 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Fri, 13 Oct 2017 11:09:08 +0100 Subject: [PATCH 06/39] DiscSystem - CDFS classes now also detect and consume CD-I (Green Book) disc images --- .../CDFS/EndianBitConverter.cs | 45 ++ .../CDFS/ISODirectoryNode.cs | 22 +- BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs | 139 +++-- .../CDFS/ISONodeRecord.cs | 123 +++- .../CDFS/ISOVolumeDescriptor.cs | 572 +++++++++++++----- 5 files changed, 700 insertions(+), 201 deletions(-) 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..d623740ef8 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,11 +159,12 @@ 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; - } + } #endregion @@ -135,6 +179,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 + } } From 3bbce67c10d68d98212a864416db6a97852c81a3 Mon Sep 17 00:00:00 2001 From: Asnivor Date: Fri, 13 Oct 2017 15:24:00 +0100 Subject: [PATCH 07/39] Added a small method to return all files recursively as a List> --- BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs | 57 +++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs b/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs index d623740ef8..e81d6316a4 100644 --- a/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs +++ b/BizHawk.Emulation.DiscSystem/CDFS/ISOFile.cs @@ -164,7 +164,62 @@ namespace BizHawk.Emulation.DiscSystem 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 From 258688ebdd88604126b3883ccd6e4a7c59359d63 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 11:07:02 -0400 Subject: [PATCH 08/39] Add files via upload --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 2 +- .../CPUs/Z80A/Operations.cs | 28 +++++++++---------- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 17 ++++++----- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs index ce3fb3f729..089185c7ca 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -593,7 +593,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A 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 R, A + 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 diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs index 64ddc1ae5c..d80fb48022 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs @@ -12,17 +12,27 @@ namespace BizHawk.Emulation.Common.Components.Z80A 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)); + 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]); + 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] + inc)) << 8), (byte)Regs[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) @@ -260,7 +270,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A public void XOR8_Func(ushort dest, ushort src) { - Regs[dest] = (ushort)(Regs[dest] ^ Regs[src]); + Regs[dest] = (ushort)((Regs[dest] ^ Regs[src])); FlagZ = Regs[dest] == 0; FlagC = false; @@ -582,16 +592,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A Regs[src_h] = temp; } - 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 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); diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index 0f640eb124..dd982d720c 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -138,6 +138,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A // Execute instructions public void ExecuteOne() { + if (Regs[A] > 255) { Console.WriteLine(RegPC); } switch (cur_instr[instr_pntr++]) { case IDLE: @@ -172,7 +173,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A iff1 = false; NMI_(); NMICallback(); - } else if (iff1 && FlagI && NO_prefix) { @@ -213,6 +213,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A } instr_pntr = 0; Regs[R]++; + Regs[R] &= 0xFF; break; case OP_R: // determine if we repeat based on what operation we are doing @@ -243,7 +244,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A // if we don't repeat, continue on as a normal opcode fetch if (repeat && temp3 > 0) { - instr_pntr = 0; cur_instr = new ushort[] {IDLE, DEC16, PCl, PCh, @@ -278,7 +278,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A { // Interrupts can occur at this point, so process them accordingly // Read the opcode of the next instruction - if (EI_pending > 0) + if (EI_pending > 0 && NO_prefix) { EI_pending--; if (EI_pending == 0) @@ -343,10 +343,11 @@ namespace BizHawk.Emulation.Common.Components.Z80A if (OnExecFetch != null) OnExecFetch(RegPC); if (TraceCallback != null) TraceCallback(State()); FetchInstruction(ReadMemory(RegPC++)); - instr_pntr = 0; Regs[R]++; + Regs[R] &= 0xFF; } } + instr_pntr = 0; break; case HALT: @@ -378,7 +379,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A iff1 = false; NMI_(); NMICallback(); - + halted = false; } else if (iff1 && FlagI && NO_prefix) { @@ -410,11 +411,13 @@ namespace BizHawk.Emulation.Common.Components.Z80A break; } IRQCallback(); + halted = false; } else { instr_pntr = 0; Regs[R]++; + Regs[R] &= 0xFF; cur_instr = new ushort[] {IDLE, IDLE, @@ -538,7 +541,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A break; case DI: IFF1 = IFF2 = false; - EI_pending = 0; break; case EXCH: EXCH_16_Func(F_s, A_s, F, A); @@ -561,6 +563,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A if (prefix_src == IXCBpre) { IXCB_prefix = true; IXCB_prefetch = true; } if (prefix_src == IYCBpre) { IYCB_prefix = true; IYCB_prefetch = true; } Regs[R]++; + Regs[R] &= 0xFF; break; case ASGN: ASGN_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); @@ -577,7 +580,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A // Not currently implemented here break; case EI_RETN: - EI_pending = 1; + iff1 = iff2; break; case OUT: OUT_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++]); From 946c025cd62d1dbe55078294fca7f423c6f6cd48 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 16:26:32 -0400 Subject: [PATCH 09/39] Add files via upload --- .../Calculator/TI83.IDebuggable.cs | 206 +++++++++--------- .../Calculator/TI83.IEmulator.cs | 18 +- .../Calculator/TI83.IStatable.cs | 61 +++--- BizHawk.Emulation.Cores/Calculator/TI83.cs | 14 +- 4 files changed, 157 insertions(+), 142 deletions(-) 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..1d6b7be044 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs @@ -13,11 +13,13 @@ 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 @@ -26,8 +28,12 @@ namespace BizHawk.Emulation.Cores.Calculators _onPressed = controller.IsPressed("ON"); // and this was derived from other emus - _cpu.ExecuteCycles(10000); - _cpu.Interrupt = true; + for (int j = 0; j < 10000; j++) + { + _cpu.ExecuteOne(); + } + + _cpu.FlagI = true; } Frame++; diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs index e6927d9962..0539da2ae0 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); diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.cs b/BizHawk.Emulation.Cores/Calculator/TI83.cs index 53a69072b6..aa83616945 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.Common.Components.Z80A; // http://www.ticalc.org/pub/text/calcinfo/ namespace BizHawk.Emulation.Cores.Calculators @@ -48,7 +48,7 @@ namespace BizHawk.Emulation.Cores.Calculators _tracer = new TraceBuffer { Header = _cpu.TraceHeader }; ser.Register(_tracer); - ser.Register(new Disassembler()); + ser.Register(_cpu); } private readonly TraceBuffer _tracer; @@ -151,7 +151,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; } @@ -428,13 +428,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 +447,7 @@ namespace BizHawk.Emulation.Cores.Calculators _ram[i] = 0xFF; } - _cpu.RegisterPC = _startPC; + _cpu.RegPC = _startPC; _cpu.IFF1 = false; _cpu.IFF2 = false; From 3be21c583e39bca4a61ef779f6a0e8b3856c8ebf Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 16:27:41 -0400 Subject: [PATCH 10/39] Add files via upload --- .../CPUs/Z80A/Interrupts.cs | 19 ++++++++++--------- .../CPUs/Z80A/Registers.cs | 4 +--- .../CPUs/Z80A/Tables_Direct.cs | 13 ++----------- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 6 +++++- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs index 33df2edf55..f658f1a09b 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs @@ -83,28 +83,28 @@ namespace BizHawk.Emulation.Common.Components.Z80A } // 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 + // 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, - IDLE, - IDLE, - IDLE, - IDLE, DEC16, SPl, SPh, - IDLE, WR, SPl, SPh, PCh, IDLE, DEC16, SPl, SPh, - IDLE, WR, SPl, SPh, PCl, - IDLE, + IDLE, ASGN, PCl, 0, - IDLE, TR, PCh, I, + IDLE, IDLE, + RD, Z, PCl, PCh, + INC16, PCl, PCh, + IDLE, + RD, W, PCl, PCh, + IDLE, + TR16, PCl, PCh, Z, W, OP }; } @@ -116,6 +116,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A IFF2 = false; NonMaskableInterrupt = false; NonMaskableInterruptPending = false; + FlagI = false; InterruptMode = 1; } } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs index e2095693ec..11dfef24cd 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs @@ -43,8 +43,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A public ushort[] Regs = new ushort[36]; - // The Z80 also has ports to communicate with external components - public bool FlagI; public bool FlagC @@ -107,7 +105,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A private void ResetRegisters() { - for (int i=0; i < 14; i++) + for (int i=0; i < 36; i++) { Regs[i] = 0; } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs index a3ca05dcb0..2d069cd8b1 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -440,11 +440,9 @@ namespace BizHawk.Emulation.Common.Components.Z80A private void LD_SP_16(ushort src_l, ushort src_h) { cur_instr = new ushort[] - {IDLE, - IDLE, + {IDLE, IDLE, TR, SPl, src_l, - IDLE, TR, SPh, src_h, IDLE, OP }; @@ -526,6 +524,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A TR16, Z, W, dest_l, dest_h, INC16, Z, W, IDLE, + IDLE, op, dest_l, dest_h, src_l, src_h, IDLE, IDLE, @@ -546,12 +545,8 @@ namespace BizHawk.Emulation.Common.Components.Z80A cur_instr = new ushort[] {IDLE, IDLE, - IDLE, - IDLE, TR16, Z, W, L, H, IDLE, - IDLE, - IDLE, RD, ALU, Z, W, IDLE, RRD, ALU, A, @@ -569,12 +564,8 @@ namespace BizHawk.Emulation.Common.Components.Z80A cur_instr = new ushort[] {IDLE, IDLE, - IDLE, - IDLE, TR16, Z, W, L, H, IDLE, - IDLE, - IDLE, RD, ALU, Z, W, IDLE, RLD, ALU, A, diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index dd982d720c..ff2bbf87e7 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -177,6 +177,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A else if (iff1 && FlagI && NO_prefix) { iff1 = iff2 = false; + EI_pending = 0; if (TraceCallback != null) { @@ -310,6 +311,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A else if (iff1 && FlagI && NO_prefix) { iff1 = iff2 = false; + EI_pending = 0; if (TraceCallback != null) { @@ -384,6 +386,7 @@ namespace BizHawk.Emulation.Common.Components.Z80A else if (iff1 && FlagI && NO_prefix) { iff1 = iff2 = false; + EI_pending = 0; if (TraceCallback != null) { @@ -415,7 +418,6 @@ namespace BizHawk.Emulation.Common.Components.Z80A } else { - instr_pntr = 0; Regs[R]++; Regs[R] &= 0xFF; cur_instr = new ushort[] @@ -424,6 +426,8 @@ namespace BizHawk.Emulation.Common.Components.Z80A IDLE, HALT }; } + + instr_pntr = 0; break; case RD: Read_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); From ce6dcab32378d88effdb07957453a5bb16db9fd9 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:50:54 -0400 Subject: [PATCH 11/39] Add files via upload --- .../Consoles/Coleco/ColecoControllers.cs | 2 +- .../Coleco/ColecoVision.IDebuggable.cs | 116 ++++++++++-------- .../Consoles/Coleco/ColecoVision.IEmulator.cs | 10 +- .../Consoles/Coleco/ColecoVision.IStatable.cs | 61 +++++---- .../Consoles/Coleco/ColecoVision.cs | 4 +- .../Consoles/Coleco/TMS9918A.cs | 13 +- 6 files changed, 111 insertions(+), 95 deletions(-) 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..f7d183f60d 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.Common.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..00049a5890 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.Common.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; } } From 438b3893e369819b33b4f42d88990a38521cc9b8 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:03 -0400 Subject: [PATCH 12/39] Delete Disassembler.cs --- .../CPUs/Z80/Disassembler.cs | 553 ------------------ 1 file changed, 553 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs diff --git a/BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs deleted file mode 100644 index d5b9c2c4e1..0000000000 --- a/BizHawk.Emulation.Cores/CPUs/Z80/Disassembler.cs +++ /dev/null @@ -1,553 +0,0 @@ -//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.Collections.Generic; - -using BizHawk.Emulation.Common; - -namespace BizHawk.Emulation.Cores.Components.Z80 -{ - public class Disassembler : 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) - { - //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(); - format = format.Replace("nn", string.Format("{0:X4}h", B + C * 256)); - } - - if (format.IndexOf("n") != -1) - { - byte B = read(); - format = format.Replace("n", string.Format("{0:X2}h", B)); - } - - if (format.IndexOf("+d") != -1) format = format.Replace("+d", "d"); - - if (format.IndexOf("d") != -1) - { - byte B = read(); - bool neg = ((B & 0x80) != 0); - char sign = neg ? '-' : '+'; - int val = neg ? 256 - B : B; - format = format.Replace("d", string.Format("{0}{1:X2}h", sign, val)); - } - - return format; - } - - readonly static string[] mnemonics = new string[] - { - "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 - "INC B", "DEC B", "LD B, n", "RLCA", //0x08 - "EX AF, AF'", "ADD HL, BC", "LD A, (BC)", "DEC BC", //0x0C - "INC C", "DEC C", "LD C, n", "RRCA", //0x10 - "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 - "INC D", "DEC D", "LD D, n", "RLA", //0x18 - "JR d", "ADD HL, DE", "LD A, (DE)", "DEC DE", //0x1C - "INC E", "DEC E", "LD E, n", "RRA", //0x20 - "JR NZ, d", "LD HL, nn", "LD (nn), HL", "INC HL", //0x24 - "INC H", "DEC H", "LD H, n", "DAA", //0x28 - "JR Z, d", "ADD HL, HL", "LD HL, (nn)", "DEC HL", //0x2C - "INC L", "DEC L", "LD L, n", "CPL", //0x30 - "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 - "INC (HL)", "DEC (HL)", "LD (HL), n", "SCF", //0x38 - "JR C, d", "ADD HL, SP", "LD A, (nn)", "DEC SP", //0x3C - "INC A", "DEC A", "LD A, n", "CCF", //0x40 - "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 - "LD B, H", "LD B, L", "LD B, (HL)", "LD B, A", //0x48 - "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C - "LD C, H", "LD C, L", "LD C, (HL)", "LD C, A", //0x50 - "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 - "LD D, H", "LD D, L", "LD D, (HL)", "LD D, A", //0x58 - "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C - "LD E, H", "LD E, L", "LD E, (HL)", "LD E, A", //0x60 - "LD H, B", "LD H, C", "LD H, D", "LD H, E", //0x64 - "LD H, H", "LD H, L", "LD H, (HL)", "LD H, A", //0x68 - "LD L, B", "LD L, B", "LD L, D", "LD L, E", //0x6C - "LD L, H", "LD L, L", "LD L, (HL)", "LD L, A", //0x70 - "LD (HL), B", "LD (HL), C", "LD (HL), D", "LD (HL), E", //0x74 - "LD (HL), H", "LD (HL), L", "HALT", "LD (HL), A", //0x78 - "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C - "LD A, H", "LD A, L", "LD A, (HL)", "LD A, A", //0x80 - "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 - "ADD A, H", "ADD A, L", "ADD A, (HL)", "ADD A, A", //0x88 - "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C - "ADC A, H", "ADC A, L", "ADC A, (HL)", "ADC A, A", //0x90 - "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 - "SUB A, H", "SUB A, L", "SUB A, (HL)", "SUB A, A", //0x98 - "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C - "SBC A, H", "SBC A, L", "SBC A, (HL)", "SBC A, A", //0xA0 - "AND B", "AND C", "AND D", "AND E", //0xA4 - "AND H", "AND L", "AND (HL)", "AND A", //0xA8 - "XOR B", "XOR C", "XOR D", "XOR E", //0xAC - "XOR H", "XOR L", "XOR (HL)", "XOR A", //0xB0 - "OR B", "OR C", "OR D", "OR E", //0xB4 - "OR H", "OR L", "OR (HL)", "OR A", //0xB8 - "CP B", "CP C", "CP D", "CP E", //0xBC - "CP H", "CP L", "CP (HL)", "CP A", //0xC0 - "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 - "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 - "RET Z", "RET", "JP Z, nn", "[CB]", //0xCC - "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 - "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 - "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 - "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC - "CALL C, nn", "[DD]", "SBC A, n", "RST $18", //0xE0 - "RET PO", "POP HL", "JP PO, nn", "EX (SP), HL", //0xE4 - "CALL C, nn", "PUSH HL", "AND n", "RST $20", //0xE8 - "RET PE", "JP HL", "JP PE, nn", "EX DE, HL", //0xEC - "CALL PE, nn", "[ED]", "XOR n", "RST $28", //0xF0 - "RET P", "POP AF", "JP P, nn", "DI", //0xF4 - "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 - "RET M", "LD SP, HL", "JP M, nn", "EI", //0xFC - "CALL M, nn", "[FD]", "CP n", "RST $38", //0x100 - }; - - readonly static string[] mnemonicsDD = new string[] - { - "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 - "INC B", "DEC B", "LD B, n", "RLCA", //0x08 - "EX AF, AF'", "ADD IX, BC", "LD A, (BC)", "DEC BC", //0x0C - "INC C", "DEC C", "LD C, n", "RRCA", //0x10 - "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 - "INC D", "DEC D", "LD D, n", "RLA", //0x18 - "JR d", "ADD IX, DE", "LD A, (DE)", "DEC DE", //0x1C - "INC E", "DEC E", "LD E, n", "RRA", //0x20 - "JR NZ, d", "LD IX, nn", "LD (nn), IX", "INC IX", //0x24 - "INC IXH", "DEC IXH", "LD IXH, n", "DAA", //0x28 - "JR Z, d", "ADD IX, IX", "LD IX, (nn)", "DEC IX", //0x2C - "INC IXL", "DEC IXL", "LD IXL, n", "CPL", //0x30 - "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 - "INC (IX+d)", "DEC (IX+d)", "LD (IX+d), n", "SCF", //0x38 - "JR C, d", "ADD IX, SP", "LD A, (nn)", "DEC SP", //0x3C - "INC A", "DEC A", "LD A, n", "CCF", //0x40 - "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 - "LD B, IXH", "LD B, IXL", "LD B, (IX+d)", "LD B, A", //0x48 - "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C - "LD C, IXH", "LD C, IXL", "LD C, (IX+d)", "LD C, A", //0x50 - "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 - "LD D, IXH", "LD D, IXL", "LD D, (IX+d)", "LD D, A", //0x58 - "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C - "LD E, IXH", "LD E, IXL", "LD E, (IX+d)", "LD E, A", //0x60 - "LD IXH, B", "LD IXH, C", "LD IXH, D", "LD IXH, E", //0x64 - "LD IXH, IXH", "LD IXH, IXL", "LD H, (IX+d)", "LD IXH, A", //0x68 - "LD IXL, B", "LD IXL, C", "LD IXL, D", "LD IXL, E", //0x6C - "LD IXL, IXH", "LD IXL, IXL", "LD L, (IX+d)", "LD IXL, A", //0x70 - "LD (IX+d), B", "LD (IX+d), C", "LD (IX+d), D", "LD (IX+d), E", //0x74 - "LD (IX+d), H", "LD (IX+d), L", "HALT", "LD (IX+d), A", //0x78 - "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C - "LD A, IXH", "LD A, IXL", "LD A, (IX+d)", "LD A, A", //0x80 - "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 - "ADD A, IXH", "ADD A, IXL", "ADD A, (IX+d)", "ADD A, A", //0x88 - "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C - "ADC A, IXH", "ADC A, IXL", "ADC A, (IX+d)", "ADC A, A", //0x90 - "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 - "SUB A, IXH", "SUB A, IXL", "SUB A, (IX+d)", "SUB A, A", //0x98 - "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C - "SBC A, IXH", "SBC A, IXL", "SBC A, (IX+d)", "SBC A, A", //0xA0 - "AND B", "AND C", "AND D", "AND E", //0xA4 - "AND IXH", "AND IXL", "AND (IX+d)", "AND A", //0xA8 - "XOR B", "XOR C", "XOR D", "XOR E", //0xAC - "XOR IXH", "XOR IXL", "XOR (IX+d)", "XOR A", //0xB0 - "OR B", "OR C", "OR D", "OR E", //0xB4 - "OR IXH", "OR IXL", "OR (IX+d)", "OR A", //0xB8 - "CP B", "CP C", "CP D", "CP E", //0xBC - "CP IXH", "CP IXL", "CP (IX+d)", "CP A", //0xC0 - "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 - "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 - "RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC - "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 - "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 - "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 - "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC - "CALL C, nn", "[!DD DD!]", "SBC A, n", "RST $18", //0xE0 - "RET PO", "POP IX", "JP PO, nn", "EX (SP), IX", //0xE4 - "CALL C, nn", "PUSH IX", "AND n", "RST $20", //0xE8 - "RET PE", "JP IX", "JP PE, nn", "EX DE, HL", //0xEC - "CALL PE, nn", "[DD ED]", "XOR n", "RST $28", //0xF0 - "RET P", "POP AF", "JP P, nn", "DI", //0xF4 - "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 - "RET M", "LD SP, IX", "JP M, nn", "EI", //0xFC - "CALL M, nn", "[!!DD FD!!]", "CP n", "RST $38", //0x100 - }; - - readonly static string[] mnemonicsFD = new string[] - { - "NOP", "LD BC, nn", "LD (BC), A", "INC BC", //0x04 - "INC B", "DEC B", "LD B, n", "RLCA", //0x08 - "EX AF, AF'", "ADD IY, BC", "LD A, (BC)", "DEC BC", //0x0C - "INC C", "DEC C", "LD C, n", "RRCA", //0x10 - "DJNZ d", "LD DE, nn", "LD (DE), A", "INC DE", //0x14 - "INC D", "DEC D", "LD D, n", "RLA", //0x18 - "JR d", "ADD IY, DE", "LD A, (DE)", "DEC DE", //0x1C - "INC E", "DEC E", "LD E, n", "RRA", //0x20 - "JR NZ, d", "LD IY, nn", "LD (nn), IY", "INC IY", //0x24 - "INC IYH", "DEC IYH", "LD IYH, n", "DAA", //0x28 - "JR Z, d", "ADD IY, IY", "LD IY, (nn)", "DEC IY", //0x2C - "INC IYL", "DEC IYL", "LD IYL, n", "CPL", //0x30 - "JR NC, d", "LD SP, nn", "LD (nn), A", "INC SP", //0x34 - "INC (IY+d)", "DEC (IY+d)", "LD (IY+d), n", "SCF", //0x38 - "JR C, d", "ADD IY, SP", "LD A, (nn)", "DEC SP", //0x3C - "INC A", "DEC A", "LD A, n", "CCF", //0x40 - "LD B, B", "LD B, C", "LD B, D", "LD B, E", //0x44 - "LD B, IYH", "LD B, IYL", "LD B, (IY+d)", "LD B, A", //0x48 - "LD C, B", "LD C, C", "LD C, D", "LD C, E", //0x4C - "LD C, IYH", "LD C, IYL", "LD C, (IY+d)", "LD C, A", //0x50 - "LD D, B", "LD D, C", "LD D, D", "LD D, E", //0x54 - "LD D, IYH", "LD D, IYL", "LD D, (IY+d)", "LD D, A", //0x58 - "LD E, B", "LD E, C", "LD E, D", "LD E, E", //0x5C - "LD E, IYH", "LD E, IYL", "LD E, (IY+d)", "LD E, A", //0x60 - "LD IYH, B", "LD IYH, C", "LD IYH, D", "LD IYH, E", //0x64 - "LD IYH, IYH", "LD IYH, IYL", "LD H, (IY+d)", "LD IYH, A", //0x68 - "LD IYL, B", "LD IYL, C", "LD IYL, D", "LD IYL, E", //0x6C - "LD IYL, IYH", "LD IYL, IYL", "LD L, (IY+d)", "LD IYL, A", //0x70 - "LD (IY+d), B", "LD (IY+d), C", "LD (IY+d), D", "LD (IY+d), E", //0x74 - "LD (IY+d), H", "LD (IY+d), L", "HALT", "LD (IY+d), A", //0x78 - "LD A, B", "LD A, C", "LD A, D", "LD A, E", //0x7C - "LD A, IYH", "LD A, IYL", "LD A, (IY+d)", "LD A, A", //0x80 - "ADD A, B", "ADD A, C", "ADD A, D", "ADD A, E", //0x84 - "ADD A, IYH", "ADD A, IYL", "ADD A, (IY+d)", "ADD A, A", //0x88 - "ADC A, B", "ADC A, C", "ADC A, D", "ADC A, E", //0x8C - "ADC A, IYH", "ADC A, IYL", "ADC A, (IY+d)", "ADC A, A", //0x90 - "SUB A, B", "SUB A, C", "SUB A, D", "SUB A, E", //0x94 - "SUB A, IYH", "SUB A, IYL", "SUB A, (IY+d)", "SUB A, A", //0x98 - "SBC A, B", "SBC A, C", "SBC A, D", "SBC A, E", //0x9C - "SBC A, IYH", "SBC A, IYL", "SBC A, (IY+d)", "SBC A, A", //0xA0 - "AND B", "AND C", "AND D", "AND E", //0xA4 - "AND IYH", "AND IYL", "AND (IY+d)", "AND A", //0xA8 - "XOR B", "XOR C", "XOR D", "XOR E", //0xAC - "XOR IYH", "XOR IYL", "XOR (IY+d)", "XOR A", //0xB0 - "OR B", "OR C", "OR D", "OR E", //0xB4 - "OR IYH", "OR IYL", "OR (IY+d)", "OR A", //0xB8 - "CP B", "CP C", "CP D", "CP E", //0xBC - "CP IYH", "CP IYL", "CP (IY+d)", "CP A", //0xC0 - "RET NZ", "POP BC", "JP NZ, nn", "JP nn", //0xC4 - "CALL NZ, nn", "PUSH BC", "ADD A, n", "RST $00", //0xC8 - "RET Z", "RET", "JP Z, nn", "[DD CB]", //0xCC - "CALL Z, nn", "CALL nn", "ADC A, n", "RST $08", //0xD0 - "RET NC", "POP DE", "JP NC, nn", "OUT n, A", //0xD4 - "CALL NC, nn", "PUSH DE", "SUB n", "RST $10", //0xD8 - "RET C", "EXX", "JP C, nn", "IN A, n", //0xDC - "CALL C, nn", "[!FD DD!]", "SBC A, n", "RST $18", //0xE0 - "RET PO", "POP IY", "JP PO, nn", "EX (SP), IY", //0xE4 - "CALL C, nn", "PUSH IY", "AND n", "RST $20", //0xE8 - "RET PE", "JP IY", "JP PE, nn", "EX DE, HL", //0xEC - "CALL PE, nn", "[FD ED]", "XOR n", "RST $28", //0xF0 - "RET P", "POP AF", "JP P, nn", "DI", //0xF4 - "CALL P, nn", "PUSH AF", "OR n", "RST $30", //0xF8 - "RET M", "LD SP, IY", "JP M, nn", "EI", //0xFC - "CALL M, nn", "[!FD FD!]", "CP n", "RST $38", //0x100 - }; - - readonly static string[] mnemonicsDDCB = new string[] - { - "RLC (IX+d)->B", "RLC (IX+d)->C", "RLC (IX+d)->D", "RLC (IX+d)->E", "RLC (IX+d)->H", "RLC (IX+d)->L", "RLC (IX+d)", "RLC (IX+d)->A", - "RRC (IX+d)->B", "RRC (IX+d)->C", "RRC (IX+d)->D", "RRC (IX+d)->E", "RRC (IX+d)->H", "RRC (IX+d)->L", "RRC (IX+d)", "RRC (IX+d)->A", - "RL (IX+d)->B", "RL (IX+d)->C", "RL (IX+d)->D", "RL (IX+d)->E", "RL (IX+d)->H", "RL (IX+d)->L", "RL (IX+d)", "RL (IX+d)->A", - "RR (IX+d)->B", "RR (IX+d)->C", "RR (IX+d)->D", "RR (IX+d)->E", "RR (IX+d)->H", "RR (IX+d)->L", "RR (IX+d)", "RR (IX+d)->A", - "SLA (IX+d)->B", "SLA (IX+d)->C", "SLA (IX+d)->D", "SLA (IX+d)->E", "SLA (IX+d)->H", "SLA (IX+d)->L", "SLA (IX+d)", "SLA (IX+d)->A", - "SRA (IX+d)->B", "SRA (IX+d)->C", "SRA (IX+d)->D", "SRA (IX+d)->E", "SRA (IX+d)->H", "SRA (IX+d)->L", "SRA (IX+d)", "SRA (IX+d)->A", - "SL1 (IX+d)->B", "SL1 (IX+d)->C", "SL1 (IX+d)->D", "SL1 (IX+d)->E", "SL1 (IX+d)->H", "SL1 (IX+d)->L", "SL1 (IX+d)", "SL1 (IX+d)->A", - "SRL (IX+d)->B", "SRL (IX+d)->C", "SRL (IX+d)->D", "SRL (IX+d)->E", "SRL (IX+d)->H", "SRL (IX+d)->L", "SRL (IX+d)", "SRL (IX+d)->A", - "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", "BIT 0, (IX+d)", - "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", "BIT 1, (IX+d)", - "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", "BIT 2, (IX+d)", - "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", "BIT 3, (IX+d)", - "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", "BIT 4, (IX+d)", - "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", "BIT 5, (IX+d)", - "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", "BIT 6, (IX+d)", - "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", "BIT 7, (IX+d)", - "RES 0 (IX+d)->B", "RES 0 (IX+d)->C", "RES 0 (IX+d)->D", "RES 0 (IX+d)->E", "RES 0 (IX+d)->H", "RES 0 (IX+d)->L", "RES 0 (IX+d)", "RES 0 (IX+d)->A", - "RES 1 (IX+d)->B", "RES 1 (IX+d)->C", "RES 1 (IX+d)->D", "RES 1 (IX+d)->E", "RES 1 (IX+d)->H", "RES 1 (IX+d)->L", "RES 1 (IX+d)", "RES 1 (IX+d)->A", - "RES 2 (IX+d)->B", "RES 2 (IX+d)->C", "RES 2 (IX+d)->D", "RES 2 (IX+d)->E", "RES 2 (IX+d)->H", "RES 2 (IX+d)->L", "RES 2 (IX+d)", "RES 2 (IX+d)->A", - "RES 3 (IX+d)->B", "RES 3 (IX+d)->C", "RES 3 (IX+d)->D", "RES 3 (IX+d)->E", "RES 3 (IX+d)->H", "RES 3 (IX+d)->L", "RES 3 (IX+d)", "RES 3 (IX+d)->A", - "RES 4 (IX+d)->B", "RES 4 (IX+d)->C", "RES 4 (IX+d)->D", "RES 4 (IX+d)->E", "RES 4 (IX+d)->H", "RES 4 (IX+d)->L", "RES 4 (IX+d)", "RES 4 (IX+d)->A", - "RES 5 (IX+d)->B", "RES 5 (IX+d)->C", "RES 5 (IX+d)->D", "RES 5 (IX+d)->E", "RES 5 (IX+d)->H", "RES 5 (IX+d)->L", "RES 5 (IX+d)", "RES 5 (IX+d)->A", - "RES 6 (IX+d)->B", "RES 6 (IX+d)->C", "RES 6 (IX+d)->D", "RES 6 (IX+d)->E", "RES 6 (IX+d)->H", "RES 6 (IX+d)->L", "RES 6 (IX+d)", "RES 6 (IX+d)->A", - "RES 7 (IX+d)->B", "RES 7 (IX+d)->C", "RES 7 (IX+d)->D", "RES 7 (IX+d)->E", "RES 7 (IX+d)->H", "RES 7 (IX+d)->L", "RES 7 (IX+d)", "RES 7 (IX+d)->A", - "SET 0 (IX+d)->B", "SET 0 (IX+d)->C", "SET 0 (IX+d)->D", "SET 0 (IX+d)->E", "SET 0 (IX+d)->H", "SET 0 (IX+d)->L", "SET 0 (IX+d)", "SET 0 (IX+d)->A", - "SET 1 (IX+d)->B", "SET 1 (IX+d)->C", "SET 1 (IX+d)->D", "SET 1 (IX+d)->E", "SET 1 (IX+d)->H", "SET 1 (IX+d)->L", "SET 1 (IX+d)", "SET 1 (IX+d)->A", - "SET 2 (IX+d)->B", "SET 2 (IX+d)->C", "SET 2 (IX+d)->D", "SET 2 (IX+d)->E", "SET 2 (IX+d)->H", "SET 2 (IX+d)->L", "SET 2 (IX+d)", "SET 2 (IX+d)->A", - "SET 3 (IX+d)->B", "SET 3 (IX+d)->C", "SET 3 (IX+d)->D", "SET 3 (IX+d)->E", "SET 3 (IX+d)->H", "SET 3 (IX+d)->L", "SET 3 (IX+d)", "SET 3 (IX+d)->A", - "SET 4 (IX+d)->B", "SET 4 (IX+d)->C", "SET 4 (IX+d)->D", "SET 4 (IX+d)->E", "SET 4 (IX+d)->H", "SET 4 (IX+d)->L", "SET 4 (IX+d)", "SET 4 (IX+d)->A", - "SET 5 (IX+d)->B", "SET 5 (IX+d)->C", "SET 5 (IX+d)->D", "SET 5 (IX+d)->E", "SET 5 (IX+d)->H", "SET 5 (IX+d)->L", "SET 5 (IX+d)", "SET 5 (IX+d)->A", - "SET 6 (IX+d)->B", "SET 6 (IX+d)->C", "SET 6 (IX+d)->D", "SET 6 (IX+d)->E", "SET 6 (IX+d)->H", "SET 6 (IX+d)->L", "SET 6 (IX+d)", "SET 6 (IX+d)->A", - "SET 7 (IX+d)->B", "SET 7 (IX+d)->C", "SET 7 (IX+d)->D", "SET 7 (IX+d)->E", "SET 7 (IX+d)->H", "SET 7 (IX+d)->L", "SET 7 (IX+d)", "SET 7 (IX+d)->A", - }; - - readonly static string[] mnemonicsFDCB = new string[] - { - "RLC (IY+d)->B", "RLC (IY+d)->C", "RLC (IY+d)->D", "RLC (IY+d)->E", "RLC (IY+d)->H", "RLC (IY+d)->L", "RLC (IY+d)", "RLC (IY+d)->A", - "RRC (IY+d)->B", "RRC (IY+d)->C", "RRC (IY+d)->D", "RRC (IY+d)->E", "RRC (IY+d)->H", "RRC (IY+d)->L", "RRC (IY+d)", "RRC (IY+d)->A", - "RL (IY+d)->B", "RL (IY+d)->C", "RL (IY+d)->D", "RL (IY+d)->E", "RL (IY+d)->H", "RL (IY+d)->L", "RL (IY+d)", "RL (IY+d)->A", - "RR (IY+d)->B", "RR (IY+d)->C", "RR (IY+d)->D", "RR (IY+d)->E", "RR (IY+d)->H", "RR (IY+d)->L", "RR (IY+d)", "RR (IY+d)->A", - "SLA (IY+d)->B", "SLA (IY+d)->C", "SLA (IY+d)->D", "SLA (IY+d)->E", "SLA (IY+d)->H", "SLA (IY+d)->L", "SLA (IY+d)", "SLA (IY+d)->A", - "SRA (IY+d)->B", "SRA (IY+d)->C", "SRA (IY+d)->D", "SRA (IY+d)->E", "SRA (IY+d)->H", "SRA (IY+d)->L", "SRA (IY+d)", "SRA (IY+d)->A", - "SL1 (IY+d)->B", "SL1 (IY+d)->C", "SL1 (IY+d)->D", "SL1 (IY+d)->E", "SL1 (IY+d)->H", "SL1 (IY+d)->L", "SL1 (IY+d)", "SL1 (IY+d)->A", - "SRL (IY+d)->B", "SRL (IY+d)->C", "SRL (IY+d)->D", "SRL (IY+d)->E", "SRL (IY+d)->H", "SRL (IY+d)->L", "SRL (IY+d)", "SRL (IY+d)->A", - "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", "BIT 0, (IY+d)", - "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", "BIT 1, (IY+d)", - "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", "BIT 2, (IY+d)", - "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", "BIT 3, (IY+d)", - "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", "BIT 4, (IY+d)", - "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", "BIT 5, (IY+d)", - "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", "BIT 6, (IY+d)", - "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", "BIT 7, (IY+d)", - "RES 0 (IY+d)->B", "RES 0 (IY+d)->C", "RES 0 (IY+d)->D", "RES 0 (IY+d)->E", "RES 0 (IY+d)->H", "RES 0 (IY+d)->L", "RES 0 (IY+d)", "RES 0 (IY+d)->A", - "RES 1 (IY+d)->B", "RES 1 (IY+d)->C", "RES 1 (IY+d)->D", "RES 1 (IY+d)->E", "RES 1 (IY+d)->H", "RES 1 (IY+d)->L", "RES 1 (IY+d)", "RES 1 (IY+d)->A", - "RES 2 (IY+d)->B", "RES 2 (IY+d)->C", "RES 2 (IY+d)->D", "RES 2 (IY+d)->E", "RES 2 (IY+d)->H", "RES 2 (IY+d)->L", "RES 2 (IY+d)", "RES 2 (IY+d)->A", - "RES 3 (IY+d)->B", "RES 3 (IY+d)->C", "RES 3 (IY+d)->D", "RES 3 (IY+d)->E", "RES 3 (IY+d)->H", "RES 3 (IY+d)->L", "RES 3 (IY+d)", "RES 3 (IY+d)->A", - "RES 4 (IY+d)->B", "RES 4 (IY+d)->C", "RES 4 (IY+d)->D", "RES 4 (IY+d)->E", "RES 4 (IY+d)->H", "RES 4 (IY+d)->L", "RES 4 (IY+d)", "RES 4 (IY+d)->A", - "RES 5 (IY+d)->B", "RES 5 (IY+d)->C", "RES 5 (IY+d)->D", "RES 5 (IY+d)->E", "RES 5 (IY+d)->H", "RES 5 (IY+d)->L", "RES 5 (IY+d)", "RES 5 (IY+d)->A", - "RES 6 (IY+d)->B", "RES 6 (IY+d)->C", "RES 6 (IY+d)->D", "RES 6 (IY+d)->E", "RES 6 (IY+d)->H", "RES 6 (IY+d)->L", "RES 6 (IY+d)", "RES 6 (IY+d)->A", - "RES 7 (IY+d)->B", "RES 7 (IY+d)->C", "RES 7 (IY+d)->D", "RES 7 (IY+d)->E", "RES 7 (IY+d)->H", "RES 7 (IY+d)->L", "RES 7 (IY+d)", "RES 7 (IY+d)->A", - "SET 0 (IY+d)->B", "SET 0 (IY+d)->C", "SET 0 (IY+d)->D", "SET 0 (IY+d)->E", "SET 0 (IY+d)->H", "SET 0 (IY+d)->L", "SET 0 (IY+d)", "SET 0 (IY+d)->A", - "SET 1 (IY+d)->B", "SET 1 (IY+d)->C", "SET 1 (IY+d)->D", "SET 1 (IY+d)->E", "SET 1 (IY+d)->H", "SET 1 (IY+d)->L", "SET 1 (IY+d)", "SET 1 (IY+d)->A", - "SET 2 (IY+d)->B", "SET 2 (IY+d)->C", "SET 2 (IY+d)->D", "SET 2 (IY+d)->E", "SET 2 (IY+d)->H", "SET 2 (IY+d)->L", "SET 2 (IY+d)", "SET 2 (IY+d)->A", - "SET 3 (IY+d)->B", "SET 3 (IY+d)->C", "SET 3 (IY+d)->D", "SET 3 (IY+d)->E", "SET 3 (IY+d)->H", "SET 3 (IY+d)->L", "SET 3 (IY+d)", "SET 3 (IY+d)->A", - "SET 4 (IY+d)->B", "SET 4 (IY+d)->C", "SET 4 (IY+d)->D", "SET 4 (IY+d)->E", "SET 4 (IY+d)->H", "SET 4 (IY+d)->L", "SET 4 (IY+d)", "SET 4 (IY+d)->A", - "SET 5 (IY+d)->B", "SET 5 (IY+d)->C", "SET 5 (IY+d)->D", "SET 5 (IY+d)->E", "SET 5 (IY+d)->H", "SET 5 (IY+d)->L", "SET 5 (IY+d)", "SET 5 (IY+d)->A", - "SET 6 (IY+d)->B", "SET 6 (IY+d)->C", "SET 6 (IY+d)->D", "SET 6 (IY+d)->E", "SET 6 (IY+d)->H", "SET 6 (IY+d)->L", "SET 6 (IY+d)", "SET 6 (IY+d)->A", - "SET 7 (IY+d)->B", "SET 7 (IY+d)->C", "SET 7 (IY+d)->D", "SET 7 (IY+d)->E", "SET 7 (IY+d)->H", "SET 7 (IY+d)->L", "SET 7 (IY+d)", "SET 7 (IY+d)->A", - }; - - readonly static string[] mnemonicsCB = new string[] - { - "RLC B", "RLC C", "RLC D", "RLC E", "RLC H", "RLC L", "RLC (HL)", "RLC A", - "RRC B", "RRC C", "RRC D", "RRC E", "RRC H", "RRC L", "RRC (HL)", "RRC A", - "RL B", "RL C", "RL D", "RL E", "RL H", "RL L", "RL (HL)", "RL A", - "RR B", "RR C", "RR D", "RR E", "RR H", "RR L", "RR (HL)", "RR A", - "SLA B", "SLA C", "SLA D", "SLA E", "SLA H", "SLA L", "SLA (HL)", "SLA A", - "SRA B", "SRA C", "SRA D", "SRA E", "SRA H", "SRA L", "SRA (HL)", "SRA A", - "SL1 B", "SL1 C", "SL1 D", "SL1 E", "SL1 H", "SL1 L", "SL1 (HL)", "SL1 A", - "SRL B", "SRL C", "SRL D", "SRL E", "SRL H", "SRL L", "SRL (HL)", "SRL A", - "BIT 0, B", "BIT 0, C", "BIT 0, D", "BIT 0, E", "BIT 0, H", "BIT 0, L", "BIT 0, (HL)", "BIT 0, A", - "BIT 1, B", "BIT 1, C", "BIT 1, D", "BIT 1, E", "BIT 1, H", "BIT 1, L", "BIT 1, (HL)", "BIT 1, A", - "BIT 2, B", "BIT 2, C", "BIT 2, D", "BIT 2, E", "BIT 2, H", "BIT 2, L", "BIT 2, (HL)", "BIT 2, A", - "BIT 3, B", "BIT 3, C", "BIT 3, D", "BIT 3, E", "BIT 3, H", "BIT 3, L", "BIT 3, (HL)", "BIT 3, A", - "BIT 4, B", "BIT 4, C", "BIT 4, D", "BIT 4, E", "BIT 4, H", "BIT 4, L", "BIT 4, (HL)", "BIT 4, A", - "BIT 5, B", "BIT 5, C", "BIT 5, D", "BIT 5, E", "BIT 5, H", "BIT 5, L", "BIT 5, (HL)", "BIT 5, A", - "BIT 6, B", "BIT 6, C", "BIT 6, D", "BIT 6, E", "BIT 6, H", "BIT 6, L", "BIT 6, (HL)", "BIT 6, A", - "BIT 7, B", "BIT 7, C", "BIT 7, D", "BIT 7, E", "BIT 7, H", "BIT 7, L", "BIT 7, (HL)", "BIT 7, A", - "RES 0, B", "RES 0, C", "RES 0, D", "RES 0, E", "RES 0, H", "RES 0, L", "RES 0, (HL)", "RES 0, A", - "RES 1, B", "RES 1, C", "RES 1, D", "RES 1, E", "RES 1, H", "RES 1, L", "RES 1, (HL)", "RES 1, A", - "RES 2, B", "RES 2, C", "RES 2, D", "RES 2, E", "RES 2, H", "RES 2, L", "RES 2, (HL)", "RES 2, A", - "RES 3, B", "RES 3, C", "RES 3, D", "RES 3, E", "RES 3, H", "RES 3, L", "RES 3, (HL)", "RES 3, A", - "RES 4, B", "RES 4, C", "RES 4, D", "RES 4, E", "RES 4, H", "RES 4, L", "RES 4, (HL)", "RES 4, A", - "RES 5, B", "RES 5, C", "RES 5, D", "RES 5, E", "RES 5, H", "RES 5, L", "RES 5, (HL)", "RES 5, A", - "RES 6, B", "RES 6, C", "RES 6, D", "RES 6, E", "RES 6, H", "RES 6, L", "RES 6, (HL)", "RES 6, A", - "RES 7, B", "RES 7, C", "RES 7, D", "RES 7, E", "RES 7, H", "RES 7, L", "RES 7, (HL)", "RES 7, A", - "SET 0, B", "SET 0, C", "SET 0, D", "SET 0, E", "SET 0, H", "SET 0, L", "SET 0, (HL)", "SET 0, A", - "SET 1, B", "SET 1, C", "SET 1, D", "SET 1, E", "SET 1, H", "SET 1, L", "SET 1, (HL)", "SET 1, A", - "SET 2, B", "SET 2, C", "SET 2, D", "SET 2, E", "SET 2, H", "SET 2, L", "SET 2, (HL)", "SET 2, A", - "SET 3, B", "SET 3, C", "SET 3, D", "SET 3, E", "SET 3, H", "SET 3, L", "SET 3, (HL)", "SET 3, A", - "SET 4, B", "SET 4, C", "SET 4, D", "SET 4, E", "SET 4, H", "SET 4, L", "SET 4, (HL)", "SET 4, A", - "SET 5, B", "SET 5, C", "SET 5, D", "SET 5, E", "SET 5, H", "SET 5, L", "SET 5, (HL)", "SET 5, A", - "SET 6, B", "SET 6, C", "SET 6, D", "SET 6, E", "SET 6, H", "SET 6, L", "SET 6, (HL)", "SET 6, A", - "SET 7, B", "SET 7, C", "SET 7, D", "SET 7, E", "SET 7, H", "SET 7, L", "SET 7, (HL)", "SET 7, A", - }; - - readonly static string[] mnemonicsED = new string[] - { - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", - - "IN B, C", "OUT C, B", "SBC HL, BC", "LD (nn), BC", //0x44 - "NEG", "RETN", "IM $0", "LD I, A", //0x48 - "IN C, C", "OUT C, C", "ADC HL, BC", "LD BC, (nn)", //0x4C - "NEG", "RETI", "IM $0", "LD R, A", //0x50 - "IN D, C", "OUT C, D", "SBC HL, DE", "LD (nn), DE", //0x54 - "NEG", "RETN", "IM $1", "LD A, I", //0x58 - "IN E, C", "OUT C, E", "ADC HL, DE", "LD DE, (nn)", //0x5C - "NEG", "RETI", "IM $2", "LD A, R", //0x60 - - "IN H, C", "OUT C, H", "SBC HL, HL", "LD (nn), HL", //0x64 - "NEG", "RETN", "IM $0", "RRD", //0x68 - "IN L, C", "OUT C, L", "ADC HL, HL", "LD HL, (nn)", //0x6C - "NEG", "RETI", "IM $0", "RLD", //0x70 - "IN 0, C", "OUT C, 0", "SBC HL, SP", "LD (nn), SP", //0x74 - "NEG", "RETN", "IM $1", "NOP", //0x78 - "IN A, C", "OUT C, A", "ADC HL, SP", "LD SP, (nn)", //0x7C - "NEG", "RETI", "IM $2", "NOP", //0x80 - - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x90 - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xA0 - "LDI", "CPI", "INI", "OUTI", //0xA4 - "NOP", "NOP", "NOP", "NOP", //0xA8 - "LDD", "CPD", "IND", "OUTD", //0xAC - "NOP", "NOP", "NOP", "NOP", //0xB0 - "LDIR", "CPIR", "INIR", "OTIR", //0xB4 - "NOP", "NOP", "NOP", "NOP", //0xB8 - "LDDR", "CPDR", "INDR", "OTDR", //0xBC - "NOP", "NOP", "NOP", "NOP", //0xC0 - - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xD0 - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xE0 - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0xF0 - "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", "NOP", //0x100 - }; - - string DisassembleInternal(Func read) - { - byte A = read(); - string format; - switch (A) - { - case 0xCB: - A = read(); - format = mnemonicsCB[A]; - break; - case 0xDD: - A = read(); - switch (A) - { - case 0xCB: format = mnemonicsDDCB[A]; break; - case 0xED: format = mnemonicsED[A]; break; - default: format = mnemonicsDD[A]; break; - } - break; - case 0xED: - A = read(); - format = mnemonicsED[A]; - break; - case 0xFD: - A = read(); - switch (A) - { - case 0xCB: format = mnemonicsFDCB[A]; break; - case 0xED: format = mnemonicsED[A]; break; - default: format = mnemonicsFD[A]; break; - } - break; - default: format = mnemonics[A]; break; - } - return format; - } - - public string Disassemble(Func read) - { - return Result(DisassembleInternal(read), read); - } - - #region IDisassemblable - - public string Cpu - { - get { return "Z80"; } - set { } - } - - public string PCRegisterName - { - get { return "PC"; } - } - - public IEnumerable AvailableCpus - { - get { yield return "Z80"; } - } - - public string Disassemble(MemoryDomain m, uint addr, out int length) - { - int loc = (int)addr; - string ret = Disassemble(() => m.PeekByte(loc++)); - length = loc - (int)addr; - return ret; - } - - #endregion - } -} From 12e709e0451719380cfa38ac56a9d20025b04054 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:17 -0400 Subject: [PATCH 13/39] Delete Execute.cs --- BizHawk.Emulation.Cores/CPUs/Z80/Execute.cs | 12491 ------------------ 1 file changed, 12491 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Execute.cs 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" - ) - }; - } - } -} From 33079bed48781be6d7ba84f48bb29634667259c9 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:27 -0400 Subject: [PATCH 14/39] Delete Interrupts.cs --- .../CPUs/Z80/Interrupts.cs | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Interrupts.cs 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 From 9776e65719a4467b75c231cbc352f7f3f51ff0f7 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:36 -0400 Subject: [PATCH 15/39] Delete Registers.cs --- BizHawk.Emulation.Cores/CPUs/Z80/Registers.cs | 270 ------------------ 1 file changed, 270 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Registers.cs 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 From ac2c6a46e0e8e54f56868edecb63745ff2cb3f71 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:45 -0400 Subject: [PATCH 16/39] Delete Tables.cs --- BizHawk.Emulation.Cores/CPUs/Z80/Tables.cs | 331 --------------------- 1 file changed, 331 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Tables.cs 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; } - } -} From 7984eecd990debd1595e5d182babf02268651085 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:52:53 -0400 Subject: [PATCH 17/39] Delete Z80A.cs --- BizHawk.Emulation.Cores/CPUs/Z80/Z80A.cs | 142 ----------------------- 1 file changed, 142 deletions(-) delete mode 100644 BizHawk.Emulation.Cores/CPUs/Z80/Z80A.cs 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 From 0fda518cb749a9a55a6e724bfa7ecc53cbc6dc21 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:58:36 -0400 Subject: [PATCH 18/39] Add files via upload --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs index 089185c7ca..b513acfca4 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -1,6 +1,6 @@ using System; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs index f658f1a09b..8dc1cd24ce 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Interrupts.cs @@ -1,6 +1,6 @@ using System; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index 62c546ca6e..44d53780c3 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using BizHawk.Emulation.Common; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public sealed partial class Z80A : IDisassemblable { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs index d80fb48022..d618c2bdcd 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs @@ -1,7 +1,7 @@ using BizHawk.Common.NumberExtensions; using System; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs index 11dfef24cd..628243c19e 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Registers.cs @@ -1,7 +1,7 @@ using System.Runtime.InteropServices; using System; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs index 2d069cd8b1..ad8bed179b 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -1,6 +1,6 @@ using System; -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs index 38890f7918..4a1c46cc03 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Indirect.cs @@ -1,4 +1,4 @@ -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public partial class Z80A { diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index ff2bbf87e7..53d85bb25b 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -7,7 +7,7 @@ using BizHawk.Emulation.Common; using BizHawk.Common.NumberExtensions; // Z80A CPU -namespace BizHawk.Emulation.Common.Components.Z80A +namespace BizHawk.Emulation.Cores.Components.Z80A { public sealed partial class Z80A { From 8b2b796b53e02e7db96cfaf97643038323ec1327 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 17:59:14 -0400 Subject: [PATCH 19/39] Add files via upload --- BizHawk.Emulation.Cores/Calculator/TI83.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.cs b/BizHawk.Emulation.Cores/Calculator/TI83.cs index aa83616945..dc70edff41 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.Common.Components.Z80A; +using BizHawk.Emulation.Cores.Components.Z80A; // http://www.ticalc.org/pub/text/calcinfo/ namespace BizHawk.Emulation.Cores.Calculators From 9d9133720c9ec67e901f923e1e5b0dd8f3575f19 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 18:00:08 -0400 Subject: [PATCH 20/39] Add files via upload --- BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs | 2 +- BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/ColecoVision.cs index f7d183f60d..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.Common.Components.Z80A; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.ColecoVision { diff --git a/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs b/BizHawk.Emulation.Cores/Consoles/Coleco/TMS9918A.cs index 00049a5890..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.Common.Components.Z80A; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.ColecoVision { From 09ce28d2bd6ed70ad9fb9e4080d516f478d6f84d Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 18:01:14 -0400 Subject: [PATCH 21/39] Add files via upload --- .../Consoles/Sega/SMS/SMS.IEmulator.cs | 180 +++++++++--------- .../Consoles/Sega/SMS/SMS.cs | 2 +- .../Consoles/Sega/SMS/VDP.cs | 2 +- 3 files changed, 92 insertions(+), 92 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs index d6f398dccd..fe2a9222a3 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IEmulator.cs @@ -1,45 +1,45 @@ -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; +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) @@ -49,51 +49,51 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem 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() - { - } - } -} + } + + 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.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index 1e9b39381d..3030c8084d 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.Common.Components.Z80A; +using BizHawk.Emulation.Cores.Components.Z80A; /***************************************************** TODO: diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/VDP.cs index f079d04608..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.Common.Components.Z80A; +using BizHawk.Emulation.Cores.Components.Z80A; namespace BizHawk.Emulation.Cores.Sega.MasterSystem From 74fbe5a261d9af4ed6c0d07c5008358bad105e66 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 13 Oct 2017 18:04:06 -0400 Subject: [PATCH 22/39] Update BizHawk.Emulation.Cores.csproj --- .../BizHawk.Emulation.Cores.csproj | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 7958b5be1a..59a4958220 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -1186,12 +1186,14 @@ - - - - - - + + + + + + + + True True @@ -1314,4 +1316,4 @@ --> - \ No newline at end of file + From 4f63cadb4a7d620cf636cec5e174a1278b2a1a33 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 14 Oct 2017 14:07:17 -0400 Subject: [PATCH 23/39] Z80 Corrections and Bug Fixes --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 12 ++++++------ .../CPUs/Z80A/NewDisassembler.cs | 1 + BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs | 15 +++++++++++++++ .../CPUs/Z80A/Tables_Direct.cs | 2 +- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 5 +++++ 5 files changed, 28 insertions(+), 7 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs index b513acfca4..299d84dd0f 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -874,7 +874,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0xDA: JP_COND(FlagC); break; // JP C case 0xDB: IN_(); break; // IN A case 0xDC: CALL_COND(FlagC); break; // CALL C - case 0xDD: JAM_(); break; // Jam (invalid) + 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 @@ -890,7 +890,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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: JAM_(); break; // Jam (invalid) + 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 @@ -906,7 +906,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0xFA: JP_COND(FlagS); break; // JP M case 0xFB: EI_(); break; // EI case 0xFC: CALL_COND(FlagS); break; // CALL M - case 0xFD: JAM_(); break; // Jam (invalid) + 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 } @@ -1139,7 +1139,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0xDA: JP_COND(FlagC); break; // JP C case 0xDB: IN_(); break; // IN A case 0xDC: CALL_COND(FlagC); break; // CALL C - case 0xDD: JAM_(); break; // Jam (invalid) + 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 @@ -1155,7 +1155,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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: JAM_(); break; // Jam (invalid) + 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 @@ -1171,7 +1171,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0xFA: JP_COND(FlagS); break; // JP M case 0xFB: EI_(); break; // EI case 0xFC: CALL_COND(FlagS); break; // CALL M - case 0xFD: JAM_(); break; // Jam (invalid) + 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 } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index 44d53780c3..c19459c741 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -34,6 +34,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A char sign = neg ? '-' : '+'; int val = neg ? 256 - B : B; format = format.Replace("d", string.Format("{0}{1:X2}h", sign, val)); + addr++; } return format; diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs index d618c2bdcd..cfaf517ec7 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Operations.cs @@ -723,5 +723,20 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs index ad8bed179b..ce40eea385 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -103,7 +103,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A {operation, dest, src, IDLE, IDLE, - IDLE, + SET_FL_IR, dest, OP }; } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index 53d85bb25b..2fb1103373 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -74,6 +74,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A public const ushort SET_FL_CP = 59; public const ushort I_BIT = 60; public const ushort HL_BIT = 61; + public const ushort SET_FL_IR = 62; public Z80A() @@ -582,6 +583,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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; @@ -610,6 +612,9 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case SET_FL_CP: SET_FL_CP_Func(); break; + case SET_FL_IR: + SET_FL_IR_Func(cur_instr[instr_pntr++]); + break; } totalExecutedCycles++; } From af9c813c5bda5867094921331fb1610c51e8bec6 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 19 Oct 2017 09:48:27 -0400 Subject: [PATCH 25/39] Add files via upload --- BizHawk.Client.Common/tools/Cheat.cs | 66 +++++++++++++++++++++------- 1 file changed, 49 insertions(+), 17 deletions(-) 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); } } From be6aa52bc8b7ef9111a86fbd0227888f49ede0e9 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 19 Oct 2017 10:55:17 -0400 Subject: [PATCH 26/39] Z80: Remove JAM The relevent opcodes behave as NOPs --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 7 +++---- .../CPUs/Z80A/Tables_Direct.cs | 9 --------- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 19 +++++++------------ 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs index 299d84dd0f..4159f31d7a 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -23,7 +23,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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 bool jammed; public ushort PF; public void FetchInstruction(byte opcode) @@ -617,7 +616,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0x74: INT_OP(NEG, A); break; // NEG case 0x75: RETN_(); break; // RETN case 0x76: INT_MODE_(1); break; // IM $1 - case 0x77: JAM_(); break; // JAM + 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 @@ -625,7 +624,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case 0x7C: INT_OP(NEG, A); break; // NEG case 0x7D: RETN_(); break; // RETI case 0x7E: INT_MODE_(2); break; // IM $2 - case 0x7F: JAM_(); break; // JAM + 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 @@ -642,7 +641,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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: JAM_(); break; // JAM + default: NOP_(); break; // NOP } } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs index ce40eea385..8e473d1527 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -448,15 +448,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A OP }; } - private void JAM_() - { - cur_instr = new ushort[] - {JAM, - IDLE, - IDLE, - IDLE }; - } - private void OUT_() { cur_instr = new ushort[] diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index 2fb1103373..9155aeb178 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -61,20 +61,20 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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 JAM = 49; // all undocumented opcodes jam the machine + 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 INT_MODE = 55; - public const ushort RRD = 56; - public const ushort RLD = 57; - public const ushort SET_FL_LD = 58; - public const ushort SET_FL_CP = 59; + 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 const ushort SET_FL_IR = 62; + public Z80A() @@ -576,10 +576,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A case ADDS: ADDS_Func(cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++], cur_instr[instr_pntr++]); break; - case JAM: - jammed = true; - 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 @@ -689,7 +685,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A ser.Sync("instruction_pointer", ref instr_pntr); ser.Sync("current instruction", ref cur_instr, false); ser.Sync("opcode", ref opcode); - ser.Sync("jammped", ref jammed); ser.Sync("FlagI", ref FlagI); ser.Sync("NO Preifx", ref NO_prefix); From 28cce355bf33d96a1cb68894fbe449aa4864eed2 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Thu, 19 Oct 2017 12:08:34 -0400 Subject: [PATCH 27/39] Z80: Fix R register operation --- BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs | 4 +- .../CPUs/Z80A/NewDisassembler.cs | 8 +- .../CPUs/Z80A/Tables_Direct.cs | 6 +- BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs | 107 ++++++++---------- 4 files changed, 55 insertions(+), 70 deletions(-) diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs index 4159f31d7a..c70e4aa503 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Execute.cs @@ -15,6 +15,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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; @@ -1194,8 +1195,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A IYCB_prefetch = false; PF = opcode; Regs[ALU] = PF; - PREFETCH_(Iyl, Iyh); - + PREFETCH_(Iyl, Iyh); return; } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs index c19459c741..596e0ff66d 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/NewDisassembler.cs @@ -34,7 +34,6 @@ namespace BizHawk.Emulation.Cores.Components.Z80A char sign = neg ? '-' : '+'; int val = neg ? 256 - B : B; format = format.Replace("d", string.Format("{0}{1:X2}h", sign, val)); - addr++; } return format; @@ -397,6 +396,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A public string Disassemble(ushort addr, Func read, out ushort size) { ushort start_addr = addr; + ushort extra_inc = 0; byte A = read(addr++); string format; switch (A) @@ -409,7 +409,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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; } @@ -422,7 +422,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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; } @@ -432,6 +432,8 @@ namespace BizHawk.Emulation.Cores.Components.Z80A string temp = Result(format, read, ref addr); + addr += extra_inc; + size = (ushort)(addr - start_addr); return temp; } diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs index 8e473d1527..71b39d6018 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Tables_Direct.cs @@ -395,10 +395,10 @@ namespace BizHawk.Emulation.Cores.Components.Z80A private void PREFIX_(ushort src) { cur_instr = new ushort[] - {PREFIX, src, + {IDLE, IDLE, IDLE, - OP }; + PREFIX, src}; } private void PREFETCH_(ushort src_l, ushort src_h) @@ -407,7 +407,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A {TR16, Z, W, src_l, src_h, ADDS, Z, W, ALU, ZERO, IDLE, - OP }; + PREFIX, IXYprefetch }; } private void DI_() diff --git a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs index 9155aeb178..2f13b0e6c7 100644 --- a/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs +++ b/BizHawk.Emulation.Cores/CPUs/Z80A/Z80A.cs @@ -75,7 +75,7 @@ namespace BizHawk.Emulation.Cores.Components.Z80A public const ushort I_BIT = 60; public const ushort HL_BIT = 61; - + public byte temp_R; public Z80A() { @@ -147,27 +147,20 @@ namespace BizHawk.Emulation.Cores.Components.Z80A break; case OP: // Read the opcode of the next instruction - if (EI_pending > 0 && NO_prefix) + if (EI_pending > 0) { EI_pending--; - if (EI_pending == 0) - { - IFF1 = IFF2 = true; - } + if (EI_pending == 0) { IFF1 = IFF2 = true; } } // Process interrupt requests. - if (nonMaskableInterruptPending && NO_prefix) + if (nonMaskableInterruptPending) { nonMaskableInterruptPending = false; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====NMI====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); } iff2 = iff1; @@ -175,18 +168,14 @@ namespace BizHawk.Emulation.Cores.Components.Z80A NMI_(); NMICallback(); } - else if (iff1 && FlagI && NO_prefix) + else if (iff1 && FlagI) { iff1 = iff2 = false; EI_pending = 0; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====IRQ====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); } switch (interruptMode) @@ -210,12 +199,15 @@ namespace BizHawk.Emulation.Cores.Components.Z80A else { if (OnExecFetch != null) OnExecFetch(RegPC); - if (TraceCallback != null && NO_prefix) TraceCallback(State()); + if (TraceCallback != null) TraceCallback(State()); FetchInstruction(ReadMemory(RegPC++)); } instr_pntr = 0; - Regs[R]++; - Regs[R] &= 0xFF; + + 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 @@ -280,47 +272,35 @@ namespace BizHawk.Emulation.Cores.Components.Z80A { // Interrupts can occur at this point, so process them accordingly // Read the opcode of the next instruction - if (EI_pending > 0 && NO_prefix) + if (EI_pending > 0) { EI_pending--; - if (EI_pending == 0) - { - IFF1 = IFF2 = true; - } + if (EI_pending == 0) { IFF1 = IFF2 = true; } } // Process interrupt requests. - if (nonMaskableInterruptPending && NO_prefix) + if (nonMaskableInterruptPending) { nonMaskableInterruptPending = false; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====NMI====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); } iff2 = iff1; iff1 = false; NMI_(); NMICallback(); - } - else if (iff1 && FlagI && NO_prefix) + else if (iff1 && FlagI) { iff1 = iff2 = false; EI_pending = 0; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====IRQ====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); } switch (interruptMode) @@ -346,36 +326,32 @@ namespace BizHawk.Emulation.Cores.Components.Z80A if (OnExecFetch != null) OnExecFetch(RegPC); if (TraceCallback != null) TraceCallback(State()); FetchInstruction(ReadMemory(RegPC++)); - Regs[R]++; - Regs[R] &= 0xFF; } + + 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 && NO_prefix) + if (EI_pending > 0) { EI_pending--; - if (EI_pending == 0) - { - IFF1 = IFF2 = true; - } + if (EI_pending == 0) { IFF1 = IFF2 = true; } } // Process interrupt requests. - if (nonMaskableInterruptPending && NO_prefix) + if (nonMaskableInterruptPending) { nonMaskableInterruptPending = false; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====NMI====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====NMI====", RegisterInfo = ""}); } iff2 = iff1; @@ -384,18 +360,14 @@ namespace BizHawk.Emulation.Cores.Components.Z80A NMICallback(); halted = false; } - else if (iff1 && FlagI && NO_prefix) + else if (iff1 && FlagI) { iff1 = iff2 = false; EI_pending = 0; if (TraceCallback != null) { - TraceCallback(new TraceInfo - { - Disassembly = "====IRQ====", - RegisterInfo = "" - }); + TraceCallback(new TraceInfo{Disassembly = "====IRQ====", RegisterInfo = ""}); } switch (interruptMode) @@ -419,14 +391,16 @@ namespace BizHawk.Emulation.Cores.Components.Z80A } else { - Regs[R]++; - Regs[R] &= 0xFF; 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; @@ -567,8 +541,17 @@ namespace BizHawk.Emulation.Cores.Components.Z80A 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; } - Regs[R]++; - Regs[R] &= 0xFF; + + 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++]); From 5e0a373c6f3361d3f459b76bf0c752a22e926458 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Fri, 20 Oct 2017 00:42:02 -0400 Subject: [PATCH 28/39] SMS Bart vs Space Mutants needs to run in PAL --- Assets/gamedb/gamedb_sega_sms.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 3c6dcf1dc3952a7e80ed9f9aa412dbba92be661a Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Fri, 20 Oct 2017 10:32:22 -0400 Subject: [PATCH 29/39] TI-83 Upgrade - Fix power on Behaviour - Fix cycle timing - Fix timer interrupt frequency - NOTE: 'ON' buton on virtual calculator doesn't work since it's only a 'click', need to use shortcut key to turn the calculator on --- .../Calculator/TI83.IEmulator.cs | 35 +++++--- .../Calculator/TI83.IStatable.cs | 9 ++ BizHawk.Emulation.Cores/Calculator/TI83.cs | 86 +++++++++++++++---- 3 files changed, 101 insertions(+), 29 deletions(-) diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs index 1d6b7be044..622664bcc7 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IEmulator.cs @@ -22,20 +22,35 @@ namespace BizHawk.Emulation.Cores.Calculators _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 - for (int j = 0; j < 10000; j++) - { - _cpu.ExecuteOne(); - } - + 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++; if (_lagged) diff --git a/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs b/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs index 0539da2ae0..d2bd9192ca 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.IStatable.cs @@ -69,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 dc70edff41..09b0928449 100644 --- a/BizHawk.Emulation.Cores/Calculator/TI83.cs +++ b/BizHawk.Emulation.Cores/Calculator/TI83.cs @@ -34,14 +34,6 @@ 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(); @@ -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; } @@ -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 @@ -447,7 +495,7 @@ namespace BizHawk.Emulation.Cores.Calculators _ram[i] = 0xFF; } - _cpu.RegPC = _startPC; + _cpu.RegPC = 0; _cpu.IFF1 = false; _cpu.IFF2 = false; From 745e42a753e0190ed36d4461e5ded21d1c13ff86 Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 21 Oct 2017 09:52:07 -0400 Subject: [PATCH 30/39] Hex Editor: Fix Cheat display Fixes #1026 --- .../tools/HexEditor/HexEditor.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index 02752e22b6..049dd1057b 100644 --- a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -526,7 +526,21 @@ 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)); + + if (_addr + j + k == 0x0020 || _addr + j + k == 0x0021) + { + Console.WriteLine(t_next); + } + } + + rowStr.AppendFormat(_digitFormatString, t_val);// MakeValue(_addr + j)); } else { @@ -569,7 +583,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) From 0fd046de0d1a665582fad13fddd1fd44132f7fee Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sat, 21 Oct 2017 09:55:03 -0400 Subject: [PATCH 31/39] Update HexEditor.cs --- BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs index 049dd1057b..b237bf0a68 100644 --- a/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs +++ b/BizHawk.Client.EmuHawk/tools/HexEditor/HexEditor.cs @@ -533,14 +533,9 @@ namespace BizHawk.Client.EmuHawk { t_next = MakeValue(1, _addr + j + k); t_val += (t_next << ((DataSize - k - 1) * 8)); - - if (_addr + j + k == 0x0020 || _addr + j + k == 0x0021) - { - Console.WriteLine(t_next); - } } - rowStr.AppendFormat(_digitFormatString, t_val);// MakeValue(_addr + j)); + rowStr.AppendFormat(_digitFormatString, t_val); } else { From edc40edd46fcb955b9e94d452b142bc37c0ee84c Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sun, 22 Oct 2017 13:21:37 -0400 Subject: [PATCH 32/39] NESHawk: FCEUX palette update --- Assets/NES/Palettes/FCEUX (2.2.0).pal | Bin 0 -> 192 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Assets/NES/Palettes/FCEUX (2.2.0).pal diff --git a/Assets/NES/Palettes/FCEUX (2.2.0).pal b/Assets/NES/Palettes/FCEUX (2.2.0).pal new file mode 100644 index 0000000000000000000000000000000000000000..7bf9128fb5fad8d07059f217f9c4f61a886da9a8 GIT binary patch literal 192 zcmXwx5f_6{0EI6O2Eia43)Gs_$%@0k|dcXqpy0JmTgU% Wk&gP#PO-1vtdt!~bEP%LO#UB@`&Kys literal 0 HcmV?d00001 From b367f28971ab5c01d0177eca97e9014032443f4d Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Sun, 22 Oct 2017 13:22:21 -0400 Subject: [PATCH 33/39] Delete FCEUX.pal --- Assets/NES/Palettes/FCEUX.pal | Bin 192 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Assets/NES/Palettes/FCEUX.pal diff --git a/Assets/NES/Palettes/FCEUX.pal b/Assets/NES/Palettes/FCEUX.pal deleted file mode 100644 index 2b8ea5d63eed04734189df388a053361ca4dc6ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 192 zcmXwx5f_6{0EI6O2Eia43F4Z3BiM45C*{@2nNC6;b8diK`QA!~l*4~iADySZ@ z*`ke>MG92o4RH357qbqMzG6}_DEQ4tai=)4_N?;rrxU&Q@vp|mWLY*%Mql>S9lMs) WBZlfmBiT1^HqwseaiP^(PyQcXXH~5L From 5e87b45df070b8c3b33c928a1caeda0973952a76 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Sat, 21 Oct 2017 21:18:23 -0400 Subject: [PATCH 34/39] EEPROM (93c46) support for SMS --- Assets/gamedb/gamedb_sega_gg.txt | 8 +- .../BizHawk.Emulation.Cores.csproj | 8 +- .../Consoles/Sega/SMS/EEPROM.93c46.cs | 222 ++++++++++++++++++ .../Consoles/Sega/SMS/MemoryMap.EEPROM.cs | 136 +++++++++++ .../Consoles/Sega/SMS/SMS.cs | 2 + 5 files changed, 369 insertions(+), 7 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs create mode 100644 BizHawk.Emulation.Cores/Consoles/Sega/SMS/MemoryMap.EEPROM.cs 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/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 59a4958220..f22d02380d 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -1071,6 +1071,8 @@ + + SMS.cs @@ -1190,9 +1192,9 @@ - + - + True @@ -1316,4 +1318,4 @@ --> - + \ No newline at end of file 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..9a6c841359 --- /dev/null +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs @@ -0,0 +1,222 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +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; + } + } +} 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.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs index 3030c8084d..423b11b965 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.cs @@ -114,6 +114,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem InitNemesisMapper(); else if (game["TerebiOekaki"]) InitTerebiOekaki(); + else if (game["EEPROM"]) + InitEEPROMMapper(); else InitSegaMapper(); From c594e48175eeae5d630734f7e7885d49a79b58d7 Mon Sep 17 00:00:00 2001 From: Tastyfish Date: Mon, 23 Oct 2017 11:49:07 -0400 Subject: [PATCH 35/39] Save stating for the 93c46 too --- .../Consoles/Sega/SMS/EEPROM.93c46.cs | 19 +++++++++++++++---- .../Consoles/Sega/SMS/SMS.IStatable.cs | 5 +++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs index 9a6c841359..ec0acddec1 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/EEPROM.93c46.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using BizHawk.Common; namespace BizHawk.Emulation.Cores.Sega.MasterSystem { @@ -218,5 +215,19 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem 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/SMS.IStatable.cs b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs index 8f29ddaf9c..0ba7d4293d 100644 --- a/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs +++ b/BizHawk.Emulation.Cores/Consoles/Sega/SMS/SMS.IStatable.cs @@ -84,6 +84,11 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem { YM2413.SyncState(ser); } + + if (EEPROM != null) + { + EEPROM.SyncState(ser); + } ser.Sync("Frame", ref _frame); ser.Sync("LagCount", ref _lagCount); From 9498206980b0ab6c3092947e4c395bade5291d7b Mon Sep 17 00:00:00 2001 From: alyosha-tas Date: Mon, 23 Oct 2017 17:15:08 -0400 Subject: [PATCH 36/39] NESHawk: FDS Timer IRQ's --- .../Consoles/Nintendo/NES/FDS/FDS.cs | 38 +++++++++---------- .../Consoles/Nintendo/NES/FDS/RamAdapter.cs | 7 +++- 2 files changed, 24 insertions(+), 21 deletions(-) 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); From 6d87be1396eb6b9ba41370bce76a7019774d826e Mon Sep 17 00:00:00 2001 From: Asnivor Date: Wed, 25 Oct 2017 17:06:16 +0100 Subject: [PATCH 37/39] Experiemental MDS/MDF Support --- BizHawk.Client.Common/RomLoader.cs | 4 +- BizHawk.Client.DiscoHawk/MainDiscoForm.cs | 2 +- BizHawk.Client.EmuHawk/FileLoader.cs | 2 +- BizHawk.Client.EmuHawk/MainForm.cs | 6 +- .../BizHawk.Emulation.DiscSystem.csproj | 1 + .../DiscFormats/MDS_Format.cs | 907 ++++++++++++++++++ BizHawk.Emulation.DiscSystem/DiscMountJob.cs | 5 + 7 files changed, 920 insertions(+), 7 deletions(-) create mode 100644 BizHawk.Emulation.DiscSystem/DiscFormats/MDS_Format.cs 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.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..2071de742d 100644 --- a/BizHawk.Client.EmuHawk/FileLoader.cs +++ b/BizHawk.Client.EmuHawk/FileLoader.cs @@ -51,7 +51,7 @@ 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" }; } diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs index 7929f31a90..4fda942f31 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -2077,9 +2077,9 @@ 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%", @@ -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%", 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/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/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: From 166edd7cbacd40935c6d897f110dccce4f1ddfcd Mon Sep 17 00:00:00 2001 From: Asnivor Date: Wed, 25 Oct 2017 17:10:26 +0100 Subject: [PATCH 38/39] Added mds to file filters --- BizHawk.Client.EmuHawk/FileLoader.cs | 2 +- BizHawk.Client.EmuHawk/MainForm.cs | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BizHawk.Client.EmuHawk/FileLoader.cs b/BizHawk.Client.EmuHawk/FileLoader.cs index 2071de742d..0009646fb4 100644 --- a/BizHawk.Client.EmuHawk/FileLoader.cs +++ b/BizHawk.Client.EmuHawk/FileLoader.cs @@ -55,7 +55,7 @@ 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", ".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 4fda942f31..170dbb2322 100644 --- a/BizHawk.Client.EmuHawk/MainForm.cs +++ b/BizHawk.Client.EmuHawk/MainForm.cs @@ -2083,7 +2083,7 @@ namespace BizHawk.Client.EmuHawk "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", @@ -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%", From e64d00bf7d1acc09f7aca62fbf08cfe7e3cf8302 Mon Sep 17 00:00:00 2001 From: zeromus Date: Wed, 25 Oct 2017 12:21:57 -0400 Subject: [PATCH 39/39] psx - fix bug where saving the state cleared the memcard dirty flags. not 100% sure we'll keep this logic, need to revisit it on the date of the great automatic-flushing-deprecation. fixes #1031 --- output/dll/octoshock.dll | Bin 1138688 -> 1139712 bytes psx/octoshock/psx/input/memcard.cpp | 4 +++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/output/dll/octoshock.dll b/output/dll/octoshock.dll index 292d2536eb06783d091f922e066dd029091a121a..3e80c9454eb135bd4efc83dd1a39c5dfce491afc 100644 GIT binary patch delta 165419 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
aPH?e!34!J~94J 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 ^BDjmQ;PB@6ipTD&rz<_CxR`eqkC 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 TZrYsLY_^2A)DM~K?8^Ed)yL$* delta 164642 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 i_oqVJf9h zlB6(U$CorXSsE-HjYG`Y`0+9tmgnx(9r=6wtb-xN#U&)&&`*0z#a{z3T zrJPXuN*Ae_cfU{3W~8p6G_Q*kFZhPiJzb=RL67IKMA$eOU#7TbEs^VqJ@AEy3H&#vs|t3nikkrfrBWe-w<{< zyD6Nt!aoO~W*TL(>N{(0Cu9Z4)0e|~<%^>tb@*hcEMeah@a0V%s=CFAYw$ngv{mEW zXzq+-e>+36iNc;G_WQ3$Q*}adZ91Ws)Koi$F6kvj^j(fBM@#wvj@kP9MaXWB>b(Y` z@5NIBkcETT_%$7`IpP#Gh#`+SUG*B^ovC_5;FTBJ>%AuV>I^{1talmz#U?@*7S=$Qc*h$SBjI>B}BHwkHN;=F7X!t zv!c0aR(?6_aLhH!?5%4Hz{=(ptN`MQL~84c&i=!iRh@k<#!r2vo&g}k30e(QCtP(R z5^2kRQnoOE4qeet8Wr3DdBa&wrYPpYCmvIC=E44VQ_T)Ew!aiETqgAO{?a#oy=_Pk zm$PT+uvP_=QZ}j`0EMnaXv6@iXVAr|=(Y8)K$W0WkL_Li~}#lsjcZ}1ErkW;WbbKHnvZ{ zZ61CXa=zY*Mhudg3;jQ)uMd(!wXNvHLDF_1eKKt^Sc(u{olN@ zn+k7yF9puYVs=C_x)#Q!5xqJDY-)MYh@oK9f_5G%+3Fwv(2Y$OkAz~CO#x$bWg@*Z zRH`j_ccY%e5cRG|(}p2xEFCdS`c4=^uiP8gVt|OZ@(dxV;#fUH>E*Xf!lVt6x}37r|BwtD5>#NV%r(= z@Dc)(EY9apqTrU8$6e*j7EumklPo%WxHL&PHlBLDCBi)mGunW5|?y7)@ zXe(l&`D0Z=QnU3(g=I!+g=V%T8JX!mN=4ldk8LAtkSC_Vt)xaM58! zZb+QNAiZiyexft4qvrE$+G3}`UOg_ z9?)4HNM7dP_;L6&?1al4OYw7=Ck4LMPjSS8`##LFino=P8ZZTf`)7DwNU*o!+$$|s1mYL0e3lpxNBGLV?Zal44PgyPq-v;Q@b9mk8} zewAhSs_9woc=8wi5uGetQp z&PozLU~$&3Va?*K@4|fABIO+0Eu1e>He{@yu6Elcnc^&Godzz<ml@B_K2>f% zoYVRO#>0eVi8#5z|Ml-LNyUq&9sQxZq%nYD-x;@;D+QxdF)J^}7jMqRJ$=ri_r7r! zC8WNOv%Gb4vd+&R@r+(?C zN~jdw|4``c`r5~oD--NPX7IlsR|eWM$MFGADDT+EUdfL<(ZSUj>3gTg@xkFEt^W3Z zD@h6V7q8$;R--YQ{X0TGwnn%rAUSnH0|c2>ZCB)mA0;V7$t3 zq|!x`{Cuw}$%7$66)# z!oNRM!~EkOwJFIkJFZDuHHjCJLz?7sO;Q5MX`0Kenj{EGdQ<(OwaP;_`ErB!XgY_R0_lQ*Zf{_Pbz zy>iPI-t;1-teel|zr3g{wSRpkzx5?tUd!La?Jq0;wcp*J?|K=_pY!{3?|Sg0{``{l z$`t#n{rH;oN^jqT{e+v(F^`Nn_4(b6iw_i?`FGLClec8x28mPY|LVuTTd&+;clP7O z8?dnZHjgjdpw!xMxig|1wx9Jnx4oj=>Ammwlj8oWk}bG1`0%0D=lR30D2GzN6|rs= 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
  • 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

    2)uqCnV_1mv!-(RyXe1Sh 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 z