nesemu/cpu/memory.c

76 lines
1.8 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_MAX_ADDR 0x2000
#define RAM_BANK_SIZE 0x800
#define PPU_MAX_ADDR 0x4000
#define PPU_BANK_SIZE 0x8
#define APU_MAX_ADDR 0x4020
#define MAX_ADDR 0xffff
byte ram[RAM_SIZE];
byte mem_get_byte(address addr) {
assert(addr <= MAX_ADDR);
if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) {
byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
ppu_read_register(reg);
}
return ram[addr];
}
byte *mem_get_ptr(address addr) {
assert(addr <= MAX_ADDR);
return &ram[addr];
}
word mem_get_word(address addr) {
assert(addr < MAX_ADDR);
word word = ram[addr];
word += ram[addr + 1] << 8; // Little endian
return word;
}
void mem_set_byte(address addr, byte byte) {
assert(addr < MAX_ADDR);
log_trace("Writing '%02x' to address 0x%04x", byte, addr);
if (addr < RAM_MAX_ADDR) {
address init_ram_addr = addr % RAM_BANK_SIZE;
// The value must also be cloned in the three mirrors
for (int i = 0; i < 4; i++) {
address ram_addr = init_ram_addr + RAM_BANK_SIZE * i;
ram[ram_addr] = byte;
}
} else if (addr < PPU_MAX_ADDR) {
address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE;
int bank_count = (PPU_MAX_ADDR - RAM_MAX_ADDR) / PPU_BANK_SIZE;
for (int i = 0; i < bank_count; i++) {
address ram_addr = reg_addr + PPU_BANK_SIZE * i + RAM_MAX_ADDR;
ram[ram_addr] = byte;
}
ppu_write_register(reg_addr);
} else {
ram[addr] = byte;
if (addr == PPU_REGISTER_OAM_DMA_ADDR) {
// Writing to this address triggers an upload to the PPU memory
cpu_trigger_oam_dma();
}
}
}