summaryrefslogtreecommitdiff
path: root/mapper.c
blob: 821224dbacf8afbaf3b55da7d2eb1c62c42c2f52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64


#include "mapper_0000.c"
#include "mapper_0003.c"
#include "mapper_0007.c"
#include "mapper_000b.c"
#include "mapper_0042.c"
#include "mapper_2002.c"


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_tick(struct nes_state *state) { // No IRQ or timing logic needed
}

/*
 *  Mapper numbers are constructed like this:  (submapper << 12 | mapperid) both in hex.
 *
 *  NOTE(peter): Mapper 0 always has to be first!
 */
static struct mapper_entry mapper_table[] = {
/* Mapper:    0 */	{ 0x00,   mapper_0000_prg_read, mapper_0000_prg_write, mapper_0000_chr_read, mapper_0000_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0000_init },
/* Mapper:    3 */	{ 0x03,   mapper_0003_prg_read, mapper_0003_prg_write, mapper_0003_chr_read, mapper_0003_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0003_init },
/* Mapper:    7 */	{ 0x07,   mapper_0007_prg_read, mapper_0007_prg_write, mapper_0007_chr_read, mapper_0007_chr_write, mapper_0007_ciram_read,    mapper_0007_ciram_write,    mapper_default_tick, mapper_0007_init },
/* Mapper:    b */	{ 0x0b,   mapper_000b_prg_read, mapper_000b_prg_write, mapper_000b_chr_read, mapper_000b_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_000b_init },
/* Mapper:   66 */	{ 0x42,   mapper_0042_prg_read, mapper_0042_prg_write, mapper_0042_chr_read, mapper_0042_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_0042_init },
/* Mapper: 2002 */	{ 0x2002, mapper_2002_prg_read, mapper_2002_prg_write, mapper_2002_chr_read, mapper_2002_chr_write, mapper_default_ciram_read, mapper_default_ciram_write, mapper_default_tick, mapper_2002_init },
};

static void mapper_setup(struct nes_state *state) {
	uint32_t mapper = (state->ines.submapper << 12) | state->ines.mapper;
	for(uint32_t i = 0; i < sizeof(mapper_table)/sizeof(mapper_table[0]); i++) {
		if(mapper_table[i].id == mapper) {
			printf("Mapper %4.4x\n", mapper);
			memcpy(&state->mapper, &mapper_table[i], sizeof(struct mapper_entry));		// NOTE(peter): BECAUSE GCC IS BROKEN
			// state->mapper = mapper_table[i];
			state->mapper.init(state);
			return;
		}
	}

	printf("Unsupported mapper %4.4x, falling back to NROM\n", mapper);
	memcpy(&state->mapper, &mapper_table[0], sizeof(struct mapper_entry));		// NOTE(peter): BECAUSE GCC IS BROKEN
	// state->mapper = mapper_table[0];
	state->mapper.init(state);
}