diff options
| author | Peter Fors <peter.fors@mindkiller.com> | 2025-11-02 09:16:03 +0100 |
|---|---|---|
| committer | Peter Fors <peter.fors@mindkiller.com> | 2025-11-02 09:16:03 +0100 |
| commit | ed41715142f419021ed8fef5522ea1f363f16441 (patch) | |
| tree | 9cf0049db6ac5b0da5552bba9e0376b82eaeb2b4 /mappers | |
| parent | e137c881d835703d1030746cd7262899de7169c6 (diff) | |
fix multiple mappers
Diffstat (limited to 'mappers')
| -rw-r--r-- | mappers/mapper_001_0.c | 231 | ||||
| -rw-r--r-- | mappers/mapper_001_0.h | 2 | ||||
| -rw-r--r-- | mappers/mapper_007_2.c | 2 | ||||
| -rw-r--r-- | mappers/mapper_011_0.c | 16 | ||||
| -rw-r--r-- | mappers/mapper_011_0.h | 2 |
5 files changed, 134 insertions, 119 deletions
diff --git a/mappers/mapper_001_0.c b/mappers/mapper_001_0.c index a449fe7..bf2f5db 100644 --- a/mappers/mapper_001_0.c +++ b/mappers/mapper_001_0.c @@ -1,90 +1,102 @@ -static uint8_t mapper_001_0_prg_rom_read(struct nes_state *state, uint32_t addr) { + +__attribute__((always_inline)) +static inline void mapper_001_0_apply_chr_banks(struct nes_state *state) { struct mapper_001_0 *mapper = &state->mapper_data.m001_0; - if(addr >= 0x8000) { - if(addr < 0xc000) { - return mapper->prg_rom_0[addr & 0x3fff]; + if(!state->ines.chr_size) { + return; + } + + if(mapper->control & 0x10) { + // 4KB CHR mode + mapper->chr_bank_0 = state->chr_rom + (mapper->chr_bank0 * 0x1000); + mapper->chr_bank_1 = state->chr_rom + (mapper->chr_bank1 * 0x1000); + } else { + // 8KB CHR mode - ignore bit 0 of bank number + mapper->chr_bank_0 = state->chr_rom + ((mapper->chr_bank0 & 0xfe) * 0x1000); + mapper->chr_bank_1 = state->chr_rom + ((mapper->chr_bank0 & 0xfe) * 0x1000) + 0x1000; + } +} + +__attribute__((always_inline)) +static inline void mapper_001_0_apply_prg_banks(struct nes_state *state) { + struct mapper_001_0 *mapper = &state->mapper_data.m001_0; + + if(mapper->control & 0x08) { + // 16KB PRG mode + if(mapper->control & 0x04) { + // Fix last bank at $C000, switch first bank at $8000 + mapper->prg_rom_0 = state->prg_rom + (mapper->prg_bank * 0x4000); + mapper->prg_rom_1 = state->prg_rom + (state->ines.prg_size - 0x4000); } else { - return mapper->prg_rom_1[addr & 0x3fff]; + // Fix first bank at $8000, switch last bank at $C000 + mapper->prg_rom_0 = state->prg_rom; + mapper->prg_rom_1 = state->prg_rom + (mapper->prg_bank * 0x4000); } + } else { + // 32KB PRG mode - ignore bit 0 + uint32_t base = (mapper->prg_bank & 0x0e) * 0x4000; + mapper->prg_rom_0 = state->prg_rom + base; + mapper->prg_rom_1 = state->prg_rom + base + 0x4000; } - return 0; } -static void mapper_001_0_prg_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) { +__attribute__((always_inline)) +static inline void mapper_001_0_write_control(struct nes_state *state, uint8_t value) { struct mapper_001_0 *mapper = &state->mapper_data.m001_0; -printf("MMC1 write: addr=%04x val=%02x\n", addr, value); + mapper->control = value; + mapper_001_0_apply_chr_banks(state); + mapper_001_0_apply_prg_banks(state); +} - if(addr < 0x8000) { - return; +static uint8_t mapper_001_0_prg_rom_read(struct nes_state *state, uint32_t addr) { + struct mapper_001_0 *mapper = &state->mapper_data.m001_0; + + if(addr < 0xc000) { + return mapper->prg_rom_0[addr & 0x3fff]; } + return mapper->prg_rom_1[addr & 0x3fff]; +} + +static void mapper_001_0_prg_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) { + struct mapper_001_0 *mapper = &state->mapper_data.m001_0; if(value & 0x80) { - mapper->shift = 0; + mapper->shift_accumulator = 0; mapper->shift_count = 0; - mapper->control |= 0x0c; + mapper_001_0_write_control(state, mapper->control | 0x0c); return; } - mapper->shift |= (value & 1) << mapper->shift_count; + mapper->shift_accumulator |= (value & 1) << mapper->shift_count; mapper->shift_count++; if(mapper->shift_count == 5) { uint8_t reg = (addr >> 13) & 3; switch(reg) { - case 0: { - mapper->control = mapper->shift; - switch(mapper->control & 3) { - case 0: { - state->ines.mirroring = MIRROR_ONESCREEN_LOW; - } break; - - case 1: { - state->ines.mirroring = MIRROR_ONESCREEN_HIGH; - } break; - - case 2: { - state->ines.mirroring = MIRROR_VERTICAL; - } break; - - case 3: { - state->ines.mirroring = MIRROR_HORIZONTAL; - } break; - } - } break; - - case 1: { - mapper->chr_bank0 = mapper->shift; - mapper->chr_bank_0 = state->chr_rom + (mapper->chr_bank0 * 0x1000); - } break; - - case 2: { - mapper->chr_bank1 = mapper->shift; - mapper->chr_bank_1 = state->chr_rom + (mapper->chr_bank1 * 0x1000); - } break; - - case 3: { - mapper->prg_bank = mapper->shift & 0x0f; - - if(mapper->control & 0x08) { - if(mapper->control & 0x04) { - mapper->prg_rom_0 = state->prg_rom; - mapper->prg_rom_1 = state->prg_rom + (mapper->prg_bank * 0x4000); - } else { - mapper->prg_rom_0 = state->prg_rom + (mapper->prg_bank * 0x4000); - mapper->prg_rom_1 = state->prg_rom + (state->ines.prg_size - 0x4000); - } - } else { - uint32_t base = (mapper->prg_bank & 0x0e) * 0x4000; - mapper->prg_rom_0 = state->prg_rom + base; - mapper->prg_rom_1 = state->prg_rom + base + 0x4000; - } - } break; + case 0: + mapper_001_0_write_control(state, mapper->shift_accumulator); + break; + + case 1: + mapper->chr_bank0 = mapper->shift_accumulator; + mapper_001_0_apply_chr_banks(state); + break; + + case 2: + mapper->chr_bank1 = mapper->shift_accumulator; + mapper_001_0_apply_chr_banks(state); + break; + + case 3: + mapper->prg_bank = mapper->shift_accumulator & 0x0f; + mapper_001_0_apply_prg_banks(state); + break; } - mapper->shift = 0; + mapper->shift_accumulator = 0; mapper->shift_count = 0; } } @@ -92,83 +104,92 @@ printf("MMC1 write: addr=%04x val=%02x\n", addr, value); static uint8_t mapper_001_0_chr_read(struct nes_state *state, uint32_t addr) { struct mapper_001_0 *mapper = &state->mapper_data.m001_0; + if(state->ines.chr_size == 0) { + // CHR-RAM - no banking + return state->chr_ram[addr]; + } + + // CHR-ROM - use banking + uint8_t val; if(mapper->control & 0x10) { + // 4KB CHR mode if(addr < 0x1000) { - return mapper->chr_bank_0[addr & 0xfff]; + val = mapper->chr_bank_0[addr & 0xfff]; } else { - return mapper->chr_bank_1[addr & 0xfff]; + val = mapper->chr_bank_1[addr & 0xfff]; } } else { - return mapper->chr_bank_0[addr & 0x1fff]; + // 8KB CHR mode + val = mapper->chr_bank_0[addr & 0x1fff]; } + return val; } static void mapper_001_0_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { state->chr_ram[addr] = value; } +static uint8_t mapper_001_0_prg_ram_read(struct nes_state *state, uint32_t addr) { + return state->sram[addr & 0x1fff]; +} + +static void mapper_001_0_prg_ram_write(struct nes_state *state, uint32_t addr, uint8_t value) { + state->sram[addr & 0x1fff] = value; +} + static uint8_t mapper_001_0_ciram_read(struct nes_state *state, uint32_t addr) { - // MMC1 can set mirroring mode dynamically via control register - switch(state->ines.mirroring) { - case MIRROR_ONESCREEN_LOW: - addr = addr & 0x3ff; - break; - case MIRROR_ONESCREEN_HIGH: - addr = 0x400 | (addr & 0x3ff); - break; - case MIRROR_HORIZONTAL: // Horizontal: NT0↔NT1, NT2↔NT3 - addr = ((addr >> 1) & 0x400) | (addr & 0x3ff); - break; - case MIRROR_VERTICAL: // Vertical: NT0↔NT2, NT1↔NT3 - addr = addr & 0x7ff; - break; + struct mapper_001_0 *mapper = &state->mapper_data.m001_0; + + switch(mapper->control & 3) { + case 0: return state->ciram[addr & 0x3ff]; // one-screen lower + case 1: return state->ciram[0x400 | (addr & 0x3ff)]; // one-screen upper + case 2: return state->ciram[addr & 0x7ff]; // vertical + case 3: return state->ciram[((addr >> 1) & 0x400) | (addr & 0x3ff)]; // horizontal } - return state->ciram[addr]; + return 0; } static void mapper_001_0_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) { - // MMC1 can set mirroring mode dynamically via control register - switch(state->ines.mirroring) { - case MIRROR_ONESCREEN_LOW: - addr = addr & 0x3ff; - break; - case MIRROR_ONESCREEN_HIGH: - addr = 0x400 | (addr & 0x3ff); - break; - case MIRROR_HORIZONTAL: // Horizontal: NT0↔NT1, NT2↔NT3 - addr = ((addr >> 1) & 0x400) | (addr & 0x3ff); - break; - case MIRROR_VERTICAL: // Vertical: NT0↔NT2, NT1↔NT3 - addr = addr & 0x7ff; - break; + struct mapper_001_0 *mapper = &state->mapper_data.m001_0; + + switch(mapper->control & 3) { + case 0: { // one-screen lower + state->ciram[addr & 0x3ff] = value; + } break; + case 1: { // one-screen upper + state->ciram[0x400 | (addr & 0x3ff)] = value; + } break; + case 2: { // vertical + state->ciram[addr & 0x7ff] = value; + } break; + case 3: { // horizontal + state->ciram[((addr >> 1) & 0x400) | (addr & 0x3ff)] = value; + } break; } - state->ciram[addr] = value; } static void mapper_001_0_init(struct nes_state *state) { struct mapper_001_0 *mapper = &state->mapper_data.m001_0; - mapper->shift = 0; - mapper->shift_count = 0; - mapper->control = 0x0c; + memset(mapper, 0, sizeof(struct mapper_001_0)); - mapper->prg_bank = 0; - mapper->chr_bank0 = 0; - mapper->chr_bank1 = 0; + mapper->control = 0x0c; - mapper->prg_rom_0 = state->prg_rom; - mapper->prg_rom_1 = state->prg_rom + (state->ines.prg_size - 0x4000); + mapper_001_0_apply_prg_banks(state); if(state->ines.chr_size) { - mapper->chr_bank_0 = state->chr_rom; - mapper->chr_bank_1 = state->chr_rom + 0x1000; + // CHR-ROM - apply banking + mapper_001_0_apply_chr_banks(state); } else { + // CHR-RAM - no banking, point directly to RAM mapper->chr_bank_0 = state->chr_ram; mapper->chr_bank_1 = state->chr_ram + 0x1000; } state->mapper_function.prg_rom_read = mapper_001_0_prg_rom_read; state->mapper_function.prg_rom_write = mapper_001_0_prg_rom_write; + state->mapper_function.prg_ram_read = mapper_001_0_prg_ram_read; + state->mapper_function.prg_ram_write = mapper_001_0_prg_ram_write; state->mapper_function.chr_read = mapper_001_0_chr_read; state->mapper_function.chr_write = mapper_001_0_chr_write; state->mapper_function.ciram_read = mapper_001_0_ciram_read; diff --git a/mappers/mapper_001_0.h b/mappers/mapper_001_0.h index deb0e29..18dfec9 100644 --- a/mappers/mapper_001_0.h +++ b/mappers/mapper_001_0.h @@ -1,6 +1,6 @@ struct mapper_001_0 { - uint8_t shift; + uint8_t shift_accumulator; uint8_t shift_count; uint8_t control; uint8_t prg_bank; diff --git a/mappers/mapper_007_2.c b/mappers/mapper_007_2.c index 9f5a3dc..3987956 100644 --- a/mappers/mapper_007_2.c +++ b/mappers/mapper_007_2.c @@ -42,7 +42,7 @@ static void mapper_007_2_ciram_write(struct nes_state *state, uint32_t addr, uin static void mapper_007_2_init(struct nes_state *state) { struct mapper_007_2 *mapper = &state->mapper_data.m007_2; mapper->prg_rom = state->prg_rom; - mapper->ciram = 0; + mapper->ciram = state->ciram; // << THIS WAS THE BUG, set ciram = 0, zero understanding to how this worked for 6+ months. state->mapper_function.prg_rom_read = mapper_007_2_prg_rom_read; state->mapper_function.prg_rom_write = mapper_007_2_prg_rom_write; diff --git a/mappers/mapper_011_0.c b/mappers/mapper_011_0.c index 12b68ba..6b31f26 100644 --- a/mappers/mapper_011_0.c +++ b/mappers/mapper_011_0.c @@ -1,33 +1,27 @@ static uint8_t mapper_011_0_prg_rom_read(struct nes_state *state, uint32_t addr) { struct mapper_011_0 *mapper = &state->mapper_data.m011_0; - - if(addr >= 0x8000) { - return mapper->prg_rom[addr - 0x8000]; - } - return 0; + return mapper->prg_rom[addr & 0x7fff]; } static void mapper_011_0_prg_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) { struct mapper_011_0 *mapper = &state->mapper_data.m011_0; - if(addr >= 0x8000) { - mapper->prg_rom = state->prg_rom + ((value >> 4) & 7) * 0x8000; - mapper->chr_ptr = state->chr_rom + (value & 0x0F) * 0x2000; - } + mapper->prg_rom = state->prg_rom + (value & 0x3) * 0x8000; + mapper->chr_rom = state->chr_rom + ((value >> 4) & 0x3) * 0x2000; } static uint8_t mapper_011_0_chr_read(struct nes_state *state, uint32_t addr) { struct mapper_011_0 *mapper = &state->mapper_data.m011_0; - return mapper->chr_ptr[addr]; + return mapper->chr_rom[addr]; } static void mapper_011_0_init(struct nes_state *state) { struct mapper_011_0 *mapper = &state->mapper_data.m011_0; mapper->prg_rom = state->prg_rom; - mapper->chr_ptr = state->chr_rom; + mapper->chr_rom = state->chr_rom; state->mapper_function.prg_rom_read = mapper_011_0_prg_rom_read; state->mapper_function.prg_rom_write = mapper_011_0_prg_rom_write; diff --git a/mappers/mapper_011_0.h b/mappers/mapper_011_0.h index 8f41e8e..5cb6ebf 100644 --- a/mappers/mapper_011_0.h +++ b/mappers/mapper_011_0.h @@ -2,5 +2,5 @@ struct mapper_011_0 { uint8_t *prg_rom; - uint8_t *chr_ptr; + uint8_t *chr_rom; } __attribute__((packed, aligned(64))); |
