nesemu/cpu/memory.c

116 lines
2.9 KiB
C

//
// Created by william on 10/15/23.
//
#include <assert.h>
#include "log.h"
#include "memory.h"
#include "../include/rom.h"
#include "cpu.h"
#define RAM_SIZE 0x0800
#define RAM_MAX_ADDR 0x2000
#define PPU_MAX_ADDR 0x4000
#define APU_MAX_ADDR 0x4020
#define UNMAPPED_MAX_ADDR 0x6000
#define CARTRIDGE_RAM_MAX_ADDR 0x8000
#define MEM_ADDR_MAX 0xffff
byte ram[RAM_SIZE];
byte *mem_get_ptr(address addr) {
assert(addr <= RAM_MAX_ADDR);
if (addr < RAM_MAX_ADDR) {
address ram_addr = addr % RAM_SIZE; // There is four mirror of RAM
return &ram[ram_addr];
}
// Only supported for RAM
assert(false);
}
byte mem_get_byte(address addr) {
assert(addr <= MEM_ADDR_MAX);
if (addr < RAM_MAX_ADDR) {
address ram_addr = addr % RAM_SIZE;
return ram[ram_addr];
} else if (addr < PPU_MAX_ADDR) {
address relative_addr = addr - RAM_MAX_ADDR;
byte ppu_reg = relative_addr % 8;
return ppu_read_reg(ppu_reg);
} else if (addr < APU_MAX_ADDR) {
// TODO NES API and I/O registers
return 0;
} else if (addr < UNMAPPED_MAX_ADDR) {
// Unmapped
assert(false);
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
// TODO Cartridge RAM
return 0;
} else {
address rom_addr = addr - CARTRIDGE_RAM_MAX_ADDR;
Mapper *mapper = system_get_mapper();
return *(mapper->mem_read(rom_addr));
}
}
word mem_get_word(address addr) {
assert(addr <= MEM_ADDR_MAX - 1);
byte data1;
byte data2;
if (addr < RAM_MAX_ADDR - 1) {
address ram_addr = addr % RAM_SIZE;
data1 = ram[ram_addr];
data2 = ram[ram_addr + 1];
} else if (addr < UNMAPPED_MAX_ADDR) {
// Unsupported
assert(false);
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
// TODO Cartridge RAM
return 0;
} else {
address rom_addr = addr - CARTRIDGE_RAM_MAX_ADDR;
Mapper *mapper = system_get_mapper();
byte *location = mapper->mem_read(rom_addr);
data1 = *location;
data2 = *(location + 1);
}
return data1 + (data2 << 8);
}
void mem_set_byte(address addr, byte data) {
assert(addr < MEM_ADDR_MAX);
if (addr < RAM_MAX_ADDR) {
address ram_addr = addr % RAM_SIZE;
ram[ram_addr] = data;
} else if (addr < PPU_MAX_ADDR) {
address relative_addr = addr - RAM_MAX_ADDR;
byte ppu_reg = relative_addr % 8;
ppu_write_reg(ppu_reg, data);
} else if (addr == PPU_REGISTER_OAM_DMA_ADDR) {
ppu_write_oamaddr(data);
// Writing to this address triggers an upload to the PPU memory
cpu_trigger_oam_dma();
} else if (addr < APU_MAX_ADDR) {
// TODO NES API and I/O registers
} else if (addr < UNMAPPED_MAX_ADDR) {
// Unmapped
assert(false);
} else if (addr < CARTRIDGE_RAM_MAX_ADDR) {
// TODO Cartridge RAM
} else {
// ROM is read-only
assert(false);
}
}