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