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
This commit is contained in:
Tim Allen 2011-01-06 21:16:07 +11:00
parent 2d49a4408d
commit f0796e546e
17 changed files with 104 additions and 22 deletions

View File

@ -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

View File

@ -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/)

View File

@ -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;

View File

@ -52,6 +52,7 @@ struct Cartridge : property<Cartridge> {
void ram_write(unsigned addr, uint8 data);
void power();
void map();
Cartridge();
~Cartridge();

View File

@ -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

View File

@ -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;

View File

@ -28,6 +28,7 @@ struct CPU : Processor, MMIO {
bool p15;
bool p14;
uint8 joyp;
uint8 mlt_req;
//$ff04 DIV
uint8 div;

View File

@ -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;
}

View File

@ -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;

View File

@ -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 <gameboy/memory/memory.hpp>
#include <gameboy/system/system.hpp>
#include <gameboy/scheduler/scheduler.hpp>
#include <gameboy/memory/memory.hpp>
#include <gameboy/cartridge/cartridge.hpp>
#include <gameboy/cpu/cpu.hpp>
#include <gameboy/lcd/lcd.hpp>

View File

@ -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() {}

View File

@ -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() {

23
gameboy/system/bootrom-dmg.cpp Executable file
View File

@ -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

23
gameboy/system/bootrom-sgb.cpp Executable file
View File

@ -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

View File

@ -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() {

View File

@ -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 <gameboy/interface/interface.hpp>

View File

@ -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();
}
}
}