void Processor::ExecuteOPCode(u8 opcode) { if (opcode == 0xCB) { opcode = FetchOPCode(); u16 opcode_address = PC.GetValue() - 1; if (!m_pMemory->IsDisassembled(opcode_address)) { m_pMemory->Disassemble(opcode_address, kOPCodeCBNames[opcode]); } (this->*m_OPCodesCB[opcode])(); m_iCurrentClockCycles += kOPCodeCBMachineCycles[opcode] * (m_bCGBSpeed ? 2 : 4); } else { u16 opcode_address = PC.GetValue() - 1; if (!m_pMemory->IsDisassembled(opcode_address)) { m_pMemory->Disassemble(opcode_address, kOPCodeNames[opcode]); } (this->*m_OPCodes[opcode])(); if (m_bBranchTaken) { m_bBranchTaken = false; m_iCurrentClockCycles += kOPCodeConditionalsMachineCycles[opcode] * (m_bCGBSpeed ? 2 : 4); } else m_iCurrentClockCycles += kOPCodeMachineCycles[opcode] * (m_bCGBSpeed ? 2 : 4); } }
u8 Processor::Tick() { m_iCurrentClockCycles = 0; if (m_bHalt) { m_iCurrentClockCycles += (m_bCGBSpeed ? 2 : 4); if (m_iUnhaltCycles > 0) { m_iUnhaltCycles -= m_iCurrentClockCycles; if (m_iUnhaltCycles <= 0) { m_iUnhaltCycles = 0; m_bHalt = false; } } if (m_bHalt && (InterruptPending() != None_Interrupt) && (m_iUnhaltCycles == 0)) { m_iUnhaltCycles = (m_bCGBSpeed ? 6 : 12); } } if (!m_bHalt) { ServeInterrupt(InterruptPending()); ExecuteOPCode(FetchOPCode()); } UpdateDelayedInterrupts(); UpdateTimers(); UpdateSerial(); if (m_iIMECycles > 0) { m_iIMECycles -= m_iCurrentClockCycles; if (m_iIMECycles <= 0) { m_iIMECycles = 0; m_bIME = true; } } return m_iCurrentClockCycles; }
u8 Processor::Tick() { m_iCurrentClockCycles = 0; if (m_iAccurateOPCodeState == 0 && m_bHalt) { m_iCurrentClockCycles += AdjustedCycles(4); if (m_iUnhaltCycles > 0) { m_iUnhaltCycles -= m_iCurrentClockCycles; if (m_iUnhaltCycles <= 0) { m_iUnhaltCycles = 0; m_bHalt = false; } } if (m_bHalt && (InterruptPending() != None_Interrupt) && (m_iUnhaltCycles == 0)) { m_iUnhaltCycles = AdjustedCycles(12); } } if (!m_bHalt) { if (m_iAccurateOPCodeState == 0) ServeInterrupt(InterruptPending()); if (m_bDuringBootROM) { u16 pc_before = PC.GetValue(); ExecuteOPCode(FetchOPCode()); u16 pc_after = PC.GetValue(); if ((pc_before == 0xFE) && (pc_after == 0x100)) { m_bEndOfBootROM = true; } } else ExecuteOPCode(FetchOPCode()); } UpdateDelayedInterrupts(); UpdateTimers(); UpdateSerial(); if (m_iAccurateOPCodeState == 0 && m_iIMECycles > 0) { m_iIMECycles -= m_iCurrentClockCycles; if (m_iIMECycles <= 0) { m_iIMECycles = 0; m_bIME = true; } } return m_iCurrentClockCycles; }
void Processor::ExecuteOPCode(u8 opcode) { const u8* accurateOPcodes; const u8* machineCycles; OPCptr* opcodeTable; bool isCB = (opcode == 0xCB); if (isCB) { accurateOPcodes = kOPCodeCBAccurate; machineCycles = kOPCodeCBMachineCycles; opcodeTable = m_OPCodesCB; opcode = FetchOPCode(); } else { accurateOPcodes = kOPCodeAccurate; machineCycles = kOPCodeMachineCycles; opcodeTable = m_OPCodes; } if ((accurateOPcodes[opcode] != 0) && (m_iAccurateOPCodeState == 0)) { int left_cycles = (accurateOPcodes[opcode] < 3 ? 2 : 3); m_iCurrentClockCycles += (machineCycles[opcode] - left_cycles) * AdjustedCycles(4); m_iAccurateOPCodeState = 1; PC.Decrement(); if (isCB) PC.Decrement(); return; } #ifdef DEBUG_GEARBOY u16 opcode_address = PC.GetValue() - 1; if (!m_pMemory->IsDisassembled(opcode_address)) { m_pMemory->Disassemble(opcode_address, kOPCodeNames[opcode]); } #endif (this->*opcodeTable[opcode])(); if (m_bBranchTaken) { m_bBranchTaken = false; m_iCurrentClockCycles += kOPCodeBranchMachineCycles[opcode] * AdjustedCycles(4); } else { switch (m_iAccurateOPCodeState) { case 0: m_iCurrentClockCycles += machineCycles[opcode] * AdjustedCycles(4); break; case 1: if (accurateOPcodes[opcode] == 3) { m_iCurrentClockCycles += 1 * AdjustedCycles(4); m_iAccurateOPCodeState = 2; PC.Decrement(); if (isCB) PC.Decrement(); } else { m_iCurrentClockCycles += 2 * AdjustedCycles(4); m_iAccurateOPCodeState = 0; } break; case 2: m_iCurrentClockCycles += 2 * AdjustedCycles(4); m_iAccurateOPCodeState = 0; break; } } }