-
Notifications
You must be signed in to change notification settings - Fork 8
/
cartidge.cpp
204 lines (169 loc) · 5.18 KB
/
cartidge.cpp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/**************************************
* Battery-backed RAM
**************************************/
uint8_t *backup_ram_shadow;
bool backup_ram_present;
bool backup_ram_enabled;
uint8_t BACKUP_RAM[0x10000];
void backup_ram_switch_w8(unsigned int address, unsigned int value)
{
if (address == 0xA130F1)
{
backup_ram_enabled = BIT(value, 0);
return;
}
io_mem_w8(address, value);
}
unsigned int backup_ram_r8(unsigned int address)
{
address &= 0xFFFF;
if (backup_ram_enabled)
return BACKUP_RAM[address];
return backup_ram_shadow[address];
}
unsigned int backup_ram_r16(unsigned int address)
{
address &= 0xFFFF;
if (backup_ram_enabled)
return (BACKUP_RAM[address] << 8) | BACKUP_RAM[address+1];
return (backup_ram_shadow[address] << 8) | backup_ram_shadow[address+1];
}
void backup_ram_w8(unsigned int address, unsigned int value)
{
address &= 0xFFFF;
if (backup_ram_enabled)
{
BACKUP_RAM[address] = value;
return;
}
assert(!"write to backup RAM when not enabled");
}
void backup_ram_w16(unsigned int address, unsigned int value)
{
address &= 0xFFFF;
if (backup_ram_enabled)
{
BACKUP_RAM[address] = value >> 8;
BACKUP_RAM[address+1] = value & 0xFF;
return;
}
assert(!"write to backup RAM when not enabled");
}
static memfunc_pair BACKUP_RAM_ACCESS = {
backup_ram_r8, backup_ram_r16, backup_ram_w8, backup_ram_w16
};
static memfunc_pair BACKUP_RAM_SWITCH = {
io_mem_r8, io_mem_r16, backup_ram_switch_w8, io_mem_w16
};
void backup_ram_init(uint8_t addr)
{
backup_ram_present = true;
backup_ram_enabled = true;
backup_ram_shadow = (uint8_t*)m68k_memtable[0x20];
m68k_memtable[addr] = MEMFUN_PAIR(&BACKUP_RAM_ACCESS);
m68k_memtable[0xA1] = MEMFUN_PAIR(&BACKUP_RAM_SWITCH);
memset(BACKUP_RAM, 0xFF, sizeof(BACKUP_RAM)); // required by dinodini
}
/**************************************
* Super Street Fighter 2
*
* This game has an additional ROM bankswitch because
* it's got a 5MB cartidge
**************************************/
unsigned int ssf2_bankswitch_r8(unsigned int address)
{
return io_mem_r8(address);
}
unsigned int ssf2_bankswitch_r16(unsigned int address)
{
return io_mem_r16(address);
}
void ssf2_bankswitch_w8(unsigned int address, unsigned int value)
{
int base = 0;
switch (address)
{
case 0xA130F3: base = 0x08; break;
case 0xA130F5: base = 0x10; break;
case 0xA130F7: base = 0x18; break;
case 0xA130F9: base = 0x20; break;
case 0xA130FB: base = 0x28; break;
case 0xA130FD: base = 0x30; break;
case 0xA130FF: base = 0x38; break;
case 0xA130F1:
if (backup_ram_present)
{
backup_ram_switch_w8(address, value);
return;
}
/* fallthrough */
default:
io_mem_w8(address, value);
return;
}
mem_log("CARTIDGE", "SSF2 bankswitch: base:%x banknum:%x\n", base, value);
assert(value < 5*1024*1024 / 512*1024);
uint8_t *rom = ROM + 512*1024 * value;
for (int i=0;i<0x8;++i)
m68k_memtable[base+i] = rom + 0x10000*i;
}
void ssf2_bankswitch_w16(unsigned int address, unsigned int value)
{
io_mem_w16(address, value);
}
static memfunc_pair SSF2_BANKSWITCH = {
ssf2_bankswitch_r8, ssf2_bankswitch_r16, ssf2_bankswitch_w8, ssf2_bankswitch_w16
};
void cartidge_init(void)
{
char name[64], region[64], code[64];
memset(name, 0, sizeof(name));
memcpy(name, &ROM[0x120], 0x30);
fprintf(stderr, "Game name: %s\n", name);
memset(code, 0, sizeof(code));
memcpy(code, &ROM[0x180], 0xD);
fprintf(stderr, "Code: %s\n", code);
memset(region, 0, sizeof(region));
memcpy(region, &ROM[0x1F0], 0x10);
fprintf(stderr, "Region: %s\n", region);
if (memchr(region, 'J', 4) || memchr(region, '1', 4))
{
VERSION_OVERSEA = 0;
VERSION_PAL = 0;
}
else if (memchr(region, 'U', 4))
{
VERSION_OVERSEA = 1;
VERSION_PAL = 0;
}
else if (memchr(region, 'E', 4) || memchr(region, '8', 4) || memchr(region, 'F', 4))
{
VERSION_OVERSEA = 1;
VERSION_PAL = 1;
}
if (ROM[0x1B0] == 'R' && ROM[0x1B1] == 'A')
{
uint32_t start = m68k_read_memory_32(0x1b4);
uint32_t end = m68k_read_memory_32(0x1b8);
fprintf(stderr, "Extra RAM definition: type:%02x start:%06x end:%06x\n",
m68k_read_memory_8(0x1b2), start, end);
backup_ram_init((start >> 16) & 0xFF);
}
else
if (memcmp(code, "GM MK-1079 ", 10) == 0 || // Sonic3
memcmp(code, "GM MK-1304 ", 10) == 0 || // Warriors of the sun
memcmp(code, "GM T-172176", 10) == 0 || // NHL98
memcmp(code, "GM T-172186", 10) == 0 || // NBA98
memcmp(code, "GM MK-1354 ", 10) == 0) // Story of thor
{
mem_log("CARTIDGE", "Backup RAM\n");
backup_ram_init(0x20);
}
// Bankswitcher
if (memcmp(code, "GM MK-12056", 10) == 0 || // Super Street Fighter 2
memcmp(code, "GM MK-1354 ", 10) == 0) // Story of thor
{
m68k_memtable[0xA1] = MEMFUN_PAIR(&SSF2_BANKSWITCH);
}
fprintf(stderr, "Autodetect mode: %s\n", VERSION_PAL ? "PAL" : "NTSC");
}