From d5bb94cc655d4410544394478587d36b1041d9d3 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 27 May 2018 10:11:18 -0400 Subject: add initial mmu code --- ops.yaml | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 181 insertions(+), 10 deletions(-) (limited to 'ops.yaml') diff --git a/ops.yaml b/ops.yaml index ed60519..360fadb 100644 --- a/ops.yaml +++ b/ops.yaml @@ -1779,7 +1779,6 @@ ops: c: code: | ctx->cpu.state = STATE_HALT; - cpu_ww(ctx, RW_PC, old_pc); // FIXME? - id: LD (HL), A hex: 0x77 cat: "8-bit load/store/move" @@ -7562,8 +7561,21 @@ templates: typedef struct { struct { - // TODO - uint8_t mem[0xFFFF]; + bool in_bios; + + // FIXME: combine these? + uint8_t bios[0x100]; // bios (256 bytes) + uint8_t ram[0x2000]; // working ram (8k) + uint8_t vram[0x2000]; // vram (8k) + uint8_t oam[0xA0]; // oam (160 bytes) + uint8_t zram[0x7F]; // zram (128 bytes) + + // rom (at least 32k) + uint8_t *rom; + uint32_t rom_size; + + // external ram (optional, 8k) + uint8_t *eram; } mmu; struct { @@ -7576,10 +7588,93 @@ templates: static uint8_t mmu_rb( - const gb_t * const ctx, + gb_t * const ctx, const uint16_t addr ) { - return ctx->mmu.mem[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]; + + break; + case 0x1000: + case 0x2000: + case 0x3000: + // return ROM0 (16k, always mapped) + return ctx->mmu.rom[addr]; + break; + case 0x4000: + case 0x5000: + case 0x6000: + case 0x7000: + // return ROM1 (16k, banked) + // TODO: + return ctx->mmu.rom[addr]; + break; + case 0x8000: + case 0x9000: + // return vram (8k) + return ctx->mmu.vram[addr & 0x1FFF]; + break; + 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? + return 0; + } + + break; + case 0xC000: + case 0xD000: + // working ram (8k) + return ctx->mmu.ram[addr & 0x1FFF]; + break; + case 0xE000: + // working ram (shadow) + return ctx->mmu.ram[addr & 0x1FFF]; + break; + 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; + } + + break; + case 0x0F00: + if (addr < 0xFF80) { + // TODO: io ports + return 0; + } else { + // zero page + return ctx->mmu.zram[addr & 0x7F]; + } + + break; + default: + // working ram (shadow) + return ctx->mmu.ram[addr & 0x1FFF]; + } + default: + // never reached + return 0; + } } static void @@ -7588,16 +7683,91 @@ templates: const uint16_t addr, const uint8_t val ) { - ctx->mmu.mem[addr] = 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: + case 0x2000: + case 0x3000: + // ROM0 (16k, always mapped) + // return ctx->rom[addr]; + break; + case 0x4000: + case 0x5000: + case 0x6000: + case 0x7000: + // ROM1 (16k, banked) + // return ctx->mmu.rom[addr]; + break; + case 0x8000: + case 0x9000: + // vram (8k) + // FIXME: can we write directly to vram? + // return ctx->mmu.vram[addr & 0x1FFF]; + break; + case 0xA000: + case 0xB000: + if (ctx->mmu.eram) { + // external ram (8k, optional) + ctx->mmu.eram[addr & 0x1FFF] = val; + } + + break; + case 0xC000: + case 0xD000: + // working ram (8k) + ctx->mmu.ram[addr & 0x1FFF] = val; + + break; + case 0xE000: + // working ram (shadow) + ctx->mmu.ram[addr & 0x1FFF] = 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 < 0xFF80) { + // TODO: io ports + } else { + // zero page + ctx->mmu.zram[addr & 0x7F] = val; + } + + break; + default: + // working ram (shadow) + ctx->mmu.ram[addr & 0x1FFF] = val; + } + } } static uint16_t mmu_rw( - const gb_t * const ctx, + gb_t * const ctx, const uint16_t addr ) { // FIXME - return (((uint16_t) mmu_rb(ctx, addr)) << 8) + mmu_rb(ctx, addr + 1); + return (((uint16_t) mmu_rb(ctx, addr + 1)) << 8) + mmu_rb(ctx, addr); } static void @@ -7606,8 +7776,9 @@ templates: const uint16_t addr, const uint16_t val ) { - ctx->mmu.mem[addr] = (val >> 8); - ctx->mmu.mem[addr + 1] = val & 0xFF; + // write lsb, msb (little endian) + mmu_wb(ctx, addr, val & 0xFF); + mmu_wb(ctx, addr + 1, val >> 8); } static uint16_t -- cgit v1.2.3