summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops.yaml195
1 files changed, 169 insertions, 26 deletions
diff --git a/ops.yaml b/ops.yaml
index ac4b0a7..d94eba1 100644
--- a/ops.yaml
+++ b/ops.yaml
@@ -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,