nesemu/cpu/memory.c

116 lines
2.9 KiB
C
Raw Normal View History

2023-11-26 12:11:49 -05:00
//
// Created by william on 10/15/23.
//
2024-01-06 14:27:09 -05:00
#include <assert.h>
2024-04-30 12:28:43 -04:00
#include "log.h"
2023-11-26 12:11:49 -05:00
#include "memory.h"
2023-12-23 16:35:23 -05:00
#include "../include/rom.h"
2024-05-06 20:23:44 -04:00
#include "cpu.h"
2023-11-26 12:11:49 -05:00
2024-05-23 23:52:04 -04:00
#define RAM_SIZE 0x0800
2024-01-06 14:27:09 -05:00
#define RAM_MAX_ADDR 0x2000
#define PPU_MAX_ADDR 0x4000
#define APU_MAX_ADDR 0x4020
2024-05-23 23:52:04 -04:00
#define UNMAPPED_MAX_ADDR 0x6000
#define CARTRIDGE_RAM_MAX_ADDR 0x8000
#define MEM_ADDR_MAX 0xffff
2023-12-23 16:35:23 -05:00
2024-05-06 20:23:44 -04:00
byte ram[RAM_SIZE];
2024-05-23 23:52:04 -04:00
byte *mem_get_ptr(address addr) {
assert(addr <= RAM_MAX_ADDR);
2024-01-06 14:27:09 -05:00
2024-05-23 23:52:04 -04:00
if (addr < RAM_MAX_ADDR) {
address ram_addr = addr % RAM_SIZE; // There is four mirror of RAM
return &ram[ram_addr];
2024-01-06 14:27:09 -05:00
}
2024-05-23 23:52:04 -04:00
// Only supported for RAM
assert(false);
2024-05-06 20:23:44 -04:00
}
2023-12-23 16:35:23 -05:00
2024-05-23 23:52:04 -04:00
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;
2024-05-06 20:23:44 -04:00
2024-05-23 23:52:04 -04:00
Mapper *mapper = system_get_mapper();
return *(mapper->mem_read(rom_addr));
}
2023-11-26 12:11:49 -05:00
}
2024-05-06 20:23:44 -04:00
word mem_get_word(address addr) {
2024-05-23 23:52:04 -04:00
assert(addr <= MEM_ADDR_MAX - 1);
2023-12-23 16:35:23 -05:00
2024-05-23 23:52:04 -04:00
byte data1;
byte data2;
2023-11-26 12:11:49 -05:00
2024-05-23 23:52:04 -04:00
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;
2024-01-06 14:27:09 -05:00
2024-05-23 23:52:04 -04:00
Mapper *mapper = system_get_mapper();
byte *location = mapper->mem_read(rom_addr);
2024-01-06 14:27:09 -05:00
2024-05-23 23:52:04 -04:00
data1 = *location;
data2 = *(location + 1);
}
2024-01-06 14:27:09 -05:00
2024-05-23 23:52:04 -04:00
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;
2024-01-06 14:27:09 -05:00
} else if (addr < PPU_MAX_ADDR) {
2024-05-23 23:52:04 -04:00
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) {
2024-05-29 21:38:52 -04:00
ppu_write_reg_oam_addr(data);
2024-05-23 23:52:04 -04:00
// 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
2024-01-06 14:27:09 -05:00
} else {
2024-05-23 23:52:04 -04:00
// ROM is read-only
assert(false);
2024-01-06 14:27:09 -05:00
}
2023-11-26 12:11:49 -05:00
}