summaryrefslogtreecommitdiff
path: root/mappers
diff options
context:
space:
mode:
Diffstat (limited to 'mappers')
-rw-r--r--mappers/mapper_001_0.c231
-rw-r--r--mappers/mapper_001_0.h2
-rw-r--r--mappers/mapper_007_2.c2
-rw-r--r--mappers/mapper_011_0.c16
-rw-r--r--mappers/mapper_011_0.h2
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)));