summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2018-05-27 10:11:18 -0400
committerPaul Duncan <pabs@pablotron.org>2018-05-27 10:11:18 -0400
commitd5bb94cc655d4410544394478587d36b1041d9d3 (patch)
treea136de185d39a443fe91f7fded585e7629fa90da
parentf9008bcfed2537bf2e4d6d33a98a72a115388d93 (diff)
downloadgb-c-d5bb94cc655d4410544394478587d36b1041d9d3.tar.bz2
gb-c-d5bb94cc655d4410544394478587d36b1041d9d3.zip
add initial mmu code
-rw-r--r--ops.yaml191
1 files changed, 181 insertions, 10 deletions
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