summaryrefslogtreecommitdiff
path: root/mknes_mapper.c
blob: 7dfb32b724304faee673503c70c73753bf659cdb (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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

#define MIRROR_HORIZONTAL       0
#define MIRROR_VERTICAL         1
#define MIRROR_FOUR_SCREEN      2
#define MIRROR_ONESCREEN_LOW    3
#define MIRROR_ONESCREEN_HIGH   4


static uint8_t mapper_default_ciram_read(struct nes_state *state, uint32_t addr) {
	if(state->ines.mirroring == MIRROR_HORIZONTAL) {
		return state->ciram[((addr >> 1) & 0x400) | (addr & 0x3ff)];
	}
	return state->ciram[addr & 0x7ff];
}

static void mapper_default_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	if(state->ines.mirroring == MIRROR_HORIZONTAL) { // Horizontal: NT0+NT1, NT2+NT3
		addr = ((addr >> 1) & 0x400) | (addr & 0x3ff);
	} else { // Vertical (default fallback): NT0+NT2, NT1+NT3
		addr = addr & 0x7ff;
	}
	state->ciram[addr] = value;
}

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

__attribute__((naked, no_instrument_function, no_profile_instrument_function)) static 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, no_instrument_function, no_profile_instrument_function)) static void mapper_default_prg_ram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	__asm__ __volatile__("ret");
}

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

// __attribute__((naked, no_instrument_function, no_profile_instrument_function)) static void mapper_default_tick(struct nes_state *state) {
// 	__asm__ __volatile__("ret");
// }


#include "mappers/mapper_000_0.c"
#include "mappers/mapper_001_0.c"
#include "mappers/mapper_002_2.c"
#include "mappers/mapper_003_0.c"
#include "mappers/mapper_003_1.c"
#include "mappers/mapper_003_2.c"
#include "mappers/mapper_004_0.c"
#include "mappers/mapper_005_0.c"
#include "mappers/mapper_007_2.c"
#include "mappers/mapper_011_0.c"
#include "mappers/mapper_066_0.c"

#define MAPPER_ID(mapper, submapper) (((mapper) << 4) | (submapper))

struct supported_mapper {
	uint32_t id;
	void (*mapper_init)(struct nes_state *state);
};

static struct supported_mapper supported_mappers[] = {
	{ 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( 4, 0), mapper_004_0_init },
	{ MAPPER_ID( 5, 0), mapper_005_0_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 },
	{ 0, 0 }
};

// 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_id = state->ines.mapper << 4 | state->ines.submapper;
#ifndef BENCHMARK
	printf("Mapper %d_%x requested.\n", state->ines.mapper, state->ines.submapper);
#endif

	mapper_reset(state);

	struct supported_mapper *m = supported_mappers;

	while(m->mapper_init) {
		if(m->id == mapper_id) {
			m->mapper_init(state);
			return;
		}
		m++;
	}

	printf("Unsupported mapper %d_%x, falling back to NROM (mapper 0)\n", state->ines.mapper, state->ines.submapper);
	mapper_000_0_init(state);

}