76 lines
1.8 KiB
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();
|
|
}
|
|
}
|
|
} |