using System;

/* TODO:
+ http://www.devrs.com/gb/files/opcodes.html was used as a flags and timing reference.  
+ [Opt] The DAA Table could be reduced from 128k to 8k.
+ Currently all instructions are using fixed m-cycles. Any instruction with variable cycles (ie branches) need to be checked.  
+ The following instructions were rewritten or substantially modified for Z80-GB. They should be
  treated with caution and checked further when the emulator is farther along.

	ADD
	ADC
	SUB
	SBC
	AND
	OR
	XOR
	CP
	SWAP
	DAA
	RLCA
	RLA
	RRCA
	RRA
	RLC
	RL
	RRC
	RR
	SLA
	SRA
	SRL
*/

namespace BizHawk.Emulation.Common.Components.Z80GB
{
	public partial class Z80
	{
		public int TotalExecutedCycles;
		public int PendingCycles;

		bool Interruptable;

		public void ExecuteInstruction()
		{
			byte TB; byte TB2; sbyte TSB; ushort TUS; int TI1; int TI2; int TIR;
			while (RegPC.Word == 0x031A)
				break;
			byte op = ReadMemory(RegPC.Word++);
			int mCycleTime = mCycleTable[op];
			PendingCycles -= mCycleTime;
			TotalExecutedCycles += mCycleTime;
			switch (op)
			{
				case 0x00: // NOP
					break;
				case 0x01: // LD BC, nn
					RegBC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					break;
				case 0x02: // LD (BC), A
					WriteMemory(RegBC.Word, RegAF.High);
					break;
				case 0x03: // INC BC
					++RegBC.Word;
					break;
				case 0x04: // INC B
					RegAF.Low = (byte)(IncTable[++RegBC.High] | (RegAF.Low & 16));
					break;
				case 0x05: // DEC B
					RegAF.Low = (byte)(DecTable[--RegBC.High] | (RegAF.Low & 16));
					break;
				case 0x06: // LD B, n
					RegBC.High = ReadMemory(RegPC.Word++);
					break;
				case 0x07: // RLCA
					RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
					RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1));
					break;
				case 0x08: // LD (imm), SP
					TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8));
					WriteMemory(TUS++, RegSP.Low);
					WriteMemory(TUS, RegSP.High);
					break;
				case 0x09: // ADD HL, BC
					TI1 = (short)RegHL.Word; TI2 = (short)RegBC.Word; TIR = TI1 + TI2;
					TUS = (ushort)TIR;
					FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF;
					FlagN = false;
					FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF;
					RegHL.Word = TUS;
					break;
				case 0x0A: // LD A, (BC)
					RegAF.High = ReadMemory(RegBC.Word);
					break;
				case 0x0B: // DEC BC
					--RegBC.Word;
					break;
				case 0x0C: // INC C
					RegAF.Low = (byte)(IncTable[++RegBC.Low] | (RegAF.Low & 16));
					break;
				case 0x0D: // DEC C
					RegAF.Low = (byte)(DecTable[--RegBC.Low] | (RegAF.Low & 16));
					break;
				case 0x0E: // LD C, n
					RegBC.Low = ReadMemory(RegPC.Word++);
					break;
				case 0x0F: // RRCA
					RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1));
					RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
					break;
				case 0x10: // STOP
					Console.WriteLine("STOP!!!!!!!!!!!!!!!!!!!!!!"); // TODO this instruction is actually STOP. not DJNZ d.
					throw new Exception("CPU stopped. What now?");
				case 0x11: // LD DE, nn
					RegDE.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					break;
				case 0x12: // LD (DE), A
					WriteMemory(RegDE.Word, RegAF.High);
					break;
				case 0x13: // INC DE
					++RegDE.Word;
					break;
				case 0x14: // INC D
					RegAF.Low = (byte)(IncTable[++RegDE.High] | (RegAF.Low & 16));
					break;
				case 0x15: // DEC D
					RegAF.Low = (byte)(DecTable[--RegDE.High] | (RegAF.Low & 16));
					break;
				case 0x16: // LD D, n
					RegDE.High = ReadMemory(RegPC.Word++);
					break;
				case 0x17: // RLA
					TB = (byte)((RegAF.High & 0x80) >> 3);
					RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0));
					RegAF.Low = TB;
					break;
				case 0x18: // JR d
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					RegPC.Word = (ushort)(RegPC.Word + TSB);
					break;
				case 0x19: // ADD HL, DE
					TI1 = (short)RegHL.Word; TI2 = (short)RegDE.Word; TIR = TI1 + TI2;
					TUS = (ushort)TIR;
					FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF;
					FlagN = false;
					FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF;
					RegHL.Word = TUS;
					break;
				case 0x1A: // LD A, (DE)
					RegAF.High = ReadMemory(RegDE.Word);
					break;
				case 0x1B: // DEC DE
					--RegDE.Word;
					break;
				case 0x1C: // INC E
					RegAF.Low = (byte)(IncTable[++RegDE.Low] | (RegAF.Low & 16));
					break;
				case 0x1D: // DEC E
					RegAF.Low = (byte)(DecTable[--RegDE.Low] | (RegAF.Low & 16));
					break;
				case 0x1E: // LD E, n
					RegDE.Low = ReadMemory(RegPC.Word++);
					break;
				case 0x1F: // RRA
					TB = (byte)((RegAF.High & 0x1) << 4);
					RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0));
					RegAF.Low = TB;
					break;
				case 0x20: // JR NZ, d
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					if (!FlagZ)
						RegPC.Word = (ushort)(RegPC.Word + TSB);
					break;
				case 0x21: // LD HL, nn
					RegHL.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					break;
				case 0x22: // LDI (HL), A
					WriteMemory(RegHL.Word++, RegAF.High);
					break;
				case 0x23: // INC HL
					++RegHL.Word;
					break;
				case 0x24: // INC H
					RegAF.Low = (byte)(IncTable[++RegHL.High] | (RegAF.Low & 16));
					break;
				case 0x25: // DEC H
					RegAF.Low = (byte)(DecTable[--RegHL.High] | (RegAF.Low & 16));
					break;
				case 0x26: // LD H, n
					RegHL.High = ReadMemory(RegPC.Word++);
					break;
				case 0x27: // DAA
					RegAF.Word = TableDaa[RegAF.Word];
					break;
				case 0x28: // JR Z, d
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					if (FlagZ)
						RegPC.Word = (ushort)(RegPC.Word + TSB);
					break;
				case 0x29: // ADD HL, HL
					TI1 = (short)RegHL.Word; TI2 = (short)RegHL.Word; TIR = TI1 + TI2;
					TUS = (ushort)TIR;
					FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF;
					FlagN = false;
					FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF;
					RegHL.Word = TUS;
					break;
				case 0x2A: // LDI A, (HL)
					RegAF.High = ReadMemory(RegHL.Word++);
					break;
				case 0x2B: // DEC HL
					--RegHL.Word;
					break;
				case 0x2C: // INC L
					RegAF.Low = (byte)(IncTable[++RegHL.Low] | (RegAF.Low & 16));
					break;
				case 0x2D: // DEC L
					RegAF.Low = (byte)(DecTable[--RegHL.Low] | (RegAF.Low & 16));
					break;
				case 0x2E: // LD L, n
					RegHL.Low = ReadMemory(RegPC.Word++);
					break;
				case 0x2F: // CPL
					RegAF.High ^= 0xFF; FlagH = true; FlagN = true;
					break;
				case 0x30: // JR NC, d
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					if (!FlagC)
						RegPC.Word = (ushort)(RegPC.Word + TSB);
					break;
				case 0x31: // LD SP, nn
					RegSP.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					break;
				case 0x32: // LDD (HL), A
					WriteMemory(RegHL.Word--, RegAF.High);
					break;
				case 0x33: // INC SP
					++RegSP.Word;
					break;
				case 0x34: // INC (HL)
					TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(IncTable[++TB] | (RegAF.Low & 16)); WriteMemory(RegHL.Word, TB);
					break;
				case 0x35: // DEC (HL)
					TB = ReadMemory(RegHL.Word); RegAF.Low = (byte)(DecTable[--TB] | (RegAF.Low & 16)); WriteMemory(RegHL.Word, TB);
					break;
				case 0x36: // LD (HL), n
					WriteMemory(RegHL.Word, ReadMemory(RegPC.Word++));
					break;
				case 0x37: // SCF
					FlagH = false; FlagN = false; FlagC = true;
					break;
				case 0x38: // JR C, d
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					if (FlagC)
						RegPC.Word = (ushort)(RegPC.Word + TSB);
					break;
				case 0x39: // ADD HL, SP
					TI1 = (short)RegHL.Word; TI2 = (short)RegSP.Word; TIR = TI1 + TI2;
					TUS = (ushort)TIR;
					FlagH = ((TI1 & 0xFFF) + (TI2 & 0xFFF)) > 0xFFF;
					FlagN = false;
					FlagC = ((ushort)TI1 + (ushort)TI2) > 0xFFFF;
					RegHL.Word = TUS;
					break;
				case 0x3A: // LDD A, (HL)
					RegAF.High = ReadMemory(RegHL.Word--);
					break;
				case 0x3B: // DEC SP
					--RegSP.Word;
					break;
				case 0x3C: // INC A
					RegAF.Low = (byte)(IncTable[++RegAF.High] | (RegAF.Low & 16));
					break;
				case 0x3D: // DEC A
					RegAF.Low = (byte)(DecTable[--RegAF.High] | (RegAF.Low & 16));
					break;
				case 0x3E: // LD A, n
					RegAF.High = ReadMemory(RegPC.Word++);
					break;
				case 0x3F: // CCF
					FlagH = FlagC; FlagN = false; FlagC ^= true;
					break;
				case 0x40: // LD B, B
					break;
				case 0x41: // LD B, C
					RegBC.High = RegBC.Low;
					break;
				case 0x42: // LD B, D
					RegBC.High = RegDE.High;
					break;
				case 0x43: // LD B, E
					RegBC.High = RegDE.Low;
					break;
				case 0x44: // LD B, H
					RegBC.High = RegHL.High;
					break;
				case 0x45: // LD B, L
					RegBC.High = RegHL.Low;
					break;
				case 0x46: // LD B, (HL)
					RegBC.High = ReadMemory(RegHL.Word);
					break;
				case 0x47: // LD B, A
					RegBC.High = RegAF.High;
					break;
				case 0x48: // LD C, B
					RegBC.Low = RegBC.High;
					break;
				case 0x49: // LD C, C
					break;
				case 0x4A: // LD C, D
					RegBC.Low = RegDE.High;
					break;
				case 0x4B: // LD C, E
					RegBC.Low = RegDE.Low;
					break;
				case 0x4C: // LD C, H
					RegBC.Low = RegHL.High;
					break;
				case 0x4D: // LD C, L
					RegBC.Low = RegHL.Low;
					break;
				case 0x4E: // LD C, (HL)
					RegBC.Low = ReadMemory(RegHL.Word);
					break;
				case 0x4F: // LD C, A
					RegBC.Low = RegAF.High;
					break;
				case 0x50: // LD D, B
					RegDE.High = RegBC.High;
					break;
				case 0x51: // LD D, C
					RegDE.High = RegBC.Low;
					break;
				case 0x52: // LD D, D
					break;
				case 0x53: // LD D, E
					RegDE.High = RegDE.Low;
					break;
				case 0x54: // LD D, H
					RegDE.High = RegHL.High;
					break;
				case 0x55: // LD D, L
					RegDE.High = RegHL.Low;
					break;
				case 0x56: // LD D, (HL)
					RegDE.High = ReadMemory(RegHL.Word);
					break;
				case 0x57: // LD D, A
					RegDE.High = RegAF.High;
					break;
				case 0x58: // LD E, B
					RegDE.Low = RegBC.High;
					break;
				case 0x59: // LD E, C
					RegDE.Low = RegBC.Low;
					break;
				case 0x5A: // LD E, D
					RegDE.Low = RegDE.High;
					break;
				case 0x5B: // LD E, E
					break;
				case 0x5C: // LD E, H
					RegDE.Low = RegHL.High;
					break;
				case 0x5D: // LD E, L
					RegDE.Low = RegHL.Low;
					break;
				case 0x5E: // LD E, (HL)
					RegDE.Low = ReadMemory(RegHL.Word);
					break;
				case 0x5F: // LD E, A
					RegDE.Low = RegAF.High;
					break;
				case 0x60: // LD H, B
					RegHL.High = RegBC.High;
					break;
				case 0x61: // LD H, C
					RegHL.High = RegBC.Low;
					break;
				case 0x62: // LD H, D
					RegHL.High = RegDE.High;
					break;
				case 0x63: // LD H, E
					RegHL.High = RegDE.Low;
					break;
				case 0x64: // LD H, H
					break;
				case 0x65: // LD H, L
					RegHL.High = RegHL.Low;
					break;
				case 0x66: // LD H, (HL)
					RegHL.High = ReadMemory(RegHL.Word);
					break;
				case 0x67: // LD H, A
					RegHL.High = RegAF.High;
					break;
				case 0x68: // LD L, B
					RegHL.Low = RegBC.High;
					break;
				case 0x69: // LD L, C
					RegHL.Low = RegBC.Low;
					break;
				case 0x6A: // LD L, D
					RegHL.Low = RegDE.High;
					break;
				case 0x6B: // LD L, E
					RegHL.Low = RegDE.Low;
					break;
				case 0x6C: // LD L, H
					RegHL.Low = RegHL.High;
					break;
				case 0x6D: // LD L, L
					break;
				case 0x6E: // LD L, (HL)
					RegHL.Low = ReadMemory(RegHL.Word);
					break;
				case 0x6F: // LD L, A
					RegHL.Low = RegAF.High;
					break;
				case 0x70: // LD (HL), B
					WriteMemory(RegHL.Word, RegBC.High);
					break;
				case 0x71: // LD (HL), C
					WriteMemory(RegHL.Word, RegBC.Low);
					break;
				case 0x72: // LD (HL), D
					WriteMemory(RegHL.Word, RegDE.High);
					break;
				case 0x73: // LD (HL), E
					WriteMemory(RegHL.Word, RegDE.Low);
					break;
				case 0x74: // LD (HL), H
					WriteMemory(RegHL.Word, RegHL.High);
					break;
				case 0x75: // LD (HL), L
					WriteMemory(RegHL.Word, RegHL.Low);
					break;
				case 0x76: // HALT
					Halt();
					break;
				case 0x77: // LD (HL), A
					WriteMemory(RegHL.Word, RegAF.High);
					break;
				case 0x78: // LD A, B
					RegAF.High = RegBC.High;
					break;
				case 0x79: // LD A, C
					RegAF.High = RegBC.Low;
					break;
				case 0x7A: // LD A, D
					RegAF.High = RegDE.High;
					break;
				case 0x7B: // LD A, E
					RegAF.High = RegDE.Low;
					break;
				case 0x7C: // LD A, H
					RegAF.High = RegHL.High;
					break;
				case 0x7D: // LD A, L
					RegAF.High = RegHL.Low;
					break;
				case 0x7E: // LD A, (HL)
					RegAF.High = ReadMemory(RegHL.Word);
					break;
				case 0x7F: // LD A, A
					break;
				case 0x80: // ADD B
					TI1 = RegAF.High + RegBC.High;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegBC.High & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x81: // ADD C
					TI1 = RegAF.High + RegBC.Low;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegBC.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x82: // ADD D
					TI1 = RegAF.High + RegDE.High;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegDE.High & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x83: // ADD E
					TI1 = RegAF.High + RegDE.Low;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegDE.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x84: // ADD H
					TI1 = RegAF.High + RegHL.High;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegHL.High & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x85: // ADD L
					TI1 = RegAF.High + RegHL.Low;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegHL.Low & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x86: // ADD (HL)
					TB = ReadMemory(RegHL.Word);
					TI1 = RegAF.High + TB;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (TB & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x87: // ADD A
					TI1 = RegAF.High + RegAF.High;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegAF.High & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x88: // ADC B
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegBC.High + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegBC.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x89: // ADC C
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegBC.Low + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegBC.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8A: // ADC D
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegDE.High + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegDE.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8B: // ADC E
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegDE.Low + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegDE.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8C: // ADC H
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegHL.High + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegHL.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8D: // ADC L
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegHL.Low + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegHL.Low & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8E: // ADC (HL)
					TB = ReadMemory(RegHL.Word);
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + TB + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (TB & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x8F: // ADC A
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + RegAF.High + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (RegAF.High & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x90: // SUB B
					TI1 = RegAF.High - RegBC.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x91: // SUB C
					TI1 = RegAF.High - RegBC.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x92: // SUB D
					TI1 = RegAF.High - RegDE.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x93: // SUB E
					TI1 = RegAF.High - RegDE.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x94: // SUB H
					TI1 = RegAF.High - RegHL.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x95: // SUB L
					TI1 = RegAF.High - RegHL.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x96: // SUB (HL)
					TB = ReadMemory(RegHL.Word);
					TI1 = RegAF.High - TB;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x97: // SUB A
					TI1 = RegAF.High - RegAF.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x98: // SBC B
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegBC.High - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x99: // SBC C
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegBC.Low - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9A: // SBC D
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegDE.High - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9B: // SBC E
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegDE.Low - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9C: // SBC H
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegHL.High - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9D: // SBC L
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegHL.Low - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9E: // SBC (HL)
					TB = ReadMemory(RegHL.Word);
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - TB - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0x9F: // SBC A
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - RegAF.High - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0xA0: // AND B
					RegAF.High &= RegBC.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA1: // AND C
					RegAF.High &= RegBC.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA2: // AND D
					RegAF.High &= RegDE.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA3: // AND E
					RegAF.High &= RegDE.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA4: // AND H
					RegAF.High &= RegHL.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA5: // AND L
					RegAF.High &= RegHL.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA6: // AND (HL)
					RegAF.High &= ReadMemory(RegHL.Word);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA7: // AND A
					RegAF.High &= RegAF.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xA8: // XOR B
					RegAF.High ^= RegBC.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xA9: // XOR C
					RegAF.High ^= RegBC.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAA: // XOR D
					RegAF.High ^= RegDE.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAB: // XOR E
					RegAF.High ^= RegDE.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAC: // XOR H
					RegAF.High ^= RegHL.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAD: // XOR L
					RegAF.High ^= RegHL.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAE: // XOR (HL)
					RegAF.High ^= ReadMemory(RegHL.Word);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xAF: // XOR A
					RegAF.High ^= RegAF.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB0: // OR B
					RegAF.High |= RegBC.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB1: // OR C
					RegAF.High |= RegBC.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB2: // OR D
					RegAF.High |= RegDE.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB3: // OR E
					RegAF.High |= RegDE.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB4: // OR H
					RegAF.High |= RegHL.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB5: // OR L
					RegAF.High |= RegHL.Low;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB6: // OR (HL)
					RegAF.High |= ReadMemory(RegHL.Word);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB7: // OR A
					RegAF.High |= RegAF.High;
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xB8: // CP B
					TI1 = RegAF.High - RegBC.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.High & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xB9: // CP C
					TI1 = RegAF.High - RegBC.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegBC.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBA: // CP D
					TI1 = RegAF.High - RegDE.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.High & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBB: // CP E
					TI1 = RegAF.High - RegDE.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegDE.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBC: // CP H
					TI1 = RegAF.High - RegHL.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.High & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBD: // CP L
					TI1 = RegAF.High - RegHL.Low;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegHL.Low & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBE: // CP (HL)
					TB = ReadMemory(RegHL.Word);
					TI1 = RegAF.High - TB;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xBF: // CP A
					TI1 = RegAF.High - RegAF.High;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (RegAF.High & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xC0: // RET NZ
					if (!FlagZ)
						RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xC1: // POP BC
					RegBC.Low = ReadMemory(RegSP.Word++); RegBC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xC2: // JP NZ, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (!FlagZ)
						RegPC.Word = TUS;
					break;
				case 0xC3: // JP nn
					RegPC.Word = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					break;
				case 0xC4: // CALL NZ, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (!FlagZ)
					{
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Word = TUS;
					}
					break;
				case 0xC5: // PUSH BC
					WriteMemory(--RegSP.Word, RegBC.High); WriteMemory(--RegSP.Word, RegBC.Low);
					break;
				case 0xC6: // ADD n
					TB = ReadMemory(RegPC.Word++);
					TI1 = RegAF.High + TB;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (TB & 0x0F) > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0xC7: // RST $00
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x00;
					break;
				case 0xC8: // RET Z
					if (FlagZ)
						RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xC9: // RET
					RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xCA: // JP Z, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (FlagZ)
						RegPC.Word = TUS;
					break;
				case 0xCB: // (Prefix)
					op = ReadMemory(RegPC.Word++);
					mCycleTime = cbMCycleTable[op];
					PendingCycles -= mCycleTime;
					TotalExecutedCycles += mCycleTime;
					switch (op)
					{
						case 0x00: // RLC B
							RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
							RegBC.High = (byte)((RegBC.High >> 7) | (RegBC.High << 1));
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x01: // RLC C
							RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
							RegBC.Low = (byte)((RegBC.Low >> 7) | (RegBC.Low << 1));
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x02: // RLC D
							RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
							RegDE.High = (byte)((RegDE.High >> 7) | (RegDE.High << 1));
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x03: // RLC E
							RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
							RegDE.Low = (byte)((RegDE.Low >> 7) | (RegDE.Low << 1));
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x04: // RLC H
							RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
							RegHL.High = (byte)((RegHL.High >> 7) | (RegHL.High << 1));
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x05: // RLC L
							RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
							RegHL.Low = (byte)((RegHL.Low >> 7) | (RegHL.Low << 1));
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x06: // RLC (HL)
							TB = ReadMemory(RegHL.Word);
							RegAF.Low = (byte)((TB & 0x80) >> 3);
							TB = (byte)((TB >> 7) | (TB << 1));
							if (TB == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB);
							break;
						case 0x07: // RLC A
							RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
							RegAF.High = (byte)((RegAF.High >> 7) | (RegAF.High << 1));
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x08: // RRC B
							RegBC.High = (byte)((RegBC.High << 7) | (RegBC.High >> 1));
							RegAF.Low = (byte)((RegBC.High & 0x80) >> 3);
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x09: // RRC C
							RegBC.Low = (byte)((RegBC.Low << 7) | (RegBC.Low >> 1));
							RegAF.Low = (byte)((RegBC.Low & 0x80) >> 3);
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x0A: // RRC D
							RegDE.High = (byte)((RegDE.High << 7) | (RegDE.High >> 1));
							RegAF.Low = (byte)((RegDE.High & 0x80) >> 3);
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x0B: // RRC E
							RegDE.Low = (byte)((RegDE.Low << 7) | (RegDE.Low >> 1));
							RegAF.Low = (byte)((RegDE.Low & 0x80) >> 3);
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x0C: // RRC H
							RegHL.High = (byte)((RegHL.High << 7) | (RegHL.High >> 1));
							RegAF.Low = (byte)((RegHL.High & 0x80) >> 3);
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x0D: // RRC L
							RegHL.Low = (byte)((RegHL.Low << 7) | (RegHL.Low >> 1));
							RegAF.Low = (byte)((RegHL.Low & 0x80) >> 3);
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x0E: // RRC (HL)
							TB = ReadMemory(RegHL.Word);
							TB = (byte)((TB << 7) | (TB >> 1));
							RegAF.Low = (byte)((TB & 0x80) >> 3);
							if (TB == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB);
							break;
						case 0x0F: // RRC A
							RegAF.High = (byte)((RegAF.High << 7) | (RegAF.High >> 1));
							RegAF.Low = (byte)((RegAF.High & 0x80) >> 3);
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x10: // RL B
							TB = (byte)((RegBC.High & 0x80) >> 3);
							RegBC.High = (byte)((RegBC.High << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x11: // RL C
							TB = (byte)((RegBC.Low & 0x80) >> 3);
							RegBC.Low = (byte)((RegBC.Low << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x12: // RL D
							TB = (byte)((RegDE.High & 0x80) >> 3);
							RegDE.High = (byte)((RegDE.High << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x13: // RL E
							TB = (byte)((RegDE.Low & 0x80) >> 3);
							RegDE.Low = (byte)((RegDE.Low << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x14: // RL H
							TB = (byte)((RegHL.High & 0x80) >> 3);
							RegHL.High = (byte)((RegHL.High << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x15: // RL L
							TB = (byte)((RegHL.Low & 0x80) >> 3);
							RegHL.Low = (byte)((RegHL.Low << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x16: // RL (HL)
							TB2 = ReadMemory(RegHL.Word);
							TB = (byte)((TB2 & 0x80) >> 3);
							TB2 = (byte)((TB2 << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (TB2 == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB2);
							break;
						case 0x17: // RL A
							TB = (byte)((RegAF.High & 0x80) >> 3);
							RegAF.High = (byte)((RegAF.High << 1) | (FlagC ? 1 : 0));
							RegAF.Low = TB;
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x18: // RR B
							TB = (byte)((RegBC.High & 0x1) << 4);
							RegBC.High = (byte)((RegBC.High >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x19: // RR C
							TB = (byte)((RegBC.Low & 0x1) << 4);
							RegBC.Low = (byte)((RegBC.Low >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x1A: // RR D
							TB = (byte)((RegDE.High & 0x1) << 4);
							RegDE.High = (byte)((RegDE.High >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x1B: // RR E
							TB = (byte)((RegDE.Low & 0x1) << 4);
							RegDE.Low = (byte)((RegDE.Low >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x1C: // RR H
							TB = (byte)((RegHL.High & 0x1) << 4);
							RegHL.High = (byte)((RegHL.High >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x1D: // RR L
							TB = (byte)((RegHL.Low & 0x1) << 4);
							RegHL.Low = (byte)((RegHL.Low >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x1E: // RR (HL)
							TB2 = ReadMemory(RegHL.Word);
							TB = (byte)((TB2 & 0x1) << 4);
							TB2 = (byte)((TB2 >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (TB2 == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB2);
							break;
						case 0x1F: // RR A
							TB = (byte)((RegAF.High & 0x1) << 4);
							RegAF.High = (byte)((RegAF.High >> 1) | (FlagC ? 0x80 : 0));
							RegAF.Low = TB;
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x20: // SLA B
							RegAF.Low = 0;
							if ((RegBC.High & 0x80) != 0) RegAF.Low |= 0x10;
							RegBC.High <<= 1;
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x21: // SLA C
							RegAF.Low = 0;
							if ((RegBC.Low & 0x80) != 0) RegAF.Low |= 0x10;
							RegBC.Low <<= 1;
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x22: // SLA D
							RegAF.Low = 0;
							if ((RegDE.High & 0x80) != 0) RegAF.Low |= 0x10;
							RegDE.High <<= 1;
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x23: // SLA E
							RegAF.Low = 0;
							if ((RegDE.Low & 0x80) != 0) RegAF.Low |= 0x10;
							RegDE.Low <<= 1;
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x24: // SLA H
							RegAF.Low = 0;
							if ((RegHL.High & 0x80) != 0) RegAF.Low |= 0x10;
							RegHL.High <<= 1;
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x25: // SLA L
							RegAF.Low = 0;
							if ((RegHL.Low & 0x80) != 0) RegAF.Low |= 0x10;
							RegHL.Low <<= 1;
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x26: // SLA (HL)
							TB = ReadMemory(RegHL.Word);
							RegAF.Low = 0;
							if ((TB & 0x80) != 0) RegAF.Low |= 0x10;
							TB <<= 1;
							if (TB == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB);
							break;
						case 0x27: // SLA A
							RegAF.Low = 0;
							if ((RegAF.High & 0x80) != 0) RegAF.Low |= 0x10;
							RegAF.High <<= 1;
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x28: // SRA B
							RegAF.Low = 0;
							if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
							RegBC.High = (byte)((RegBC.High >> 1) | (RegBC.High & 0x80));
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x29: // SRA C
							RegAF.Low = 0;
							if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
							RegBC.Low = (byte)((RegBC.Low >> 1) | (RegBC.Low & 0x80));
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x2A: // SRA D
							RegAF.Low = 0;
							if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
							RegDE.High = (byte)((RegDE.High >> 1) | (RegDE.High & 0x80));
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x2B: // SRA E
							RegAF.Low = 0;
							if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
							RegDE.Low = (byte)((RegDE.Low >> 1) | (RegDE.Low & 0x80));
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x2C: // SRA H
							RegAF.Low = 0;
							if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
							RegHL.High = (byte)((RegHL.High >> 1) | (RegHL.High & 0x80));
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x2D: // SRA L
							RegAF.Low = 0;
							if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
							RegHL.Low = (byte)((RegHL.Low >> 1) | (RegHL.Low & 0x80));
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x2E: // SRA (HL)
							TB = ReadMemory(RegHL.Word);
							RegAF.Low = 0;
							if ((TB & 1) != 0) RegAF.Low |= 0x10;
							TB = (byte)((TB >> 1) | (TB & 0x80));
							if (TB == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB);
							break;
						case 0x2F: // SRA A
							RegAF.Low = 0;
							if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
							RegAF.High = (byte)((RegAF.High >> 1) | (RegAF.High & 0x80));
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x30: // SWAP B
							RegBC.High = SwapTable[RegBC.High];
							FlagZ = (RegBC.High == 0);
							break;
						case 0x31: // SWAP C
							RegBC.Low = SwapTable[RegBC.Low];
							FlagZ = (RegBC.Low == 0);
							break;
						case 0x32: // SWAP D
							RegDE.High = SwapTable[RegDE.High];
							FlagZ = (RegDE.High == 0);
							break;
						case 0x33: // SWAP E
							RegDE.Low = SwapTable[RegDE.Low];
							FlagZ = (RegDE.Low == 0);
							break;
						case 0x34: // SWAP H
							RegHL.High = SwapTable[RegHL.High];
							FlagZ = (RegHL.High == 0);
							break;
						case 0x35: // SWAP L 
							RegHL.Low = SwapTable[RegHL.Low];
							FlagZ = (RegHL.Low == 0);
							break;
						case 0x36: // SWAP (HL)
							TB = SwapTable[ReadMemory(RegHL.Word)];
							WriteMemory(RegHL.Word, TB);
							FlagZ = (TB == 0);
							break;
						case 0x37: // SWAP A
							RegAF.High = SwapTable[RegAF.High];
							FlagZ = (RegAF.High == 0);
							break;
						case 0x38: // SRL B
							RegAF.Low = 0;
							if ((RegBC.High & 1) != 0) RegAF.Low |= 0x10;
							RegBC.High >>= 1;
							if (RegBC.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x39: // SRL C
							RegAF.Low = 0;
							if ((RegBC.Low & 1) != 0) RegAF.Low |= 0x10;
							RegBC.Low >>= 1;
							if (RegBC.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x3A: // SRL D
							RegAF.Low = 0;
							if ((RegDE.High & 1) != 0) RegAF.Low |= 0x10;
							RegDE.High >>= 1;
							if (RegDE.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x3B: // SRL E
							RegAF.Low = 0;
							if ((RegDE.Low & 1) != 0) RegAF.Low |= 0x10;
							RegDE.Low >>= 1;
							if (RegDE.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x3C: // SRL H
							RegAF.Low = 0;
							if ((RegHL.High & 1) != 0) RegAF.Low |= 0x10;
							RegHL.High >>= 1;
							if (RegHL.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x3D: // SRL L
							RegAF.Low = 0;
							if ((RegHL.Low & 1) != 0) RegAF.Low |= 0x10;
							RegHL.Low >>= 1;
							if (RegHL.Low == 0) RegAF.Low |= 0x80;
							break;
						case 0x3E: // SRL (HL)
							TB = ReadMemory(RegHL.Word);
							RegAF.Low = 0;
							if ((TB & 1) != 0) RegAF.Low |= 0x10;
							TB >>= 1;
							if (TB == 0) RegAF.Low |= 0x80;
							WriteMemory(RegHL.Word, TB);
							break;
						case 0x3F: // SRL A
							RegAF.Low = 0;
							if ((RegAF.High & 1) != 0) RegAF.Low |= 0x10;
							RegAF.High >>= 1;
							if (RegAF.High == 0) RegAF.Low |= 0x80;
							break;
						case 0x40: // BIT 0, B
							FlagZ = (RegBC.High & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x41: // BIT 0, C
							FlagZ = (RegBC.Low & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x42: // BIT 0, D
							FlagZ = (RegDE.High & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x43: // BIT 0, E
							FlagZ = (RegDE.Low & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x44: // BIT 0, H
							FlagZ = (RegHL.High & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x45: // BIT 0, L
							FlagZ = (RegHL.Low & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x46: // BIT 0, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x47: // BIT 0, A
							FlagZ = (RegAF.High & 0x01) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x48: // BIT 1, B
							FlagZ = (RegBC.High & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x49: // BIT 1, C
							FlagZ = (RegBC.Low & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4A: // BIT 1, D
							FlagZ = (RegDE.High & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4B: // BIT 1, E
							FlagZ = (RegDE.Low & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4C: // BIT 1, H
							FlagZ = (RegHL.High & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4D: // BIT 1, L
							FlagZ = (RegHL.Low & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4E: // BIT 1, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x4F: // BIT 1, A
							FlagZ = (RegAF.High & 0x02) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x50: // BIT 2, B
							FlagZ = (RegBC.High & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x51: // BIT 2, C
							FlagZ = (RegBC.Low & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x52: // BIT 2, D
							FlagZ = (RegDE.High & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x53: // BIT 2, E
							FlagZ = (RegDE.Low & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x54: // BIT 2, H
							FlagZ = (RegHL.High & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x55: // BIT 2, L
							FlagZ = (RegHL.Low & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x56: // BIT 2, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x57: // BIT 2, A
							FlagZ = (RegAF.High & 0x04) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x58: // BIT 3, B
							FlagZ = (RegBC.High & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x59: // BIT 3, C
							FlagZ = (RegBC.Low & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5A: // BIT 3, D
							FlagZ = (RegDE.High & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5B: // BIT 3, E
							FlagZ = (RegDE.Low & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5C: // BIT 3, H
							FlagZ = (RegHL.High & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5D: // BIT 3, L
							FlagZ = (RegHL.Low & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5E: // BIT 3, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x5F: // BIT 3, A
							FlagZ = (RegAF.High & 0x08) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x60: // BIT 4, B
							FlagZ = (RegBC.High & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x61: // BIT 4, C
							FlagZ = (RegBC.Low & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x62: // BIT 4, D
							FlagZ = (RegDE.High & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x63: // BIT 4, E
							FlagZ = (RegDE.Low & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x64: // BIT 4, H
							FlagZ = (RegHL.High & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x65: // BIT 4, L
							FlagZ = (RegHL.Low & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x66: // BIT 4, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x67: // BIT 4, A
							FlagZ = (RegAF.High & 0x10) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x68: // BIT 5, B
							FlagZ = (RegBC.High & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x69: // BIT 5, C
							FlagZ = (RegBC.Low & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6A: // BIT 5, D
							FlagZ = (RegDE.High & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6B: // BIT 5, E
							FlagZ = (RegDE.Low & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6C: // BIT 5, H
							FlagZ = (RegHL.High & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6D: // BIT 5, L
							FlagZ = (RegHL.Low & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6E: // BIT 5, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x6F: // BIT 5, A
							FlagZ = (RegAF.High & 0x20) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x70: // BIT 6, B
							FlagZ = (RegBC.High & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x71: // BIT 6, C
							FlagZ = (RegBC.Low & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x72: // BIT 6, D
							FlagZ = (RegDE.High & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x73: // BIT 6, E
							FlagZ = (RegDE.Low & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x74: // BIT 6, H
							FlagZ = (RegHL.High & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x75: // BIT 6, L
							FlagZ = (RegHL.Low & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x76: // BIT 6, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x77: // BIT 6, A
							FlagZ = (RegAF.High & 0x40) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x78: // BIT 7, B
							FlagZ = (RegBC.High & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x79: // BIT 7, C
							FlagZ = (RegBC.Low & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7A: // BIT 7, D
							FlagZ = (RegDE.High & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7B: // BIT 7, E
							FlagZ = (RegDE.Low & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7C: // BIT 7, H
							FlagZ = (RegHL.High & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7D: // BIT 7, L
							FlagZ = (RegHL.Low & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7E: // BIT 7, (HL)
							FlagZ = (ReadMemory(RegHL.Word) & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x7F: // BIT 7, A
							FlagZ = (RegAF.High & 0x80) == 0;
							FlagH = true;
							FlagN = false;
							break;
						case 0x80: // RES 0, B
							RegBC.High &= unchecked((byte)~0x01);
							break;
						case 0x81: // RES 0, C
							RegBC.Low &= unchecked((byte)~0x01);
							break;
						case 0x82: // RES 0, D
							RegDE.High &= unchecked((byte)~0x01);
							break;
						case 0x83: // RES 0, E
							RegDE.Low &= unchecked((byte)~0x01);
							break;
						case 0x84: // RES 0, H
							RegHL.High &= unchecked((byte)~0x01);
							break;
						case 0x85: // RES 0, L
							RegHL.Low &= unchecked((byte)~0x01);
							break;
						case 0x86: // RES 0, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x01)));
							break;
						case 0x87: // RES 0, A
							RegAF.High &= unchecked((byte)~0x01);
							break;
						case 0x88: // RES 1, B
							RegBC.High &= unchecked((byte)~0x02);
							break;
						case 0x89: // RES 1, C
							RegBC.Low &= unchecked((byte)~0x02);
							break;
						case 0x8A: // RES 1, D
							RegDE.High &= unchecked((byte)~0x02);
							break;
						case 0x8B: // RES 1, E
							RegDE.Low &= unchecked((byte)~0x02);
							break;
						case 0x8C: // RES 1, H
							RegHL.High &= unchecked((byte)~0x02);
							break;
						case 0x8D: // RES 1, L
							RegHL.Low &= unchecked((byte)~0x02);
							break;
						case 0x8E: // RES 1, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x02)));
							break;
						case 0x8F: // RES 1, A
							RegAF.High &= unchecked((byte)~0x02);
							break;
						case 0x90: // RES 2, B
							RegBC.High &= unchecked((byte)~0x04);
							break;
						case 0x91: // RES 2, C
							RegBC.Low &= unchecked((byte)~0x04);
							break;
						case 0x92: // RES 2, D
							RegDE.High &= unchecked((byte)~0x04);
							break;
						case 0x93: // RES 2, E
							RegDE.Low &= unchecked((byte)~0x04);
							break;
						case 0x94: // RES 2, H
							RegHL.High &= unchecked((byte)~0x04);
							break;
						case 0x95: // RES 2, L
							RegHL.Low &= unchecked((byte)~0x04);
							break;
						case 0x96: // RES 2, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x04)));
							break;
						case 0x97: // RES 2, A
							RegAF.High &= unchecked((byte)~0x04);
							break;
						case 0x98: // RES 3, B
							RegBC.High &= unchecked((byte)~0x08);
							break;
						case 0x99: // RES 3, C
							RegBC.Low &= unchecked((byte)~0x08);
							break;
						case 0x9A: // RES 3, D
							RegDE.High &= unchecked((byte)~0x08);
							break;
						case 0x9B: // RES 3, E
							RegDE.Low &= unchecked((byte)~0x08);
							break;
						case 0x9C: // RES 3, H
							RegHL.High &= unchecked((byte)~0x08);
							break;
						case 0x9D: // RES 3, L
							RegHL.Low &= unchecked((byte)~0x08);
							break;
						case 0x9E: // RES 3, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x08)));
							break;
						case 0x9F: // RES 3, A
							RegAF.High &= unchecked((byte)~0x08);
							break;
						case 0xA0: // RES 4, B
							RegBC.High &= unchecked((byte)~0x10);
							break;
						case 0xA1: // RES 4, C
							RegBC.Low &= unchecked((byte)~0x10);
							break;
						case 0xA2: // RES 4, D
							RegDE.High &= unchecked((byte)~0x10);
							break;
						case 0xA3: // RES 4, E
							RegDE.Low &= unchecked((byte)~0x10);
							break;
						case 0xA4: // RES 4, H
							RegHL.High &= unchecked((byte)~0x10);
							break;
						case 0xA5: // RES 4, L
							RegHL.Low &= unchecked((byte)~0x10);
							break;
						case 0xA6: // RES 4, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x10)));
							break;
						case 0xA7: // RES 4, A
							RegAF.High &= unchecked((byte)~0x10);
							break;
						case 0xA8: // RES 5, B
							RegBC.High &= unchecked((byte)~0x20);
							break;
						case 0xA9: // RES 5, C
							RegBC.Low &= unchecked((byte)~0x20);
							break;
						case 0xAA: // RES 5, D
							RegDE.High &= unchecked((byte)~0x20);
							break;
						case 0xAB: // RES 5, E
							RegDE.Low &= unchecked((byte)~0x20);
							break;
						case 0xAC: // RES 5, H
							RegHL.High &= unchecked((byte)~0x20);
							break;
						case 0xAD: // RES 5, L
							RegHL.Low &= unchecked((byte)~0x20);
							break;
						case 0xAE: // RES 5, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x20)));
							break;
						case 0xAF: // RES 5, A
							RegAF.High &= unchecked((byte)~0x20);
							break;
						case 0xB0: // RES 6, B
							RegBC.High &= unchecked((byte)~0x40);
							break;
						case 0xB1: // RES 6, C
							RegBC.Low &= unchecked((byte)~0x40);
							break;
						case 0xB2: // RES 6, D
							RegDE.High &= unchecked((byte)~0x40);
							break;
						case 0xB3: // RES 6, E
							RegDE.Low &= unchecked((byte)~0x40);
							break;
						case 0xB4: // RES 6, H
							RegHL.High &= unchecked((byte)~0x40);
							break;
						case 0xB5: // RES 6, L
							RegHL.Low &= unchecked((byte)~0x40);
							break;
						case 0xB6: // RES 6, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x40)));
							break;
						case 0xB7: // RES 6, A
							RegAF.High &= unchecked((byte)~0x40);
							break;
						case 0xB8: // RES 7, B
							RegBC.High &= unchecked((byte)~0x80);
							break;
						case 0xB9: // RES 7, C
							RegBC.Low &= unchecked((byte)~0x80);
							break;
						case 0xBA: // RES 7, D
							RegDE.High &= unchecked((byte)~0x80);
							break;
						case 0xBB: // RES 7, E
							RegDE.Low &= unchecked((byte)~0x80);
							break;
						case 0xBC: // RES 7, H
							RegHL.High &= unchecked((byte)~0x80);
							break;
						case 0xBD: // RES 7, L
							RegHL.Low &= unchecked((byte)~0x80);
							break;
						case 0xBE: // RES 7, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) & unchecked((byte)~0x80)));
							break;
						case 0xBF: // RES 7, A
							RegAF.High &= unchecked((byte)~0x80);
							break;
						case 0xC0: // SET 0, B
							RegBC.High |= unchecked(0x01);
							break;
						case 0xC1: // SET 0, C
							RegBC.Low |= unchecked(0x01);
							break;
						case 0xC2: // SET 0, D
							RegDE.High |= unchecked(0x01);
							break;
						case 0xC3: // SET 0, E
							RegDE.Low |= unchecked(0x01);
							break;
						case 0xC4: // SET 0, H
							RegHL.High |= unchecked(0x01);
							break;
						case 0xC5: // SET 0, L
							RegHL.Low |= unchecked(0x01);
							break;
						case 0xC6: // SET 0, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x01)));
							break;
						case 0xC7: // SET 0, A
							RegAF.High |= unchecked(0x01);
							break;
						case 0xC8: // SET 1, B
							RegBC.High |= unchecked(0x02);
							break;
						case 0xC9: // SET 1, C
							RegBC.Low |= unchecked(0x02);
							break;
						case 0xCA: // SET 1, D
							RegDE.High |= unchecked(0x02);
							break;
						case 0xCB: // SET 1, E
							RegDE.Low |= unchecked(0x02);
							break;
						case 0xCC: // SET 1, H
							RegHL.High |= unchecked(0x02);
							break;
						case 0xCD: // SET 1, L
							RegHL.Low |= unchecked(0x02);
							break;
						case 0xCE: // SET 1, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x02)));
							break;
						case 0xCF: // SET 1, A
							RegAF.High |= unchecked(0x02);
							break;
						case 0xD0: // SET 2, B
							RegBC.High |= unchecked(0x04);
							break;
						case 0xD1: // SET 2, C
							RegBC.Low |= unchecked(0x04);
							break;
						case 0xD2: // SET 2, D
							RegDE.High |= unchecked(0x04);
							break;
						case 0xD3: // SET 2, E
							RegDE.Low |= unchecked(0x04);
							break;
						case 0xD4: // SET 2, H
							RegHL.High |= unchecked(0x04);
							break;
						case 0xD5: // SET 2, L
							RegHL.Low |= unchecked(0x04);
							break;
						case 0xD6: // SET 2, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x04)));
							break;
						case 0xD7: // SET 2, A
							RegAF.High |= unchecked(0x04);
							break;
						case 0xD8: // SET 3, B
							RegBC.High |= unchecked(0x08);
							break;
						case 0xD9: // SET 3, C
							RegBC.Low |= unchecked(0x08);
							break;
						case 0xDA: // SET 3, D
							RegDE.High |= unchecked(0x08);
							break;
						case 0xDB: // SET 3, E
							RegDE.Low |= unchecked(0x08);
							break;
						case 0xDC: // SET 3, H
							RegHL.High |= unchecked(0x08);
							break;
						case 0xDD: // SET 3, L
							RegHL.Low |= unchecked(0x08);
							break;
						case 0xDE: // SET 3, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x08)));
							break;
						case 0xDF: // SET 3, A
							RegAF.High |= unchecked(0x08);
							break;
						case 0xE0: // SET 4, B
							RegBC.High |= unchecked(0x10);
							break;
						case 0xE1: // SET 4, C
							RegBC.Low |= unchecked(0x10);
							break;
						case 0xE2: // SET 4, D
							RegDE.High |= unchecked(0x10);
							break;
						case 0xE3: // SET 4, E
							RegDE.Low |= unchecked(0x10);
							break;
						case 0xE4: // SET 4, H
							RegHL.High |= unchecked(0x10);
							break;
						case 0xE5: // SET 4, L
							RegHL.Low |= unchecked(0x10);
							break;
						case 0xE6: // SET 4, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x10)));
							break;
						case 0xE7: // SET 4, A
							RegAF.High |= unchecked(0x10);
							break;
						case 0xE8: // SET 5, B
							RegBC.High |= unchecked(0x20);
							break;
						case 0xE9: // SET 5, C
							RegBC.Low |= unchecked(0x20);
							break;
						case 0xEA: // SET 5, D
							RegDE.High |= unchecked(0x20);
							break;
						case 0xEB: // SET 5, E
							RegDE.Low |= unchecked(0x20);
							break;
						case 0xEC: // SET 5, H
							RegHL.High |= unchecked(0x20);
							break;
						case 0xED: // SET 5, L
							RegHL.Low |= unchecked(0x20);
							break;
						case 0xEE: // SET 5, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x20)));
							break;
						case 0xEF: // SET 5, A
							RegAF.High |= unchecked(0x20);
							break;
						case 0xF0: // SET 6, B
							RegBC.High |= unchecked(0x40);
							break;
						case 0xF1: // SET 6, C
							RegBC.Low |= unchecked(0x40);
							break;
						case 0xF2: // SET 6, D
							RegDE.High |= unchecked(0x40);
							break;
						case 0xF3: // SET 6, E
							RegDE.Low |= unchecked(0x40);
							break;
						case 0xF4: // SET 6, H
							RegHL.High |= unchecked(0x40);
							break;
						case 0xF5: // SET 6, L
							RegHL.Low |= unchecked(0x40);
							break;
						case 0xF6: // SET 6, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x40)));
							break;
						case 0xF7: // SET 6, A
							RegAF.High |= unchecked(0x40);
							break;
						case 0xF8: // SET 7, B
							RegBC.High |= unchecked(0x80);
							break;
						case 0xF9: // SET 7, C
							RegBC.Low |= unchecked(0x80);
							break;
						case 0xFA: // SET 7, D
							RegDE.High |= unchecked(0x80);
							break;
						case 0xFB: // SET 7, E
							RegDE.Low |= unchecked(0x80);
							break;
						case 0xFC: // SET 7, H
							RegHL.High |= unchecked(0x80);
							break;
						case 0xFD: // SET 7, L
							RegHL.Low |= unchecked(0x80);
							break;
						case 0xFE: // SET 7, (HL)
							WriteMemory(RegHL.Word, (byte)(ReadMemory(RegHL.Word) | unchecked(0x80)));
							break;
						case 0xFF: // SET 7, A
							RegAF.High |= unchecked(0x80);
							break;
					}
					break;
				case 0xCC: // CALL Z, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (FlagZ)
					{
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Word = TUS;
					}
					break;
				case 0xCD: // CALL nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = TUS;
					break;
				case 0xCE: // ADC n
					TB = ReadMemory(RegPC.Word++);
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High + TB + TI2;
					RegAF.Low = 0;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 > 0xFF) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) + (TB & 0x0F) + TI2 > 0x0F) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0xCF: // RST $08
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x08;
					break;
				case 0xD0: // RET NC
					if (!FlagC)
						RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xD1: // POP DE
					RegDE.Low = ReadMemory(RegSP.Word++); RegDE.High = ReadMemory(RegSP.Word++);
					break;
				case 0xD2: // JP NC, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (!FlagC)
						RegPC.Word = TUS;
					break;
				case 0xD3: // NOP
					break;
				case 0xD4: // CALL NC, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (!FlagC)
					{
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Word = TUS;
					}
					break;
				case 0xD5: // PUSH DE
					WriteMemory(--RegSP.Word, RegDE.High); WriteMemory(--RegSP.Word, RegDE.Low);
					break;
				case 0xD6: // SUB n
					TB = ReadMemory(RegPC.Word++);
					TI1 = RegAF.High - TB;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0xD7: // RST $10
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x10;
					break;
				case 0xD8: // RET C
					if (FlagC)
						RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					break;
				case 0xD9: // RETI
					RegPC.Low = ReadMemory(RegSP.Word++); RegPC.High = ReadMemory(RegSP.Word++);
					// TODO Nothing else special needs to be done?
					break;
				case 0xDA: // JP C, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (FlagC)
						RegPC.Word = TUS;
					break;
				case 0xDB: // NOP
					break;
				case 0xDC: // CALL C, nn
					TUS = (ushort)(ReadMemory(RegPC.Word++) + ReadMemory(RegPC.Word++) * 256);
					if (FlagC)
					{
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Word = TUS;
					}
					break;
				case 0xDD: // NOP
					break;
				case 0xDE: // SBC A, n
					TB = ReadMemory(RegPC.Word++);
					TI2 = FlagC ? 1 : 0;
					TI1 = RegAF.High - TB - TI2;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) - TI2 < 0) RegAF.Low |= 0x20;
					RegAF.High = (byte)TI1;
					break;
				case 0xDF: // RST $18
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x18;
					break;
				case 0xE0: // LD ($FF00+nn), A
					WriteMemory((ushort)(0xFF00 + ReadMemory(RegPC.Word++)), RegAF.High);
					break;
				case 0xE1: // POP HL
					RegHL.Low = ReadMemory(RegSP.Word++); RegHL.High = ReadMemory(RegSP.Word++);
					break;
				case 0xE2: // LD ($FF00+C), A
					WriteMemory((ushort)(0xFF00 + RegBC.Low), RegAF.High);
					break;
				case 0xE3: // NOP
					break;
				case 0xE4: // NOP
					break;
				case 0xE5: // PUSH HL
					WriteMemory(--RegSP.Word, RegHL.High); WriteMemory(--RegSP.Word, RegHL.Low);
					break;
				case 0xE6: // AND n
					RegAF.High &= ReadMemory(RegPC.Word++);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0xA0 : 0x20);
					break;
				case 0xE7: // RST $20
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x20;
					break;
				case 0xE8: // ADD SP, n
					Console.WriteLine("E8 : ADD SP, n being executed. verify correctness");
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					RegAF.Low = 0;
					if (RegSP.Word + TSB > 0xFFFF) RegAF.Low |= 0x10;
					if (((RegSP.Word & 0xFFF) + TSB) > 0xFFF) RegAF.Low |= 0x20;
					RegSP.Word = (ushort)(RegSP.Word + TSB);
					break;
				case 0xE9: // JP HL
					RegPC.Word = RegHL.Word;
					break;
				case 0xEA: // LD (imm), A
					TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8));
					WriteMemory(TUS, RegAF.High);
					break;
				case 0xEB: // NOP
					break;
				case 0xEC: // NOP
					break;
				case 0xED: // NOP
					break;
				case 0xEE: // XOR n
					RegAF.High ^= ReadMemory(RegPC.Word++);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xEF: // RST $28
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x28;
					break;
				case 0xF0: // LD A, ($FF00+nn)
					RegAF.High = ReadMemory((ushort)(0xFF00 + ReadMemory(RegPC.Word++)));
					break;
				case 0xF1: // POP AF
					RegAF.Low = ReadMemory(RegSP.Word++); RegAF.High = ReadMemory(RegSP.Word++);
					break;
				case 0xF2: // LD A, ($FF00+C)
					RegAF.High = ReadMemory((ushort)(0xFF00 + RegBC.Low));
					break;
				case 0xF3: // DI
					IFF1 = IFF2 = false;
					break;
				case 0xF4: // NOP
					break;
				case 0xF5: // PUSH AF
					WriteMemory(--RegSP.Word, RegAF.High); WriteMemory(--RegSP.Word, RegAF.Low);
					break;
				case 0xF6: // OR n
					RegAF.High |= ReadMemory(RegPC.Word++);
					RegAF.Low = (byte)(RegAF.High == 0 ? 0x80 : 0);
					break;
				case 0xF7: // RST $30
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x30;
					break;
				case 0xF8: // LD HL, SP+nn
					Console.WriteLine("F8 : LD HL, SP+n being executed. verify correctness");
					TSB = (sbyte)ReadMemory(RegPC.Word++);
					RegAF.Low = 0;
					if (RegSP.Word + TSB > 0xFFFF) RegAF.Low |= 0x10;
					if (((RegSP.Word & 0xFFF) + TSB) > 0xFFF) RegAF.Low |= 0x20;
					RegHL.Word = (ushort)(RegSP.Word + TSB);
					break;
				case 0xF9: // LD SP, HL
					RegSP.Word = RegHL.Word;
					break;
				case 0xFA: // LD A, (nnnn)
					TUS = (ushort)(ReadMemory(RegPC.Word++) | (ReadMemory(RegPC.Word++) << 8));
					RegAF.High = ReadMemory(TUS);
					break;
				case 0xFB: // EI
					IFF1 = IFF2 = true;
					Interruptable = false;
					break;
				case 0xFC: // NOP
					break;
				case 0xFD: // NOP
					break;
				case 0xFE: // CP n
					TB = ReadMemory(RegPC.Word++);
					TI1 = RegAF.High - TB;
					RegAF.Low = 0x40;
					if ((byte)TI1 == 0) RegAF.Low |= 0x80;
					if (TI1 < 0) RegAF.Low |= 0x10;
					if ((RegAF.High & 0x0F) - (TB & 0x0F) < 0) RegAF.Low |= 0x20;
					break;
				case 0xFF: // RST $38
					WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
					RegPC.Word = 0x38;
					break;
				default: throw new Exception("unhandled opcode");
			}
			LogData();
		}

		void CheckIrq()
		{
			if (nonMaskableInterruptPending)
			{
				halted = false;

				PendingCycles -= 3;
				TotalExecutedCycles += 3;
				nonMaskableInterruptPending = false;

				iff2 = iff1;
				iff1 = false;

				WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
				RegPC.Word = 0x66;
			}
			else if (iff1 && interrupt && Interruptable)
			{
				Halted = false;

				iff1 = iff2 = false;

				switch (interruptMode)
				{
					case 0:
						PendingCycles -= 4;
						TotalExecutedCycles += 4;
						break;
					case 1:
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Word = 0x38;
						PendingCycles -= 4;
						TotalExecutedCycles += 4;
						break;
					case 2:
						ushort TUS = (ushort)(RegI * 256 + 0);
						WriteMemory(--RegSP.Word, RegPC.High); WriteMemory(--RegSP.Word, RegPC.Low);
						RegPC.Low = ReadMemory(TUS++); RegPC.High = ReadMemory(TUS);
						PendingCycles -= 5;
						TotalExecutedCycles += 5;
						break;
				}
			}
		}

		public void SingleStepInto()
		{
			if (halted) return;
			ExecuteInstruction();
			CheckIrq();
		}

		public void ExecuteCycles(int cycles)
		{
			PendingCycles += cycles;

			while (PendingCycles > 0)
			{
				Interruptable = true;

				if (halted)
				{
					PendingCycles -= 1;
				}
				else
				{
					ExecuteInstruction();
				}

				CheckIrq();
			}
		}
	}
}