diff options
-rw-r--r-- | ops.yaml | 195 |
1 files changed, 169 insertions, 26 deletions
@@ -7595,6 +7595,16 @@ templates: const uint8_t *rom; uint32_t rom_size; + union { + struct { + // mbc1 registers + uint8_t rom_bank; + bool ram_enable; + uint8_t ram_bank; + bool rom_ram_mode; + } mbc1; + }; + // enable interrupt flags (addr: 0xFFFF) uint8_t ie; @@ -7645,6 +7655,101 @@ templates: } cpu; } gb_t; + #define CART_TYPE_ROM_ONLY 0x00 + #define CART_TYPE_MBC1 0x01 + #define CART_TYPE_MBC1_RAM 0x02 + #define CART_TYPE_MBC1_RAM_BATTERY 0x03 + #define CART_TYPE_MBC2 0x05 + #define CART_TYPE_MBC2_BATTERY 0x06 + #define CART_TYPE_ROM_RAM 0x08 + #define CART_TYPE_ROM_RAM_BATTERY 0x09 + #define CART_TYPE_MMM01 0x0B + #define CART_TYPE_MMM01_RAM 0x0C + #define CART_TYPE_MMM01_RAM_BATTERY 0x0D + #define CART_TYPE_MBC3_TIMER_BATTERY 0x0F + #define CART_TYPE_MBC3_TIMER_RAM_BATTERY 0x10 + #define CART_TYPE_MBC3 0x11 + #define CART_TYPE_MBC3_RAM 0x12 + #define CART_TYPE_MBC3_RAM_BATTERY 0x13 + #define CART_TYPE_MBC5 0x19 + #define CART_TYPE_MBC5_RAM 0x1A + #define CART_TYPE_MBC5_RAM_BATTERY 0x1B + #define CART_TYPE_MBC5_RUMBLE 0x1C + #define CART_TYPE_MBC5_RUMBLE_RAM 0x1D + #define CART_TYPE_MBC5_RUMBLE_RAM_BATTERY 0x1E + #define CART_TYPE_MBC6 0x20 + #define CART_TYPE_MBC7_SENSOR_RUMBLE_RAM_BATTERY 0x22 + #define CART_TYPE_POCKET_CAMERA 0xFC + #define CART_TYPE_BANDAI_TAMA5 0xFD + #define CART_TYPE_HuC3 0xFE + #define CART_TYPE_HuC1_RAM_BATTERY 0xFF + + static uint8_t + rom_get_cart_type( + const gb_t * const ctx + ) { + return ctx->mmu.rom[0x147]; + } + + #define MBC_TYPE_NONE 0 + #define MBC_TYPE_MBC1 1 + #define MBC_TYPE_MBC2 2 + #define MBC_TYPE_ROM_RAM 3 + #define MBC_TYPE_MMM01 4 + #define MBC_TYPE_MBC3 5 + #define MBC_TYPE_MBC5 6 + #define MBC_TYPE_MBC6 7 + #define MBC_TYPE_MBC7 8 + #define MBC_TYPE_UNKNOWN 9 + + static uint8_t + rom_get_mbc_type( + const gb_t * const ctx + ) { + switch (rom_get_cart_type(ctx)) { + case CART_TYPE_ROM_ONLY: + return MBC_TYPE_NONE; + case CART_TYPE_MBC1: + case CART_TYPE_MBC1_RAM: + case CART_TYPE_MBC1_RAM_BATTERY: + return MBC_TYPE_MBC1; + case CART_TYPE_MBC2: + case CART_TYPE_MBC2_BATTERY: + return MBC_TYPE_MBC2; + case CART_TYPE_ROM_RAM: + case CART_TYPE_ROM_RAM_BATTERY: + return MBC_TYPE_ROM_RAM; + case CART_TYPE_MMM01: + case CART_TYPE_MMM01_RAM: + case CART_TYPE_MMM01_RAM_BATTERY: + return MBC_TYPE_MMM01; + case CART_TYPE_MBC3_TIMER_BATTERY: + case CART_TYPE_MBC3_TIMER_RAM_BATTERY: + case CART_TYPE_MBC3: + case CART_TYPE_MBC3_RAM: + case CART_TYPE_MBC3_RAM_BATTERY: + return MBC_TYPE_MBC3; + case CART_TYPE_MBC5: + case CART_TYPE_MBC5_RAM: + case CART_TYPE_MBC5_RAM_BATTERY: + case CART_TYPE_MBC5_RUMBLE: + case CART_TYPE_MBC5_RUMBLE_RAM: + case CART_TYPE_MBC5_RUMBLE_RAM_BATTERY: + return MBC_TYPE_MBC5; + case CART_TYPE_MBC6: + return MBC_TYPE_MBC6; + case CART_TYPE_MBC7_SENSOR_RUMBLE_RAM_BATTERY: + return MBC_TYPE_MBC7; + case CART_TYPE_POCKET_CAMERA: + case CART_TYPE_BANDAI_TAMA5: + case CART_TYPE_HuC3: + case CART_TYPE_HuC1_RAM_BATTERY: + // TODO + default: + return MBC_TYPE_UNKNOWN; + } + } + static uint8_t timer_get_shift( const gb_t * const ctx @@ -7912,7 +8017,7 @@ templates: } static uint8_t - rom_rb( + mbc1_rom_rb( gb_t * const ctx, const uint16_t addr ) { @@ -7932,15 +8037,31 @@ templates: case 0x1000: case 0x2000: case 0x3000: - // return ROM0 (16k, always mapped) + // ROM0 (16k, always mapped) return ctx->mmu.rom[addr]; case 0x4000: case 0x5000: case 0x6000: case 0x7000: - // return ROM1 (16k, banked) - // TODO: - return ctx->mmu.rom[addr]; + // 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]; + } default: // never reached return 0; @@ -7948,6 +8069,22 @@ templates: } static uint8_t + rom_rb( + gb_t * const ctx, + const uint16_t addr + ) { + switch (rom_get_mbc_type(ctx)) { + case MBC_TYPE_NONE: + return ctx->mmu.rom[addr]; + case MBC_TYPE_MBC1: + return mbc1_rom_rb(ctx, addr); + default: + // TODO: implement remaining MBC types + return 0; + } + } + + static uint8_t ram_rb( gb_t * const ctx, const uint16_t addr @@ -8032,41 +8169,31 @@ templates: } static void - rom_wb( + mbc1_rom_wb( gb_t * const ctx, const uint16_t addr, const uint8_t val ) { - // TODO: implement banking - UNUSED(val); - switch (addr & 0xF000) { case 0x0000: - // bios memory (maybe) - if (ctx->mmu.in_bios) { - if (addr < 0x100) { - // ctx->mmu.bios[addr]; - } else { - // ctx->mmu.in_bios = false; - } - } - - // ROM0 (16k, always mapped) - // return ctx->rom[addr]; - - break; case 0x1000: + // toggle ram_enable + ctx->mmu.mbc1.ram_enable = ((val & 0x0F) == 0x0A); + break; case 0x2000: case 0x3000: - // ROM0 (16k, always mapped) - // return ctx->rom[addr]; + // set rom bank + ctx->mmu.mbc1.rom_bank = val & 0x1F; break; case 0x4000: case 0x5000: + // set ram_bank/upper_rom_bank bits + ctx->mmu.mbc1.ram_bank = val & 0x3; + break; case 0x6000: case 0x7000: - // ROM1 (16k, banked) - // return ctx->mmu.rom[addr]; + // set rom/ram mode + ctx->mmu.mbc1.rom_ram_mode = val & 0x1; break; default: // never reached @@ -8075,6 +8202,22 @@ templates: } static void + rom_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + switch (rom_get_mbc_type(ctx)) { + case MBC_TYPE_MBC1: + mbc1_rom_wb(ctx, addr, val); + break; + default: + // do nothing + break; + } + } + + static void ram_wb( gb_t * const ctx, const uint16_t addr, |