Update to release v000r09.

byuu says:

Changelog:
- added skeleton HuC1 (gets to a menu)
- added skeleton HuC3 (gets to a menu, this one is supposedly a lot more
  complex (IR, RTC, etc.))
- added MMM01 emulation
This commit is contained in:
Tim Allen 2011-01-05 20:59:22 +11:00
parent a7ffbd784b
commit 2d49a4408d
9 changed files with 237 additions and 7 deletions

View File

@ -1,5 +1,7 @@
#include <gameboy/gameboy.hpp>
#include <nall/crc32.hpp>
#define CARTRIDGE_CPP
namespace GameBoy {
@ -8,9 +10,15 @@ namespace GameBoy {
#include "mbc2/mbc2.cpp"
#include "mbc3/mbc3.cpp"
#include "mbc5/mbc5.cpp"
#include "mmm01/mmm01.cpp"
#include "huc1/huc1.cpp"
#include "huc3/huc3.cpp"
Cartridge cartridge;
void Cartridge::load(uint8_t *data, unsigned size) {
//uint32_t crc = crc32_calculate(data, size);
//print("CRC32 = ", hex<4>(crc), "\n");
romdata = new uint8[romsize = size];
memcpy(romdata, data, size);
@ -37,6 +45,9 @@ void Cartridge::load(uint8_t *data, unsigned size) {
case 0x06: info.mapper = Mapper::MBC2; info.ram = true; info.battery = true; break;
case 0x08: info.mapper = Mapper::MBC0; info.ram = true; break;
case 0x09: info.mapper = Mapper::MBC0; info.ram = true; info.battery = true; break;
case 0x0b: info.mapper = Mapper::MMM01; break;
case 0x0c: info.mapper = Mapper::MMM01; info.ram = true; break;
case 0x0d: info.mapper = Mapper::MMM01; info.ram = true; info.battery = true; break;
case 0x0f: info.mapper = Mapper::MBC3; info.rtc = true; info.battery = true; break;
case 0x10: info.mapper = Mapper::MBC3; info.rtc = true; info.ram = true; info.battery = true; break;
case 0x11: info.mapper = Mapper::MBC3; break;
@ -48,8 +59,12 @@ void Cartridge::load(uint8_t *data, unsigned size) {
case 0x1c: info.mapper = Mapper::MBC5; info.rumble = true; break;
case 0x1d: info.mapper = Mapper::MBC5; info.rumble = true; info.ram = true; break;
case 0x1e: info.mapper = Mapper::MBC5; info.rumble = true; info.ram = true; info.battery = true; break;
default: print("Unknown mapper: ", hex<2>(romdata[0x0147]), "\n"); break;
case 0xfc: break; //Pocket Camera
case 0xfd: break; //Bandai TAMA5
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");
switch(romdata[0x0148]) { default:
case 0x00: info.romsize = 2 * 16 * 1024; break;
@ -88,6 +103,8 @@ 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];
}
@ -115,14 +132,20 @@ void Cartridge::power() {
mbc2.power();
mbc3.power();
mbc5.power();
mmm01.power();
huc1.power();
huc3.power();
MMIO *mapper = 0;
switch(info.mapper) { default:
case Mapper::MBC0: mapper = &mbc0; break;
case Mapper::MBC1: mapper = &mbc1; break;
case Mapper::MBC2: mapper = &mbc2; break;
case Mapper::MBC3: mapper = &mbc3; break;
case Mapper::MBC5: mapper = &mbc5; break;
case Mapper::MBC0: mapper = &mbc0; break;
case Mapper::MBC1: mapper = &mbc1; break;
case Mapper::MBC2: mapper = &mbc2; break;
case Mapper::MBC3: mapper = &mbc3; break;
case Mapper::MBC5: mapper = &mbc5; break;
case Mapper::MMM01: mapper = &mmm01; break;
case Mapper::HuC1: mapper = &huc1; break;
case Mapper::HuC3: mapper = &huc3; break;
}
if(mapper) {

View File

@ -4,6 +4,9 @@ struct Cartridge : property<Cartridge> {
#include "mbc2/mbc2.hpp"
#include "mbc3/mbc3.hpp"
#include "mbc5/mbc5.hpp"
#include "mmm01/mmm01.hpp"
#include "huc1/huc1.hpp"
#include "huc3/huc3.hpp"
enum Mapper : unsigned {
MBC0,
@ -11,6 +14,9 @@ struct Cartridge : property<Cartridge> {
MBC2,
MBC3,
MBC5,
MMM01,
HuC1,
HuC3,
Unknown,
};

53
gameboy/cartridge/huc1/huc1.cpp Executable file
View File

@ -0,0 +1,53 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::HuC1::mmio_read(uint16 addr) {
if((addr & 0xc000) == 0x0000) { //0000-3fff
return cartridge.rom_read(addr);
}
if((addr & 0xc000) == 0x4000) { //4000-7fff
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
}
if((addr & 0xe000) == 0xa000) { //a000-bfff
if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
return 0x00;
}
return 0x00;
}
void Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) {
if((addr & 0xe000) == 0x0000) { //0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
}
if((addr & 0xe000) == 0x2000) { //2000-3fff
rom_select = data;
return;
}
if((addr & 0xe000) == 0x4000) { //4000-5fff
ram_select = data;
return;
}
if((addr & 0xe000) == 0x6000) { //6000-7fff
//unknown purpose
return;
}
if((addr & 0xe000) == 0xa000) { //a000-bfff
if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
return;
}
}
void Cartridge::HuC1::power() {
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
}
#endif

View File

@ -0,0 +1,9 @@
struct HuC1 : MMIO {
bool ram_enable; //0000-1fff
uint8 rom_select; //2000-3fff
uint8 ram_select; //4000-5fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} huc1;

53
gameboy/cartridge/huc3/huc3.cpp Executable file
View File

@ -0,0 +1,53 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::HuC3::mmio_read(uint16 addr) {
if((addr & 0xc000) == 0x0000) { //0000-3fff
return cartridge.rom_read(addr);
}
if((addr & 0xc000) == 0x4000) { //4000-7fff
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
}
if((addr & 0xe000) == 0xa000) { //a000-bfff
if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
return 0x00;
}
return 0x00;
}
void Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) {
if((addr & 0xe000) == 0x0000) { //0000-1fff
ram_enable = (data & 0x0f) == 0x0a;
return;
}
if((addr & 0xe000) == 0x2000) { //2000-3fff
rom_select = data;
return;
}
if((addr & 0xe000) == 0x4000) { //4000-5fff
ram_select = data;
return;
}
if((addr & 0xe000) == 0x6000) { //6000-7fff
//unknown purpose
return;
}
if((addr & 0xe000) == 0xa000) { //a000-bfff
if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
return;
}
}
void Cartridge::HuC3::power() {
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
}
#endif

View File

@ -0,0 +1,9 @@
struct HuC3 : MMIO {
bool ram_enable; //0000-1fff
uint8 rom_select; //2000-3fff
uint8 ram_select; //4000-5fff
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} huc3;

View File

@ -0,0 +1,65 @@
#ifdef CARTRIDGE_CPP
uint8 Cartridge::MMM01::mmio_read(uint16 addr) {
if((addr & 0x8000) == 0x0000) {
if(rom_mode == 0) return cartridge.rom_read(addr);
}
if((addr & 0xc000) == 0x0000) {
return cartridge.rom_read(0x8000 + (rom_base << 14) + (addr & 0x3fff));
}
if((addr & 0xc000) == 0x4000) {
return cartridge.rom_read(0x8000 + (rom_base << 14) + (rom_select << 14) + (addr & 0x3fff));
}
if((addr & 0xe000) == 0xa000) {
if(ram_enable) return cartridge.ram_read((ram_select << 13) + (addr & 0x1fff));
return 0x00;
}
return 0x00;
}
void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
if((addr & 0xe000) == 0x0000) { //0000-1fff
if(rom_mode == 0) {
rom_mode = 1;
} else {
ram_enable = (data & 0x0f) == 0x0a;
}
}
if((addr & 0xe000) == 0x2000) { //2000-3fff
if(rom_mode == 0) {
rom_base = data & 0x3f;
} else {
rom_select = data;
}
}
if((addr & 0xe000) == 0x4000) { //4000-5fff
if(rom_mode == 1) {
ram_select = data;
}
}
if((addr & 0xe000) == 0x6000) { //6000-7fff
//unknown purpose
}
if((addr & 0xe000) == 0xa000) { //a000-bfff
if(ram_enable) cartridge.ram_write((ram_select << 13) + (addr & 0x1fff), data);
}
}
void Cartridge::MMM01::power() {
rom_mode = 0;
rom_base = 0x00;
ram_enable = false;
rom_select = 0x01;
ram_select = 0x00;
}
#endif

View File

@ -0,0 +1,12 @@
struct MMM01 : MMIO {
bool rom_mode;
uint8 rom_base;
bool ram_enable;
uint8 rom_select;
uint8 ram_select;
uint8 mmio_read(uint16 addr);
void mmio_write(uint16 addr, uint8 data);
void power();
} mmm01;

View File

@ -5,7 +5,7 @@
namespace GameBoy {
namespace Info {
static const char Name[] = "bgameboy";
static const char Version[] = "000.08";
static const char Version[] = "000.09";
}
}