Basic HUC3 support

This commit is contained in:
Lior Halphon 2016-10-17 18:51:43 +03:00
parent 3fc4fcc538
commit 11f8c41305
4 changed files with 37 additions and 19 deletions

View File

@ -1143,7 +1143,14 @@ static bool mbc(GB_gameboy_t *gb, char *arguments, const debugger_command_t *com
} }
if (cartridge->mbc_type) { if (cartridge->mbc_type) {
GB_log(gb, "MBC%d\n", cartridge->mbc_type); static const char * const mapper_names[] = {
[GB_MBC1] = "MBC1",
[GB_MBC2] = "MBC2",
[GB_MBC3] = "MBC3",
[GB_MBC5] = "MBC5",
[GB_HUC3] = "HUC3",
};
GB_log(gb, "%s\n", mapper_names[cartridge->mbc_type]);
GB_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank); GB_log(gb, "Current mapped ROM bank: %x\n", gb->mbc_rom_bank);
if (cartridge->has_ram) { if (cartridge->has_ram) {
GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank); GB_log(gb, "Current mapped RAM bank: %x\n", gb->mbc_ram_bank);

View File

@ -168,13 +168,13 @@ typedef struct {
GB_MBC1, GB_MBC1,
GB_MBC2, GB_MBC2,
GB_MBC3, GB_MBC3,
GB_MBC4, // Does this exist???
GB_MBC5, GB_MBC5,
GB_HUC3,
} mbc_type; } mbc_type;
enum { enum {
GB_STANDARD_MBC, GB_STANDARD_MBC,
GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */ GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */
GB_CAMERA, /* Not emulated as well */ GB_CAMERA,
} mbc_subtype; } mbc_subtype;
bool has_ram; bool has_ram;
bool has_battery; bool has_battery;
@ -283,6 +283,11 @@ typedef struct GB_gameboy_s {
uint8_t rom_bank_high:1; uint8_t rom_bank_high:1;
uint8_t ram_bank:4; uint8_t ram_bank:4;
} mbc5; } mbc5;
struct {
uint8_t rom_bank;
uint8_t ram_bank;
} huc3;
}; };
uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */ uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */
bool camera_registers_mapped; bool camera_registers_mapped;

View File

@ -6,7 +6,7 @@
const GB_cartridge_t GB_cart_defs[256] = { const GB_cartridge_t GB_cart_defs[256] = {
// From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type // From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type
/* MBC SUBTYPE RAM BAT. RTC RUMB. EXTRA */ /* MBC SUBTYPE RAM BAT. RTC RUMB. EXTRA */
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false, }, // 00h ROM ONLY { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 00h ROM ONLY
{ GB_MBC1 , GB_STANDARD_MBC, false, false, false, false}, // 01h MBC1 { GB_MBC1 , GB_STANDARD_MBC, false, false, false, false}, // 01h MBC1
{ GB_MBC1 , GB_STANDARD_MBC, true , false, false, false}, // 02h MBC1+RAM { GB_MBC1 , GB_STANDARD_MBC, true , false, false, false}, // 02h MBC1+RAM
{ GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY { GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY
@ -17,7 +17,7 @@ const GB_cartridge_t GB_cart_defs[256] = {
{ GB_NO_MBC, GB_STANDARD_MBC, true , false, false, false}, // 08h ROM+RAM { GB_NO_MBC, GB_STANDARD_MBC, true , false, false, false}, // 08h ROM+RAM
{ GB_NO_MBC, GB_STANDARD_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY { GB_NO_MBC, GB_STANDARD_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY
[0xB] = [0xB] =
// Todo: What are these? /* Todo: Not supported yet */
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Ch MMM01+RAM { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Ch MMM01+RAM
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Dh MMM01+RAM+BATTERY { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Dh MMM01+RAM+BATTERY
@ -27,30 +27,25 @@ const GB_cartridge_t GB_cart_defs[256] = {
{ GB_MBC3 , GB_STANDARD_MBC, false, false, false, false}, // 11h MBC3 { GB_MBC3 , GB_STANDARD_MBC, false, false, false, false}, // 11h MBC3
{ GB_MBC3 , GB_STANDARD_MBC, true , false, false, false}, // 12h MBC3+RAM { GB_MBC3 , GB_STANDARD_MBC, true , false, false, false}, // 12h MBC3+RAM
{ GB_MBC3 , GB_STANDARD_MBC, true , true , false, false}, // 13h MBC3+RAM+BATTERY { GB_MBC3 , GB_STANDARD_MBC, true , true , false, false}, // 13h MBC3+RAM+BATTERY
[0x15] =
// Todo: Do these exist?
{ GB_MBC4 , GB_STANDARD_MBC, false, false, false, false}, // 15h MBC4
{ GB_MBC4 , GB_STANDARD_MBC, true , false, false, false}, // 16h MBC4+RAM
{ GB_MBC4 , GB_STANDARD_MBC, true , true , false, false}, // 17h MBC4+RAM+BATTERY
[0x19] = [0x19] =
{ GB_MBC5 , GB_STANDARD_MBC, false, false, false, false}, // 19h MBC5 { GB_MBC5 , GB_STANDARD_MBC, false, false, false, false}, // 19h MBC5
{ GB_MBC5 , GB_STANDARD_MBC, true , false, false, false}, // 1Ah MBC5+RAM { GB_MBC5 , GB_STANDARD_MBC, true , false, false, false}, // 1Ah MBC5+RAM
{ GB_MBC5 , GB_STANDARD_MBC, true , true , false, false}, // 1Bh MBC5+RAM+BATTERY { GB_MBC5 , GB_STANDARD_MBC, true , true , false, false}, // 1Bh MBC5+RAM+BATTERY
/* Todo: Rumble supported yet */
{ GB_MBC5 , GB_STANDARD_MBC, false, false, false, true }, // 1Ch MBC5+RUMBLE { GB_MBC5 , GB_STANDARD_MBC, false, false, false, true }, // 1Ch MBC5+RUMBLE
{ GB_MBC5 , GB_STANDARD_MBC, true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM { GB_MBC5 , GB_STANDARD_MBC, true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM
{ GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY { GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY
[0xFC] = [0xFC] =
// Todo: What are these? { GB_MBC5 , GB_CAMERA , true , true , false, false}, // FCh POCKET CAMERA
{ GB_MBC5 , GB_CAMERA , true, true, false, false}, // FCh POCKET CAMERA { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FDh BANDAI TAMA5 (Todo: Not supported)
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FDh BANDAI TAMA5 { GB_HUC3 , GB_STANDARD_MBC, true , true , false, false}, // FEh HuC3 (Todo: Mapper support only)
{ GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FEh HuC3 { GB_MBC1 , GB_HUC1 , true , true , false, false}, // FFh HuC1+RAM+BATTERY (Todo: No IR bindings)
{ GB_MBC1 , GB_HUC1 , true , true , false, false}, // FFh HuC1+RAM+BATTERY
}; };
void GB_update_mbc_mappings(GB_gameboy_t *gb) void GB_update_mbc_mappings(GB_gameboy_t *gb)
{ {
switch (gb->cartridge_type->mbc_type) { switch (gb->cartridge_type->mbc_type) {
case GB_NO_MBC: case GB_MBC4: return; case GB_NO_MBC: return;
case GB_MBC1: case GB_MBC1:
/* Todo: some obscure behaviors of MBC1 are not supported. See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */ /* Todo: some obscure behaviors of MBC1 are not supported. See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */
if (gb->mbc1.mode == 0) { if (gb->mbc1.mode == 0) {
@ -91,8 +86,12 @@ void GB_update_mbc_mappings(GB_gameboy_t *gb)
gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8); gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8);
gb->mbc_ram_bank = gb->mbc5.ram_bank; gb->mbc_ram_bank = gb->mbc5.ram_bank;
break; break;
case GB_HUC3:
gb->mbc_rom_bank = gb->huc3.rom_bank;
gb->mbc_ram_bank = gb->huc3.ram_bank;
break;
} }
if (gb->mbc_rom_bank == 0 && gb->cartridge_type->mbc_type != GB_MBC5) { if (gb->mbc_rom_bank == 0 && gb->cartridge_type->mbc_type != GB_MBC5 && gb->cartridge_type->mbc_type != GB_HUC3) {
gb->mbc_rom_bank = 1; gb->mbc_rom_bank = 1;
} }
} }

View File

@ -280,7 +280,7 @@ uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr)
static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
{ {
switch (gb->cartridge_type->mbc_type) { switch (gb->cartridge_type->mbc_type) {
case GB_NO_MBC: case GB_MBC4: return; case GB_NO_MBC: return;
case GB_MBC1: case GB_MBC1:
switch (addr & 0xF000) { switch (addr & 0xF000) {
case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
@ -291,7 +291,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
break; break;
case GB_MBC2: case GB_MBC2:
switch (addr & 0xF000) { switch (addr & 0xF000) {
case 0x0000: case 0x1000: if (!(addr & 0x100)) gb->mbc_ram_enable = value == 0xA; break; case 0x0000: case 0x1000: if (!(addr & 0x100)) gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
case 0x2000: case 0x3000: if ( addr & 0x100) gb->mbc2.rom_bank = value; break; case 0x2000: case 0x3000: if ( addr & 0x100) gb->mbc2.rom_bank = value; break;
} }
break; break;
@ -319,6 +319,13 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
break; break;
} }
break; break;
case GB_HUC3:
switch (addr & 0xF000) {
case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
case 0x2000: case 0x3000: gb->huc3.rom_bank = value; break;
case 0x4000: case 0x5000: gb->huc3.ram_bank = value; break;
}
break;
} }
GB_update_mbc_mappings(gb); GB_update_mbc_mappings(gb);
} }