// Z80m.cpp: implementation of the CZ80m class.
//
//////////////////////////////////////////////////////////////////////

#include "Z80m.h"
#include <stdlib.h>
#include "GBMachine.h"
#include "interrupt.h"
#include "Input.h"
#include "log.h"

extern bool FB_OK;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

const u32 LUT_Clocks[256] = {
		4,12, 8, 8, 4, 4, 8, 4, 20, 8, 8, 8, 4, 4, 8, 4,
		4,12, 8, 8, 4, 4, 8, 4, 12, 8, 8, 8, 4, 4, 8, 4,
		0,12, 8, 8, 4, 4, 8, 4,  0, 8, 8, 8, 4, 4, 8, 4,
		0,12, 8, 8,12,12,12, 4,  0, 8, 8, 8, 4, 4, 8, 4,
		
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		8, 8, 8, 8, 8, 8, 4, 8,  4, 4, 4, 4, 4, 4, 8, 4,
		
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		4, 4, 4, 4, 4, 4, 8, 4,  4, 4, 4, 4, 4, 4, 8, 4,
		
		0,12, 0,16, 0,16, 8,16,  0,16, 0, 0, 0,24, 8,16,
		0,12,12, 0, 0,16, 8,16,  0,16, 0, 0, 0, 0, 8,16,
		12,12, 8, 0, 0,16, 8,16, 16, 4,16, 0, 0, 0, 8,16,
		12,12, 8, 4, 0,16, 8,16, 12, 8,16, 4, 0, 0, 8,16
} ;

const u32 LUT_Clocks_CB[256] = {
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		
		8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8,
		8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8,
		8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8,
		8, 8, 8, 8, 8, 8, 12, 8, 8, 8, 8, 8, 8, 8, 12, 8,
		
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8,
		8, 8, 8, 8, 8, 8, 16, 8, 8, 8, 8, 8, 8, 8, 16, 8
	} ;


CZ80m::~CZ80m()
{

}

//////////////////////////////////////////////////////////////////////////

void CZ80m::InitCPU()
{
//	_Z80m_8BIT_& Reg8 = m_Reg8;
//	_Z80m_16BIT_& Reg16 = m_Reg16;
//	_Z80m_FLAGS_& Flags = m_Flags;

// 	if(GameBoy.Emulator.CGBEnabled == 1)
// 	{
// 		GameBoy.Emulator.ScreenMode = 1;
// 		GameBoy.Memory.IO_Ports[STAT_REG-0xFF00] = 0x01;
// 		GameBoy.Emulator.CurrentScanLine = 0x90;
// 	}
	
	//Registers
	
	if(!g_configinfo.m_bLoadInnerROM)
	{
        m_Reg8.F = 0xB0;
		/*
        if(GameBoy.Emulator.CGBEnabled)
        {
            GameBoy.CPU.Reg16.BC = 0x0000;
            GameBoy.CPU.Reg16.DE = 0xFF56;
            GameBoy.CPU.Reg16.HL = 0x000D;
        }
        else
        {*/
            m_Reg16.BC = 0x0013;
            m_Reg16.DE = 0x00D8;
            m_Reg16.HL = 0x014D;
        //}
		
        m_Reg16.PC = 0x0100;
        m_Reg16.SP = 0xFFFE;
		
        switch(g_configinfo.m_HWType)
        {
    case HW_AUTO: //this should be modified in the future
		case HW_GB:
		case HW_SGB:
			m_Reg8.A = 0x01; // SGB or Normal Gameboy
			break;
		case HW_GBP:
		case HW_SGB2:
			m_Reg8.A = 0xFF; // SGB2 or Pocket Gameboy
			break;
		case HW_GBA:
			m_Reg8.B |= 0x01; // GBA
			//NO BREAK
		case HW_GBC:
			m_Reg8.A = 0x11; // CGB or GBA
			break;
        }
	}
	else
	{
		// No idea of the real initial values (except the PC one, it must be 0x0000).
		// Maybe they are random?
		m_Reg16.AF = 0x0000;
		m_Reg16.BC = 0x0000;
		m_Reg16.DE = 0x0000;
		m_Reg16.HL = 0x0000;
		m_Reg16.PC = 0x0000;
		m_Reg16.SP = 0x0000;
	}
}

void CZ80m::SetMachine(CGBMachine* pMachine)
{
	m_pMachine = pMachine;
}

void CZ80m::SetMemory(CMemory* pMemory)
{
	m_pMemory = pMemory;
}

void CZ80m::SetInterrupt(CInterrupt* pInterrupt)
{
	m_pInterrupt = pInterrupt;
}

int nTic = 0;

void CZ80m::ExecStep(void)
{
#define MemRead8	m_pMemory->Read8
#define MemRead16	m_pMemory->Read16
#define MemWrite8	m_pMemory->Write8
#define MemWrite16	m_pMemory->Write16


	m_pInterrupt->HandleClock();
	
	if(m_pInterrupt->HandleInterrupts())
		AddClock(14);

	if(m_pMachine->HaltStop()) //if halt or stop...
	{
		int nHaltStop = m_pMachine->HaltStop();
		if(nHaltStop == GB_HALT) //halt
		{
			AddClock(4);
			m_pInterrupt->HandleClock();
			return;
		}
		else //STOP
		{			
			FB_OK = true; //this line only works for NDS or 3DS
			
			u8& p1_reg = m_pMemory->m_IOPorts[P1_REG-0xFF00];

			m_pInput->HasKeydown(p1_reg);
			{
				m_pMachine->HaltStop(GB_NORM);
			}
			return;
		}
	}


//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

	_Z80m_8BIT_& Reg8 = m_Reg8;
	_Z80m_16BIT_& Reg16 = m_Reg16;
	_Z80m_FLAGS_& Flags = m_Flags;

	u32 t1,t2,t3;//temporary valuable
	u8 Opcode;
/*
	int aaaaa = 0;


	if(Reg16.PC == 0x40)
	{
		aaaaa++;
	}
	if(Reg16.PC == 0x21)
	{
		aaaaa++;
	}
	if(Reg16.PC == 0x34)
	{
		aaaaa++;
	}
	if(Reg16.PC == 0x55)
	{
		aaaaa++;
	}
	if(Reg16.PC == 0x91)
	{
		aaaaa++;
	}
	if(Reg16.PC == 0x64)
	{
		aaaaa++;
	}
	static bool bbb=false;
	if(Reg16.PC == 0x2ba)
	{
		aaaaa++;
		bbb = true;
	}
	if(Reg16.PC == 0x322)
	{
		aaaaa++; 
		bbb = true;
	}
*///the up block of codes just used for testing

/*
	if(interrupts_enable_count)
	{
		interrupts_enable_count = 0;
		m_pMachine->IME(true);
	}
*/
	Opcode=MemRead8(Reg16.PC++);

	nTic++;

	switch (Opcode)
    {
	case 0x00: //NOP	--4
		break;
	case 0x01: //LD BC,nn	--12
		Reg16.BC = MemRead16(Reg16.PC);
		Reg16.PC +=2;
		break;
	case 0x02: //LD (BC),A	--8
		MemWrite8(Reg16.BC,Reg8.A);
		break;
	case 0x03: //INC BC	--8
		Reg16.BC = (Reg16.BC+1) & 0xFFFF;
		break;
	case 0x04: //INC B	--4
		Reg16.AF &= ~N_FLAG;
		Flags.H = ( (Reg8.B & 0xF) == 0xF);
		Reg8.B ++;
		Flags.Z = (Reg8.B == 0);
		break;
	case 0x05: //DEC B	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.B & 0xF) == 0x0);
		Reg8.B --;
		Flags.Z = (Reg8.B == 0);
		break;
	case 0x06: //LD B,n	--8
		Reg8.B = MemRead8(Reg16.PC/*++*/);
		Reg16.PC++;
		break;
	case 0x07: //RLCA	--4 
		//different doc has different says
		Reg16.AF &= ~(N_FLAG | H_FLAG | Z_FLAG);
		Flags.C = (Reg8.A & 0x80) != 0;//Old bit 7 of A to Carry flag
		Reg8.A = (Reg8.A << 1) | Flags.C;
		//Flags.Z = (Reg8.A == 0);
		break;
	case 0x08: //LD (nn),SP	--20
		{
			u16 nn = MemRead16(Reg16.PC);
			MemWrite16(nn, Reg16.SP);
			Reg16.PC +=2;
			break;
		}
	case 0x09: //ADD HL,BC	--8
		Reg16.AF &= ~N_FLAG;
		t1 = Reg16.HL + Reg16.BC;
		Flags.C = (t1 > 0xFFFF);
		Flags.H = ( ( (Reg16.HL & 0x0FFF) + (Reg16.BC & 0x0FFF) ) > 0x0FFF );
		Reg16.HL = t1 & 0xFFFF;
		break;
	case 0x0A: //LD A,(BC)	--8
		Reg8.A = MemRead8(Reg16.BC);
		break;
	case 0x0B: //DEC BC	--8
		Reg16.BC = (Reg16.BC-1) & 0xFFFF;
		break;
	case 0x0C: //INC C	--4
		Reg16.AF &= ~N_FLAG;	//reset N flag bit
		Flags.H = ( (Reg8.C & 0xF) == 0xF); //set if half carry
		Reg8.C ++;
		Flags.Z = (Reg8.C == 0);
		break;
	case 0x0D: //DEC C	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.C & 0xF) == 0x0);
		Reg8.C --;
		Flags.Z = (Reg8.C == 0);
		break;
	case 0x0E: //LD C,n	--8
		Reg8.C = MemRead8(Reg16.PC++);
		break;
	case 0x0F: //RRCA	--4
		Reg16.AF &= ~(N_FLAG|H_FLAG|Z_FLAG);
		Flags.C = (Reg8.A & 0x01) != 0; //copy the bit 0 to carry
		Reg8.A = (Reg8.A >> 1) | (Flags.C << 7); //bit 0 to bit 7
		break;
	case 0x10: //STOP	--4
		// Halt CPU & LCD display until button pressed.
		//MemRead8(Reg16.PC++);
		
		m_pMachine->HaltStop(GB_STOP);
		Reg16.PC++;
// 		if(MemRead8(Reg16.PC++) != 0)
// 			DebugMessage("Corrupted stop.\nPC: %04x\nROM: %d",
// 			GameBoy.CPU.Reg16.PC,GameBoy.Memory.selected_rom);
// 		
// 		if(GameBoy.Emulator.CGBEnabled == 0)
// 		{
// 			GameBoy.Emulator.CPUHalt = 2;
// 		}
// 		else //Switch to double speed mode (CGB)
// 		{
// 			if(mem->IO_Ports[KEY1_REG-0xFF00]&1)
// 			{
// 				GameBoy.Emulator.DoubleSpeed ^= 1;
// 				mem->IO_Ports[KEY1_REG-0xFF00] = GameBoy.Emulator.DoubleSpeed<<7;
// 			}
// 			else
// 			{
// 				GameBoy.Emulator.CPUHalt = 2;
// 			}
// 		}
// 		
		break;
	case 0x11: //LD DE,nn	--12
		Reg16.DE = MemRead16(Reg16.PC);
		Reg16.PC +=2;
		break;
	case 0x12: //LD (DE),A	--8
		MemWrite8(Reg16.DE, Reg8.A);
		break;
	case 0x13: //INC DE	--8
		//no affect to flags
		Reg16.DE = (Reg16.DE+1) & 0xFFFF;
		break;
	case 0x14: //INC D	--4
		Reg16.AF &= ~(N_FLAG);
		Flags.H = ( (Reg8.D & 0xF) == 0xF);
		Reg8.D++;
		Flags.Z = (Reg8.D == 0);
		break;
	case 0x15: //DEC D	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.D & 0xF) == 0x0);
		Reg8.D --;
		Flags.Z = (Reg8.D == 0);
		break;
	case 0x16: //LD D,n	--8
		Reg8.D = MemRead8(Reg16.PC++);
		break;
	case 0x17: //RLA	--4
		//different doc has different says
		Reg16.AF &= ~(N_FLAG|H_FLAG|Z_FLAG);
		t1 = Flags.C; //old carry flag
		Flags.C = (Reg8.A & 0x80) != 0; //new carry flag
		Reg8.A = (Reg8.A << 1) | t1;
		//Flags.Z = (Reg8.A == 0);
		break;
	case 0x18: //JR n	--8
		//the relative num "n" is add to the PC value, when PC is moved over this full instruction
		Reg16.PC = (Reg16.PC + 1 + (s8)MemRead8(Reg16.PC)) & 0xFFFF;
		break;
	case 0x19: //ADD HL,DE	--8
		Reg16.AF &= ~N_FLAG;
		t1 = Reg16.HL + Reg16.DE;
		Flags.C = ( t1 > 0xFFFF );
		Flags.H = ( ( (Reg16.HL & 0xFFF) + (Reg16.DE & 0xFFF) ) > 0xFFF );
		Reg16.HL = t1 & 0xFFFF;
		break;
	case 0x1A: //LD A,(DE)	--8
		Reg8.A = MemRead8(Reg16.DE);
		break;
	case 0x1B: //DEC DE	--8
		Reg16.DE = (Reg16.DE-1) & 0xFFFF;
		break;
	case 0x1C: //INC E	--4
		Reg16.AF &= ~N_FLAG;
		Flags.H = ( (Reg8.E & 0xF) == 0xF);
		Reg8.E ++;
		Flags.Z = (Reg8.E == 0);
		break;
	case 0x1D: //DEC E	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.E & 0xF) == 0x0);
		Reg8.E --;
		Flags.Z = (Reg8.E == 0);
		break;
	case 0x1E: //LD E,n	--8
		Reg8.E = MemRead8(Reg16.PC++);
		break;
	case 0x1F: //RRA	--4
		Reg16.AF &= ~(N_FLAG|H_FLAG|Z_FLAG);
		t1 = Flags.C; //old carry flag
		Flags.C = Reg8.A & 0x01; //new carry flag(bit 0 of A)
		Reg8.A = (Reg8.A >> 1) | (t1 << 7);
		break;
	case 0x20: //JR NZ,n	--8
		if(Flags.Z == 0)
		{
			Reg16.PC = (Reg16.PC + 1 + (s8)MemRead8(Reg16.PC)) & 0xFFFF;
			AddClock(12 >> m_nDoubleSpeed); 
		}
		else
		{
			Reg16.PC ++;
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0x21: //LD HL,nn	--12
		Reg16.HL = MemRead16(Reg16.PC);
		Reg16.PC +=2;
		break;
	case 0x22: //LD (HLI),A | LD (HL+),A | LDI (HL),A	--8
		MemWrite8(Reg16.HL,Reg8.A);
		Reg16.HL = (Reg16.HL+1) & 0xFFFF;
		break;
	case 0x23: //INC HL	--8
		Reg16.HL = (Reg16.HL+1) & 0xFFFF;
		break;
	case 0x24: //INC H	--4
		Reg16.AF &= ~N_FLAG;
		Flags.H = ( (Reg8.H & 0xF) == 0xF);
		Reg8.H ++;
		Flags.Z = (Reg8.H == 0);
		break;
	case 0x25: //DEC H	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.H & 0xF) == 0x0);
		Reg8.H --;
		Flags.Z = (Reg8.H == 0);
		break;
	case 0x26: //LD H,n	--8
		Reg8.H = MemRead8(Reg16.PC++);
		break;
	case 0x27: //DAA(Decimal adjust register A)	--4
		t3 = Reg8.A;
		t1 = t3 & 0x0F;
		t2 = (t3 & 0xF0) >> 4;
		
		if(Reg16.AF & N_FLAG) //Substraction
		{
			if(Reg16.AF & C_FLAG)
			{
				if( (t2 > 6) && (!Flags.H) && (t1 < 10) )
				{
					t3 += 0xA0;
					//		cpu->Reg16.AF |= F_CARRY;
					//cpu->Reg16.AF &= ~(F_HALFCARRY);
				}
				else if( (t2 > 5) && (Flags.H) && (t1 > 5) )
				{
					t3 += 0x9A;
					Reg16.AF |= C_FLAG; //(F_CARRY|F_HALFCARRY);
				}
			}
			else
			{
				if( (t2 < 10) && (!Flags.H) && (t1 < 10) )
				{
					Reg16.AF &= ~C_FLAG; //(F_CARRY|F_HALFCARRY);
				}
				else if( (t2 < 9) && (Flags.H) && (t1 > 5) )
				{
					t3 += 0xFA;
					//		cpu->Reg16.AF &= ~F_CARRY;
					//cpu->Reg16.AF |= F_HALFCARRY;
				}
			}
		}
		else //Addition
		{
			if(Reg16.AF & C_FLAG)
			{
				if( (t2 < 3) && (!Flags.H) && (t1 < 10))
				{
					t3 += 0x60;
					//		cpu->Reg16.AF |= F_CARRY;
					//cpu->Reg16.AF &= ~F_HALFCARRY;
				}
				else if( (t2 < 3) && (!Flags.H) && (t1 > 9))
				{
					t3 += 0x66;
					Reg16.AF |= C_FLAG; //F_CARRY|F_HALFCARRY;
				}
				else if( (t2 < 4) && (Flags.H) && (t1 < 4))
				{
					t3 += 0x66;
					//		cpu->Reg16.AF |= F_CARRY;
					//cpu->Reg16.AF &= ~F_HALFCARRY;
				}
			}
			else
			{
				if( (t2 < 10) && (!Flags.H) && (t1 < 10))
				{
					Reg16.AF &= ~C_FLAG; //(F_CARRY|F_HALFCARRY);
				}
				else if( (t2 < 9) && (!Flags.H) && (t1 > 9))
				{
					t3 += 0x06;
					//		cpu->Reg16.AF &= ~F_CARRY;
					//cpu->Reg16.AF |= F_HALFCARRY;
				}
				else if( (t2 < 10) && (Flags.H) && (t1 < 4))
				{
					t3 += 0x06;
					Reg16.AF &= ~C_FLAG; //(F_CARRY|F_HALFCARRY);
				}
				else if( (t2 > 9) && (!Flags.H) && (t1 < 10))
				{
					t3 += 0x60;
					Reg16.AF |= C_FLAG;
					//cpu->Reg16.AF &= ~F_HALFCARRY;
				}
				else if( (t2 > 8) && (!Flags.H) && (t1 > 9))
				{
					t3 += 0x66;
					Reg16.AF |= C_FLAG; //(F_CARRY|F_HALFCARRY);
				}
				else if( (t2 > 9) && (Flags.H) && (t1 < 4))
				{
					t3 += 0x66;
					Reg16.AF |= C_FLAG;
					//cpu->Reg16.AF &= ~F_HALFCARRY;
				}
			}
		}
		
		t3 &= 0xFF;
		
		Reg8.A = t3;
		Flags.Z = (t3 == 0);
		break;
	case 0x28: //JR Z,n	--8
		if(Flags.Z)
		{
			Reg16.PC = (Reg16.PC + 1 + (s8)MemRead8(Reg16.PC)) & 0xFFFF;
			AddClock(12 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC ++;
			AddClock(8 >> m_nDoubleSpeed); 
		}
		return;
	case 0x29: //ADD HL,HL	--8
		Reg16.AF &= ~N_FLAG;
		Flags.C = (Reg16.HL & 0x8000) != 0;
		Flags.H = (Reg16.HL & 0x0800) != 0;
		Reg16.HL = (Reg16.HL << 1) & 0xFFFF; //Reg16.HL = (Reg16.HL + Reg16.HL) & 0xFFFF;
		break;
	case 0x2A: //LD A,(HLI) | LD A,(HL+) | LDI A,(HL)	--8
		Reg8.A = MemRead8(Reg16.HL);
		Reg16.HL = (Reg16.HL+1) & 0xFFFF;
		break;
	case 0x2B: //DEC HL	--8
		Reg16.HL = (Reg16.HL-1) & 0xFFFF;
		break;
	case 0x2C: //INC L	--4
		Reg16.AF &= ~N_FLAG;
		Flags.H = ( (Reg8.L & 0xF) == 0xF);
		Reg8.L ++;
		Flags.Z = (Reg8.L == 0);
		break;
	case 0x2D: //DEC L	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.L & 0xF) == 0x0);
		Reg8.L --;
		Flags.Z = (Reg8.L == 0);
		break;
	case 0x2E: //LD L,n		--8
		Reg8.L = MemRead8(Reg16.PC++);
		break;
	case 0x2F: //CPL (Complement A register. (Flip all bits.))	--4
		Reg16.AF |= (N_FLAG|H_FLAG);
		Reg8.A = ~Reg8.A;
		break;
	case 0x30: //JR NC,n	--8
		if(Flags.C == 0) //Carry is reset, so, need to jump
		{
			Reg16.PC = (Reg16.PC + 1 + (s8)MemRead8(Reg16.PC)) & 0xFFFF;
			AddClock(12 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC ++;
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0x31: //LD SP,nn	--12
		Reg16.SP = MemRead16(Reg16.PC);
		Reg16.PC +=2;
		break;
	case 0x32: //LD (HLD),A | LD (HL-),A | LDD (HL),A	--8
		MemWrite8(Reg16.HL, Reg8.A);
		Reg16.HL = (Reg16.HL-1) & 0xFFFF;
		break;
	case 0x33: //INC SP	--8
		Reg16.SP = (Reg16.SP+1) & 0xFFFF;
		break;
	case 0x34: //INC (HL)	--12
		Reg16.AF &= ~N_FLAG;
		t1 = MemRead8(Reg16.HL);
		Flags.H = ( (t1 & 0xF) == 0xF);
		t1 = (t1 + 1) & 0xFF;
		Flags.Z = (t1 == 0);
		MemWrite8(Reg16.HL,t1);
		break;
	case 0x35: //DEC (HL)	--12
		Reg16.AF |= N_FLAG;
		t1 = MemRead8(Reg16.HL);
		Flags.H = ( (t1 & 0xF) == 0x0);
		t1  = (t1 - 1) & 0xFF;
		Flags.Z = (t1 == 0);
		MemWrite8(Reg16.HL,t1);
		break;
	case 0x36: //LD (HL),n	--12
		MemWrite8(Reg16.HL, MemRead8(Reg16.PC++)); //MemRead8(Reg16.PC++) just is n
		break;
	case 0x37: //SCF  (Set Carry Flag)	--4
		Reg16.AF &= ~(N_FLAG|H_FLAG);
		Reg16.AF |= C_FLAG;
		break;
	case 0x38: //JR C,n	--8
		if(Flags.C == 1) //if Carry bit is set, then jump
		{
			Reg16.PC = (Reg16.PC + 1 + (s8)MemRead8(Reg16.PC)) & 0xFFFF;
			AddClock(12 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC ++;
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0x39: //ADD HL,SP	--8
		Reg16.AF &= ~N_FLAG;
		t1 = Reg16.HL + Reg16.SP;
		Flags.C = (t1 > 0xFFFF);
		Flags.H = ( ( (Reg16.HL & 0x0FFF) + (Reg16.SP & 0x0FFF) ) > 0x0FFF );
		Reg16.HL = t1 & 0xFFFF;
		break;
	case 0x3A: //LD A,(HLD) | LD A,(HL-) | LDD A,(HL)	--8
		Reg8.A = MemRead8(Reg16.HL);
		Reg16.HL = (Reg16.HL-1) & 0xFFFF;
		break;
	case 0x3B: //DEC SP	--8
		Reg16.SP = (Reg16.SP-1) & 0xFFFF;
		break;
	case 0x3C: //INC A	--4
		Reg16.AF &= ~N_FLAG;
		Flags.H = ( (Reg8.A & 0xF) == 0xF);
		Reg8.A ++;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x3D: //DEC A	--4
		Reg16.AF |= N_FLAG;
		Flags.H = ( (Reg8.A & 0xF) == 0x0);
		Reg8.A --;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x3E: //LD A,n	--8
		Reg8.A = MemRead8(Reg16.PC++);
		break;
	case 0x3F: //CCF (Complement carry flag)	--4
		Reg16.AF &= ~(N_FLAG|H_FLAG);
		Flags.C = !Flags.C;
		break;
	case 0x40: //LD B,B	--4
		Reg8.B = Reg8.B;
		break;
	case 0x41: //LD B,C	--4
		Reg8.B = Reg8.C;
		break;
	case 0x42: //LD B,D	--4
		Reg8.B = Reg8.D;
		break;
	case 0x43: //LD B,E	--4
		Reg8.B = Reg8.E;
		break;
	case 0x44: //LD B,H	--4
		Reg8.B = Reg8.H;
		break;
	case 0x45: //LD B,L	--4
		Reg8.B = Reg8.L;
		break;
	case 0x46: //LD B,(HL)	--8
		Reg8.B = MemRead8(Reg16.HL);
		break;
	case 0x47: //LD B,A	--4
		Reg8.B = Reg8.A;
		break;
	case 0x48: //LD C,B	--4
		Reg8.C = Reg8.B;
		break;
	case 0x49: //LD C,C	--4
		Reg8.C = Reg8.C;
		break;
	case 0x4A: //LD C,D	--4
		Reg8.C = Reg8.D;
		break;
	case 0x4B: //LD C,E	--4
		Reg8.C = Reg8.E;
		break;
	case 0x4C: //LD C,H	--4
		Reg8.C = Reg8.H;
		break;
	case 0x4D: //LD C,L	--4
		Reg8.C = Reg8.L;
		break;
	case 0x4E: //LD C,(HL)	--8
		Reg8.C = MemRead8(Reg16.HL);
		break;
	case 0x4F: //LD C,A	--4
		Reg8.C = Reg8.A;
		break;
	case 0x50: //LD D,B	--4
		Reg8.D = Reg8.B;
		break;
	case 0x51: //LD D,C
		Reg8.D = Reg8.C;
		break;
	case 0x52: //LD D,D	--4
		Reg8.D = Reg8.D;
		break;
	case 0x53: //LD D,E	--4
		Reg8.D = Reg8.E;
		break;
	case 0x54: //LD D,H	--4
		Reg8.D = Reg8.H;
		break;
	case 0x55: //LD D,L	--4
		Reg8.D = Reg8.L;
		break;
	case 0x56: //LD D,(HL)	--8
		Reg8.D = MemRead8(Reg16.HL);
		break;
	case 0x57: //LD D,A	--4
		Reg8.D = Reg8.A;
		break;
	case 0x58: //LD E,B	--4
		Reg8.E = Reg8.B;
		break;
	case 0x59: //LD E,C	--4
		Reg8.E = Reg8.C;
		break;
	case 0x5A: //LD E,D	--4
		Reg8.E = Reg8.D;
		break;
	case 0x5B: //LD E,E	--4
		Reg8.E = Reg8.E;
		break;
	case 0x5C: //LD E,H	--4
		Reg8.E = Reg8.H;
		break;
	case 0x5D: //LD E,L	--4
		Reg8.E = Reg8.L;
		break;
	case 0x5E: //LD E,(HL)	--8
		Reg8.E = MemRead8(Reg16.HL);
		break;
	case 0x5F: //LD E,A	--4
		Reg8.E = Reg8.A;
		break;
	case 0x60: //LD H,B	--4
		Reg8.H = Reg8.B;
		break;
	case 0x61: //LD H,C	--4
		Reg8.H = Reg8.C;
		break;
	case 0x62: //LD H,D	--4
		Reg8.H = Reg8.D;
		break;
	case 0x63: //LD H,E	--4
		Reg8.H = Reg8.E;
		break;
	case 0x64: //LD H,H	--4
		Reg8.H = Reg8.H;
		break;
	case 0x65: //LD H,L	--4
		Reg8.H = Reg8.L;
		break;
	case 0x66: //LD H,(HL)	--8
		Reg8.H = MemRead8(Reg16.HL);
		break;
	case 0x67: //LD H,A	--4
		Reg8.H = Reg8.A;
		break;
	case 0x68: //LD L,B	--4
		Reg8.L = Reg8.B;
		break;
	case 0x69: //LD L,C	--4
		Reg8.L = Reg8.C;
		break;
	case 0x6A: //LD L,D	--4
		Reg8.L = Reg8.D;
		break;
	case 0x6B: //LD L,E	--4
		Reg8.L = Reg8.E;
		break;
	case 0x6C: //LD L,H	--4
		Reg8.L = Reg8.H;
		break;
	case 0x6D: //LD L,L	--4
		Reg8.L = Reg8.L;
		break;
	case 0x6E: //LD L,(HL)	--8
		Reg8.L = MemRead8(Reg16.HL);
		break;
	case 0x6F: //LD L,A	--4
		Reg8.L = Reg8.A;
		break;
	case 0x70: //LD (HL),B	--8
		MemWrite8(Reg16.HL, Reg8.B);
		break;
	case 0x71: //LD (HL),C	--8
		MemWrite8(Reg16.HL, Reg8.C);
		break;
	case 0x72: //LD (HL),D	--8
		MemWrite8(Reg16.HL, Reg8.D);
		break;
	case 0x73: //LD (HL),E	--8
		MemWrite8(Reg16.HL, Reg8.E);
		break;
	case 0x74: //LD (HL),H	--8
		MemWrite8(Reg16.HL, Reg8.H);
		break;
	case 0x75: //LD (HL),L	--8
		MemWrite8(Reg16.HL, Reg8.L);
		break;
	case 0x76: //HALT	--4
		//Description:
		//Power down CPU until an interrupt occurs. Use this
		//when ever possible to reduce energy consumption.
		m_pMachine->HaltStop(GB_HALT);

//		if(GameBoy.Memory.InterruptMasterEnable == 1)
//		{
			//	if(GameBoy.Emulator.HDMAenabled == HDMA_NONE)
			//	{
//			GameBoy.Emulator.CPUHalt = 1;
			//	}
//		}
//		else
//		{
		/*		if(mem->IO_Ports[IF_REG-0xFF00] & mem->HighRAM[IE_REG-0xFF80] & 0x1F)
		{
		
		  The first byte of the next instruction
		  after HALT is read. The Program Counter (PC) fails to
		  increment to the next memory location. As a results, the
		  first byte after HALT is read again. From this point on
		  the Program Counter once again operates normally
		  
			}
			else
			{
			//Nothing
			}
			*/
//			GameBoy.Emulator.halt_not_executed = 1;
//		}
		break;
	case 0x77: //LD (HL),A	--8
		MemWrite8(Reg16.HL, Reg8.A);
		break;
	case 0x78: //LD A,B	--4
		Reg8.A = Reg8.B;
		break;
	case 0x79: //LD A,C	--4
		Reg8.A = Reg8.C;
		break;
	case 0x7A: //LD A,D	--4
		Reg8.A = Reg8.D;
		break;
	case 0x7B: //LD A,E	--4
		Reg8.A = Reg8.E;
		break;
	case 0x7C: //LD A,H	--4
		Reg8.A = Reg8.H;
		break;
	case 0x7D: //LD A,L	--4
		Reg8.A = Reg8.L;
		break;
	case 0x7E: //LD A,(HL)	--8
		Reg8.A = MemRead8(Reg16.HL);
		break;
	case 0x7F: //LD A,A	--4
		Reg8.A = Reg8.A;
		break;
	case 0x80: //ADD A,B	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.B & 0xF) ) > 0xF;
		Reg8.A += Reg8.B;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x81: //ADD A,C	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.C & 0xF) ) > 0xF;
		Reg8.A += Reg8.C;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x82: //ADD A,D	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.D & 0xF) ) > 0xF;
		Reg8.A += Reg8.D;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x83: //ADD A,E	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.E & 0xF) ) > 0xF;
		Reg8.A += Reg8.E;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x84: //ADD A,H	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.H & 0xF) ) > 0xF;
		Reg8.A += Reg8.H;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x85: //ADD A,L	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		Flags.H = ( (t1 & 0xF) + ((u32)Reg8.L & 0xF) ) > 0xF;
		Reg8.A += Reg8.L;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x86: //ADD A,(HL)	--8
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		t2 = MemRead8(Reg16.HL); //@@@@@@@ in GiiBii is MemRead16(Reg16.HL), I use MemRead8(Reg16.HL)
		Flags.H = ( (t1 & 0xF) + (t2 & 0xF) ) > 0xF;
		Reg8.A += t2;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0x87: //ADD A,A
		Reg16.AF &= ~N_FLAG;
		Flags.H = (Reg8.A & 0x08) != 0; //@@@@@@@@
		Flags.C = (Reg8.A & 0x80) != 0; //@@@@@@@@
		Reg8.A += Reg8.A;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x88: //ADC A,B	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A + Reg8.B + Flags.C;
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.B & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		t1 &= 0xFF;
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x89: //ADC A,C	--4
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A + Reg8.C + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.C & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8A: //ADC A,D
		Reg16.AF &= ~N_FLAG;
		
		t1 = Reg8.A + Reg8.D + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.D & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8B: //ADC A,E
		Reg16.AF &= ~N_FLAG;
		
		t1 = Reg8.A + Reg8.E + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.E & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8C: //ADC A,H
		Reg16.AF &= ~N_FLAG;
		
		t1 = Reg8.A + Reg8.H + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.H & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8D: //ADC A,L
		Reg16.AF &= ~N_FLAG;
		
		t1 = Reg8.A + Reg8.L + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (Reg8.L & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8E: //ADC A,(HL)
		Reg16.AF &= ~N_FLAG;
		t1 = MemRead8(Reg16.HL);
		t2 = Reg8.A + t1 + Flags.C;
		
		Flags.H = ( ((Reg8.A & 0xF) + (t1 & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t2 > 0xFF);
		
		t2 &= 0xFF;
		
		Reg8.A = t2;
		Flags.Z = (t1 == 0); 
		break;
	case 0x8F: //ADC A,A
		Reg16.AF &= ~N_FLAG;
		
		t1 = ( ((u32)Reg8.A) << 1 ) + Flags.C;
		
		//Carry flag not needed to test this, gaoc: yes!
		Flags.H = (Reg8.A & 0x08) != 0;
		
		Flags.C = (t1 > 0xFF);
		
		t1 &= 0xFF;
		
		Reg8.A = t1;
		Flags.Z = (t1 == 0); 
		break;
	case 0x90: //SUB B (Subtract B from A) 
		//PanDoc has mistake? see <GBCPUman.pdf> P82, Yes! see <TheNintendoGameboy.pdf> P127
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.B & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.B;
		
		Reg8.A -= Reg8.B;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x91: //SUB C
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.C & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.C;
		
		Reg8.A -= Reg8.C;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x92: //SUB D
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.D & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.D;
		
		Reg8.A -= Reg8.D;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x93: //SUB E
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.E & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.E;
		
		Reg8.A -= Reg8.E;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x94: //SUB H
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.H & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.H;
		
		Reg8.A -= Reg8.H;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x95: //SUB L
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (Reg8.L & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.L;
		
		Reg8.A -= Reg8.L;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x96: //SUB (HL)
		t1 = MemRead8(Reg16.HL);
		Reg8.F = N_FLAG;
		
		Flags.H = (Reg8.A & 0xF) < (t1 & 0xF);
		Flags.C = (u32)Reg8.A < (u32)t1;
		
		Reg8.A -= t1;
		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0x97: //SUB A
		Reg8.F = N_FLAG|Z_FLAG;
		Reg8.A = 0;
		break;
	case 0x98: //SBC A,B
		t1 = Reg8.A - Reg8.B - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.B ^ t1) & 0x10 ) != 0 ; //!!!!!!!!!!!
		Reg8.A = t1;
		break;
	case 0x99: //SBC A,C
		t1 = Reg8.A - Reg8.C - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.C ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9A: //SBC A,D
		t1 = Reg8.A - Reg8.D - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.D ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9B: //SBC A,E
		t1 = Reg8.A - Reg8.E - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.E ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9C: //SBC A,H
		t1 = Reg8.A - Reg8.H - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.H ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9D: //SBC A,L
		t1 = Reg8.A - Reg8.L - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ Reg8.L ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9E: //SBC A,(HL)
		t2 = MemRead8(Reg16.HL);
		t1 = Reg8.A - t2 - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ t2 ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0x9F: //SBC A,A
		Reg16.AF = Reg8.F & C_FLAG ?
			( (0xFF/* A - A - 1 = 0xFF */ << 8) | C_FLAG | H_FLAG | N_FLAG ) : (Z_FLAG | N_FLAG) ;
		break;
	case 0xA0: //AND B	--4
		Reg16.AF |= H_FLAG; //HalfCarry flag is always set.
		Reg16.AF &= ~(N_FLAG | C_FLAG); // N and C flag always reset.
		Reg8.A &= Reg8.B;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA1: //AND C	--4
		Reg16.AF |= H_FLAG; //see above
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= Reg8.C;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA2: //AND D	--4
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= Reg8.D;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA3: //AND E	--4
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= Reg8.E;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA4: //AND H	--4
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= Reg8.H;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA5: //AND L	--4
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= Reg8.L;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA6: //AND (HL)	--8
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg8.A &= MemRead8(Reg16.HL);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA7: //AND A	--4
		Reg16.AF |= H_FLAG;
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		//Reg8.A &= Reg8.A; //AND itself is itself as well.
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA8: //XOR B	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.B;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xA9: //XOR C	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.C;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAA: //XOR D	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.D;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAB: //XOR E	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.E;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAC: //XOR H	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.H;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAD: //XOR L	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= Reg8.L;		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAE: //XOR (HL)	--8
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= MemRead8(Reg16.HL);		
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xAF: //XOR A	--4
		Reg16.AF = Z_FLAG; //this assignment is also reset N,H,C flag.
		break;
	case 0xB0: //OR B	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.B;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB1: //OR C	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.C;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB2: //OR D	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.D;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB3: //OR E	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.E;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB4: //OR H	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.H;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB5: //OR L	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= Reg8.L;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB6: //OR (HL)	--8
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= MemRead8(Reg16.HL);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB7: //OR A	--4
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);		
		//Reg8.A |= Reg8.A;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xB8: //CP B	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.B & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.B;
		Flags.Z = (Reg8.A == Reg8.B);
		break;
	case 0xB9: //CP C	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.C & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.C;
		Flags.Z = (Reg8.A == Reg8.C);
		break;
	case 0xBA: //CP D	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.D & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.D;
		Flags.Z = (Reg8.A == Reg8.D);
		break;
	case 0xBB: //CP E	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.E & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.E;
		Flags.Z = (Reg8.A == Reg8.E);
		break;
	case 0xBC: //CP H	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.H & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.H;
		Flags.Z = (Reg8.A == Reg8.H);
		break;
	case 0xBD: //CP L	--4
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (Reg8.L & 0xF);
		Flags.C = (u32)Reg8.A < (u32)Reg8.L;
		Flags.Z = (Reg8.A == Reg8.L);
		break;
	case 0xBE: //CP (HL)	--8
		Reg16.AF |= N_FLAG;
		t1 = MemRead8(Reg16.HL);
		Flags.H = (Reg8.A & 0xF) < (t1 & 0xF);
		Flags.C = (u32)Reg8.A < t1;
		Flags.Z = (Reg8.A == t1);
		break;
	case 0xBF: //CP A	--4
		Reg16.AF |= (N_FLAG | Z_FLAG);
		Reg16.AF &= ~(H_FLAG | C_FLAG);
		break;
	case 0xC0: //RET NZ	--8
		if(Flags.Z == 0) // if Z flag is reset(0), then return.
		{
			Reg16.PC = MemRead16(Reg16.SP);
			Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
			AddClock(20 >> m_nDoubleSpeed);
		}
		else
		{
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0xC1: //POP BC	--12
		Reg16.BC = MemRead16(Reg16.SP);
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		break;
	case 0xC2: //JP NZ,nn	--12
		if(Flags.Z == 0) // if Z is reset, then jump.
		{
			Reg16.PC = MemRead16(Reg16.PC);
			AddClock(16 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC += 2; //move over the immediate number nn.
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xC3: //JP nn	--12
		// nn = two byte immediate value. (LS byte first.)
		Reg16.PC = MemRead16(Reg16.PC);
		break;
	case 0xC4: //CALL NZ,nn	--12
		// nn = two byte immediate value. (LS byte first.)
		if(Flags.Z == 0) // if Z flag is reset, then call.
		{
			Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
			MemWrite16(Reg16.SP, Reg16.PC+2); // save the old PC value into stack
			Reg16.PC = MemRead16(Reg16.PC);
			AddClock(24 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC  += 2;	// next instruction
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xC5: //PUSH BC	--16
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.BC);
		break;
	case 0xC6: //ADD A,n (n is a immediate value)	--8
		Reg16.AF &= ~N_FLAG;
		t1 = Reg8.A;
		t2 = MemRead8(Reg16.PC++);
		Flags.H = ( (t1 & 0xF) + (t2 & 0xF) ) > 0xF;
		Reg8.A += t2;
		Flags.Z = (Reg8.A == 0);
		Flags.C = (t1 > Reg8.A);
		break;
	case 0xC7: //RST 0x00	--32
		//Push present address onto stack.
		//Jump to address $0000.
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0000;
		break;
	case 0xC8: //RET Z	--8
		if(Flags.Z == 1) // if Z flag is set, then return.
		{
			Reg16.PC = MemRead16(Reg16.SP);
			Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
			AddClock(20 >> m_nDoubleSpeed);
		}
		else
		{
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0xC9: //RET	--8
		//Pop two bytes from stack & jump to that address.
		Reg16.PC = MemRead16(Reg16.SP);
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		break;
	case 0xCA: //JP Z,nn	--12
		if(Flags.Z == 1) // if Z flag is set,  then jump.
		{
			Reg16.PC = MemRead16(Reg16.PC);
			AddClock(16 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC += 2;			
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xCB: //CB prefix
		t3 = MemRead8(Reg16.PC++);

#if defined(NMGB_PLATFORM_WIN32)
	#define REG8(X)	Reg8.##X
#else
	#define REG8(X)	Reg8.X
#endif

#define RLC(X)	\
	Reg16.AF &= ~(N_FLAG|H_FLAG); \
	Flags.C = (Reg8.B & 0x80) != 0; \
	REG8(X) = (REG8(X) << 1) | Flags.C; \
	Flags.Z = (REG8(X) == 0);

		switch(t3)
		{
		case 0x00: //RLC B	--8
			RLC(B)
			break;
		case 0x01: //RLC C
			RLC(C)
			break;
		case 0x02: //RLC D
			RLC(D)
			break;
		case 0x03: //RLC E
			RLC(E)
			break;
		case 0x04: //RLC H
			RLC(H)
			break;
		case 0x05: //RLC L
			RLC(L)
			break;
		case 0x06: //RLC (HL)
			Reg16.AF &= ~(N_FLAG|H_FLAG);
			t1 = MemRead8(Reg16.HL);
			Flags.C = (t1 & 0x80) != 0;
			t1 = (t1 << 1) | Flags.C;
			Flags.Z = (t1 == 0);
			MemWrite8(Reg16.HL, t1);
			break;
		case 0x07: //RLC A
			RLC(A)
			break;
			
#define RRC(X)	\
	Reg16.AF &= ~(N_FLAG|H_FLAG); \
	Flags.C = (REG8(X) & 0x01) != 0; \
	REG8(X) = (REG8(X) >> 1) | (Flags.C << 7); \
	Flags.Z = (REG8(X) == 0);

		case 0x08: //RRC B
			RRC(B)
			break;
		case 0x09: //RRC C
			RRC(C)
			break;
		case 0x0A: //RRC D
			RRC(D)
			break;
		case 0x0B: //RRC E
			RRC(E)
			break;
		case 0x0C: //RRC H
			RRC(H)
			break;
		case 0x0D: //RRC L
			RRC(L)
			break;
		case 0x0E: //RRC (HL)
			Reg16.AF &= ~(N_FLAG|H_FLAG);
			t1 = MemRead8(Reg16.HL);
			Flags.C = (t1 & 0x01) != 0;
			t1 = (t1 >> 1) | (Flags.C << 7);
			Flags.Z = (t1 == 0);
			MemWrite8(Reg16.HL, t1);
			break;
		case 0x0F: //RRC A
			RRC(A)
			break;
			
// RL --8
#define RL(X)	\
	Reg16.AF &= ~(N_FLAG|H_FLAG); \
	t1 = Flags.C; \
	Flags.C = (REG8(X) & 0x80) != 0; \
	REG8(X) = (REG8(X) << 1) | t1; \
	Flags.Z = (REG8(X) == 0);

		case 0x10: //RL B
			RL(B)
			break;
		case 0x11: //RL C
			RL(C)
			break;
		case 0x12: //RL D
			RL(D)
			break;
		case 0x13: //RL E
			RL(E)
			break;
		case 0x14: //RL H
			RL(H)
			break;
		case 0x15: //RL L
			RL(L)
			break;
		case 0x16: //RL (HL)
			Reg16.AF &= ~(N_FLAG | H_FLAG);
			t1 = Flags.C; //old carry flag
			t2 = MemRead8(Reg16.HL);
			Flags.C = (t2 & 0x80) != 0;
			t2 = ((t2 << 1) | t1) & 0xFF;
			Flags.Z = (t2 == 0);
			MemWrite8(Reg16.HL, t2);
			break;
		case 0x17: //RL A
			RL(A)
			break;

// RR(X)	--8
#define RR(X)	\
	Reg16.AF &= ~(N_FLAG | H_FLAG); \
	t1 = Flags.C; \
	Flags.C = (REG8(X) & 0x01) != 0; \
	REG8(X) = (REG8(X) >> 1) | (t1 << 7); \
	Flags.Z = (REG8(X) == 0);


		case 0x18: //RR B
			RR(B)
			break;
		case 0x19: //RR C
			RR(C)
			break;
		case 0x1A: //RR D
			RR(D)
			break;
		case 0x1B: //RR E
			RR(E)
			break;
		case 0x1C: //RR H
			RR(H)
			break;
		case 0x1D: //RR L
			RR(L)
			break;
		case 0x1E: //RR (HL)
			Reg16.AF &= ~(N_FLAG | H_FLAG);
			t1 = Flags.C; //old carry flag
			t2 = MemRead8(Reg16.HL);
			Flags.C = (t2 & 0x01) != 0;
			t2 = (t2 >> 1) | (t1 << 7);
			Flags.Z = (t2 == 0);
			MemWrite8(Reg16.HL, t2);
			break;
		case 0x1F: //RR A
			RR(A)
			break;

// SLA B	--8
// Shift n left into Carry. LSB of n set to 0.
#define SLA(X)	\
	Reg16.AF &= ~(N_FLAG | H_FLAG); \
	Flags.C = (REG8(X) & 0x80) != 0; \
	REG8(X) = REG8(X) << 1; \
	Flags.Z = (REG8(X) == 0);

		case 0x20: //SLA B
			SLA(B)
			break;
		case 0x21: //SLA C
			SLA(C)
			break;
		case 0x22: //SLA D
			SLA(D)
			break;
		case 0x23: //SLA E
			SLA(E)
			break;
		case 0x24: //SLA H
			SLA(H)
			break;
		case 0x25: //SLA L
			SLA(L)
			break;
		case 0x26: //SLA (HL)
			Reg16.AF &= ~(N_FLAG|H_FLAG);
			t1 = MemRead8(Reg16.HL);
			Flags.C = (t1 & 0x80) != 0;
			t1 = (t1 << 1) & 0xFF;
			Flags.Z = (t1 == 0);
			MemWrite8(Reg16.HL, t1);
			break;
		case 0x27: //SLA A
			SLA(A)
			break;

// SRA B	--8
// Shift n right into Carry. MSB doesn't change.			
#define SRA(X)	\
	Reg16.AF &= ~(N_FLAG | H_FLAG); \
	Flags.C = (REG8(X) & 0x01) != 0; \
	REG8(X) = (REG8(X) & 0x80) | (REG8(X) >> 1); \
	Flags.Z = (REG8(X) == 0);

		case 0x28: //SRA B
			SRA(B)
			break;
		case 0x29: //SRA C
			SRA(C)
			break;
		case 0x2A: //SRA D
			SRA(D)
			break;
		case 0x2B: //SRA E
			SRA(E)
			break;
		case 0x2C: //SRA H
			SRA(H)
			break;
		case 0x2D: //SRA L
			SRA(L)
			break;
		case 0x2E: //SRA (HL)	--16
			Reg16.AF &= ~(N_FLAG | H_FLAG);
			t1 = MemRead8(Reg16.HL);
			Flags.C = (t1 & 0x01) != 0;
			t1 = (t1 & 0x80) | (t1 >> 1); //MSB doesn't change
			Flags.Z = (t1 == 0);
			MemWrite8(Reg16.HL, t1);
			break;
		case 0x2F: //SRA A
			SRA(A)
			break;

// SWAP B	--8
// Swap upper & lower nibles of n.			
#define SWAP(X)	\
	Reg16.AF &= ~(N_FLAG | H_FLAG | C_FLAG); \
	REG8(X) = ((REG8(X) >> 4) | (REG8(X) << 4)); \
	Flags.Z = (REG8(X) == 0);


		case 0x30: //SWAP B
			SWAP(B)
			break;
		case 0x31: //SWAP C
			SWAP(C)
			break;
		case 0x32: //SWAP D
			SWAP(D)
			break;
		case 0x33: //SWAP E
			SWAP(E)
			break;
		case 0x34: //SWAP H
			SWAP(H)
			break;
		case 0x35: //SWAP L
			SWAP(L)
			break;
		case 0x36: //SWAP (HL)	--16
			Reg16.AF &= ~(N_FLAG | H_FLAG | C_FLAG);
			t1 = MemRead8(Reg16.HL);
			t1 = ((t1 >> 4) | (t1 << 4)) & 0xFF;
			MemWrite8(Reg16.HL,t1);
			Flags.Z = (t1 == 0);
			break;
		case 0x37: //SWAP A
			SWAP(A)
			break;

// SRL B	--8
// Shift n right into Carry. MSB set to 0.
// Z - Set if result is zero.
// N - Reset.
// H - Reset.
// C - Contains old bit 0 data.
#define SRL(X)	\
	Reg16.AF &= ~(N_FLAG | H_FLAG); \
	Flags.C = (REG8(X) & 0x01) != 0; \
	REG8(X) = REG8(X) >> 1; \
	Flags.Z = (REG8(X) == 0);

		case 0x38: //SRL B
			SRL(B)
			break;
		case 0x39: //SRL C
			SRL(C)
			break;
		case 0x3A: //SRL D
			SRL(D)
			break;
		case 0x3B: //SRL E
			SRL(E)
			break;
		case 0x3C: //SRL H
			SRL(H)
			break;
		case 0x3D: //SRL L
			SRL(L)
			break;
		case 0x3E: //SRL (HL)
			Reg16.AF &= ~(N_FLAG | H_FLAG);
			t1 = MemRead8(Reg16.HL);
			Flags.C = (t1 & 0x01) != 0;
			t1 = t1 >> 1;
			Flags.Z = (t1 == 0);
			MemWrite8(Reg16.HL, t1);
			break;
		case 0x3F: //SRL A
			SRL(A)
			break;


// BIT b,r	--8
// Description:
//			Test bit b in register r.
// Use with:    
//			b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
// Flags affected:
//			Z - Set if bit b of register r is 0.
//			N - Reset.
//			H - Set.
//			C - Not affected.
#define BIT_TST(b,X)	\
	Reg16.AF &= ~N_FLAG; \
	Reg16.AF |= H_FLAG; \
	Flags.Z = (REG8(X) & ( 1<<(b) )) == 0;

#define BIT_TST_HL(b)	\
	Reg16.AF &= ~N_FLAG; \
	Reg16.AF |= H_FLAG; \
	Flags.Z = (MemRead8(Reg16.HL) & (1<<b)) == 0;

		case 0x40: //BIT 0,B
			BIT_TST(0,B)
			break;
		case 0x41: //BIT 0,C
			BIT_TST(0,C)
			break;
		case 0x42: //BIT 0,D
			BIT_TST(0,D)
			break;
		case 0x43: //BIT 0,E
			BIT_TST(0,E)
			break;
		case 0x44: //BIT 0,H
			BIT_TST(0,H)
			break;
		case 0x45: //BIT 0,L
			BIT_TST(0,L)
			break;
		case 0x46: //BIT 0,(HL)	--16
			BIT_TST_HL(0)
			break;
		case 0x47: //BIT 0,A
			BIT_TST(0,A)
			break;
			
		case 0x48: //BIT 1,B
			BIT_TST(1,B)
			break;
		case 0x49: //BIT 1,C
			BIT_TST(1,C)
			break;
		case 0x4A: //BIT 1,D
			BIT_TST(1,D)
			break;
		case 0x4B: //BIT 1,E
			BIT_TST(1,E)
			break;
		case 0x4C: //BIT 1,H
			BIT_TST(1,H)
			break;
		case 0x4D: //BIT 1,L
			BIT_TST(1,L)
			break;
		case 0x4E: //BIT 1,(HL)	--16
			BIT_TST_HL(1)
			break;
		case 0x4F: //BIT 1,A
			BIT_TST(1,A)
			break;
		case 0x50: //BIT 2,B
			BIT_TST(2,B)
			break;
		case 0x51: //BIT 2,C
			BIT_TST(2,C)
			break;
		case 0x52: //BIT 2,D
			BIT_TST(2,D)
			break;
		case 0x53: //BIT 2,E
			BIT_TST(2,E)
			break;
		case 0x54: //BIT 2,H
			BIT_TST(2,H)
			break;
		case 0x55: //BIT 2,L
			BIT_TST(2,L)
			break;
		case 0x56: //BIT 2,(HL)
			BIT_TST_HL(2)
			break;
		case 0x57: //BIT 2,A
			BIT_TST(2,A)
			break;
		case 0x58: //BIT 3,B
			BIT_TST(3,B)
			break;
		case 0x59: //BIT 3,C
			BIT_TST(3,C)
			break;
		case 0x5A: //BIT 3,D
			BIT_TST(3,D)
			break;
		case 0x5B: //BIT 3,E
			BIT_TST(3,E)
			break;
		case 0x5C: //BIT 3,H
			BIT_TST(3,H)
			break;
		case 0x5D: //BIT 3,L
			BIT_TST(3,L)
			break;
		case 0x5E: //BIT 3,(HL)
			BIT_TST_HL(3)
			break;
		case 0x5F: //BIT 3,A
			BIT_TST(3,A)
			break;
		case 0x60: //BIT 4,B
			BIT_TST(4,B)
			break;
		case 0x61: //BIT 4,C
			BIT_TST(4,C)
			break;
		case 0x62: //BIT 4,D
			BIT_TST(4,D)
			break;
		case 0x63: //BIT 4,E
			BIT_TST(4,E)
			break;
		case 0x64: //BIT 4,H
			BIT_TST(4,H)
			break;
		case 0x65: //BIT 4,L
			BIT_TST(4,L)
			break;
		case 0x66: //BIT 4,(HL)
			BIT_TST_HL(4)
			break;
		case 0x67: //BIT 4,A
			BIT_TST(4,A)
			break;
		case 0x68: //BIT 5,B
			BIT_TST(5,B)
			break;
		case 0x69: //BIT 5,C
			BIT_TST(5,C)
			break;
		case 0x6A: //BIT 5,D
			BIT_TST(5,D)
			break;
		case 0x6B: //BIT 5,E
			BIT_TST(5,E)
			break;
		case 0x6C: //BIT 5,H
			BIT_TST(5,H)
			break;
		case 0x6D: //BIT 5,L
			BIT_TST(5,L)
			break;
		case 0x6E: //BIT 5,(HL)
			BIT_TST_HL(5)
			break;
		case 0x6F: //BIT 5,A
			BIT_TST(5,A)
			break;
		case 0x70: //BIT 6,B
			BIT_TST(6,B)
			break;
		case 0x71: //BIT 6,C
			BIT_TST(6,C)
			break;
		case 0x72: //BIT 6,D
			BIT_TST(6,D)
			break;
		case 0x73: //BIT 6,E
			BIT_TST(6,E)
			break;
		case 0x74: //BIT 6,H
			BIT_TST(6,H)
			break;
		case 0x75: //BIT 6,L
			BIT_TST(6,L)
			break;
		case 0x76: //BIT 6,(HL)
			BIT_TST_HL(6)
			break;
		case 0x77: //BIT 6,A
			BIT_TST(6,A)
			break;
		case 0x78: //BIT 7,B
			BIT_TST(7,B)
			break;
		case 0x79: //BIT 7,C
			BIT_TST(7,C)
			break;
		case 0x7A: //BIT 7,D
			BIT_TST(7,D)
			break;
		case 0x7B: //BIT 7,E
			BIT_TST(7,E)
			break;
		case 0x7C: //BIT 7,H
			BIT_TST(7,H)
			break;
		case 0x7D: //BIT 7,L
			BIT_TST(7,L)
			break;
		case 0x7E: //BIT 7,(HL)
			BIT_TST_HL(7)
			break;
		case 0x7F: //BIT 7,A
			BIT_TST(7,A)
			break;


// RES b,r	--8(16)
// Description:
//			Reset bit b in register r.
// Use with:    
//			b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
// Flags affected:
//			None.
#define RES(b,X)	REG8(X) &= ~(1 << b);
#define RES_HL(b)	MemWrite8(Reg16.HL, MemRead8(Reg16.HL) & (~(1 << b)));
			
		case 0x80: //RES 0,B
			RES(0,B)
			break;
		case 0x81: //RES 0,C
			RES(0,C)
			break;
		case 0x82: //RES 0,D
			RES(0,D)
			break;
		case 0x83: //RES 0,E
			RES(0,E)
			break;
		case 0x84: //RES 0,H
			RES(0,H)
			break;
		case 0x85: //RES 0,L
			RES(0,H)
			break;
		case 0x86: //RES 0,(HL)
			RES_HL(0)
			break;
		case 0x87: //RES 0,A
			RES(0,A)
			break;
		case 0x88: //RES 1,B
			RES(1,B)
			break;
		case 0x89: //RES 1,C
			RES(1,C)
			break;
		case 0x8A: //RES 1,D
			RES(1,D)
			break;
		case 0x8B: //RES 1,E
			RES(1,E)
			break;
		case 0x8C: //RES 1,H
			RES(1,H)
			break;
		case 0x8D: //RES 1,L
			RES(1,L)
			break;
		case 0x8E: //RES 1,(HL)
			RES_HL(1)
			break;
		case 0x8F: //RES 1,A
			RES(1,A)
			break;
		case 0x90: //RES 2,B
			RES(2,B)
			break;
		case 0x91: //RES 2,C
			RES(2,C)
			break;
		case 0x92: //RES 2,D
			RES(2,D)
			break;
		case 0x93: //RES 2,E
			RES(2,E)
			break;
		case 0x94: //RES 2,H
			RES(2,H)
			break;
		case 0x95: //RES 2,L
			RES(2,L)
			break;
		case 0x96: //RES 2,(HL)
			RES_HL(2)
			break;
		case 0x97: //RES 2,A
			RES(2,A)
			break;
		case 0x98: //RES 3,B
			RES(3,B)
			break;
		case 0x99: //RES 3,C
			RES(3,C)
			break;
		case 0x9A: //RES 3,D
			RES(3,D)
			break;
		case 0x9B: //RES 3,E
			RES(3,E)
			break;
		case 0x9C: //RES 3,H
			RES(3,H)
			break;
		case 0x9D: //RES 3,L
			RES(3,L)
			break;
		case 0x9E: //RES 3,(HL)
			RES_HL(3)
			break;
		case 0x9F: //RES 3,A
			RES(3,A)
			break;
		case 0xA0: //RES 4,B
			RES(4,B)
			break;
		case 0xA1: //RES 4,C
			RES(4,C)
			break;
		case 0xA2: //RES 4,D
			RES(4,D)
			break;
		case 0xA3: //RES 4,E
			RES(4,E)
			break;
		case 0xA4: //RES 4,H
			RES(4,H)
			break;
		case 0xA5: //RES 4,L
			RES(4,L)
			break;
		case 0xA6: //RES 4,(HL)
			RES_HL(4)
			break;
		case 0xA7: //RES 4,A
			RES(4,A)
			break;
		case 0xA8: //RES 5,B
			RES(5,B)
			break;
		case 0xA9: //RES 5,C
			RES(5,C)
			break;
		case 0xAA: //RES 5,D
			RES(5,D)
			break;
		case 0xAB: //RES 5,E
			RES(5,E)
			break;
		case 0xAC: //RES 5,H
			RES(5,H)
			break;
		case 0xAD: //RES 5,L
			RES(5,L)
			break;
		case 0xAE: //RES 5,(HL)
			RES_HL(5)
			break;
		case 0xAF: //RES 5,A
			RES(5,A)
			break;
		case 0xB0: //RES 6,B
			RES(6,B)
			break;
		case 0xB1: //RES 6,C
			RES(6,C)
			break;
		case 0xB2: //RES 6,D
			RES(6,D)
			break;
		case 0xB3: //RES 6,E
			RES(6,E)
			break;
		case 0xB4: //RES 6,H
			RES(6,H)
			break;
		case 0xB5: //RES 6,L
			RES(6,L)
			break;
		case 0xB6: //RES 6,(HL)
			RES_HL(6)
			break;
		case 0xB7: //RES 6,A
			RES(6,A)
			break;
		case 0xB8: //RES 7,B
			RES(7,B)
			break;
		case 0xB9: //RES 7,C
			RES(7,C)
			break;
		case 0xBA: //RES 7,D
			RES(7,D)
			break;
		case 0xBB: //RES 7,E
			RES(7,E)
			break;
		case 0xBC: //RES 7,H
			RES(7,H)
			break;
		case 0xBD: //RES 7,L
			RES(7,L)
			break;
		case 0xBE: //RES 7,(HL)
			RES_HL(7)
			break;
		case 0xBF: //RES 7,A
			RES(7,A)
			break;


// SET b,r
// Description:
//			Set bit b in register r.
// Use with:    
//			b = 0 - 7, r = A,B,C,D,E,H,L,(HL)
// Flags affected:
//			None.
#define SET(b,X)	REG8(X) |= (1 << b);
#define SET_HL(b)	MemWrite8(Reg16.HL, MemRead8(Reg16.HL) | (1 << b));

		case 0xC0: //SET 0,B
			SET(0,B)
			break;
		case 0xC1: //SET 0,C
			SET(0,C)
			break;
		case 0xC2: //SET 0,D
			SET(0,D)
			break;
		case 0xC3: //SET 0,E
			SET(0,E)
			break;
		case 0xC4: //SET 0,H
			SET(0,H)
			break;
		case 0xC5: //SET 0,L
			SET(0,L)
			break;
		case 0xC6: //SET 0,(HL)
			SET_HL(0)
			break;
		case 0xC7: //SET 0,A
			SET(0,A)
			break;
		case 0xC8: //SET 1,B
			SET(1,B)
			break;
		case 0xC9: //SET 1,C
			SET(1,C)
			break;
		case 0xCA: //SET 1,D
			SET(1,D)
			break;
		case 0xCB: //SET 1,E
			SET(1,E)
			break;
		case 0xCC: //SET 1,H
			SET(1,H)
			break;
		case 0xCD: //SET 1,L
			SET(1,L)
			break;
		case 0xCE: //SET 1,(HL)
			SET_HL(1)
			break;
		case 0xCF: //SET 1,A
			SET(1,A)
			break;
		case 0xD0: //SET 2,B
			SET(2,B)
			break;
		case 0xD1: //SET 2,C
			SET(2,C)
			break;
		case 0xD2: //SET 2,D
			SET(2,D)
			break;
		case 0xD3: //SET 2,E
			SET(2,E)
			break;
		case 0xD4: //SET 2,H
			SET(2,H)
			break;
		case 0xD5: //SET 2,L
			SET(2,L)
			break;
		case 0xD6: //SET 2,(HL)
			SET_HL(2)
			break;
		case 0xD7: //SET 2,A
			SET(2,A)
			break;
		case 0xD8: //SET 3,B
			SET(3,B)
			break;
		case 0xD9: //SET 3,C
			SET(3,C)
			break;
		case 0xDA: //SET 3,D
			SET(3,D)
			break;
		case 0xDB: //SET 3,E
			SET(3,E)
			break;
		case 0xDC: //SET 3,H
			SET(3,H)
			break;
		case 0xDD: //SET 3,L
			SET(3,L)
			break;
		case 0xDE: //SET 3,(HL)
			SET_HL(3)
			break;
		case 0xDF: //SET 3,A
			SET(3,A)
			break;
		case 0xE0: //SET 4,B
			SET(4,B)
			break;
		case 0xE1: //SET 4,C
			SET(4,C)
			break;
		case 0xE2: //SET 4,D
			SET(4,D)
			break;
		case 0xE3: //SET 4,E
			SET(4,E)
			break;
		case 0xE4: //SET 4,H
			SET(4,H)
			break;
		case 0xE5: //SET 4,L
			SET(4,L)
			break;
		case 0xE6: //SET 4,(HL)
			SET_HL(4)
			break;
		case 0xE7: //SET 4,A
			SET(4,A)
			break;
		case 0xE8: //SET 5,B
			SET(5,B)
			break;
		case 0xE9: //SET 5,C
			SET(5,C)
			break;
		case 0xEA: //SET 5,D
			SET(5,D)
			break;
		case 0xEB: //SET 5,E
			SET(5,E)
			break;
		case 0xEC: //SET 5,H
			SET(5,H)
			break;
		case 0xED: //SET 5,L
			SET(5,L)
			break;
		case 0xEE: //SET 5,(HL)
			SET_HL(5)
			break;
		case 0xEF: //SET 5,A
			SET(5,A)
			break;
		case 0xF0: //SET 6,B
			SET(6,B)
			break;
		case 0xF1: //SET 6,C
			SET(6,C)
			break;
		case 0xF2: //SET 6,D
			SET(6,D)
			break;
		case 0xF3: //SET 6,E
			SET(6,E)
			break;
		case 0xF4: //SET 6,H
			SET(6,H)
			break;
		case 0xF5: //SET 6,L
			SET(6,L)
			break;
		case 0xF6: //SET 6,(HL)
			SET_HL(6)
			break;
		case 0xF7: //SET 6,A
			SET(6,A)
			break;
		case 0xF8: //SET 7,B
			SET(7,B)
			break;
		case 0xF9: //SET 7,C
			SET(7,C)
			break;
		case 0xFA: //SET 7,D
			SET(7,D)
			break;
		case 0xFB: //SET 7,E
			SET(7,E)
			break;
		case 0xFC: //SET 7,H
			SET(7,H)
			break;
		case 0xFD: //SET 7,L
			SET(7,L)
			break;
		case 0xFE: //SET 7,(HL)
			SET_HL(7)
			break;
		case 0xFF: //SET 7,A
			SET(7,A)
			break;
		default:
			// impossible
			break;
		} //CB prefix end switch

		AddClock(LUT_Clocks_CB[t3] >> m_nDoubleSpeed);
		return; //CB Opcode end
		
	case 0xCC: //CALL Z,nn	--12
		if(Flags.Z == 1) //if Z flag is set, then Call.
		{
			Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
			MemWrite16(Reg16.SP,Reg16.PC+2);
			Reg16.PC = MemRead16(Reg16.PC);
			AddClock(24 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC  += 2;
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xCD: //CALL nn	--12
		// Push address of next instruction onto stack and then 
		// jump to address nn.
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC+2); 
		Reg16.PC = MemRead16(Reg16.PC);
		break;
	case 0xCE: //ADC A,n
		Reg16.AF &= ~N_FLAG;
		t1 = MemRead8(Reg16.PC++);
		t2 = Reg8.A + t1 + Flags.C;
		Flags.H = ( ((Reg8.A & 0xF) + (t1 & 0xF) ) + Flags.C) > 0xF;
		Flags.C = (t2 > 0xFF);
		Reg8.A = (t2 & 0xFF);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xCF: //RST 0x08	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0008;
		break;
	case 0xD0: //RET NC	--8
		if(Flags.C == 0)
		{
			Reg16.PC = MemRead16(Reg16.SP);
			Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
			AddClock(20 >> m_nDoubleSpeed);
		}
		else
		{
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0xD1: //POP DE	--12
		Reg16.DE = MemRead16(Reg16.SP);
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		break;
	case 0xD2: //JP NC,nn	--12
		if(Flags.C == 0) // if C flag is reset, then jump.
		{
			Reg16.PC =  MemRead16(Reg16.PC);
			AddClock(16 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC += 2;
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xD3:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. D3\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xD4: //CALL NC,nn	--12
		if(Flags.C == 0) // if C flag is reset, then Call.
		{
			Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
			MemWrite16(Reg16.SP, Reg16.PC+2);
			Reg16.PC = MemRead16(Reg16.PC);
			AddClock(24 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC  += 2;
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xD5: //PUSH DE	--16
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.DE);
		break;
	case 0xD6:  //SUB n	--8
		t1 = MemRead8(Reg16.PC++);
		Reg16.AF |= N_FLAG;
		Flags.H = (Reg8.A & 0xF) < (t1 & 0xF);
		Flags.C = (u32)Reg8.A < t1;
		Reg8.A -= t1;
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xD7: //RST 0x10	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0010;
		break;
	case 0xD8: //RET C	--8
		if(Flags.C == 1) // if C flag is set, then return.
		{
			Reg16.PC = MemRead16(Reg16.SP);
			Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
			
			AddClock(20 >> m_nDoubleSpeed);
		}
		else
		{
			AddClock(8 >> m_nDoubleSpeed);
		}
		return;
	case 0xD9: //RETI
		Reg16.PC = MemRead16(Reg16.SP);
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		//GameBoy.Memory.InterruptMasterEnable = 1;
		m_pMachine->IME(true);
		break;
	case 0xDA: //JP C,nn	--12
		if(Flags.C == 1)
		{
			Reg16.PC = MemRead16(Reg16.PC);
			
			AddClock(16 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC += 2;
			
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
		
	case 0xDB:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. DB\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
		
	case 0xDC: //CALL C,nn	--12
		if(Flags.C == 1)
		{
			Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
			MemWrite16(Reg16.SP, Reg16.PC+2);
			Reg16.PC = MemRead16(Reg16.PC);
			
			AddClock(24 >> m_nDoubleSpeed);
		}
		else
		{
			Reg16.PC  += 2;
			
			AddClock(12 >> m_nDoubleSpeed);
		}
		return;
	case 0xDD:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. DD\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xDE: //SBC A,n	--??
		t2 = MemRead8(Reg16.PC++);
		t1 = Reg8.A - t2 - ((Reg8.F & C_FLAG) ? 1 : 0);
		Reg8.F = ((t1 & ~0xFF) ? C_FLAG : 0) | ((t1 & 0xFF) ? 0 : Z_FLAG) | N_FLAG;
		Flags.H = ( (Reg8.A ^ t2 ^ t1) & 0x10 ) != 0 ;
		Reg8.A = t1;
		break;
	case 0xDF: //RST 0x18	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0018;
		break;

	case 0xE0: //LDH (n),A	--12
		MemWrite8(0xFF00 + (u32)MemRead8(Reg16.PC++), Reg8.A);
		break;
	case 0xE1: //POP HL	--12
		Reg16.HL = MemRead16(Reg16.SP);
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		break;
	case 0xE2: //LD (C),A	--8
		MemWrite8(0xFF00 + (u32)Reg8.C, Reg8.A);
		break;
	case 0xE3:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. E3\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xE4:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. E4\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xE5: //PUSH HL	--16
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.HL);
		break;
	case 0xE6: //AND n	--8
		Reg16.AF &= ~(N_FLAG | C_FLAG);
		Reg16.AF |= H_FLAG;
		Reg8.A &= MemRead8(Reg16.PC++);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xE7: //RST 0x20	--32
		Reg16.SP = (Reg16.SP- 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0020;
		break;
	case 0xE8: //ADD SP,n	--16
		t1 = ( MemRead8(Reg16.PC++) ^ 0x80) - 0x80; //expand sign
		Reg8.F = 0;
		Flags.C = ( (Reg16.SP + t1) > 0xFFFF);
		Flags.H = ( ( (Reg16.SP & 0x000F) + (t1 & 0x000F) ) > 0x000F );
		Reg16.SP = (Reg16.SP + t1) & 0xFFFF;
		break;
	case 0xE9: //JP HL	--4
		Reg16.PC = Reg16.HL; 
		break;
	case 0xEA: //LD (nn),A	--16
		MemWrite8(MemRead16(Reg16.PC), Reg8.A);
		Reg16.PC += 2;
		break;
	case 0xEB:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. EB\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xEC:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. EC\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xED:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. ED\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xEE: //XOR n	--8
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A ^= MemRead8(Reg16.PC++);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xEF: //RST 0x28	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0028;
		break;

	case 0xF0: //LDH A,(n)	--12
		Reg8.A = MemRead8(0xFF00 + (u32)MemRead8(Reg16.PC++));
		break;
	case 0xF1: //POP AF	--12
		Reg16.AF = MemRead16(Reg16.SP) & 0xFFF0;
		Reg16.SP = (Reg16.SP + 2) & 0xFFFF;
		break;
	case 0xF2: //LD A,(C)	--8
		Reg8.A = MemRead8(0xFF00 + (u32)Reg8.C);
		break;
	case 0xF3: //DI	--4
		//GameBoy.Memory.InterruptMasterEnable = 0; //@@@@@@@@@@
		//GameBoy.Memory.interrupts_enable_count = 0; //@@@@@@@@@@
		interrupts_enable_count = 0;
		m_pMachine->IME(false);
		break;
	case 0xF4:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. F4\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xF5: //PUSH AF	--16
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.AF);
		break;
	case 0xF6: //OR n	--8
		Reg16.AF &= ~(N_FLAG | C_FLAG | H_FLAG);
		Reg8.A |= MemRead8(Reg16.PC++);
		Flags.Z = (Reg8.A == 0);
		break;
	case 0xF7: //RST 0x30	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0030;
		break;
	case 0xF8: //LD HL,SP+n | LDHL SP,n	--12
		t1 = (MemRead8(Reg16.PC++) ^ 0x80) - 0x80; //expand sign
		Reg16.HL = Reg16.SP + t1;
		Reg8.F = 0;
		Flags.C = (Reg16.HL > 0xFFFF);
		Flags.H = ( ( (Reg16.SP & 0x000F) + (t1 & 0x000F) ) > 0x000F );
		Reg16.HL &= 0xFFFF;
		break;
	case 0xF9: //LD SP,HL	--8
		Reg16.SP = Reg16.HL;
		break;
	case 0xFA: //LD A,(nn)	--16
		Reg8.A = MemRead8(MemRead16(Reg16.PC));
		Reg16.PC += 2;
		break;
	case 0xFB: //EI	--4
		//GameBoy.Memory.interrupts_enable_count = 1;
		interrupts_enable_count = 1;
		m_pMachine->IME(true);
		break;
	case 0xFC:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. FC\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xFD:
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. FD\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	case 0xFE: //CP n	--8
		Reg16.AF |= N_FLAG;
		t1 = MemRead8(Reg16.PC++);
		t2 = Reg8.A;
		Flags.H = (t2 & 0xF) < (t1 & 0xF);
		Flags.C = (t2 < t1);
		Flags.Z = (t2 == t1);
		break;
	case 0xFF: //RST 0x38	--32
		Reg16.SP = (Reg16.SP - 2) & 0xFFFF;
		MemWrite16(Reg16.SP, Reg16.PC);
		Reg16.PC = 0x0038;
		break;
	default: //wtf...?
		NMGB_DEBUG_PRINT(NMGB_DEBUG_COLOR_RED,"Unidentified opcode. Out of all instruction.\nPC: %04x\nROM: %d",Reg16.PC,m_pMemory->SelectedROMIndex());
		break;
	}//end switch

	//GB_CPUClock(clocks_table[opcode] >> GameBoy.Emulator.DoubleSpeed);
	AddClock(LUT_Clocks[Opcode]);
}

