#include #include #include "map.h" typedef struct { uint8_t* prg_rom; int prg_rom_banks; uint8_t mirror; uint8_t bank; 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_set_bank(uxrom_mapper* map, uint8_t bank) { map->bank = (bank % map->prg_rom_banks); map->prg_bank_lo = &map->prg_rom[ map->bank * nes_prg_rom_page_size ]; } static void uxrom_reset(void* data) { uxrom_mapper* map = (uxrom_mapper*)data; uxrom_set_bank(map, 0); map->prg_bank_lo = map->prg_rom; } static void* uxrom_init(nes_mapper* nes_map, nes_cart* cart) { uxrom_mapper* map = calloc(1, sizeof(uxrom_mapper)); 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(map); } return map; } static void uxrom_done(void* data) { free(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(void* _map, uint16_t addr) { uint8_t val = 0; if (addr >= nes_mem_rom_start) { val = *(uxrom_prg_addr((uxrom_mapper*)_map, addr)); } return val; } static void uxrom_write(void* _map, uint16_t addr, uint8_t val) { uxrom_mapper* map = (uxrom_mapper*)_map; if (addr >= nes_mem_rom_start) { uxrom_set_bank(map, val); } } static uint8_t* uxrom_chr_addr(void* data, uint16_t addr) { return &((uxrom_mapper*)data)->chr_ram[addr]; } static uint8_t* uxrom_vram_addr(void* data, uint16_t addr) { uxrom_mapper* map = (uxrom_mapper*)data; int page = addr >> 10U; page >>= map->mirror; addr = ((page & 1) << 10U) | (addr & 0x3FFU); return &map->vram[addr]; } static void uxrom_chr_write(void* data, uint16_t addr, uint8_t val) { ((uxrom_mapper*)data)->chr_ram[addr] = val; } /* Save State */ int uxrom_state_size(const void* _map) { uxrom_mapper* map = (uxrom_mapper*)_map; return ( sizeof(uint32_t) + sizeof(map->vram) + sizeof(map->chr_ram)); } int uxrom_state_read(void* _map, const void* data) { uxrom_mapper* map = (uxrom_mapper*)_map; const void* ptr = data; map->bank = *(uint32_t*)ptr; ptr += sizeof(uint32_t); memcpy(map->vram, ptr, sizeof(map->vram)); ptr += sizeof(map->vram); memcpy(map->chr_ram, ptr, sizeof(map->chr_ram)); ptr += sizeof(map->chr_ram); return (ptr - data); } int uxrom_state_write(const void* _map, void* data) { uxrom_mapper* map = (uxrom_mapper*)_map; void* ptr = data; uint32_t bank = map->bank; memcpy(ptr, &bank, sizeof(bank)); ptr += sizeof(bank); memcpy(ptr, map->vram, sizeof(map->vram)); ptr += sizeof(map->vram); memcpy(ptr, map->chr_ram, sizeof(map->chr_ram)); ptr += sizeof(map->chr_ram); return (ptr - data); } nes_mapper mapper_uxrom = { .name = "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, .state_size = uxrom_state_size, .state_read = uxrom_state_read, .state_write = uxrom_state_write, };