|
|
|
@@ -4,9 +4,10 @@ |
|
|
|
|
|
|
|
|
|
|
|
typedef struct { |
|
|
|
// TODO: Does this even support CHR ROM? |
|
|
|
uint8_t* prg_rom; |
|
|
|
int prg_rom_banks; |
|
|
|
uint8_t* chr_rom; |
|
|
|
int chr_rom_banks; |
|
|
|
|
|
|
|
uint8_t reg_shift; |
|
|
|
uint8_t reg_n_shift; |
|
|
|
@@ -19,8 +20,10 @@ typedef struct { |
|
|
|
uint8_t* vram_bank[4]; |
|
|
|
uint8_t* prg_bank[2]; |
|
|
|
|
|
|
|
uint8_t* chr_ram; |
|
|
|
uint8_t* chr; |
|
|
|
|
|
|
|
uint8_t vram[2][nes_vram_page_size]; |
|
|
|
uint8_t chr[32][nes_chr_page_size]; |
|
|
|
uint8_t wram[nes_mem_wram_size]; |
|
|
|
} mmc1_mapper; |
|
|
|
|
|
|
|
@@ -54,12 +57,16 @@ static void mmc1_update_chr(mmc1_mapper* map) { |
|
|
|
if (!(map->reg_control & 0b10000)) { |
|
|
|
int bank = (map->reg_chr_0 & 0b11110); |
|
|
|
MAP_LOG("CHR: 8 KB: %d + %d", bank, bank + 1); |
|
|
|
map->chr_bank[0] = map->chr[bank]; |
|
|
|
map->chr_bank[1] = map->chr[bank + 1]; |
|
|
|
map->chr_bank[0] = &map->chr[ bank * |
|
|
|
nes_chr_page_size]; |
|
|
|
map->chr_bank[1] = &map->chr[ (bank + 1) * |
|
|
|
nes_chr_page_size]; |
|
|
|
} else { |
|
|
|
MAP_LOG("CHR: %d + %d", map->reg_chr_0, map->reg_chr_1); |
|
|
|
map->chr_bank[0] = map->chr[map->reg_chr_0]; |
|
|
|
map->chr_bank[1] = map->chr[map->reg_chr_1]; |
|
|
|
map->chr_bank[0] = &map->chr[ map->reg_chr_0 * |
|
|
|
nes_chr_page_size]; |
|
|
|
map->chr_bank[1] = &map->chr[ map->reg_chr_1 * |
|
|
|
nes_chr_page_size]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@@ -106,13 +113,27 @@ static int mmc1_init(nes_mapper* nes_map, nes_cart* cart) { |
|
|
|
if (NULL != map) { |
|
|
|
map->prg_rom = cart->prg_rom; |
|
|
|
map->prg_rom_banks = cart->prg_rom_banks; |
|
|
|
map->chr_rom_banks = cart->chr_rom_banks / 2; |
|
|
|
if (map->chr_rom_banks > 0) { |
|
|
|
map->chr_rom = cart->chr_rom; |
|
|
|
map->chr_ram = NULL; |
|
|
|
map->chr = map->chr_rom; |
|
|
|
} else { |
|
|
|
map->chr_rom = NULL; |
|
|
|
map->chr_ram = calloc(32, nes_chr_page_size); |
|
|
|
map->chr = map->chr_ram; |
|
|
|
} |
|
|
|
|
|
|
|
mmc1_reset(nes_map); |
|
|
|
} |
|
|
|
return (NULL == map ? -1 : 0); |
|
|
|
} |
|
|
|
|
|
|
|
static void mmc1_done(nes_mapper* nes_map) { |
|
|
|
free(nes_map->data); |
|
|
|
if (NULL != nes_map->data) { |
|
|
|
free(((mmc1_mapper*)nes_map->data)->chr_ram); |
|
|
|
free(nes_map->data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline uint8_t* mmc1_prg_addr(mmc1_mapper* map, |
|
|
|
@@ -148,7 +169,7 @@ static void mmc1_write(nes_mapper* nes_map, |
|
|
|
map->reg_control |= 0b01100; |
|
|
|
mmc1_update_prg(map); |
|
|
|
} else { |
|
|
|
// TODO: Handle consective-cycle writes? |
|
|
|
// TODO: Handle consecutive-cycle writes? |
|
|
|
int done = (map->reg_shift & 1); |
|
|
|
map->reg_shift = (map->reg_shift >> 1) | |
|
|
|
((val & 1) << 4); |
|
|
|
@@ -192,8 +213,9 @@ static uint8_t* mmc1_chr_addr(nes_mapper* nes_map, |
|
|
|
|
|
|
|
static void mmc1_chr_write(nes_mapper* nes_map, |
|
|
|
uint16_t addr, uint8_t val) { |
|
|
|
// TODO: Check if this is ROM? |
|
|
|
*(mmc1_chr_addr(nes_map, addr)) = val; |
|
|
|
if (NULL != ((mmc1_mapper*)nes_map->data)->chr_ram) { |
|
|
|
*(mmc1_chr_addr(nes_map, addr)) = val; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static uint8_t* mmc1_vram_addr(nes_mapper* nes_map, |
|
|
|
@@ -206,6 +228,7 @@ static uint8_t* mmc1_vram_addr(nes_mapper* nes_map, |
|
|
|
|
|
|
|
|
|
|
|
nes_mapper mapper_mmc1 = { |
|
|
|
.name = "MMC1", |
|
|
|
.init = mmc1_init, |
|
|
|
.reset = mmc1_reset, |
|
|
|
.done = mmc1_done, |
|
|
|
|