summaryrefslogtreecommitdiff
path: root/mappers
diff options
context:
space:
mode:
Diffstat (limited to 'mappers')
-rw-r--r--mappers/mapper.c63
-rw-r--r--mappers/mapper.h29
-rw-r--r--mappers/mapper_000_0.c22
-rw-r--r--mappers/mapper_000_0.h6
-rw-r--r--mappers/mapper_002_2.c41
-rw-r--r--mappers/mapper_002_2.h7
-rw-r--r--mappers/mapper_003_0.c27
-rw-r--r--mappers/mapper_003_0.h4
-rw-r--r--mappers/mapper_007_2.c53
-rw-r--r--mappers/mapper_007_2.h8
-rw-r--r--mappers/mapper_011_0.c37
-rw-r--r--mappers/mapper_011_0.h6
-rw-r--r--mappers/mapper_066_0.c38
-rw-r--r--mappers/mapper_066_0.h5
14 files changed, 346 insertions, 0 deletions
diff --git a/mappers/mapper.c b/mappers/mapper.c
new file mode 100644
index 0000000..d63e2a0
--- /dev/null
+++ b/mappers/mapper.c
@@ -0,0 +1,63 @@
+
+static uint8_t mapper_default_ciram_read(struct nes_state *state, uint32_t addr) {
+ if(state->ines.mirroring == 0) { // Horizontal
+ addr = (addr & 0x800) | (addr & 0x3ff);
+ } else { // Vertical (default fallback)
+ addr = addr & 0x7ff;
+ }
+
+ return state->ciram[addr];
+}
+
+static void mapper_default_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ if(state->ines.mirroring == 0) {
+ addr = (addr & 0x800) | (addr & 0x3ff);
+ } else {
+ addr = addr & 0x7ff;
+ }
+ state->ciram[addr] = value;
+}
+
+static void mapper_default_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) { }
+static void mapper_default_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) { }
+static void mapper_default_tick(struct nes_state *state) { }
+
+#include "mapper_000_0.c"
+#include "mapper_002_2.c"
+#include "mapper_003_0.c"
+#include "mapper_007_2.c"
+#include "mapper_011_0.c"
+#include "mapper_066_0.c"
+
+#define MAPPER_ID(mapper, submapper) (((mapper) << 4) | (submapper))
+
+static void (*mapper_table[4096])(struct nes_state *state) = {
+ [MAPPER_ID( 0, 0)] = mapper_000_0_init,
+ [MAPPER_ID( 2, 2)] = mapper_002_2_init,
+ [MAPPER_ID( 3, 0)] = mapper_003_0_init,
+ [MAPPER_ID( 7, 2)] = mapper_007_2_init,
+ [MAPPER_ID(11, 0)] = mapper_011_0_init,
+ [MAPPER_ID(66, 0)] = mapper_011_0_init,
+};
+
+static void mapper_reset(struct nes_state *state) {
+ state->mapper.prg_read = 0;
+ state->mapper.prg_write = mapper_default_prg_write;
+ state->mapper.chr_read = 0;
+ state->mapper.chr_write = mapper_default_chr_write;
+ state->mapper.ciram_read = mapper_default_ciram_read;
+ state->mapper.ciram_write = mapper_default_ciram_write;
+ state->mapper.tick = mapper_default_tick;
+}
+
+static void mapper_setup(struct nes_state *state) {
+ uint32_t mapper = state->ines.mapper << 4 | state->ines.submapper;
+ mapper_reset(state);
+ if(mapper_table[mapper]) {
+ mapper_table[mapper](state);
+ } else {
+ printf("Unsupported mapper %d_%x, falling back to NROM\n", state->ines.mapper, state->ines.submapper);
+ mapper_table[0](state);
+ }
+}
+
diff --git a/mappers/mapper.h b/mappers/mapper.h
new file mode 100644
index 0000000..0961370
--- /dev/null
+++ b/mappers/mapper.h
@@ -0,0 +1,29 @@
+
+#include "mapper_000_0.h"
+#include "mapper_002_2.h"
+#include "mapper_003_0.h"
+#include "mapper_007_2.h"
+#include "mapper_011_0.h"
+#include "mapper_066_0.h"
+
+struct nes_state;
+
+struct mapper_functions {
+ uint8_t (*prg_read)(struct nes_state *state, uint32_t addr);
+ void (*prg_write)(struct nes_state *state, uint32_t addr, uint8_t value);
+ uint8_t (*chr_read)(struct nes_state *state, uint32_t addr);
+ void (*chr_write)(struct nes_state *state, uint32_t addr, uint8_t value);
+ uint8_t (*ciram_read)(struct nes_state *state, uint32_t addr);
+ void (*ciram_write)(struct nes_state *state, uint32_t addr, uint8_t value);
+ void (*tick)(struct nes_state *state);
+} __attribute__((aligned(64)));
+
+union mapper_data {
+ struct mapper_000_0 m000_0;
+ struct mapper_002_2 m002_2;
+ struct mapper_003_0 m003_0;
+ struct mapper_007_2 m007_2;
+ struct mapper_011_0 m011_0;
+ struct mapper_066_0 m066_0;
+} __attribute__((aligned(64)));
+
diff --git a/mappers/mapper_000_0.c b/mappers/mapper_000_0.c
new file mode 100644
index 0000000..b79cdbf
--- /dev/null
+++ b/mappers/mapper_000_0.c
@@ -0,0 +1,22 @@
+
+
+__attribute__((hot))
+static uint8_t mapper_000_0_prg_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_000_0 *mapper = (struct mapper_000_0 *)&state->map;
+
+ return state->prg_rom[addr & mapper->mask];
+}
+
+__attribute__((hot))
+static uint8_t mapper_000_0_chr_read(struct nes_state *state, uint32_t addr) {
+ return state->chr_rom[addr];
+}
+
+static void mapper_000_0_init(struct nes_state *state) {
+ struct mapper_000_0 *mapper = (struct mapper_000_0 *)&state->map;
+ state->mapper.prg_read = mapper_000_0_prg_read;
+ state->mapper.chr_read = mapper_000_0_chr_read;
+ mapper->mask = (state->ines.prg_size == 16384) ? 0x3fff : 0x7fff;
+}
+
+
diff --git a/mappers/mapper_000_0.h b/mappers/mapper_000_0.h
new file mode 100644
index 0000000..86e279c
--- /dev/null
+++ b/mappers/mapper_000_0.h
@@ -0,0 +1,6 @@
+
+
+
+struct mapper_000_0 {
+ uint32_t mask;
+} __attribute__((packed, aligned(64)));
diff --git a/mappers/mapper_002_2.c b/mappers/mapper_002_2.c
new file mode 100644
index 0000000..079fb0b
--- /dev/null
+++ b/mappers/mapper_002_2.c
@@ -0,0 +1,41 @@
+
+
+static uint8_t mapper_002_2_prg_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map;
+
+ if(addr >= 0x8000 && addr < 0xc000) {
+ return mapper->prg_bank0[addr & 0x3fff];
+
+ } else if(addr >= 0xc000) {
+ return mapper->prg_bank1[addr & 0x3fff];
+ }
+ return 0;
+}
+
+static void mapper_002_2_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map;
+
+ if(addr >= 0x8000) {
+ mapper->prg_bank0 = state->prg_rom + ((value & 0x0f) * 0x4000);
+ }
+}
+
+static uint8_t mapper_002_2_chr_read(struct nes_state *state, uint32_t addr) {
+ return state->chr_ram[addr];
+}
+
+static void mapper_002_2_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ state->chr_ram[addr] = value;
+}
+
+static void mapper_002_2_init(struct nes_state *state) {
+ struct mapper_002_2 *mapper = (struct mapper_002_2 *)&state->map;
+
+ mapper->prg_bank0 = state->prg_rom;
+ mapper->prg_bank1 = state->prg_rom + state->ines.prg_size - 0x4000;
+
+ state->mapper.prg_read = mapper_002_2_prg_read;
+ state->mapper.prg_write = mapper_002_2_prg_write;
+ state->mapper.chr_read = mapper_002_2_chr_read;
+ state->mapper.chr_write = mapper_002_2_chr_write;
+}
diff --git a/mappers/mapper_002_2.h b/mappers/mapper_002_2.h
new file mode 100644
index 0000000..b136274
--- /dev/null
+++ b/mappers/mapper_002_2.h
@@ -0,0 +1,7 @@
+
+
+
+struct mapper_002_2 {
+ uint8_t *prg_bank0; // $8000–BFFF (switchable)
+ uint8_t *prg_bank1; // $C000–FFFF (fixed to last 16KB)
+} __attribute__((packed, aligned(64)));
diff --git a/mappers/mapper_003_0.c b/mappers/mapper_003_0.c
new file mode 100644
index 0000000..5ccfb53
--- /dev/null
+++ b/mappers/mapper_003_0.c
@@ -0,0 +1,27 @@
+
+static uint8_t mapper_003_0_prg_read(struct nes_state *state, uint32_t addr) {
+ return state->prg_rom[addr & 0x7fff];
+}
+
+static void mapper_003_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map;
+
+ if(addr >= 0x8000) {
+ mapper->chr_ptr = state->chr_rom + (value & 3) * 0x2000;
+ }
+}
+
+static uint8_t mapper_003_0_chr_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map;
+ return mapper->chr_ptr[addr];
+}
+
+static void mapper_003_0_init(struct nes_state *state) {
+ struct mapper_003_0 *mapper = (struct mapper_003_0 *)&state->map;
+
+ mapper->chr_ptr = state->chr_rom;
+
+ state->mapper.prg_read = mapper_003_0_prg_read;
+ state->mapper.prg_write = mapper_003_0_prg_write;
+ state->mapper.chr_read = mapper_003_0_chr_read;
+}
diff --git a/mappers/mapper_003_0.h b/mappers/mapper_003_0.h
new file mode 100644
index 0000000..f03b106
--- /dev/null
+++ b/mappers/mapper_003_0.h
@@ -0,0 +1,4 @@
+
+struct mapper_003_0 {
+ uint8_t *chr_ptr;
+} __attribute__((packed, aligned(64)));
diff --git a/mappers/mapper_007_2.c b/mappers/mapper_007_2.c
new file mode 100644
index 0000000..ed56dd0
--- /dev/null
+++ b/mappers/mapper_007_2.c
@@ -0,0 +1,53 @@
+
+
+static uint8_t mapper_007_2_prg_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map;
+ if(addr >= 0x8000) {
+ return mapper->prg_rom[addr & 0x7fff];
+ }
+ return 0;
+}
+
+static void mapper_007_2_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map;
+ if(addr >= 0x8000) {
+ uint32_t prg_off = (value & 0x0f) << 15;
+ uint32_t ciram_off = (value & 0x10) << 11;
+ mapper->prg_rom = state->prg_rom + prg_off;
+ mapper->ciram = state->ciram + ciram_off;
+
+ // mapper->prg_rom = state->prg_rom + ((value & 0x0f) * 0x8000);
+ // mapper->ciram = state->ciram + ((value & 0x10) ? 0x400 : 0x000);
+ }
+}
+
+static uint8_t mapper_007_2_chr_read(struct nes_state *state, uint32_t addr) {
+ return state->chr_ram[addr];
+}
+
+static void mapper_007_2_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ state->chr_ram[addr] = value;
+}
+
+static uint8_t mapper_007_2_ciram_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map;
+ return mapper->ciram[addr & 0x3ff];
+}
+
+static void mapper_007_2_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map;
+ mapper->ciram[addr & 0x3ff] = value;
+}
+
+static void mapper_007_2_init(struct nes_state *state) {
+ struct mapper_007_2 *mapper = (struct mapper_007_2 *)&state->map;
+ mapper->prg_rom = state->prg_rom;
+ mapper->ciram = 0;
+
+ state->mapper.prg_read = mapper_007_2_prg_read;
+ state->mapper.prg_write = mapper_007_2_prg_write;
+ state->mapper.chr_read = mapper_007_2_chr_read;
+ state->mapper.chr_write = mapper_007_2_chr_write;
+ state->mapper.ciram_read = mapper_007_2_ciram_read;
+ state->mapper.ciram_write = mapper_007_2_ciram_write;
+}
diff --git a/mappers/mapper_007_2.h b/mappers/mapper_007_2.h
new file mode 100644
index 0000000..c0a2d06
--- /dev/null
+++ b/mappers/mapper_007_2.h
@@ -0,0 +1,8 @@
+
+
+struct mapper_007_2 {
+ uint8_t *prg_rom;
+ uint8_t *ciram;
+ // uint32_t ciram_base;
+} __attribute__((packed, aligned(64)));
+
diff --git a/mappers/mapper_011_0.c b/mappers/mapper_011_0.c
new file mode 100644
index 0000000..ce390a0
--- /dev/null
+++ b/mappers/mapper_011_0.c
@@ -0,0 +1,37 @@
+
+
+static uint8_t mapper_011_0_prg_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map;
+
+ if(addr >= 0x8000) {
+ return mapper->prg_rom[addr - 0x8000];
+ }
+ return 0;
+}
+
+static void mapper_011_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map;
+
+ if(addr >= 0x8000) {
+ mapper->prg_rom = state->prg_rom + ((value >> 4) & 7) * 0x8000;
+ mapper->chr_ptr = state->chr_rom + (value & 0x0F) * 0x2000;
+ }
+}
+
+static uint8_t mapper_011_0_chr_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map;
+
+ return mapper->chr_ptr[addr];
+}
+
+static void mapper_011_0_init(struct nes_state *state) {
+ struct mapper_011_0 *mapper = (struct mapper_011_0 *)&state->map;
+
+ mapper->prg_rom = state->prg_rom;
+ mapper->chr_ptr = state->chr_rom;
+
+ state->mapper.prg_read = mapper_011_0_prg_read;
+ state->mapper.prg_write = mapper_011_0_prg_write;
+ state->mapper.chr_read = mapper_011_0_chr_read;
+}
+
diff --git a/mappers/mapper_011_0.h b/mappers/mapper_011_0.h
new file mode 100644
index 0000000..8f41e8e
--- /dev/null
+++ b/mappers/mapper_011_0.h
@@ -0,0 +1,6 @@
+
+
+struct mapper_011_0 {
+ uint8_t *prg_rom;
+ uint8_t *chr_ptr;
+} __attribute__((packed, aligned(64)));
diff --git a/mappers/mapper_066_0.c b/mappers/mapper_066_0.c
new file mode 100644
index 0000000..bf31720
--- /dev/null
+++ b/mappers/mapper_066_0.c
@@ -0,0 +1,38 @@
+
+static uint8_t mapper_066_0_prg_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map;
+
+ if(addr >= 0x8000) {
+ return state->prg_rom[addr & 0x7fff];
+ }
+ return 0;
+}
+
+static void mapper_066_0_prg_write(struct nes_state *state, uint32_t addr, uint8_t value) {
+ struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map;
+
+ if(addr >= 0x8000) {
+ uint32_t prg_bank = (value >> 4) & 3;
+ uint32_t chr_bank = (value >> 0) & 3;
+
+ mapper->prg_offset = state->prg_rom + (prg_bank * 0x8000);
+ mapper->chr_offset = state->chr_rom + (chr_bank * 0x2000);
+ }
+}
+
+static uint8_t mapper_066_0_chr_read(struct nes_state *state, uint32_t addr) {
+ struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map;
+ return mapper->chr_offset[addr];
+}
+
+static void mapper_066_0_init(struct nes_state *state) {
+ struct mapper_066_0 *mapper = (struct mapper_066_0 *)&state->map;
+
+ mapper->prg_offset = state->prg_rom;
+ mapper->chr_offset = state->chr_rom;
+
+ state->mapper.prg_read = mapper_066_0_prg_read;
+ state->mapper.prg_write = mapper_066_0_prg_write;
+ state->mapper.chr_read = mapper_066_0_chr_read;
+}
+
diff --git a/mappers/mapper_066_0.h b/mappers/mapper_066_0.h
new file mode 100644
index 0000000..b09ee56
--- /dev/null
+++ b/mappers/mapper_066_0.h
@@ -0,0 +1,5 @@
+
+struct mapper_066_0 {
+ uint8_t *prg_offset;
+ uint8_t *chr_offset;
+} __attribute__((packed, aligned(64)));