summaryrefslogtreecommitdiff
path: root/mappers/mapper.c
blob: 0b5612bc7f40b10dbfc985a87d9373260a853c93 (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

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_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) { }
// static uint8_t	mapper_default_prg_ram_read(struct nes_state *state, uint32_t addr) { return 0; }
// static void	mapper_default_prg_ram_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) { }

__attribute__((naked)) void mapper_default_prg_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	__asm__ __volatile__("ret");
}

__attribute__((naked)) uint8_t mapper_default_prg_ram_read(struct nes_state *state, uint32_t addr) {
	__asm__ __volatile__("xor %%al, %%al\n\t" "ret" : : : "al");
}

__attribute__((naked)) void mapper_default_prg_ram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	__asm__ __volatile__("ret");
}

__attribute__((naked)) void mapper_default_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	__asm__ __volatile__("ret");
}

__attribute__((naked)) void mapper_default_tick(struct nes_state *state) {
	__asm__ __volatile__("ret");
}


#include "mapper_000_0.c"
#include "mapper_001_0.c"
#include "mapper_002_2.c"
#include "mapper_003_0.c"
#include "mapper_003_1.c"
#include "mapper_003_2.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( 1, 0)] = mapper_001_0_init,
	[MAPPER_ID( 2, 2)] = mapper_002_2_init,
	[MAPPER_ID( 3, 0)] = mapper_003_0_init,
	[MAPPER_ID( 3, 1)] = mapper_003_1_init,
	[MAPPER_ID( 3, 2)] = mapper_003_2_init,
	[MAPPER_ID( 7, 2)] = mapper_007_2_init,
	[MAPPER_ID(11, 0)] = mapper_011_0_init,
	[MAPPER_ID(66, 0)] = mapper_066_0_init,
};

// NOTE(peter): The entries with 0x0 will always have to be supplied/set by the mapper!
static void mapper_reset(struct nes_state *state) {
	state->mapper_function.prg_rom_read = 0x0;
	state->mapper_function.prg_rom_write = mapper_default_prg_rom_write;
	state->mapper_function.prg_ram_read = mapper_default_prg_ram_read;
	state->mapper_function.prg_ram_write = mapper_default_prg_ram_write;
	state->mapper_function.chr_read = 0x0;
	state->mapper_function.chr_write = mapper_default_chr_write;
	state->mapper_function.ciram_read = mapper_default_ciram_read;
	state->mapper_function.ciram_write = mapper_default_ciram_write;
	state->mapper_function.tick = 0;
}

static void mapper_setup(struct nes_state *state) {
	uint32_t mapper = state->ines.mapper << 4 | state->ines.submapper;
	printf("Mapper %d_%x requested.\n", state->ines.mapper, state->ines.submapper);

	mapper_reset(state);
	if(mapper_table[mapper]) {
		mapper_table[mapper](state);
	} else {
		printf("Unsupported mapper %d_%x, falling back to NROM (mapper 0)\n", state->ines.mapper, state->ines.submapper);
		mapper_table[0](state);
	}
}