#include namespace GameBoy { #include "io.cpp" #include "memory.cpp" #include "timing.cpp" #include "serialization.cpp" CPU cpu; auto CPU::Enter() -> void { while(true) scheduler.synchronize(), cpu.main(); } auto CPU::main() -> void { interruptTest(); instruction(); } auto CPU::raise(CPU::Interrupt id) -> void { if(id == Interrupt::Vblank) { status.interruptRequestVblank = 1; if(status.interruptEnableVblank) r.halt = false; } if(id == Interrupt::Stat) { status.interruptRequestStat = 1; if(status.interruptEnableStat) r.halt = false; } if(id == Interrupt::Timer) { status.interruptRequestTimer = 1; if(status.interruptEnableTimer) r.halt = false; } if(id == Interrupt::Serial) { status.interruptRequestSerial = 1; if(status.interruptEnableSerial) r.halt = false; } if(id == Interrupt::Joypad) { status.interruptRequestJoypad = 1; if(status.interruptEnableJoypad) r.halt = r.stop = false; } } auto CPU::interruptTest() -> void { if(!r.ime) return; if(status.interruptRequestVblank && status.interruptEnableVblank) { status.interruptRequestVblank = 0; return interrupt(0x0040); } if(status.interruptRequestStat && status.interruptEnableStat) { status.interruptRequestStat = 0; return interrupt(0x0048); } if(status.interruptRequestTimer && status.interruptEnableTimer) { status.interruptRequestTimer = 0; return interrupt(0x0050); } if(status.interruptRequestSerial && status.interruptEnableSerial) { status.interruptRequestSerial = 0; return interrupt(0x0058); } if(status.interruptRequestJoypad && status.interruptEnableJoypad) { status.interruptRequestJoypad = 0; return interrupt(0x0060); } } auto CPU::stop() -> bool { if(status.speedSwitch) { status.speedSwitch = 0; status.speedDouble ^= 1; if(status.speedDouble == 0) frequency = 4 * 1024 * 1024; if(status.speedDouble == 1) frequency = 8 * 1024 * 1024; return true; } return false; } auto CPU::power() -> void { create(Enter, 4 * 1024 * 1024); LR35902::power(); for(uint n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM for(uint n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror) for(uint n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM bus.mmio[0xff00] = this; //JOYP bus.mmio[0xff01] = this; //SB bus.mmio[0xff02] = this; //SC bus.mmio[0xff04] = this; //DIV bus.mmio[0xff05] = this; //TIMA bus.mmio[0xff06] = this; //TMA bus.mmio[0xff07] = this; //TAC bus.mmio[0xff0f] = this; //IF bus.mmio[0xffff] = this; //IE if(system.cgb()) { bus.mmio[0xff4d] = this; //KEY1 bus.mmio[0xff51] = this; //HDMA1 bus.mmio[0xff52] = this; //HDMA2 bus.mmio[0xff53] = this; //HDMA3 bus.mmio[0xff54] = this; //HDMA4 bus.mmio[0xff55] = this; //HDMA5 bus.mmio[0xff56] = this; //RP bus.mmio[0xff6c] = this; //??? bus.mmio[0xff70] = this; //SVBK bus.mmio[0xff72] = this; //??? bus.mmio[0xff73] = this; //??? bus.mmio[0xff74] = this; //??? bus.mmio[0xff75] = this; //??? bus.mmio[0xff76] = this; //??? bus.mmio[0xff77] = this; //??? } for(auto& n : wram) n = 0x00; for(auto& n : hram) n = 0x00; r[PC] = 0x0000; r[SP] = 0x0000; r[AF] = 0x0000; r[BC] = 0x0000; r[DE] = 0x0000; r[HL] = 0x0000; memory::fill(&status, sizeof(Status)); status.dmaCompleted = true; status.wramBank = 1; } }