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);
}
|