// // Created by william on 10/15/23. // #include #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); } }