From f0796e546e3c2077e7deb58c32f5d159acdb7eb4 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 6 Jan 2011 21:16:07 +1100 Subject: [PATCH] Update to release v000r10. byuu says: Changelog: - fixed LYC interrupt at LY=0 (fixes Makai Toushi SaGa) - fixed MBC3 ROM bank mapping (fixes Harvest Moon GBC) - added Super Game Boy MLT_REQ support to JOYP, needed for ICD2-R emulation - temporarily changed System::run() to execute only four cycles before exiting for bsnes, will make two versions later - uses actual boot ROMs, has DMG+SGB1 for now. Need SGB2, don't care about CGB. Defaults to SGB1, no way to select just yet. DMG 4-second wait is annoying. Does not force games to act like SGB on bgameboy itself, because that has no ICD2 and fails the required MLT_REQ check --- Makefile | 4 +++- gameboy/Makefile | 5 +---- gameboy/cartridge/cartridge.cpp | 7 ++++--- gameboy/cartridge/cartridge.hpp | 1 + gameboy/cartridge/mbc3/mbc3.cpp | 2 +- gameboy/cpu/cpu.cpp | 7 ++++--- gameboy/cpu/cpu.hpp | 1 + gameboy/cpu/mmio/mmio.cpp | 2 ++ gameboy/cpu/timing/timing.cpp | 3 +++ gameboy/gameboy.hpp | 4 ++-- gameboy/interface/interface.hpp | 2 ++ gameboy/lcd/lcd.cpp | 7 +++---- gameboy/system/bootrom-dmg.cpp | 23 +++++++++++++++++++++++ gameboy/system/bootrom-sgb.cpp | 23 +++++++++++++++++++++++ gameboy/system/system.cpp | 20 ++++++++++++++++++++ gameboy/system/system.hpp | 13 ++++++++++--- ui/main.cpp | 2 +- 17 files changed, 104 insertions(+), 22 deletions(-) create mode 100755 gameboy/system/bootrom-dmg.cpp create mode 100755 gameboy/system/bootrom-sgb.cpp diff --git a/Makefile b/Makefile index e1e5d9e0..64eeb85a 100755 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ c := $(compiler) -std=gnu99 cpp := $(subst cc,++,$(compiler)) -std=gnu++0x flags := -O3 -fomit-frame-pointer -I. link := -objects := +objects := libco # profile-guided instrumentation # flags += -fprofile-generate @@ -44,6 +44,8 @@ compile = \ all: build; +obj/libco.o: libco/libco.c libco/* + include $(gameboy)/Makefile include $(ui)/Makefile diff --git a/gameboy/Makefile b/gameboy/Makefile index b50d3ad4..149614c4 100755 --- a/gameboy/Makefile +++ b/gameboy/Makefile @@ -1,11 +1,8 @@ -gameboy_objects := libco -gameboy_objects += gameboy-system gameboy-scheduler +gameboy_objects := gameboy-system gameboy-scheduler gameboy_objects += gameboy-memory gameboy-cartridge gameboy_objects += gameboy-cpu gameboy-lcd objects += $(gameboy_objects) -obj/libco.o: libco/libco.c libco/* - obj/gameboy-system.o: $(gameboy)/system/system.cpp $(call rwildcard,$(gameboy)/system/) obj/gameboy-scheduler.o: $(gameboy)/scheduler/scheduler.cpp $(call rwildcard,$(gameboy)/scheduler/) obj/gameboy-cartridge.o: $(gameboy)/cartridge/cartridge.cpp $(call rwildcard,$(gameboy)/cartridge/) diff --git a/gameboy/cartridge/cartridge.cpp b/gameboy/cartridge/cartridge.cpp index 6e79803b..7939d68c 100755 --- a/gameboy/cartridge/cartridge.cpp +++ b/gameboy/cartridge/cartridge.cpp @@ -64,7 +64,7 @@ void Cartridge::load(uint8_t *data, unsigned size) { case 0xfe: info.mapper = Mapper::HuC3; break; case 0xff: info.mapper = Mapper::HuC1; info.ram = true; info.battery = true; break; } - print("Mapper: ", hex<2>(romdata[0x0147]), "\n"); +//print("Mapper: ", hex<2>(romdata[0x0147]), "\n"); switch(romdata[0x0148]) { default: case 0x00: info.romsize = 2 * 16 * 1024; break; @@ -103,8 +103,6 @@ void Cartridge::unload() { } uint8 Cartridge::rom_read(unsigned addr) { -//if(addr >= 0x028000) print(hex<6>(addr), " - ", romsize, "\n"); - if(addr >= romsize) addr %= romsize; return romdata[addr]; } @@ -135,7 +133,10 @@ void Cartridge::power() { mmm01.power(); huc1.power(); huc3.power(); + map(); +} +void Cartridge::map() { MMIO *mapper = 0; switch(info.mapper) { default: case Mapper::MBC0: mapper = &mbc0; break; diff --git a/gameboy/cartridge/cartridge.hpp b/gameboy/cartridge/cartridge.hpp index 633a947f..fc0cb15f 100755 --- a/gameboy/cartridge/cartridge.hpp +++ b/gameboy/cartridge/cartridge.hpp @@ -52,6 +52,7 @@ struct Cartridge : property { void ram_write(unsigned addr, uint8 data); void power(); + void map(); Cartridge(); ~Cartridge(); diff --git a/gameboy/cartridge/mbc3/mbc3.cpp b/gameboy/cartridge/mbc3/mbc3.cpp index 709970dc..de7701ea 100755 --- a/gameboy/cartridge/mbc3/mbc3.cpp +++ b/gameboy/cartridge/mbc3/mbc3.cpp @@ -24,7 +24,7 @@ uint8 Cartridge::MBC3::mmio_read(uint16 addr) { } if((addr & 0xc000) == 0x4000) { //4000-7fff - return cartridge.rom_read((rom_select << 13) | (addr & 0x3fff)); + return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff)); } if((addr & 0xe000) == 0xa000) { //a000-bfff diff --git a/gameboy/cpu/cpu.cpp b/gameboy/cpu/cpu.cpp index 6978f965..5e00802f 100755 --- a/gameboy/cpu/cpu.cpp +++ b/gameboy/cpu/cpu.cpp @@ -82,9 +82,9 @@ void CPU::power() { for(unsigned n = 0; n < 8192; n++) wram[n] = 0x00; for(unsigned n = 0; n < 128; n++) hram[n] = 0x00; - r[PC] = 0x0100; - r[SP] = 0xfffe; - r[AF] = 0x0100; + r[PC] = 0x0000; + r[SP] = 0x0000; + r[AF] = 0x0000; r[BC] = 0x0000; r[DE] = 0x0000; r[HL] = 0x0000; @@ -102,6 +102,7 @@ void CPU::power() { status.p15 = 0; status.p14 = 0; status.joyp = 0; + status.mlt_req = 0; status.div = 0; diff --git a/gameboy/cpu/cpu.hpp b/gameboy/cpu/cpu.hpp index 23b632da..50ad7264 100755 --- a/gameboy/cpu/cpu.hpp +++ b/gameboy/cpu/cpu.hpp @@ -28,6 +28,7 @@ struct CPU : Processor, MMIO { bool p15; bool p14; uint8 joyp; + uint8 mlt_req; //$ff04 DIV uint8 div; diff --git a/gameboy/cpu/mmio/mmio.cpp b/gameboy/cpu/mmio/mmio.cpp index 610474b9..1e02bd66 100755 --- a/gameboy/cpu/mmio/mmio.cpp +++ b/gameboy/cpu/mmio/mmio.cpp @@ -14,6 +14,7 @@ void CPU::mmio_joyp_poll() { dpad |= system.interface->input_poll((unsigned)Input::Right) << 0; status.joyp = 0x0f; + if(status.p15 == 1 && status.p14 == 1) status.joyp -= status.mlt_req; if(status.p15 == 0) status.joyp &= button ^ 0x0f; if(status.p14 == 0) status.joyp &= dpad ^ 0x0f; if(status.joyp != 0x0f) interrupt_raise(Interrupt::Joypad); @@ -74,6 +75,7 @@ void CPU::mmio_write(uint16 addr, uint8 data) { if(addr == 0xff00) { //JOYP status.p15 = data & 0x20; status.p14 = data & 0x10; + system.interface->joyp_write(status.p15, status.p14); mmio_joyp_poll(); return; } diff --git a/gameboy/cpu/timing/timing.cpp b/gameboy/cpu/timing/timing.cpp index 987dc9ea..3a400d06 100755 --- a/gameboy/cpu/timing/timing.cpp +++ b/gameboy/cpu/timing/timing.cpp @@ -13,6 +13,9 @@ #include "opcode.cpp" void CPU::add_clocks(unsigned clocks) { + system.clocks_executed += clocks; + scheduler.exit(); + status.clock += clocks; if(status.clock >= 4 * 1024 * 1024) { status.clock -= 4 * 1024 * 1024; diff --git a/gameboy/gameboy.hpp b/gameboy/gameboy.hpp index 4327602e..4a5e6773 100755 --- a/gameboy/gameboy.hpp +++ b/gameboy/gameboy.hpp @@ -5,7 +5,7 @@ namespace GameBoy { namespace Info { static const char Name[] = "bgameboy"; - static const char Version[] = "000.09"; + static const char Version[] = "000.10"; } } @@ -43,9 +43,9 @@ namespace GameBoy { inline Processor() : thread(0) {} }; + #include #include #include - #include #include #include #include diff --git a/gameboy/interface/interface.hpp b/gameboy/interface/interface.hpp index e43a4a16..372cbd7f 100755 --- a/gameboy/interface/interface.hpp +++ b/gameboy/interface/interface.hpp @@ -1,5 +1,7 @@ class Interface { public: + virtual void joyp_write(bool p15, bool p14) {} + virtual void video_refresh(const uint8_t *data) {} virtual void audio_sample(signed left, signed right) {} virtual void input_poll() {} diff --git a/gameboy/lcd/lcd.cpp b/gameboy/lcd/lcd.cpp index f555e40e..33143362 100755 --- a/gameboy/lcd/lcd.cpp +++ b/gameboy/lcd/lcd.cpp @@ -30,19 +30,18 @@ void LCD::add_clocks(unsigned clocks) { void LCD::scanline() { status.lx -= 456; - status.ly++; + if(++status.ly == 154) frame(); if(status.interrupt_lyc == true) { if(status.ly == status.lyc) cpu.interrupt_raise(CPU::Interrupt::Stat); } + if(status.ly < 144) render(); + if(status.ly == 144) { cpu.interrupt_raise(CPU::Interrupt::Vblank); if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat); } - if(status.ly == 154) frame(); - - if(status.ly < 144) render(); } void LCD::frame() { diff --git a/gameboy/system/bootrom-dmg.cpp b/gameboy/system/bootrom-dmg.cpp new file mode 100755 index 00000000..5fb38844 --- /dev/null +++ b/gameboy/system/bootrom-dmg.cpp @@ -0,0 +1,23 @@ +#ifdef SYSTEM_CPP + +//MD5SUM = 32fbbd84168d3482956eb3c5051637f5 +const uint8_t System::BootROM::dmg[256] = { + 0x31,0xfe,0xff,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb,0x21,0x26,0xff,0x0e, + 0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77,0x77,0x3e,0xfc,0xe0, + 0x47,0x11,0x04,0x01,0x21,0x10,0x80,0x1a,0xcd,0x95,0x00,0xcd,0x96,0x00,0x13,0x7b, + 0xfe,0x34,0x20,0xf3,0x11,0xd8,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9, + 0x3e,0x19,0xea,0x10,0x99,0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20, + 0xf9,0x2e,0x0f,0x18,0xf3,0x67,0x3e,0x64,0x57,0xe0,0x42,0x3e,0x91,0xe0,0x40,0x04, + 0x1e,0x02,0x0e,0x0c,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x0d,0x20,0xf7,0x1d,0x20,0xf2, + 0x0e,0x13,0x24,0x7c,0x1e,0x83,0xfe,0x62,0x28,0x06,0x1e,0xc1,0xfe,0x64,0x20,0x06, + 0x7b,0xe2,0x0c,0x3e,0x87,0xe2,0xf0,0x42,0x90,0xe0,0x42,0x15,0x20,0xd2,0x05,0x20, + 0x4f,0x16,0x20,0x18,0xcb,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17, + 0x05,0x20,0xf5,0x22,0x23,0x22,0x23,0xc9,0xce,0xed,0x66,0x66,0xcc,0x0d,0x00,0x0b, + 0x03,0x73,0x00,0x83,0x00,0x0c,0x00,0x0d,0x00,0x08,0x11,0x1f,0x88,0x89,0x00,0x0e, + 0xdc,0xcc,0x6e,0xe6,0xdd,0xdd,0xd9,0x99,0xbb,0xbb,0x67,0x63,0x6e,0x0e,0xec,0xcc, + 0xdd,0xdc,0x99,0x9f,0xbb,0xb9,0x33,0x3e,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c, + 0x21,0x04,0x01,0x11,0xa8,0x00,0x1a,0x13,0xbe,0x20,0xfe,0x23,0x7d,0xfe,0x34,0x20, + 0xf5,0x06,0x19,0x78,0x86,0x23,0x05,0x20,0xfb,0x86,0x20,0xfe,0x3e,0x01,0xe0,0x50, +}; + +#endif diff --git a/gameboy/system/bootrom-sgb.cpp b/gameboy/system/bootrom-sgb.cpp new file mode 100755 index 00000000..ac58529d --- /dev/null +++ b/gameboy/system/bootrom-sgb.cpp @@ -0,0 +1,23 @@ +#ifdef SYSTEM_CPP + +//MD5SUM = d574d4f9c12f305074798f54c091a8b4 +const uint8_t System::BootROM::sgb[256] = { + 0x31,0xfe,0xff,0x3e,0x30,0xe0,0x00,0xaf,0x21,0xff,0x9f,0x32,0xcb,0x7c,0x20,0xfb, + 0x21,0x26,0xff,0x0e,0x11,0x3e,0x80,0x32,0xe2,0x0c,0x3e,0xf3,0xe2,0x32,0x3e,0x77, + 0x77,0x3e,0xfc,0xe0,0x47,0x21,0x5f,0xc0,0x0e,0x08,0xaf,0x32,0x0d,0x20,0xfc,0x11, + 0x4f,0x01,0x3e,0xfb,0x0e,0x06,0xf5,0x06,0x00,0x1a,0x1b,0x32,0x80,0x47,0x0d,0x20, + 0xf8,0x32,0xf1,0x32,0x0e,0x0e,0xd6,0x02,0xfe,0xef,0x20,0xea,0x11,0x04,0x01,0x21, + 0x10,0x80,0x1a,0xcd,0xd3,0x00,0xcd,0xd4,0x00,0x13,0x7b,0xfe,0x34,0x20,0xf3,0x11, + 0xe6,0x00,0x06,0x08,0x1a,0x13,0x22,0x23,0x05,0x20,0xf9,0x3e,0x19,0xea,0x10,0x99, + 0x21,0x2f,0x99,0x0e,0x0c,0x3d,0x28,0x08,0x32,0x0d,0x20,0xf9,0x2e,0x0f,0x18,0xf3, + 0x3e,0x91,0xe0,0x40,0x21,0x00,0xc0,0x0e,0x00,0x3e,0x00,0xe2,0x3e,0x30,0xe2,0x06, + 0x10,0x1e,0x08,0x2a,0x57,0xcb,0x42,0x3e,0x10,0x20,0x02,0x3e,0x20,0xe2,0x3e,0x30, + 0xe2,0xcb,0x1a,0x1d,0x20,0xef,0x05,0x20,0xe8,0x3e,0x20,0xe2,0x3e,0x30,0xe2,0xcd, + 0xc2,0x00,0x7d,0xfe,0x60,0x20,0xd2,0x0e,0x13,0x3e,0xc1,0xe2,0x0c,0x3e,0x07,0xe2, + 0x18,0x3a,0x16,0x04,0xf0,0x44,0xfe,0x90,0x20,0xfa,0x1e,0x00,0x1d,0x20,0xfd,0x15, + 0x20,0xf2,0xc9,0x4f,0x06,0x04,0xc5,0xcb,0x11,0x17,0xc1,0xcb,0x11,0x17,0x05,0x20, + 0xf5,0x22,0x23,0x22,0x23,0xc9,0x3c,0x42,0xb9,0xa5,0xb9,0xa5,0x42,0x3c,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x01,0xe0,0x50, +}; + +#endif diff --git a/gameboy/system/system.cpp b/gameboy/system/system.cpp index 360c4a3b..4e959d4b 100755 --- a/gameboy/system/system.cpp +++ b/gameboy/system/system.cpp @@ -3,8 +3,23 @@ #define SYSTEM_CPP namespace GameBoy { +#include "bootrom-dmg.cpp" +#include "bootrom-sgb.cpp" System system; +uint8 System::mmio_read(uint16 addr) { + if((addr & 0xff00) == 0x0000) { + return BootROM::sgb[addr]; + } + return 0x00; +} + +void System::mmio_write(uint16 addr, uint8 data) { + if(addr == 0xff50) { + if(data == 0x01) cartridge.map(); + } +} + void System::init(Interface *interface_) { interface = interface_; } @@ -15,6 +30,11 @@ void System::power() { cpu.power(); lcd.power(); scheduler.init(); + + for(unsigned n = 0x0000; n <= 0x00ff; n++) bus.mmio[n] = this; + bus.mmio[0xff50] = this; + + system.clocks_executed = 0; } void System::run() { diff --git a/gameboy/system/system.hpp b/gameboy/system/system.hpp index 4bbb7040..7d54d529 100755 --- a/gameboy/system/system.hpp +++ b/gameboy/system/system.hpp @@ -4,14 +4,21 @@ enum class Input : unsigned { Up, Down, Left, Right, B, A, Select, Start, }; -class System { -public: +struct System : MMIO { + struct BootROM { + static const uint8 dmg[256]; + static const uint8 sgb[256]; + } bootROM; + + uint8 mmio_read(uint16 addr); + void mmio_write(uint16 addr, uint8 data); + void init(Interface*); void power(); void run(); -//private: Interface *interface; + unsigned clocks_executed; }; #include diff --git a/ui/main.cpp b/ui/main.cpp index 4fcc6e4c..5aebd270 100755 --- a/ui/main.cpp +++ b/ui/main.cpp @@ -46,7 +46,7 @@ void Application::main(int argc, char **argv) { OS::run(); if(GameBoy::cartridge.loaded()) { - GameBoy::system.run(); + for(unsigned n = 0; n < 1024 * 1024; n++) GameBoy::system.run(); } } }