summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops.yaml168
1 files changed, 150 insertions, 18 deletions
diff --git a/ops.yaml b/ops.yaml
index aa71087..84696e7 100644
--- a/ops.yaml
+++ b/ops.yaml
@@ -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) {