diff --git a/Core/gb.h b/Core/gb.h index 7847f83..75066c0 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -172,6 +172,7 @@ typedef struct { enum { GB_STANDARD_MBC, GB_HUC1, /* Todo: HUC1 features are not emulated. Should be unified with the CGB IR sensor API. */ + GB_CAMERA, /* Not emulated as well */ } mbc_subtype; bool has_ram; bool has_battery; @@ -282,6 +283,7 @@ typedef struct GB_gameboy_s { } mbc5; }; uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */ + bool camera_registers_mapped; ); diff --git a/Core/mbc.c b/Core/mbc.c index ef09575..ddc5a31 100644 --- a/Core/mbc.c +++ b/Core/mbc.c @@ -41,7 +41,7 @@ const GB_cartridge_t GB_cart_defs[256] = { { GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY [0xFC] = // Todo: What are these? - { GB_NO_MBC, GB_STANDARD_MBC, false, false, 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 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FEh HuC3 { GB_MBC1 , GB_HUC1 , true , true , false, false}, // FFh HuC1+RAM+BATTERY diff --git a/Core/memory.c b/Core/memory.c index 9bc8809..f003565 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -74,7 +74,7 @@ static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr) static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) { - if (!gb->mbc_ram_enable || !gb->mbc_ram_size) return 0xFF; + if ((!gb->mbc_ram_enable || !gb->mbc_ram_size) && gb->cartridge_type->mbc_subtype != GB_CAMERA) return 0xFF; if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) { /* RTC read */ @@ -82,6 +82,10 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) return gb->rtc_latched.data[gb->mbc_ram_bank - 8]; } + if (gb->camera_registers_mapped) { + return 0; + } + if (!gb->mbc_ram) { return 0xFF; } @@ -282,7 +286,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) break; case GB_MBC2: switch (addr & 0xF000) { - case 0x0000: case 0x1000: if (!(addr & 0x100)) gb->mbc_ram_enable = value == 10; break; + case 0x0000: case 0x1000: if (!(addr & 0x100)) gb->mbc_ram_enable = value == 0xA; break; case 0x2000: case 0x3000: if ( addr & 0x100) gb->mbc2.rom_bank = value; break; } break; @@ -292,7 +296,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break; case 0x4000: case 0x5000: gb->mbc3.ram_bank = value; break; case 0x6000: case 0x7000: - if (!gb->rtc_latch && (value & 1)) { /* Todo: verify condition is correct*/ + if (!gb->rtc_latch && (value & 1)) { /* Todo: verify condition is correct */ memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real)); } gb->rtc_latch = value & 1; @@ -304,7 +308,10 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break; case 0x2000: gb->mbc5.rom_bank_low = value; break; case 0x3000: gb->mbc5.rom_bank_high = value; break; - case 0x4000: case 0x5000: gb->mbc5.ram_bank = value; break; + case 0x4000: case 0x5000: + gb->mbc5.ram_bank = value; + gb->camera_registers_mapped = (value & 0x10) && gb->cartridge_type->mbc_subtype == GB_CAMERA; + break; } break; } @@ -333,6 +340,10 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; } + if (gb->camera_registers_mapped) { + return; + } + gb->mbc_ram[((addr & 0x1FFF) + gb->mbc_ram_bank * 0x2000) & (gb->mbc_ram_size - 1)] = value; }