~sircmpwn/hdmg

e6f5293160494368479c59b1ab981eb862111659 — Drew DeVault 2 years ago 1e06eb7
dmg: flesh out MMU

Not entirely satisfied with this
2 files changed, 69 insertions(+), 8 deletions(-)

M dmg/cart.ha
M dmg/mmu.ha
M dmg/cart.ha => dmg/cart.ha +3 -1
@@ 1,3 1,5 @@
use sm83;

export type cart = struct {
	rom0: [16384]u8,
	sm83::mmu,
};

M dmg/mmu.ha => dmg/mmu.ha +66 -7
@@ 1,3 1,5 @@
// XXX: These if statement chains might be better implemented as a mapping table
// or something. Dunno.
use sm83;

export type mmu = struct {


@@ 6,12 8,13 @@ export type mmu = struct {
	vram: [0x2000]u8,
	ram0: [0x1000]u8,
	ram1: [0x1000]u8,
	ram2: [0x80]u8,
	sprites: [0xA0]u8,
};

// Creates a new DMG MMU.
export fn new_mmu(cart: *cart) *mmu = {
	return alloc(mmu {
	let mmu = alloc(mmu {
		readb = &mmu_readb,
		readw = &mmu_readw,
		writeb = &mmu_writeb,


@@ 19,6 22,7 @@ export fn new_mmu(cart: *cart) *mmu = {
		cart = cart,
		...
	});
	return mmu;
};

// Frees a DMG MMU.


@@ 26,18 30,73 @@ export fn mmu_free(mmu: *mmu) void = {
	free(mmu);
};

fn mmu_readb(mmu: *sm83::mmu, addr: u16) u8 = {
	abort(); // TODO
fn mmu_readb(mem: *sm83::mmu, addr: u16) u8 = {
	const mem = mem: *mmu;
	const base = addr >> 8;
	if (base >= 0x00 && base < 0x80) {
		return mem.cart.readb(mem.cart, addr);
	} else if (base >= 0xA0 && base < 0xC0) {
		return mem.cart.readb(mem.cart, addr);
	};

	if (base >= 0xC0 && base < 0xD0) {
		return mem.ram0[addr - 0xC000];
	} else if (base >= 0xD0 && base < 0xE0) {
		return mem.ram1[addr - 0xD000];
	} else if (base >= 0xE0 && base < 0xF0) {
		return mem.ram0[addr - 0xE000];
	} else if (base >= 0xF0 && base < 0xDE) {
		return mem.ram1[addr - 0xF000];
	};

	if (addr >= 0xFE00 && addr < 0xFEA0) {
		return mem.sprites[addr - 0xFE00];
	};

	if (addr >= 0xFF80 && addr < 0xFFFF) {
		return mem.ram2[addr - 0xFF80];
	};

	if (addr >= 0xFF00) {
		// TODO: I/O
		return 0;
	};

	// "Unusable" memory
	return 0;
};

fn mmu_readw(mmu: *sm83::mmu, addr: u16) u16 = {
	abort(); // TODO
	const low: u16 = mmu_readb(mmu, addr);
	const high: u16 = mmu_readb(mmu, addr + 1);
	return low | (high << 8);
};

fn mmu_writeb(mmu: *sm83::mmu, addr: u16, b: u8) void = {
	abort(); // TODO
fn mmu_writeb(mem: *sm83::mmu, addr: u16, b: u8) void = {
	const mem = mem: *mmu;
	const base = addr >> 8;
	if (base >= 0x00 && base < 0x80) {
		mem.cart.writeb(mem.cart, addr, b);
	} else if (base >= 0xA0 && base < 0xC0) {
		mem.cart.writeb(mem.cart, addr, b);
	} else if (base >= 0xC0 && base < 0xD0) {
		mem.ram0[addr - 0xC000] = b;
	} else if (base >= 0xD0 && base < 0xE0) {
		mem.ram1[addr - 0xD000] = b;
	} else if (base >= 0xE0 && base < 0xF0) {
		mem.ram0[addr - 0xE000] = b;
	} else if (base >= 0xF0 && base < 0xDE) {
		mem.ram1[addr - 0xF000] = b;
	} else if (addr >= 0xFE00 && addr < 0xFEA0) {
		mem.sprites[addr - 0xFE00] = b;
	} else if (addr >= 0xFF80 && addr < 0xFFFF) {
		mem.ram2[addr - 0xFF80] = b;
	} else if (addr >= 0xFF00) {
		void; // TODO: I/O
	};
};

fn mmu_writew(mmu: *sm83::mmu, addr: u16, w: u16) void = {
	abort(); // TODO
	mmu_writeb(mmu, addr, (w & 0xFF): u8);
	mmu_writeb(mmu, addr + 1, (w >> 8): u8);
};