summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ops.yaml300
1 files changed, 183 insertions, 117 deletions
diff --git a/ops.yaml b/ops.yaml
index d94eba1..aa71087 100644
--- a/ops.yaml
+++ b/ops.yaml
@@ -7750,6 +7750,136 @@ templates:
}
}
+ /******************/
+ /* mbc1 functions */
+ /******************/
+
+ static uint8_t
+ mbc1_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)
+ {
+ // 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;
+ }
+ }
+
+ static uint16_t
+ mbc1_eram_get_addr(
+ const gb_t * const ctx,
+ const uint16_t addr
+ ) {
+ // switchable ram bank
+ // AAB BBBB BBBB BBBB
+ return (
+ // A: ram_bank (2 bits, if rom_ram_mode == 1)
+ (((ctx->mmu.mbc1.rom_ram_mode ? ctx->mmu.mbc1.ram_bank : 0) & 0x3) << 13) |
+
+ // B: address (13 bits)
+ (addr & 0x1FFF)
+ );
+ }
+
+ static uint8_t
+ mbc1_eram_rb(
+ const gb_t * const ctx,
+ const uint16_t addr
+ ) {
+ if (ctx->mmu.eram && ctx->mmu.mbc1.ram_enable) {
+ return ctx->mmu.eram[mbc1_eram_get_addr(ctx, addr)];
+ } else {
+ // FIXME: what do we do with no eram?
+ return 0;
+ }
+ }
+
+ static void
+ mbc1_rom_wb(
+ gb_t * const ctx,
+ const uint16_t addr,
+ const uint8_t val
+ ) {
+ switch (addr & 0xF000) {
+ case 0x0000:
+ case 0x1000:
+ // toggle ram_enable
+ ctx->mmu.mbc1.ram_enable = ((val & 0x0F) == 0x0A);
+ break;
+ case 0x2000:
+ case 0x3000:
+ // 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:
+ // set rom/ram mode
+ ctx->mmu.mbc1.rom_ram_mode = val & 0x1;
+ break;
+ default:
+ // never reached
+ break;
+ }
+ }
+
+ static void
+ mbc1_eram_wb(
+ gb_t * const ctx,
+ const uint16_t addr,
+ const uint8_t val
+ ) {
+ if (ctx->mmu.eram && ctx->mmu.mbc1.ram_enable) {
+ ctx->mmu.eram[mbc1_eram_get_addr(ctx, addr)] = val;
+ }
+ }
+
+
static uint8_t
timer_get_shift(
const gb_t * const ctx
@@ -7769,6 +7899,31 @@ templates:
}
}
+ /***************/
+ /* mmu OAM dma */
+ /***************/
+
+ // forward references for mmu_oam_dma()
+ static uint8_t mmu_rb(gb_t * const, const uint16_t);
+ static void mmu_wb(gb_t * const, const uint16_t, const uint8_t);
+
+ static void
+ mmu_oam_dma(
+ gb_t * const ctx,
+ const uint8_t val
+ ) {
+ const uint16_t src_addr = (val << 8);
+ // copy 160 bytes of data to OAM
+ // (src: http://gbdev.gg8.se/wiki/articles/Video_Display#LCD_OAM_DMA_Transfers)
+ for (uint8_t i = 0; i < 160; i++) {
+ mmu_wb(ctx, 0xFE00 + i, mmu_rb(ctx, src_addr + i));
+ }
+ }
+
+ /**********************/
+ /* mmu port functions */
+ /**********************/
+
#define PORT_P1 0xFF00
// timer registers
@@ -7795,23 +7950,6 @@ templates:
#define PORT_WY 0xFF4A
#define PORT_WX 0xFF4B
- // forward references for mmu_oam_dma()
- static uint8_t mmu_rb(gb_t * const, const uint16_t);
- static void mmu_wb(gb_t * const, const uint16_t, const uint8_t);
-
- static void
- mmu_oam_dma(
- gb_t * const ctx,
- const uint8_t val
- ) {
- const uint16_t src_addr = (val << 8);
- // copy 160 bytes of data to OAM
- // (src: http://gbdev.gg8.se/wiki/articles/Video_Display#LCD_OAM_DMA_Transfers)
- for (uint8_t i = 0; i < 160; i++) {
- mmu_wb(ctx, 0xFE00 + i, mmu_rb(ctx, src_addr + i));
- }
- }
-
static uint8_t
mmu_rp(
const gb_t * const ctx,
@@ -8016,57 +8154,9 @@ templates:
}
}
- static uint8_t
- mbc1_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)
- {
- // 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;
- }
- }
+ /*****************/
+ /* mmu functions */
+ /*****************/
static uint8_t
rom_rb(
@@ -8096,20 +8186,18 @@ templates:
return ctx->mmu.vram[addr & 0x1FFF];
case 0xA000:
case 0xB000:
- if (ctx->mmu.eram) {
- // external ram (8k, optional)
- return ctx->mmu.eram[addr & 0x1FFF];
- } else {
- // FIXME: what do we do with no eram?
+ // switchable external ram bank (8k, banked, optional)
+ switch (rom_get_mbc_type(ctx)) {
+ case MBC_TYPE_MBC1:
+ return mbc1_eram_rb(ctx, addr);
+ case MBC_TYPE_NONE:
+ default:
return 0;
}
- case 0xC000:
+ case 0xC000: // working ram (8k)
case 0xD000:
- // working ram (8k)
- return ctx->mmu.ram[addr & 0x1FFF];
- case 0xE000:
+ case 0xE000: // working ram (shadow)
case 0xF000:
- // working ram (shadow)
return ctx->mmu.ram[addr & 0x1FFF];
default:
// never reached
@@ -8169,39 +8257,6 @@ templates:
}
static void
- mbc1_rom_wb(
- gb_t * const ctx,
- const uint16_t addr,
- const uint8_t val
- ) {
- switch (addr & 0xF000) {
- case 0x0000:
- case 0x1000:
- // toggle ram_enable
- ctx->mmu.mbc1.ram_enable = ((val & 0x0F) == 0x0A);
- break;
- case 0x2000:
- case 0x3000:
- // 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:
- // set rom/ram mode
- ctx->mmu.mbc1.rom_ram_mode = val & 0x1;
- break;
- default:
- // never reached
- break;
- }
- }
-
- static void
rom_wb(
gb_t * const ctx,
const uint16_t addr,
@@ -8232,18 +8287,29 @@ templates:
break;
case 0xA000:
case 0xB000:
- if (ctx->mmu.eram) {
- // external ram (8k, optional)
- ctx->mmu.eram[addr & 0x1FFF] = val;
+ switch (rom_get_mbc_type(ctx)) {
+ case MBC_TYPE_MBC1:
+ mbc1_eram_wb(ctx, addr, val);
+ break;
+ case MBC_TYPE_NONE:
+ // TODO: implement remaining mbcs
+ if (ctx->mmu.eram) {
+ // external ram (8k, optional)
+ ctx->mmu.eram[addr & 0x1FFF] = val;
+ }
+ break;
+ default:
+ // do nothing
+ break;
}
break;
- case 0xC000:
+ case 0xC000: // working ram (8k)
case 0xD000:
- case 0xE000:
+ case 0xE000: // working ram (8k, shadow)
case 0xF000:
- // working ram (8k, shadow)
ctx->mmu.ram[addr & 0x1FFF] = val;
+ break;
default:
// never reached
break;