1 #include <stdbool.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "gb.h"
5
6 const GB_cartridge_t GB_cart_defs[256] = {
7 // From http://gbdev.gg8.se/wiki/articles/The_Cartridge_Header#0147_-_Cartridge_Type
8 /* MBC SUBTYPE RAM BAT. RTC RUMB. */
9 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 00h ROM ONLY
10 { GB_MBC1 , GB_STANDARD_MBC, false, false, false, false}, // 01h MBC1
11 { GB_MBC1 , GB_STANDARD_MBC, true , false, false, false}, // 02h MBC1+RAM
12 { GB_MBC1 , GB_STANDARD_MBC, true , true , false, false}, // 03h MBC1+RAM+BATTERY
13 [5] =
14 { GB_MBC2 , GB_STANDARD_MBC, true , false, false, false}, // 05h MBC2
15 { GB_MBC2 , GB_STANDARD_MBC, true , true , false, false}, // 06h MBC2+BATTERY
16 [8] =
17 { GB_NO_MBC, GB_STANDARD_MBC, true , false, false, false}, // 08h ROM+RAM
18 { GB_NO_MBC, GB_STANDARD_MBC, true , true , false, false}, // 09h ROM+RAM+BATTERY
19 [0xB] =
20 /* Todo: Not supported yet */
21 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Bh MMM01
22 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Ch MMM01+RAM
23 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // 0Dh MMM01+RAM+BATTERY
24 [0xF] =
25 { GB_MBC3 , GB_STANDARD_MBC, false, true, true , false}, // 0Fh MBC3+TIMER+BATTERY
26 { GB_MBC3 , GB_STANDARD_MBC, true , true, true , false}, // 10h MBC3+TIMER+RAM+BATTERY
27 { GB_MBC3 , GB_STANDARD_MBC, false, false, false, false}, // 11h MBC3
28 { GB_MBC3 , GB_STANDARD_MBC, true , false, false, false}, // 12h MBC3+RAM
29 { GB_MBC3 , GB_STANDARD_MBC, true , true , false, false}, // 13h MBC3+RAM+BATTERY
30 [0x19] =
31 { GB_MBC5 , GB_STANDARD_MBC, false, false, false, false}, // 19h MBC5
32 { GB_MBC5 , GB_STANDARD_MBC, true , false, false, false}, // 1Ah MBC5+RAM
33 { GB_MBC5 , GB_STANDARD_MBC, true , true , false, false}, // 1Bh MBC5+RAM+BATTERY
34 { GB_MBC5 , GB_STANDARD_MBC, false, false, false, true }, // 1Ch MBC5+RUMBLE
35 { GB_MBC5 , GB_STANDARD_MBC, true , false, false, true }, // 1Dh MBC5+RUMBLE+RAM
36 { GB_MBC5 , GB_STANDARD_MBC, true , true , false, true }, // 1Eh MBC5+RUMBLE+RAM+BATTERY
37 [0xFC] =
38 { GB_MBC5 , GB_CAMERA , true , true , false, false}, // FCh POCKET CAMERA
39 { GB_NO_MBC, GB_STANDARD_MBC, false, false, false, false}, // FDh BANDAI TAMA5 (Todo: Not supported)
40 { GB_HUC3 , GB_STANDARD_MBC, true , true , true, false}, // FEh HuC3
41 { GB_HUC1 , GB_STANDARD_MBC, true , true , false, false}, // FFh HuC1+RAM+BATTERY
42 };
43
GB_update_mbc_mappings(GB_gameboy_t * gb)44 void GB_update_mbc_mappings(GB_gameboy_t *gb)
45 {
46 switch (gb->cartridge_type->mbc_type) {
47 case GB_NO_MBC: return;
48 case GB_MBC1:
49 switch (gb->mbc1_wiring) {
50 case GB_STANDARD_MBC1_WIRING:
51 gb->mbc_rom_bank = gb->mbc1.bank_low | (gb->mbc1.bank_high << 5);
52 if (gb->mbc1.mode == 0) {
53 gb->mbc_ram_bank = 0;
54 gb->mbc_rom0_bank = 0;
55 }
56 else {
57 gb->mbc_ram_bank = gb->mbc1.bank_high;
58 gb->mbc_rom0_bank = gb->mbc1.bank_high << 5;
59 }
60 if ((gb->mbc_rom_bank & 0x1F) == 0) {
61 gb->mbc_rom_bank++;
62 }
63 break;
64 case GB_MBC1M_WIRING:
65 gb->mbc_rom_bank = (gb->mbc1.bank_low & 0xF) | (gb->mbc1.bank_high << 4);
66 if (gb->mbc1.mode == 0) {
67 gb->mbc_ram_bank = 0;
68 gb->mbc_rom0_bank = 0;
69 }
70 else {
71 gb->mbc_rom0_bank = gb->mbc1.bank_high << 4;
72 gb->mbc_ram_bank = 0;
73 }
74 if ((gb->mbc1.bank_low & 0x1F) == 0) {
75 gb->mbc_rom_bank++;
76 }
77 break;
78 }
79 break;
80 case GB_MBC2:
81 gb->mbc_rom_bank = gb->mbc2.rom_bank;
82 if ((gb->mbc_rom_bank & 0xF) == 0) {
83 gb->mbc_rom_bank = 1;
84 }
85 break;
86 case GB_MBC3:
87 gb->mbc_rom_bank = gb->mbc3.rom_bank;
88 gb->mbc_ram_bank = gb->mbc3.ram_bank;
89 if (!gb->is_mbc30) {
90 gb->mbc_rom_bank &= 0x7F;
91 }
92 if (gb->mbc_rom_bank == 0) {
93 gb->mbc_rom_bank = 1;
94 }
95 break;
96 case GB_MBC5:
97 gb->mbc_rom_bank = gb->mbc5.rom_bank_low | (gb->mbc5.rom_bank_high << 8);
98 gb->mbc_ram_bank = gb->mbc5.ram_bank;
99 break;
100 case GB_HUC1:
101 if (gb->huc1.mode == 0) {
102 gb->mbc_rom_bank = gb->huc1.bank_low | (gb->mbc1.bank_high << 6);
103 gb->mbc_ram_bank = 0;
104 }
105 else {
106 gb->mbc_rom_bank = gb->huc1.bank_low;
107 gb->mbc_ram_bank = gb->huc1.bank_high;
108 }
109 break;
110 case GB_HUC3:
111 gb->mbc_rom_bank = gb->huc3.rom_bank;
112 gb->mbc_ram_bank = gb->huc3.ram_bank;
113 break;
114 case GB_TPP1:
115 gb->mbc_rom_bank = gb->tpp1_rom_bank;
116 gb->mbc_ram_bank = gb->tpp1_ram_bank;
117 gb->mbc_ram_enable = (gb->tpp1_mode == 2) || (gb->tpp1_mode == 3);
118 break;
119 }
120 }
121
GB_configure_cart(GB_gameboy_t * gb)122 void GB_configure_cart(GB_gameboy_t *gb)
123 {
124 gb->cartridge_type = &GB_cart_defs[gb->rom[0x147]];
125 if (gb->rom[0x147] == 0xbc &&
126 gb->rom[0x149] == 0xc1 &&
127 gb->rom[0x14a] == 0x65) {
128 static const GB_cartridge_t tpp1 = {GB_TPP1, GB_STANDARD_MBC, true, true, true, true};
129 gb->cartridge_type = &tpp1;
130 gb->tpp1_rom_bank = 1;
131 }
132
133 if (gb->rom[0x147] == 0 && gb->rom_size > 0x8000) {
134 GB_log(gb, "ROM header reports no MBC, but file size is over 32Kb. Assuming cartridge uses MBC3.\n");
135 gb->cartridge_type = &GB_cart_defs[0x11];
136 }
137 else if (gb->rom[0x147] != 0 && memcmp(gb->cartridge_type, &GB_cart_defs[0], sizeof(GB_cart_defs[0])) == 0) {
138 GB_log(gb, "Cartridge type %02x is not yet supported.\n", gb->rom[0x147]);
139 }
140
141 if (gb->mbc_ram) {
142 free(gb->mbc_ram);
143 gb->mbc_ram = NULL;
144 gb->mbc_ram_size = 0;
145 }
146
147 if (gb->cartridge_type->has_ram) {
148 if (gb->cartridge_type->mbc_type == GB_MBC2) {
149 gb->mbc_ram_size = 0x200;
150 }
151 else if (gb->cartridge_type->mbc_type == GB_TPP1) {
152 if (gb->rom[0x152] >= 1 && gb->rom[0x152] <= 9) {
153 gb->mbc_ram_size = 0x2000 << (gb->rom[0x152] - 1);
154 }
155 }
156 else {
157 static const unsigned ram_sizes[256] = {0, 0x800, 0x2000, 0x8000, 0x20000, 0x10000};
158 gb->mbc_ram_size = ram_sizes[gb->rom[0x149]];
159 }
160
161 if (gb->mbc_ram_size) {
162 gb->mbc_ram = malloc(gb->mbc_ram_size);
163 }
164
165 /* Todo: Some games assume unintialized MBC RAM is 0xFF. It this true for all cartridge types? */
166 memset(gb->mbc_ram, 0xFF, gb->mbc_ram_size);
167 }
168
169 /* MBC1 has at least 3 types of wiring (We currently support two (Standard and 4bit-MBC1M) of these).
170 See http://forums.nesdev.com/viewtopic.php?f=20&t=14099 */
171
172 /* Attempt to "guess" wiring */
173 if (gb->cartridge_type->mbc_type == GB_MBC1) {
174 if (gb->rom_size >= 0x44000 && memcmp(gb->rom + 0x104, gb->rom + 0x40104, 0x30) == 0) {
175 gb->mbc1_wiring = GB_MBC1M_WIRING;
176 }
177 }
178
179 /* Detect MBC30 */
180 if (gb->cartridge_type->mbc_type == GB_MBC3) {
181 if (gb->rom_size > 0x200000 || gb->mbc_ram_size > 0x8000) {
182 gb->is_mbc30 = true;
183 }
184 }
185
186 /* Set MBC5's bank to 1 correctly */
187 if (gb->cartridge_type->mbc_type == GB_MBC5) {
188 gb->mbc5.rom_bank_low = 1;
189 }
190 }
191