GameBoy Emulator 1
Game Boy emulator core and tooling
Loading...
Searching...
No Matches
ProcessingUnit.cpp
1#include "../../../include/ProcessingUnit.hpp"
2#include "../../../include/mmu.hpp"
3#include "../../../include/opcode_table.hpp"
4
5ProcessingUnit::ProcessingUnit(){
6 reset();
7}
8
9void ProcessingUnit::reset(){
10 A = 0x01; F = 0xB0; B = 0x00; C = 0x13; D = 0x00; E = 0xD8; H = 0x01; L = 0x4D;
11 SP = 0xFFFE; PC = 0x0100;
12 IME = false; halt = false;
13}
14
15int ProcessingUnit::step(MMU &mmu) {
16 last_instr_cycles = 0;
17 check_interrupts(mmu);
18 if (last_instr_cycles > 0) return last_instr_cycles;
19
20 if (halt) {
21 return 4;
22 }
23
24 last_pc = PC;
25 const u8 opcode = mmu.read(PC++);
26 try {
27 return instructionTable[opcode](*this, mmu);
28 } catch (...) {
29 // Illegal opcode — treat as NOP and keep going
30 return 4;
31 }
32}
33
34void ProcessingUnit::check_interrupts(MMU &mmu) {
35 u8 if_reg = mmu.read(0xFF0F);
36 u8 ie_reg = mmu.read(0xFFFF);
37 u8 pending = if_reg & ie_reg & 0x1F;
38
39 if (pending > 0) {
40 halt = false;
41 }
42
43 if (!IME || pending == 0) return;
44
45 if (pending & 0x01) execute_interrupt(mmu, 0x0040, 0);
46 else if (pending & 0x02) execute_interrupt(mmu, 0x0048, 1);
47 else if (pending & 0x04) execute_interrupt(mmu, 0x0050, 2);
48 else if (pending & 0x08) execute_interrupt(mmu, 0x0058, 3);
49 else if (pending & 0x10) execute_interrupt(mmu, 0x0060, 4);
50}
51
52void ProcessingUnit::execute_interrupt(MMU &mmu, u16 address, int bit) {
53 IME = false;
54 u8 if_reg = mmu.read(0xFF0F);
55 mmu.write(0xFF0F, if_reg & ~(1 << bit));
56
57 mmu.write(--SP, (PC >> 8) & 0xFF);
58 mmu.write(--SP, PC & 0xFF);
59 PC = address;
60 last_instr_cycles = 20;
61}
62
63void ProcessingUnit::printStatus() const {}
64u16 ProcessingUnit::get_pc() const { return PC; }
65u16 ProcessingUnit::get_sp() const { return SP; }
66void ProcessingUnit::setHalt(bool newValue) { halt = newValue; }
67bool ProcessingUnit::isHalt() const { return halt; }
68void ProcessingUnit::setIME(bool newValue) { IME = newValue; }
69bool ProcessingUnit::getIME() const { return IME; }
70u8& ProcessingUnit::reg(Register r) {
71 switch (r) {
72 case Register::B: return B; case Register::C: return C;
73 case Register::D: return D; case Register::E: return E;
74 case Register::H: return H; case Register::L: return L;
75 case Register::A: return A; case Register::F: return F;
76 }
77 throw std::runtime_error("Invalid register");
78}
79const u8& ProcessingUnit::reg(Register r) const { return const_cast<ProcessingUnit*>(this)->reg(r); }
80u16 ProcessingUnit::inc_pc() { return PC++; }
Definition mmu.hpp:12