diff options
-rw-r--r-- | ops.yaml | 168 |
1 files changed, 150 insertions, 18 deletions
@@ -7754,6 +7754,25 @@ templates: /* mbc1 functions */ /******************/ + static uint32_t + mbc1_rom_get_addr( + gb_t * const ctx, + const uint16_t addr + ) { + // mbc1 rom1 banking (TCAGBD.pdf, 11.2.2) + // A ABBB BBCC CCCC CCCC CCCC + return ( + // A: ram_bank (2 bits, if rom_ram_mode == 0) + (((ctx->mmu.mbc1.rom_ram_mode ? 0 : ctx->mmu.mbc1.ram_bank) & 0x3) << 19) | + + // B: rom_bank (5 bits, low bit set) + (((ctx->mmu.mbc1.rom_bank & 0x1F) | 0x1) << 15) | + + // C: address (14 bits) + ((addr - 0x4000) & 0x3FFF) + ); + } + static uint8_t mbc1_rom_rb( gb_t * const ctx, @@ -7782,24 +7801,9 @@ templates: case 0x6000: case 0x7000: // ROM1 (16k, banked) - { - // mbc1 rom1 banking (TCAGBD.pdf, 11.2.2) - // FIXME: clamp to rom size? - - // A ABBB BBCC CCCC CCCC CCCC - const uint32_t full_addr = ( - // A: ram_bank (2 bits, if rom_ram_mode == 0) - (((ctx->mmu.mbc1.rom_ram_mode ? 0 : ctx->mmu.mbc1.ram_bank) & 0x3) << 19) | - - // B: rom_bank (5 bits, low bit set) - (((ctx->mmu.mbc1.rom_bank & 0x1F) | 0x1) << 15) | - - // C: address (14 bits) - ((addr - 0x4000) & 0x3FFF) - ); - - return ctx->mmu.rom[full_addr]; - } + // FIXME: clamp to rom size? + // mbc1 rom1 banking (TCAGBD.pdf, 11.2.2) + return ctx->mmu.rom[mbc1_rom_get_addr(ctx, addr)]; default: // never reached return 0; @@ -7879,6 +7883,124 @@ templates: } } + /******************/ + /* mbc2 functions */ + /******************/ + + static uint32_t + mbc2_rom_get_addr( + gb_t * const ctx, + const uint16_t addr + ) { + // mbc2 rom1 banking (TCAGBD.pdf, 11.2.3) + + // AA AABB BBBB BBBB BBBB + return ( + // B: rom_bank (4 bits, low bit set) + (((ctx->mmu.mbc2.rom_bank & 0xF) << 13) | + + // C: address (14 bits) + ((addr - 0x4000) & 0x3FFF) + ); + } + + static uint8_t + mbc2_rom_rb( + gb_t * const ctx, + const uint16_t addr + ) { + switch (addr & 0xF000) { + case 0x0000: + // bios memory (maybe) + if (ctx->mmu.in_bios) { + if (addr < 0x100) { + return ctx->mmu.bios[addr]; + } else { + ctx->mmu.in_bios = false; + } + } + + // return ROM0 (16k, always mapped) + return ctx->mmu.rom[addr]; + case 0x1000: + case 0x2000: + case 0x3000: + // ROM0 (16k, always mapped) + return ctx->mmu.rom[addr]; + case 0x4000: + case 0x5000: + case 0x6000: + case 0x7000: + // ROM1 (16k, banked) + // FIXME: clamp to rom size? + return ctx->mmu.rom[mbc2_rom_get_addr(ctx, addr)]; + default: + // never reached + return 0; + } + } + + static void + mbc2_rom_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + switch (addr & 0xF000) { + case 0x0000: + case 0x1000: + if (!(addr & 0x10)) { + // toggle ram_enable + ctx->mmu.mbc2.ram_enable = ((val & 0x0F) == 0x0A); + } + break; + case 0x2000: + case 0x3000: + if (addr & 0x10) { + // set rom bank + ctx->mmu.mbc2.rom_bank = val & 0x0F; + } + break; + default: + // do nothing + break; + } + } + + static uint16_t + mbc2_eram_get_addr( + const gb_t * const ctx, + const uint16_t addr + ) { + return (addr & 0x1FF); + } + + static uint8_t + mbc2_eram_rb( + const gb_t * const ctx, + const uint16_t addr + ) { + if (ctx->mmu.eram && ctx->mmu.mbc2.ram_enable) { + return ctx->mmu.eram[mbc2_eram_get_addr(ctx, addr)] & 0x0F; + } else { + return 0; + } + } + + static void + mbc2_eram_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + if (ctx->mmu.eram && ctx->mmu.mbc2.ram_enable) { + ctx->mmu.eram[mbc2_eram_get_addr(ctx, addr)] = val & 0x0F; + } + } + + /************************/ + /* timer shift function */ + /************************/ static uint8_t timer_get_shift( @@ -8168,6 +8290,8 @@ templates: return ctx->mmu.rom[addr]; case MBC_TYPE_MBC1: return mbc1_rom_rb(ctx, addr); + case MBC_TYPE_MBC2: + return mbc2_rom_rb(ctx, addr); default: // TODO: implement remaining MBC types return 0; @@ -8190,6 +8314,8 @@ templates: switch (rom_get_mbc_type(ctx)) { case MBC_TYPE_MBC1: return mbc1_eram_rb(ctx, addr); + case MBC_TYPE_MBC2: + return mbc2_eram_rb(ctx, addr); case MBC_TYPE_NONE: default: return 0; @@ -8266,6 +8392,9 @@ templates: case MBC_TYPE_MBC1: mbc1_rom_wb(ctx, addr, val); break; + case MBC_TYPE_MBC2: + mbc2_rom_wb(ctx, addr, val); + break; default: // do nothing break; @@ -8291,6 +8420,9 @@ templates: case MBC_TYPE_MBC1: mbc1_eram_wb(ctx, addr, val); break; + case MBC_TYPE_MBC2: + mbc2_eram_wb(ctx, addr, val); + break; case MBC_TYPE_NONE: // TODO: implement remaining mbcs if (ctx->mmu.eram) { |