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
|
|
|
}
|