From c52aa91f2661c1218db2562772adaa100e544094 Mon Sep 17 00:00:00 2001 From: MadMaurice Date: Fri, 1 Sep 2023 23:19:02 +0200 Subject: [PATCH] Implement everything for Gameboy Doctor --- cartridge/cartridge.h | 16 +++++--- cpu/cpu.cpp | 8 ++++ cpu/cpu.h | 1 + main.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++- memory/bus.cpp | 12 +++--- memory/bus.h | 3 +- memory/register.cpp | 6 +++ memory/register.h | 13 +++++++ 8 files changed, 136 insertions(+), 14 deletions(-) diff --git a/cartridge/cartridge.h b/cartridge/cartridge.h index 2364aaa..90636f0 100644 --- a/cartridge/cartridge.h +++ b/cartridge/cartridge.h @@ -5,10 +5,10 @@ #include enum CartridgeType : u8 { - ROM_ONLY = 0x00, - MBC1 = 0x01, - MBC1_RAM = 0x02, - MBC1_RAM_BATTERY = 0x03, + CT_ROM_ONLY = 0x00, + CT_MBC1 = 0x01, + CT_MBC1_RAM = 0x02, + CT_MBC1_RAM_BATTERY = 0x03, }; class Cartridge { @@ -28,10 +28,14 @@ public: u8 operator[](size_t addr); inline - const char* title() + const char* title() const { return _title; } inline - size_t size() + CartridgeType type() const + { return (CartridgeType)_data[0x147]; } + + inline + size_t size() const { return _size; } }; diff --git a/cpu/cpu.cpp b/cpu/cpu.cpp index 94d9580..11393d9 100644 --- a/cpu/cpu.cpp +++ b/cpu/cpu.cpp @@ -23,6 +23,14 @@ u16 Cpu_state::getAF() (carry ? 0x10 : 0); } +u8 Cpu_state::getF() +{ + return (zero ? 0x80 : 0) | + (subtract ? 0x40 : 0) | + (halfcarry ? 0x20 : 0) | + (carry ? 0x10 : 0); +} + u8& Cpu_state::reg8(Cpu& cpu, u8 idx) { switch(idx) diff --git a/cpu/cpu.h b/cpu/cpu.h index 37ba825..46d749c 100644 --- a/cpu/cpu.h +++ b/cpu/cpu.h @@ -130,6 +130,7 @@ struct Cpu_state { void setAF(u16 v); u16 getAF(); + u8 getF(); u8& reg8(Cpu& cpu, u8 idx); u16& reg16(Cpu& cpu, u8 idx); diff --git a/main.cpp b/main.cpp index d123e09..45625a2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,4 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + int main(int argc, char** argv) { - return 0; + if(argc < 2) + return 1; + + std::ifstream file(argv[1]); + Cartridge cart(file); + + if(cart.type() != CT_MBC1) + return 2; + + RAM wram1(0x1000); + RAM wram2(0x1000); + RAM hram(0x100); + RAM oam(0x100); + + MBC1 mbc1(cart); + + ConstRegister ly_reg(0x90); + + Bus b; + b.map_device(0x0000, 0x7FFF, &mbc1); + b.map_device(0xA000, 0xBFFF, &mbc1, 0xA000); + b.map_device(0xC000, 0xCFFF, &wram1); + b.map_device(0xD000, 0xDFFF, &wram2); + b.map_device(0xE000, 0xFDFF, &wram1); + b.map_device(0xFE00, 0xFE9F, &oam); + b.map_device(0xFF44, 0xFF44, &ly_reg); + b.map_device(0xFF80, 0xFFFE, &hram); + + Cpu cpu(&b); + + BoundRegister ie_mapped(cpu.state.IE); + BoundRegister if_mapped(cpu.state.IF); + b.map_device(0xFFFF, 0xFFFF, &ie_mapped); + b.map_device(0xFF0F, 0xFF0F, &ie_mapped); + + cpu.state.A = 0x1; + cpu.state.carry = true; + cpu.state.halfcarry = true; + cpu.state.subtract = false; + cpu.state.zero = true; + + cpu.state.B = 0x00; + cpu.state.C = 0x13; + cpu.state.D = 0x00; + cpu.state.E = 0xD8; + cpu.state.H = 0x01; + cpu.state.L = 0x4D; + + cpu.state.SP = 0xFFFE; + cpu.state.PC = 0x100; + + const std::chrono::milliseconds delay(1); + + while(!cpu.state.stopped) + { + std::cout + << "A:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.A + << " F:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.getF() + << " B:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.B + << " C:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.C + << " D:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.D + << " E:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.E + << " H:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.H + << " L:" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << (unsigned)cpu.state.L + << " SP:" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << (unsigned)cpu.state.SP + << " PC:" << std::setfill('0') << std::setw(4) << std::hex << std::uppercase << (unsigned)cpu.state.PC + << " PCMEM:" + << std::setw(2) << std::hex << std::uppercase << (unsigned)b.read8(cpu.state.PC) << "," + << std::setw(2) << std::hex << std::uppercase << (unsigned)b.read8(cpu.state.PC+1) << "," + << std::setw(2) << std::hex << std::uppercase << (unsigned)b.read8(cpu.state.PC+2) << "," + << std::setw(2) << std::hex << std::uppercase << (unsigned)b.read8(cpu.state.PC+3) << std::endl; + + cpu.step(); + + std::this_thread::sleep_for(delay); + } + } diff --git a/memory/bus.cpp b/memory/bus.cpp index 2628322..7c8b602 100644 --- a/memory/bus.cpp +++ b/memory/bus.cpp @@ -13,9 +13,9 @@ std::optional Bus::find_entry(u16 addr) return {}; } -void Bus::map_device(u16 start, u16 end, Mem_device* dev) +void Bus::map_device(u16 start, u16 end, Mem_device* dev, u16 offset) { - map.push_back(Bus::MapEntry{ Range(start,end), dev }); + map.push_back(Bus::MapEntry{ Range(start,end), offset, dev }); } void Bus::write8(u16 addr, u8 data) @@ -24,7 +24,7 @@ void Bus::write8(u16 addr, u8 data) if(!mapentry) return; - mapentry->dev->write8(addr - mapentry->range.start, data); + mapentry->dev->write8(addr - mapentry->range.start + mapentry->offset, data); } u8 Bus::read8(u16 addr) @@ -33,19 +33,19 @@ u8 Bus::read8(u16 addr) if(!mapentry) return 0xFFu; - return mapentry->dev->read8(addr - mapentry->range.start); + return mapentry->dev->read8(addr - mapentry->range.start + mapentry->offset); } void Bus::write16(u16 addr, u16 data) { auto mapentry = find_entry(addr); if(!mapentry) return; - mapentry->dev->write16(addr - mapentry->range.start, data); + mapentry->dev->write16(addr - mapentry->range.start + mapentry->offset, data); } u16 Bus::read16(u16 addr) { auto mapentry = find_entry(addr); if(!mapentry) return 0xFFFFu; - return mapentry->dev->read16(addr - mapentry->range.start); + return mapentry->dev->read16(addr - mapentry->range.start + mapentry->offset); } diff --git a/memory/bus.h b/memory/bus.h index eb14c7c..3102942 100644 --- a/memory/bus.h +++ b/memory/bus.h @@ -9,6 +9,7 @@ class Bus : public Mem_device { private: struct MapEntry { Range range; + u16 offset; Mem_device *dev; }; @@ -17,7 +18,7 @@ private: public: Bus(); - void map_device(u16 start, u16 end, Mem_device* dev); + void map_device(u16 start, u16 end, Mem_device* dev, u16 offset = 0x0); virtual void write8(u16 addr, u8 data); virtual u8 read8(u16 addr); diff --git a/memory/register.cpp b/memory/register.cpp index 2dcc64d..a282d0d 100644 --- a/memory/register.cpp +++ b/memory/register.cpp @@ -11,3 +11,9 @@ u8 BoundRegister::read8(u16 addr) if(addr) return 0xFF; return reg; } + +void ConstRegister::write8(u16 addr, u8 data) +{} + +u8 ConstRegister::read8(u16 addr) +{ return value; } diff --git a/memory/register.h b/memory/register.h index 6bbd1cb..5d9c660 100644 --- a/memory/register.h +++ b/memory/register.h @@ -15,3 +15,16 @@ public: virtual void write8(u16 addr, u8 data); virtual u8 read8(u16 addr); }; + +class ConstRegister : public Mem_device { +private: + u8 value; +public: + inline + ConstRegister(u8 value) + : value(value) + {} + + virtual void write8(u16 addr, u8 data); + virtual u8 read8(u16 addr); +};