From d41c188cfd479e01c45ad940e3de4202c205f1b9 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 11 Jun 2022 14:44:06 +0300 Subject: [PATCH] More accurate Camera MBC emulation --- Core/debugger.c | 18 ++++++++------ Core/gb.h | 2 +- Core/mbc.c | 62 ++++++++++++++++++++++++----------------------- Core/mbc.h | 5 +--- Core/memory.c | 15 +++++++++--- Core/save_state.c | 8 ++++++ 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/Core/debugger.c b/Core/debugger.c index 5fa168b..516095a 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -1546,14 +1546,16 @@ static bool mbc(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg } else { static const char *const mapper_names[] = { - [GB_MBC1] = "MBC1", - [GB_MBC2] = "MBC2", - [GB_MBC3] = "MBC3", - [GB_MBC5] = "MBC5", - [GB_MBC7] = "MBC7", - [GB_MMM01] = "MMM01", - [GB_HUC1] = "HUC-1", - [GB_HUC3] = "HUC-3", + [GB_MBC1] = "MBC1", + [GB_MBC2] = "MBC2", + [GB_MBC3] = "MBC3", + [GB_MBC5] = "MBC5", + [GB_MBC7] = "MBC7", + [GB_MMM01] = "MMM01", + [GB_HUC1] = "HUC-1", + [GB_HUC3] = "HUC-3", + [GB_CAMERA] = "MAC-GBD", + }; GB_log(gb, "%s\n", mapper_names[cartridge->mbc_type]); } diff --git a/Core/gb.h b/Core/gb.h index 11f0b3b..1103647 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -466,7 +466,7 @@ struct GB_gameboy_internal_s { uint8_t rom_bank_low; uint8_t rom_bank_high:1; uint8_t ram_bank:4; - } mbc5; + } mbc5; // Also used for GB_CAMERA struct { uint8_t rom_bank; diff --git a/Core/mbc.c b/Core/mbc.c index fe20b28..bb5f917 100644 --- a/Core/mbc.c +++ b/Core/mbc.c @@ -5,41 +5,41 @@ const GB_cartridge_t GB_cart_defs[256] = { // From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type - /* MBC SUBTYPE RAM BAT. RTC RUMB. */ - { 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, true , false, false, false}, // 02h MBC1+RAM - { GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY + /* MBC RAM BAT. RTC RUMB. */ + { GB_NO_MBC, false, false, false, false}, // 00h ROM ONLY + { GB_MBC1 , false, false, false, false}, // 01h MBC1 + { GB_MBC1 , true , false, false, false}, // 02h MBC1+RAM + { GB_MBC1 , true , true , false, false}, // 03h MBC1+RAM+BATTERY [5] = - { GB_MBC2 , GB_STANDARD_MBC, true , false, false, false}, // 05h MBC2 - { GB_MBC2 , GB_STANDARD_MBC, true , true , false, false}, // 06h MBC2+BATTERY + { GB_MBC2 , true , false, false, false}, // 05h MBC2 + { GB_MBC2 , true , true , false, false}, // 06h MBC2+BATTERY [8] = - { 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, true , false, false, false}, // 08h ROM+RAM + { GB_NO_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY [0xB] = - { GB_MMM01 , GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01 - { GB_MMM01 , GB_STANDARD_MBC, true , false, false, false}, // 0Ch MMM01+RAM - { GB_MMM01 , GB_STANDARD_MBC, true , true , false, false}, // 0Dh MMM01+RAM+BATTERY + { GB_MMM01 , false, false, false, false}, // 0Bh MMM01 + { GB_MMM01 , true , false, false, false}, // 0Ch MMM01+RAM + { GB_MMM01 , true , true , false, false}, // 0Dh MMM01+RAM+BATTERY [0xF] = - { GB_MBC3 , GB_STANDARD_MBC, false, true, true , false}, // 0Fh MBC3+TIMER+BATTERY - { GB_MBC3 , GB_STANDARD_MBC, true , true, true , false}, // 10h MBC3+TIMER+RAM+BATTERY - { 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 , true , false, false}, // 13h MBC3+RAM+BATTERY + { GB_MBC3 , false, true, true , false}, // 0Fh MBC3+TIMER+BATTERY + { GB_MBC3 , true , true, true , false}, // 10h MBC3+TIMER+RAM+BATTERY + { GB_MBC3 , false, false, false, false}, // 11h MBC3 + { GB_MBC3 , true , false, false, false}, // 12h MBC3+RAM + { GB_MBC3 , true , true , false, false}, // 13h MBC3+RAM+BATTERY [0x19] = - { 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 , true , false, false}, // 1Bh MBC5+RAM+BATTERY - { 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 , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY + { GB_MBC5 , false, false, false, false}, // 19h MBC5 + { GB_MBC5 , true , false, false, false}, // 1Ah MBC5+RAM + { GB_MBC5 , true , true , false, false}, // 1Bh MBC5+RAM+BATTERY + { GB_MBC5 , false, false, false, true }, // 1Ch MBC5+RUMBLE + { GB_MBC5 , true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM + { GB_MBC5 , true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY [0x22] = - { GB_MBC7 , GB_STANDARD_MBC, true, true, false, false}, // 22h MBC7+ACCEL+EEPROM + { GB_MBC7 , true, true, false, false}, // 22h MBC7+ACCEL+EEPROM [0xFC] = - { 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_HUC3 , GB_STANDARD_MBC, true , true , true, false}, // FEh HuC3 - { GB_HUC1 , GB_STANDARD_MBC, true , true , false, false}, // FFh HuC1+RAM+BATTERY + { GB_CAMERA, true , true , false, false}, // FCh POCKET CAMERA + { GB_NO_MBC, false, false, false, false}, // FDh BANDAI TAMA5 (Todo: Not supported) + { GB_HUC3 , true , true , true, false}, // FEh HuC3 + { GB_HUC1 , true , true , false, false}, // FFh HuC1+RAM+BATTERY }; void GB_update_mbc_mappings(GB_gameboy_t *gb) @@ -96,6 +96,7 @@ void GB_update_mbc_mappings(GB_gameboy_t *gb) } break; case GB_MBC5: + case GB_CAMERA: gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8); gb->mbc_ram_bank = gb->mbc5.ram_bank; break; @@ -185,7 +186,7 @@ void GB_configure_cart(GB_gameboy_t *gb) if (gb->rom[0x147] == 0xBC && gb->rom[0x149] == 0xC1 && gb->rom[0x14A] == 0x65) { - static const GB_cartridge_t tpp1 = {GB_TPP1, GB_STANDARD_MBC, true, true, true, true}; + static const GB_cartridge_t tpp1 = {GB_TPP1, true, true, true, true}; gb->cartridge_type = &tpp1; gb->tpp1.rom_bank = 1; } @@ -255,7 +256,8 @@ void GB_reset_mbc(GB_gameboy_t *gb) gb->mbc_rom_bank = -1; gb->mbc_rom0_bank = -2; } - else if (gb->cartridge_type->mbc_type == GB_MBC5) { + else if (gb->cartridge_type->mbc_type == GB_MBC5 || + gb->cartridge_type->mbc_type == GB_CAMERA) { gb->mbc5.rom_bank_low = 1; gb->mbc_rom_bank = 1; } diff --git a/Core/mbc.h b/Core/mbc.h index c3f6190..8bdb079 100644 --- a/Core/mbc.h +++ b/Core/mbc.h @@ -15,11 +15,8 @@ typedef struct { GB_HUC1, GB_HUC3, GB_TPP1, - } mbc_type; - enum { - GB_STANDARD_MBC, GB_CAMERA, - } mbc_subtype; + } mbc_type; bool has_ram; bool has_battery; bool has_rtc; diff --git a/Core/memory.c b/Core/memory.c index 1d71490..bf7f957 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -383,7 +383,7 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) } } else if ((!gb->mbc_ram_enable) && - gb->cartridge_type->mbc_subtype != GB_CAMERA && + gb->cartridge_type->mbc_type != GB_CAMERA && gb->cartridge_type->mbc_type != GB_HUC1 && gb->cartridge_type->mbc_type != GB_HUC3) { return 0xFF; @@ -414,7 +414,7 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) return 0xFF; } - if (gb->cartridge_type->mbc_subtype == GB_CAMERA && gb->mbc_ram_bank == 0 && addr >= 0xA100 && addr < 0xAF00) { + if (gb->cartridge_type->mbc_type == GB_CAMERA && gb->mbc_ram_bank == 0 && addr >= 0xA100 && addr < 0xAF00) { return GB_camera_read_image(gb, addr - 0xA100); } @@ -827,7 +827,16 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) value &= 7; } gb->mbc5.ram_bank = value; - gb->camera_registers_mapped = (value & 0x10) && gb->cartridge_type->mbc_subtype == GB_CAMERA; + break; + } + break; + case GB_CAMERA: + switch (addr & 0xF000) { + case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; + case 0x2000: case 0x3000: gb->mbc5.rom_bank_low = value; break; + case 0x4000: case 0x5000: + gb->mbc5.ram_bank = value; + gb->camera_registers_mapped = (value & 0x10); break; } break; diff --git a/Core/save_state.c b/Core/save_state.c index ebb3646..20f0eef 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -254,6 +254,8 @@ static size_t bess_size_for_cartridge(const GB_cartridge_t *cart) return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t) + (cart->has_rtc? sizeof(BESS_RTC_t) : 0); case GB_MBC5: return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t); + case GB_CAMERA: + return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t); case GB_MBC7: return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_MBC7_t); case GB_MMM01: @@ -459,6 +461,12 @@ static int save_bess_mbc_block(GB_gameboy_t *gb, virtual_file_t *file) pairs[3] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc5.ram_bank}; mbc_block.size = 4 * sizeof(pairs[0]); break; + case GB_CAMERA: + pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0}; + pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc5.rom_bank_low}; + pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc5.ram_bank}; + mbc_block.size = 3 * sizeof(pairs[0]); + break; case GB_MBC7: pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0}; pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc7.rom_bank};