From bd1f4fb90999c799fa0469629456ff11a161d654 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 20 Jun 2018 13:27:38 -0400 Subject: add remaining mbc1, clean up mbc1 --- ops.yaml | 300 ++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 183 insertions(+), 117 deletions(-) (limited to 'ops.yaml') 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 @@ -8168,39 +8256,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, @@ -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; -- cgit v1.2.3