|
|
|
@@ -0,0 +1,96 @@ |
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
#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, |
|
|
|
}; |