summaryrefslogtreecommitdiff
path: root/mappers/mapper_001_0.c
blob: 51d22a2bfd271e4f719880c228d86e26594bf5d9 (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
116
117
118
119
120
121

__attribute__((section(".mapper_001_0")))
static uint8_t mapper_001_0_prg_rom_read(struct nes_state *state, uint32_t addr) {
	struct mapper_001_0 *mapper = &state->mapper_data.m001_0;
	if(addr >= 0x8000) {
		if(addr < 0xc000) {
			return mapper->prg_rom_0[addr & 0x3fff];
		} else {
			return mapper->prg_rom_1[addr & 0x3fff];
		}
	}
	return 0;
}

__attribute__((section(".mapper_001_0")))
static void mapper_001_0_prg_rom_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	struct mapper_001_0 *mapper = &state->mapper_data.m001_0;
	if(addr < 0x8000) return;

	if(value & 0x80) {
		mapper->shift = 0;
		mapper->shift_count = 0;
		mapper->control |= 0x0c;
		return;
	}

	mapper->shift |= (value & 1) << mapper->shift_count;
	mapper->shift_count++;

	if(mapper->shift_count == 5) {
		uint32_t bank;
		uint8_t reg = (addr >> 13) & 0x03;
		switch(reg) {
			case 0: {// Control
				mapper->control = mapper->shift;
			} break;

			case 1: { // CHR bank 0
				mapper->chr_bank0 = mapper->shift;
				mapper->chr_bank_0 = state->chr_rom + (mapper->chr_bank0 * 0x1000);
			} break;

			case 2: { // CHR bank 1
				mapper->chr_bank1 = mapper->shift;
				mapper->chr_bank_1 = state->chr_rom + (mapper->chr_bank1 * 0x1000);
			} break;

			case 3: { // PRG bank
				mapper->prg_bank = mapper->shift & 0x0f;
				if(mapper->control & 0x08) {
					// 16KB bank switching
					if(mapper->control & 0x04) {
						mapper->prg_rom_0 = state->prg_rom + 0x4000 * 0;
						mapper->prg_rom_1 = state->prg_rom + 0x4000 * mapper->prg_bank;
					} else {
						mapper->prg_rom_0 = state->prg_rom + 0x4000 * mapper->prg_bank;
						mapper->prg_rom_1 = state->prg_rom + 0x4000 * (state->ines.prg_size / 0x4000 - 1);
					}
				} else {
					// 32KB mode
					bank = (mapper->prg_bank & 0x0e) * 0x4000;
					mapper->prg_rom_0 = state->prg_rom + bank;
					mapper->prg_rom_1 = state->prg_rom + bank + 0x4000;
				}
			} break;
		}
		mapper->shift = 0;
		mapper->shift_count = 0;
	}
}

__attribute__((section(".mapper_001_0")))
static uint8_t mapper_001_0_chr_read(struct nes_state *state, uint32_t addr) {
	struct mapper_001_0 *mapper = &state->mapper_data.m001_0;
	if(mapper->control & 0x10) {
		// 4KB mode
		if(addr < 0x1000) {
			return mapper->chr_bank_0[addr];
		} else {
			return mapper->chr_bank_1[addr - 0x1000];
		}
	} else {
		// 8KB mode
		return mapper->chr_bank_0[addr];
	}
}

__attribute__((section(".mapper_001_0")))
static void mapper_001_0_chr_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	// CHR RAM write (if present)
	state->chr_ram[addr] = value;
}

__attribute__((section(".mapper_001_0")))
static uint8_t mapper_001_0_ciram_read(struct nes_state *state, uint32_t addr) {
	return state->ciram[addr & 0x3ff];
}

__attribute__((section(".mapper_001_0")))
static void mapper_001_0_ciram_write(struct nes_state *state, uint32_t addr, uint8_t value) {
	state->ciram[addr & 0x3ff] = value;
}

__attribute__((section(".mapper_001_0")))
static void mapper_001_0_init(struct nes_state *state) {
	struct mapper_001_0 *mapper = &state->mapper_data.m001_0;

	mapper->control = 0x0c;
	mapper->prg_rom_0 = state->prg_rom;
	mapper->prg_rom_1 = state->prg_rom + (state->ines.prg_size - 0x4000);

	mapper->chr_bank_0 = state->chr_rom;
	mapper->chr_bank_1 = state->chr_rom + 0x1000;

	state->mapper_function.prg_rom_read		= mapper_001_0_prg_rom_read;
	state->mapper_function.prg_rom_write	= mapper_001_0_prg_rom_write;
	state->mapper_function.chr_read			= mapper_001_0_chr_read;
	state->mapper_function.chr_write			= mapper_001_0_chr_write;
	state->mapper_function.ciram_read		= mapper_001_0_ciram_read;
	state->mapper_function.ciram_write		= mapper_001_0_ciram_write;
}