From 303c0812bde164b588767a3d62d396347cde9355 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Mon, 17 Mar 2025 11:38:29 -0700 Subject: [PATCH] Add Mapper 002 (UxROM); more refactoring for redundant mapper init --- src/cart.c | 63 +++++++++++++++++++++++++++++++----------------- src/map/map000.c | 1 + src/map/map001.c | 15 +++--------- src/map/map002.c | 44 +++++++++++++++++++++++++++++++++ src/mapper.c | 2 ++ src/mapper.h | 4 +-- 6 files changed, 93 insertions(+), 36 deletions(-) create mode 100644 src/map/map002.c diff --git a/src/cart.c b/src/cart.c index 5eeb824..3eb7a9f 100644 --- a/src/cart.c +++ b/src/cart.c @@ -53,26 +53,6 @@ int nes_cart_load_mem(void* data, int size, nes* sys) { } if (0 == status) { - // PPU Bank 0 - 7: Default pattern tables - for (int page = 0; page < 8; ++page) { - mem->ppu.bank[page] = chr_page(&mem->ppu, page); - } - - // PPU Bank 8 - 11: Mirrored VRAM - nes_ppu_set_mirroring( - &mem->ppu, hdr->flags_6 & ines_Flag_Vert_Mirror - ); - - // PPU Bank 12 - 15: Unused & Palette - for (int page = 12; page < 16; ++page) { - mem->ppu.bank[page] = mem->ppu.pal_bank; - } - - // Map the SRAM bank to battery-backed SRAM if present - if (hdr->flags_6 & ines_Flag_Battery) { - mem->sram_bank = mem->sram; - } - int i_mapper = (hdr->flags_7 & ines_Mapper_Nibble_Hi) | ((hdr->flags_6 & ines_Mapper_Nibble_Lo) >> 4); const nes_Mapper *mapper = nes_mappers[i_mapper]; @@ -80,9 +60,48 @@ int nes_cart_load_mem(void* data, int size, nes* sys) { LOGE("Mapper %d not supported", i_mapper); status = -1; } else { - LOGI("Mapper %d", i_mapper); + // Set up CHR RAM if used + if (hdr->chr_size_lsb <= 0) { + int chr_size = mapper->max_chr_banks * + NES_CHR_ROM_PAGE_SIZE; + mem->ppu.chr_ram = calloc(1, chr_size); + LOGI("CHR RAM: %d kB", chr_size / 1024); + mem->ppu.chr = mem->ppu.chr_ram; + mem->ppu.n_chr_banks = chr_size / + NES_CHR_ROM_PAGE_SIZE; + } + + LOGI("Mapper %d: %s", i_mapper, mapper->name); mem->mapper = *mapper; - status = mem->mapper.init(&mem->mapper, hdr, mem); + mem->mapper.data = calloc(1, mapper->data_size); + if (NULL == mem->mapper.data) { + LOGE("Failed to allocate mapper data"); + status = -1; + } else { + // PPU Bank 0 - 7: Default pattern tables + for (int page = 0; page < 8; ++page) { + mem->ppu.bank[page] = chr_page(&mem->ppu, page); + } + + // PPU Bank 8 - 11: Mirrored VRAM + nes_ppu_set_mirroring( + &mem->ppu, hdr->flags_6 & ines_Flag_Vert_Mirror + ); + + // PPU Bank 12 - 15: Unused & Palette + for (int page = 12; page < 16; ++page) { + mem->ppu.bank[page] = mem->ppu.pal_bank; + } + + // Map the SRAM bank to battery-backed SRAM if present + if (hdr->flags_6 & ines_Flag_Battery) { + mem->sram_bank = mem->sram; + } + + status = mem->mapper.init(&mem->mapper, + hdr, mem); + } + // TODO: Deallocate mapper data when we're done } } diff --git a/src/map/map000.c b/src/map/map000.c index 9fb6de3..31c4ec0 100644 --- a/src/map/map000.c +++ b/src/map/map000.c @@ -22,5 +22,6 @@ static int map000_init(nes_Mapper* map, const ines_Header* hdr, const nes_Mapper map000 = { .name = "NROM", .max_chr_banks = 8, + .data_size = 0, .init = map000_init, }; diff --git a/src/map/map001.c b/src/map/map001.c index 1ae854b..4ca4c44 100644 --- a/src/map/map001.c +++ b/src/map/map001.c @@ -1,5 +1,3 @@ -#include - #include "memory.h" //#define DEBUG "MMC1" @@ -90,16 +88,8 @@ static void map001_reset(nes_Mapper* map, nes_Memory* mem) { static int map001_init(nes_Mapper* map, const ines_Header* hdr, nes_Memory* mem) { - int status = -1; - - map->data = calloc(1, sizeof(map001_data)); - - if (NULL != map->data) { - map001_reset(map, mem); - status = 0; - } - - return status; + map001_reset(map, mem); + return 0; } static int map001_write_rom(nes_Mapper* map, nes_Memory* mem, @@ -156,6 +146,7 @@ static int map001_write_rom(nes_Mapper* map, nes_Memory* mem, const nes_Mapper map001 = { .name = "MMC1", .max_chr_banks = 128, + .data_size = sizeof(map001_data), .init = map001_init, .reset = map001_reset, .write_rom = map001_write_rom, diff --git a/src/map/map002.c b/src/map/map002.c new file mode 100644 index 0000000..0890b0c --- /dev/null +++ b/src/map/map002.c @@ -0,0 +1,44 @@ +#include "memory.h" + + +typedef struct { + uint8_t bank; +} map002_data; + + +static inline void uxrom_set_bank(map002_data* data, + nes_Memory* mem, + uint8_t bank) { + data->bank = (bank % (mem->n_rom_banks / 2)); + mem->rom_bank[0] = prg_rom_page(mem, (data->bank * 2) + 0); + mem->rom_bank[1] = prg_rom_page(mem, (data->bank * 2) + 1); +} + +static void map002_reset(nes_Mapper* map, nes_Memory* mem) { + uxrom_set_bank((map002_data*)map->data, mem, 0); +} + +static int map002_init(nes_Mapper* map, const ines_Header* hdr, + nes_Memory* mem) { + int last_bank = (mem->n_rom_banks / 2) - 1; + mem->rom_bank[2] = prg_rom_page(mem, (last_bank * 2) + 0); + mem->rom_bank[3] = prg_rom_page(mem, (last_bank * 2) + 1); + map002_reset(map, mem); + return 0; +} + +static int map002_write_rom(nes_Mapper* map, nes_Memory* mem, + uint16_t addr, uint8_t val) { + uxrom_set_bank((map002_data*)map->data, mem, val); + return 0; +} + + +const nes_Mapper map002 = { + .name = "UxROM", + .max_chr_banks = 8, + .data_size = sizeof(map002_data), + .init = map002_init, + .reset = map002_reset, + .write_rom = map002_write_rom, +}; diff --git a/src/mapper.c b/src/mapper.c index 6b6c27e..c499337 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -3,8 +3,10 @@ extern const nes_Mapper map000; extern const nes_Mapper map001; +extern const nes_Mapper map002; const nes_Mapper* nes_mappers[256] = { &map000, &map001, + &map002, }; diff --git a/src/mapper.h b/src/mapper.h index c277cdb..598889b 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -11,6 +11,8 @@ struct nes_Memory; struct nes_Mapper { const char* name; int max_chr_banks; + int data_size; + void* data; int (*init)(struct nes_Mapper*, const ines_Header*, struct nes_Memory*); void (*done)(struct nes_Mapper*); @@ -26,8 +28,6 @@ struct nes_Mapper { void (*ppu_bus)(struct nes_Mapper*, uint16_t addr); void (*ppu_mem_mode)(struct nes_Mapper*, uint8_t mode); - - void* data; }; typedef struct nes_Mapper nes_Mapper;