From 4cdf2839b3ba0e9f6e1973285e8abcb24e8656a3 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Fri, 3 Jan 2025 01:44:29 -0800 Subject: [PATCH] Add UxROM mapper (Castlevania, Mega Man) --- Makefile | 2 +- src/map/uxrom.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ src/mapper.c | 2 ++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/map/uxrom.c diff --git a/Makefile b/Makefile index c51c00f..e835e30 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ SRC_SRCS_1 += sdl_render.c sdl_input.c SRC_SRCS_1 += apu.c MAPDIR = src/map -MAP_SRCS_1 = nrom.c mmc1.c cnrom.c mmc3.c +MAP_SRCS_1 = nrom.c mmc1.c uxrom.c cnrom.c mmc3.c EXT_SRCS_1 = e6502/e6502.c e6502/opcodes.c blip-buf/blip_buf.c diff --git a/src/map/uxrom.c b/src/map/uxrom.c new file mode 100644 index 0000000..d420fa5 --- /dev/null +++ b/src/map/uxrom.c @@ -0,0 +1,96 @@ +#include + +#include "map.h" + + +typedef struct { + uint8_t* prg_rom; + int prg_rom_banks; + uint8_t mirror; + uint8_t vram[nes_vram_page_size * 2]; + uint8_t chr_ram[8 * 1024]; + + uint8_t* prg_bank_lo; + uint8_t* prg_bank_hi; +} uxrom_mapper; + + +static void uxrom_reset(nes_mapper* nes_map) { + uxrom_mapper* map = (uxrom_mapper*)nes_map->data; + map->prg_bank_lo = map->prg_rom; +} + +static int uxrom_init(nes_mapper* nes_map, nes_cart* cart) { + uxrom_mapper* map = calloc(1, sizeof(uxrom_mapper)); + nes_map->data = map; + if (NULL != map) { + map->prg_rom = cart->prg_rom; + map->prg_rom_banks = cart->prg_rom_banks; + map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; + map->prg_bank_hi = &map->prg_rom[(map->prg_rom_banks - 1) * + nes_prg_rom_page_size]; + uxrom_reset(nes_map); + } + return (NULL == map ? -1 : 0); +} + +static void uxrom_done(nes_mapper* nes_map) { + free(nes_map->data); +} + +static inline uint8_t* uxrom_prg_addr(uxrom_mapper* map, + uint16_t addr) { + uint8_t* bank = ( addr < 0xC000U ? + map->prg_bank_lo : map->prg_bank_hi ); + return &(bank[addr & 0x3FFF]); +} + + +static uint8_t uxrom_read(nes_mapper* map, uint16_t addr) { + uint8_t val = 0; + if (addr >= nes_mem_rom_start) { + val = *(uxrom_prg_addr((uxrom_mapper*)map->data, addr)); + } + return val; +} + +static void uxrom_write(nes_mapper* nes_map, + uint16_t addr, uint8_t val) { + uxrom_mapper* map = (uxrom_mapper*)nes_map->data; + if (addr >= nes_mem_rom_start) { + map->prg_bank_lo = &map->prg_rom[ + (val % map->prg_rom_banks) * + nes_prg_rom_page_size + ]; + } +} + +static uint8_t* uxrom_chr_addr(nes_mapper* nes_map, + uint16_t addr) { + return &((uxrom_mapper*)nes_map->data)->chr_ram[addr]; +} + +static uint8_t* uxrom_vram_addr(nes_mapper* nes_map, + uint16_t addr) { + uxrom_mapper* map = (uxrom_mapper*)nes_map->data; + int page = addr >> 10U; + page >>= map->mirror; + addr = ((page & 1) << 10U) | (addr & 0x3FFU); + return &map->vram[addr]; +} + +static void uxrom_chr_write(nes_mapper* nes_map, + uint16_t addr, uint8_t val) { + ((uxrom_mapper*)nes_map->data)->chr_ram[addr] = val; +} + +nes_mapper mapper_uxrom = { + .init = uxrom_init, + .reset = uxrom_reset, + .done = uxrom_done, + .read = uxrom_read, + .write = uxrom_write, + .chr_addr = uxrom_chr_addr, + .vram_addr = uxrom_vram_addr, + .chr_write = uxrom_chr_write, +}; diff --git a/src/mapper.c b/src/mapper.c index 7828047..f20092f 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -3,6 +3,7 @@ extern nes_mapper mapper_nrom; extern nes_mapper mapper_mmc1; +extern nes_mapper mapper_uxrom; extern nes_mapper mapper_cnrom; extern nes_mapper mapper_mmc3; @@ -10,6 +11,7 @@ extern nes_mapper mapper_mmc3; nes_mapper* nes_mappers[256] = { [ 0] = &mapper_nrom, [ 1] = &mapper_mmc1, + [ 2] = &mapper_uxrom, [ 3] = &mapper_cnrom, [ 4] = &mapper_mmc3, };