Browse Source

Fix up MMC3 ROM banks

- Gun-Nac working great
 - Kirby menus are garbage
 - SMB3 overworld sprites are garbage
master
Nathaniel Walizer 1 year ago
parent
commit
98acb09236
3 changed files with 53 additions and 22 deletions
  1. +1
    -1
      Makefile
  2. +51
    -21
      src/map/mmc3.c
  3. +1
    -0
      src/ppu.c

+ 1
- 1
Makefile View File

@@ -1,6 +1,6 @@
CC = gcc
LD = $(CC)
PFLAGS = -g
PFLAGS = -g #-DE6502_DEBUG
CFLAGS = $(PFLAGS) -Wall -Werror -Wshadow -I..
LDFLAGS = $(PFLAGS)



+ 51
- 21
src/map/mmc3.c View File

@@ -25,6 +25,7 @@ typedef struct {
uint8_t* chr_bank[8]; // 1 KB
uint8_t* vram_bank[4];

uint8_t r[8];
mmc3_Flag flags;
uint8_t bank_select;
uint8_t irq_count;
@@ -44,17 +45,8 @@ static inline void mmc3_map_prg(mmc3_mapper* map,
map->prg_bank[reg] = mmc3_prg_bank(map, bank);
}

static inline void mmc3_update_rom_mode(mmc3_mapper* map) {
if (!(map->bank_select & mmc3_Bank_Select_PRG)) {
mmc3_map_prg(map, 2, map->prg_rom_banks - 2);
} else {
mmc3_map_prg(map, 0, map->prg_rom_banks - 2);
}
}

static inline void mmc3_update_prg(mmc3_mapper* map, uint8_t bank) {
int reg = (map->bank_select & mmc3_Bank_Select_Reg);

static inline void mmc3_update_prg(mmc3_mapper* map,
int reg, uint8_t bank) {
if (reg == 7) {
mmc3_map_prg(map, 1, bank);
} else {
@@ -72,6 +64,11 @@ static inline uint8_t* mmc3_chr_bank(mmc3_mapper* map, int bank) {

static inline void mmc3_map_2k_chr(mmc3_mapper* map,
int reg, int bank) {
bank &= ~1;
if (bank >= map->chr_rom_banks) {
MAP_LOG("CHR ROM OOB: %d > %d", bank, map->chr_rom_banks);
bank = bank % map->chr_rom_banks;
}
MAP_LOG("CHR ROM: 2k $%04x <- bank %d + %d", reg << 10, bank & ~1, bank | 1);
map->chr_bank[reg + 0] = mmc3_chr_bank(map, bank & ~1);
map->chr_bank[reg + 1] = mmc3_chr_bank(map, bank | 1);
@@ -79,13 +76,16 @@ static inline void mmc3_map_2k_chr(mmc3_mapper* map,

static inline void mmc3_map_1k_chr(mmc3_mapper* map,
int reg, int bank) {
if (bank >= map->chr_rom_banks) {
MAP_LOG("CHR ROM OOB: %d > %d", bank, map->chr_rom_banks);
bank = bank % map->chr_rom_banks;
}
MAP_LOG("CHR ROM: 1k $%04x <- bank %d", reg << 10, bank);
map->chr_bank[reg] = mmc3_chr_bank(map, bank);
}

static inline void mmc3_update_chr(mmc3_mapper* map, uint8_t bank) {
int reg = (map->bank_select & mmc3_Bank_Select_Reg);

static inline void mmc3_update_chr(mmc3_mapper* map,
int reg, uint8_t bank) {
if (!(map->bank_select & mmc3_Bank_Select_CHR)) {
if (1 >= reg) {
mmc3_map_2k_chr(map, reg * 2, bank);
@@ -102,6 +102,33 @@ static inline void mmc3_update_chr(mmc3_mapper* map, uint8_t bank) {
}
}

static inline void mmc3_update_rom_mode(mmc3_mapper* map, int val) {
uint8_t delta = map->bank_select ^ val;

map->bank_select = val;

if (delta & mmc3_Bank_Select_PRG) {
mmc3_map_prg(map, 1, map->r[7]);
if (!(val & mmc3_Bank_Select_PRG)) {
mmc3_map_prg(map, 0, map->r[6]);
mmc3_map_prg(map, 2, map->prg_rom_banks - 2);
} else {
mmc3_map_prg(map, 0, map->prg_rom_banks - 2);
mmc3_map_prg(map, 2, map->r[6]);
}

}

if (delta & mmc3_Bank_Select_CHR) {
mmc3_update_chr(map, 0, map->r[0]);
mmc3_update_chr(map, 1, map->r[1]);
mmc3_update_chr(map, 2, map->r[2]);
mmc3_update_chr(map, 3, map->r[3]);
mmc3_update_chr(map, 4, map->r[4]);
mmc3_update_chr(map, 5, map->r[5]);
}
}

static inline void mmc3_update_vram(mmc3_mapper* map) {
if (!(map->flags & mmc3_Flag_Horizontal)) {
// Vertical mirroring
@@ -119,10 +146,12 @@ static inline void mmc3_update_vram(mmc3_mapper* map) {
static void mmc3_reset(nes_mapper* nes_map) {
mmc3_mapper* map = (mmc3_mapper*)nes_map->data;
map->flags = 0;
map->bank_select = 0;
map->bank_select = mmc3_Bank_Select_PRG |
mmc3_Bank_Select_CHR;
map->irq_count = 0;
map->irq_latch = 0;
map->prg_bank[3] = mmc3_prg_bank(map, map->prg_rom_banks - 1);
mmc3_update_rom_mode(map, 0);
mmc3_map_prg(map, 3, map->prg_rom_banks - 1);
mmc3_update_vram(map);
}

@@ -192,15 +221,16 @@ static void mmc3_write(nes_mapper* nes_map,
} else if (addr < 0xA000U) {
if (addr & 1) {
// Bank data
if ((map->bank_select & mmc3_Bank_Select_Reg) >= 6) {
mmc3_update_prg(map, val);
int reg = (map->bank_select & mmc3_Bank_Select_Reg);
if (reg >= 6) {
mmc3_update_prg(map, reg, val);
} else {
mmc3_update_chr(map, val);
mmc3_update_chr(map, reg, val);
}
map->r[reg] = val;
} else {
// Bank select
map->bank_select = val;
mmc3_update_rom_mode(map);
mmc3_update_rom_mode(map, val);
}

} else if (addr < 0xC000U) {


+ 1
- 0
src/ppu.c View File

@@ -199,6 +199,7 @@ int nes_ppu_run(nes_ppu* ppu, int cycles) {

if ( NULL != ppu->mapper->scanline &&
ppu->scanline < nes_ppu_render &&
(ppu->mask & (ppu_Mask_Back | ppu_Mask_Sprite)) &&
ppu->cycle < 260 && next_cycle >= 260) {
ppu->mapper->scanline(ppu->mapper);
}


Loading…
Cancel
Save