diff options
-rw-r--r-- | ops.yaml | 250 |
1 files changed, 171 insertions, 79 deletions
@@ -8208,6 +8208,52 @@ templates: } static uint8_t + eram_rb( + const gb_t * const ctx, + const uint16_t addr + ) { + // 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_MBC2: + return mbc2_eram_rb(ctx, addr); + case MBC_TYPE_NONE: + default: + return 0; + } + } + + static uint8_t + vram_rb( + const gb_t * const ctx, + const uint16_t addr + ) { + switch (ctx->gpu.mode) { + case GPU_MODE_VRAM: + return 0xFF; + default: + // return vram (8k) + return ctx->mmu.vram[addr & 0x1FFF]; + } + } + + static uint8_t + oam_rb( + const gb_t * const ctx, + const uint16_t addr + ) { + switch (ctx->gpu.mode) { + case GPU_MODE_HBLANK: + case GPU_MODE_VBLANK: + // oam memory (160 bytes): + return ctx->mmu.oam[addr & 0xFF]; + default: + return 0; + } + } + + static uint8_t ram_rb( gb_t * const ctx, const uint16_t addr @@ -8216,24 +8262,36 @@ templates: case 0x8000: case 0x9000: // return vram (8k) - return ctx->mmu.vram[addr & 0x1FFF]; + return vram_rb(ctx, addr); case 0xA000: case 0xB000: // 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_MBC2: - return mbc2_eram_rb(ctx, addr); - case MBC_TYPE_NONE: - default: - return 0; - } + return eram_rb(ctx, addr); case 0xC000: // working ram (8k) case 0xD000: case 0xE000: // working ram (shadow) - case 0xF000: return ctx->mmu.ram[addr & 0x1FFF]; + case 0xF000: + switch (addr & 0x0F00) { + case 0x0E00: + if (addr < 0xFEA0) { + return oam_rb(ctx, addr); + } else { + // rest of page reads as zero + return 0; + } + case 0x0F00: + if (addr == PORT_IE || addr < 0xFF80) { + // io port + return mmu_rp(ctx, addr); + } else { + // zero page + return ctx->mmu.zram[addr & 0x7F]; + } + default: + // working ram (<0xFE00, 8k, shadow) + return ctx->mmu.ram[addr & 0x1FFF]; + } default: // never reached return 0; @@ -8262,29 +8320,8 @@ templates: case 0xC000: case 0xD000: case 0xE000: - return ram_rb(ctx, addr); case 0xF000: - switch (addr & 0x0F00) { - case 0x0E00: - if (addr < 0xFEA0) { - // oam memory (160 bytes): - return ctx->mmu.oam[addr & 0xFF]; - } else { - // rest of page reads as zero - return 0; - } - case 0x0F00: - if (addr == PORT_IE || addr < 0xFF80) { - // io port - return mmu_rp(ctx, addr); - } else { - // zero page - return ctx->mmu.zram[addr & 0x7F]; - } - default: - // working ram (<0xFE00, 8k, shadow) - return ram_rb(ctx, addr); - } + return ram_rb(ctx, addr); default: // never reached return 0; @@ -8311,6 +8348,72 @@ templates: } static void + eram_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + switch (rom_get_mbc_type(ctx)) { + 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) { + // external ram (8k, optional) + ctx->mmu.eram[addr & 0x1FFF] = val; + } + break; + default: + // do nothing + break; + } + } + + static void + vram_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + switch (ctx->gpu.mode) { + case GPU_MODE_HBLANK: + case GPU_MODE_VBLANK: + case GPU_MODE_OAM: + // vram (8k) + ctx->mmu.vram[addr & 0x1FFF] = val; + break; + default: + // do nothing + break; + } + } + + static void + oam_wb( + gb_t * const ctx, + const uint16_t addr, + const uint8_t val + ) { + switch (ctx->gpu.mode) { + case GPU_MODE_HBLANK: + case GPU_MODE_VBLANK: + // oam memory (160 bytes): + ctx->mmu.oam[addr & 0xFF] = val; + + // TODO: invalidate OAM cache + + break; + default: + // do nothing + break; + } + } + + static void ram_wb( gb_t * const ctx, const uint16_t addr, @@ -8319,38 +8422,41 @@ templates: switch (addr & 0xF000) { case 0x8000: case 0x9000: - // vram (8k) - // (FIXME: can we write directly to vram?) - ctx->mmu.vram[addr & 0x1FFF] = val; + vram_wb(ctx, addr, val); break; case 0xA000: case 0xB000: - switch (rom_get_mbc_type(ctx)) { - 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) { - // external ram (8k, optional) - ctx->mmu.eram[addr & 0x1FFF] = val; - } - break; - default: - // do nothing - break; - } - + eram_wb(ctx, addr, val); break; case 0xC000: // working ram (8k) case 0xD000: case 0xE000: // working ram (8k, shadow) - case 0xF000: ctx->mmu.ram[addr & 0x1FFF] = val; break; + case 0xF000: + switch (addr & 0x0F00) { + case 0x0E00: + if (addr < 0xFEA0) { + // oam memory (160 bytes): + oam_wb(ctx, addr, val); + } + + break; + case 0x0F00: + if (addr == PORT_IE || addr < 0xFF80) { + // io ports + mmu_wp(ctx, addr, val); + } else { + // zero page + ctx->mmu.zram[addr & 0x7F] = val; + } + + break; + default: + // working ram (<0xFE00, 8k, shadow) + ctx->mmu.ram[addr & 0x1FFF] = val; + break; + } default: // never reached break; @@ -8381,31 +8487,9 @@ templates: case 0xC000: case 0xD000: case 0xE000: + case 0xF000: ram_wb(ctx, addr, val); break; - case 0xF000: - switch (addr & 0x0F00) { - case 0x0E00: - if (addr < 0xFEA0) { - // oam memory (160 bytes): - ctx->mmu.oam[addr & 0xFF] = val; - } - - break; - case 0x0F00: - if (addr == PORT_IE || addr < 0xFF80) { - // io ports - mmu_wp(ctx, addr, val); - } else { - // zero page - ctx->mmu.zram[addr & 0x7F] = val; - } - - break; - default: - // working ram (<0xFE00, 8k, shadow) - ram_wb(ctx, addr, val); - } } } @@ -9710,8 +9794,10 @@ templates: gb_frame( gb_t * const ctx ) { + // get current frame const uint32_t frame = ctx->gpu.frame; + // run until next frame while (ctx->gpu.frame == frame) { gb_step(ctx); } @@ -9733,6 +9819,7 @@ templates: // init cpu registers // (src: TCAGBD.pdf, 3.2) + // TODO: this varies by model (DGB/CGB/SGB/GBA/etc) ctx->cpu.rs[RW_AF] = 0x01B0; ctx->cpu.rs[RW_BC] = 0x0013; ctx->cpu.rs[RW_DE] = 0x00D8; @@ -9749,9 +9836,14 @@ templates: // clear context memset(ctx, 0, sizeof(gb_t)); + // init cpu cpu_init(ctx); // init mmu ctx->mmu.rom = rom; ctx->mmu.rom_size = rom_size; + + // init gpu + ctx->gpu.mode = GPU_MODE_OAM; + ctx->gpu.line = 0; } |