rlm@1
|
1 #include "gbGlobals.h"
|
rlm@1
|
2 #include "gbMemory.h"
|
rlm@1
|
3 #include "../common/System.h"
|
rlm@1
|
4 #include "../common/movie.h"
|
rlm@1
|
5
|
rlm@1
|
6 mapperMBC1 gbDataMBC1 = {
|
rlm@1
|
7 0, // RAM enable
|
rlm@1
|
8 1, // ROM bank
|
rlm@1
|
9 0, // RAM bank
|
rlm@1
|
10 0, // memory model
|
rlm@1
|
11 0, // ROM high address
|
rlm@1
|
12 0 // RAM address
|
rlm@1
|
13 };
|
rlm@1
|
14
|
rlm@1
|
15 // MBC1 ROM write registers
|
rlm@1
|
16 void mapperMBC1ROM(u16 address, u8 value)
|
rlm@1
|
17 {
|
rlm@1
|
18 int tmpAddress = 0;
|
rlm@1
|
19
|
rlm@1
|
20 switch (address & 0x6000)
|
rlm@1
|
21 {
|
rlm@1
|
22 case 0x0000: // RAM enable register
|
rlm@1
|
23 gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
|
rlm@1
|
24 break;
|
rlm@1
|
25 case 0x2000: // ROM bank select
|
rlm@1
|
26 // value = value & 0x1f;
|
rlm@1
|
27 if (value == 0)
|
rlm@1
|
28 value = 1;
|
rlm@1
|
29 if (value == gbDataMBC1.mapperROMBank)
|
rlm@1
|
30 break;
|
rlm@1
|
31
|
rlm@1
|
32 tmpAddress = value << 14;
|
rlm@1
|
33
|
rlm@1
|
34 // check current model
|
rlm@1
|
35 if (gbDataMBC1.mapperMemoryModel == 0)
|
rlm@1
|
36 {
|
rlm@1
|
37 // model is 16/8, so we have a high address in use
|
rlm@1
|
38 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
|
rlm@1
|
39 }
|
rlm@1
|
40
|
rlm@1
|
41 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
42 gbDataMBC1.mapperROMBank = value;
|
rlm@1
|
43 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
44 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
45 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
46 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
47 break;
|
rlm@1
|
48 case 0x4000: // RAM bank select
|
rlm@1
|
49 if (gbDataMBC1.mapperMemoryModel == 1)
|
rlm@1
|
50 {
|
rlm@1
|
51 // 4/32 model, RAM bank switching provided
|
rlm@1
|
52 value = value & 0x03;
|
rlm@1
|
53 if (value == gbDataMBC1.mapperRAMBank)
|
rlm@1
|
54 break;
|
rlm@1
|
55 tmpAddress = value << 13;
|
rlm@1
|
56 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
57 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
58 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
59 gbDataMBC1.mapperRAMBank = value;
|
rlm@1
|
60 gbDataMBC1.mapperRAMAddress = tmpAddress;
|
rlm@1
|
61 }
|
rlm@1
|
62 else
|
rlm@1
|
63 {
|
rlm@1
|
64 // 16/8, set the high address
|
rlm@1
|
65 gbDataMBC1.mapperROMHighAddress = value & 0x03;
|
rlm@1
|
66 tmpAddress = gbDataMBC1.mapperROMBank << 14;
|
rlm@1
|
67 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
|
rlm@1
|
68 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
69 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
70 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
71 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
72 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
73 }
|
rlm@1
|
74 break;
|
rlm@1
|
75 case 0x6000: // memory model select
|
rlm@1
|
76 gbDataMBC1.mapperMemoryModel = value & 1;
|
rlm@1
|
77 break;
|
rlm@1
|
78 }
|
rlm@1
|
79 }
|
rlm@1
|
80
|
rlm@1
|
81 // MBC1 RAM write
|
rlm@1
|
82 void mapperMBC1RAM(u16 address, u8 value)
|
rlm@1
|
83 {
|
rlm@1
|
84 if (gbDataMBC1.mapperRAMEnable)
|
rlm@1
|
85 {
|
rlm@1
|
86 if (gbRamSize)
|
rlm@1
|
87 {
|
rlm@1
|
88 gbWriteMemoryQuick(address, value);
|
rlm@1
|
89 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
90 }
|
rlm@1
|
91 }
|
rlm@1
|
92 }
|
rlm@1
|
93
|
rlm@1
|
94 void memoryUpdateMapMBC1()
|
rlm@1
|
95 {
|
rlm@1
|
96 int tmpAddress = gbDataMBC1.mapperROMBank << 14;
|
rlm@1
|
97
|
rlm@1
|
98 // check current model
|
rlm@1
|
99 if (gbDataMBC1.mapperMemoryModel == 1)
|
rlm@1
|
100 {
|
rlm@1
|
101 // model is 16/8, so we have a high address in use
|
rlm@1
|
102 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
|
rlm@1
|
103 }
|
rlm@1
|
104
|
rlm@1
|
105 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
106 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
107 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
108 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
109 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
110
|
rlm@1
|
111 if (gbRamSize)
|
rlm@1
|
112 {
|
rlm@1
|
113 gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
|
rlm@1
|
114 gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
|
rlm@1
|
115 }
|
rlm@1
|
116 }
|
rlm@1
|
117
|
rlm@1
|
118 mapperMBC2 gbDataMBC2 = {
|
rlm@1
|
119 0, // RAM enable
|
rlm@1
|
120 1 // ROM bank
|
rlm@1
|
121 };
|
rlm@1
|
122
|
rlm@1
|
123 // MBC2 ROM write registers
|
rlm@1
|
124 void mapperMBC2ROM(u16 address, u8 value)
|
rlm@1
|
125 {
|
rlm@1
|
126 switch (address & 0x6000)
|
rlm@1
|
127 {
|
rlm@1
|
128 case 0x0000: // RAM enable
|
rlm@1
|
129 if (!(address & 0x0100))
|
rlm@1
|
130 {
|
rlm@1
|
131 gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a;
|
rlm@1
|
132 }
|
rlm@1
|
133 break;
|
rlm@1
|
134 case 0x2000: // ROM bank select
|
rlm@1
|
135 if (address & 0x0100)
|
rlm@1
|
136 {
|
rlm@1
|
137 value &= 0x0f;
|
rlm@1
|
138
|
rlm@1
|
139 if (value == 0)
|
rlm@1
|
140 value = 1;
|
rlm@1
|
141 if (gbDataMBC2.mapperROMBank != value)
|
rlm@1
|
142 {
|
rlm@1
|
143 gbDataMBC2.mapperROMBank = value;
|
rlm@1
|
144
|
rlm@1
|
145 int tmpAddress = value << 14;
|
rlm@1
|
146
|
rlm@1
|
147 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
148
|
rlm@1
|
149 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
150 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
151 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
152 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
153 }
|
rlm@1
|
154 }
|
rlm@1
|
155 break;
|
rlm@1
|
156 }
|
rlm@1
|
157 }
|
rlm@1
|
158
|
rlm@1
|
159 // MBC2 RAM write
|
rlm@1
|
160 void mapperMBC2RAM(u16 address, u8 value)
|
rlm@1
|
161 {
|
rlm@1
|
162 if (gbDataMBC2.mapperRAMEnable)
|
rlm@1
|
163 {
|
rlm@1
|
164 if (gbRamSize && address < 0xa200)
|
rlm@1
|
165 {
|
rlm@1
|
166 gbWriteMemoryQuick(address, value);
|
rlm@1
|
167 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
168 }
|
rlm@1
|
169 }
|
rlm@1
|
170 }
|
rlm@1
|
171
|
rlm@1
|
172 void memoryUpdateMapMBC2()
|
rlm@1
|
173 {
|
rlm@1
|
174 int tmpAddress = gbDataMBC2.mapperROMBank << 14;
|
rlm@1
|
175
|
rlm@1
|
176 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
177
|
rlm@1
|
178 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
179 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
180 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
181 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
182 }
|
rlm@1
|
183
|
rlm@1
|
184 mapperMBC3 gbDataMBC3 = {
|
rlm@1
|
185 0, // RAM enable
|
rlm@1
|
186 1, // ROM bank
|
rlm@1
|
187 0, // RAM bank
|
rlm@1
|
188 0, // RAM address
|
rlm@1
|
189 0, // timer clock latch
|
rlm@1
|
190 0, // timer clock register
|
rlm@1
|
191 0, // timer seconds
|
rlm@1
|
192 0, // timer minutes
|
rlm@1
|
193 0, // timer hours
|
rlm@1
|
194 0, // timer days
|
rlm@1
|
195 0, // timer control
|
rlm@1
|
196 0, // timer latched seconds
|
rlm@1
|
197 0, // timer latched minutes
|
rlm@1
|
198 0, // timer latched hours
|
rlm@1
|
199 0, // timer latched days
|
rlm@1
|
200 0, // timer latched control
|
rlm@1
|
201 (time_t)-1 // last time
|
rlm@1
|
202 };
|
rlm@1
|
203
|
rlm@1
|
204 void memoryUpdateMBC3Clock()
|
rlm@1
|
205 {
|
rlm@1
|
206 time_t now;
|
rlm@1
|
207
|
rlm@1
|
208 if (VBAMovieActive() || VBAMovieLoading())
|
rlm@1
|
209 now = (time_t)(VBAMovieGetId() + VBAMovieGetFrameCounter()/60); /// FIXME: is /60 the right factor?
|
rlm@1
|
210 else
|
rlm@1
|
211 now = time(NULL);
|
rlm@1
|
212
|
rlm@1
|
213 time_t diff = now - gbDataMBC3.mapperLastTime;
|
rlm@1
|
214 if (diff > 0)
|
rlm@1
|
215 {
|
rlm@1
|
216 // update the clock according to the last update time
|
rlm@1
|
217 gbDataMBC3.mapperSeconds += (int)(diff % 60);
|
rlm@1
|
218 if (gbDataMBC3.mapperSeconds > 59)
|
rlm@1
|
219 {
|
rlm@1
|
220 gbDataMBC3.mapperSeconds -= 60;
|
rlm@1
|
221 gbDataMBC3.mapperMinutes++;
|
rlm@1
|
222 }
|
rlm@1
|
223
|
rlm@1
|
224 diff /= 60;
|
rlm@1
|
225
|
rlm@1
|
226 gbDataMBC3.mapperMinutes += (int)(diff % 60);
|
rlm@1
|
227 if (gbDataMBC3.mapperMinutes > 60)
|
rlm@1
|
228 {
|
rlm@1
|
229 gbDataMBC3.mapperMinutes -= 60;
|
rlm@1
|
230 gbDataMBC3.mapperHours++;
|
rlm@1
|
231 }
|
rlm@1
|
232
|
rlm@1
|
233 diff /= 60;
|
rlm@1
|
234
|
rlm@1
|
235 gbDataMBC3.mapperHours += (int)(diff % 24);
|
rlm@1
|
236 if (gbDataMBC3.mapperHours > 24)
|
rlm@1
|
237 {
|
rlm@1
|
238 gbDataMBC3.mapperHours -= 24;
|
rlm@1
|
239 gbDataMBC3.mapperDays++;
|
rlm@1
|
240 }
|
rlm@1
|
241 diff /= 24;
|
rlm@1
|
242
|
rlm@1
|
243 gbDataMBC3.mapperDays += (int)diff;
|
rlm@1
|
244 if (gbDataMBC3.mapperDays > 255)
|
rlm@1
|
245 {
|
rlm@1
|
246 if (gbDataMBC3.mapperDays > 511)
|
rlm@1
|
247 {
|
rlm@1
|
248 gbDataMBC3.mapperDays %= 512;
|
rlm@1
|
249 gbDataMBC3.mapperControl |= 0x80;
|
rlm@1
|
250 }
|
rlm@1
|
251 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
|
rlm@1
|
252 (gbDataMBC3.mapperDays > 255 ? 1 : 0);
|
rlm@1
|
253 }
|
rlm@1
|
254 }
|
rlm@1
|
255 gbDataMBC3.mapperLastTime = now;
|
rlm@1
|
256 }
|
rlm@1
|
257
|
rlm@1
|
258 // MBC3 ROM write registers
|
rlm@1
|
259 void mapperMBC3ROM(u16 address, u8 value)
|
rlm@1
|
260 {
|
rlm@1
|
261 int tmpAddress = 0;
|
rlm@1
|
262
|
rlm@1
|
263 switch (address & 0x6000)
|
rlm@1
|
264 {
|
rlm@1
|
265 case 0x0000: // RAM enable register
|
rlm@1
|
266 gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
|
rlm@1
|
267 break;
|
rlm@1
|
268 case 0x2000: // ROM bank select
|
rlm@1
|
269 value = value & 0x7f;
|
rlm@1
|
270 if (value == 0)
|
rlm@1
|
271 value = 1;
|
rlm@1
|
272 if (value == gbDataMBC3.mapperROMBank)
|
rlm@1
|
273 break;
|
rlm@1
|
274
|
rlm@1
|
275 tmpAddress = value << 14;
|
rlm@1
|
276
|
rlm@1
|
277 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
278 gbDataMBC3.mapperROMBank = value;
|
rlm@1
|
279 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
280 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
281 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
282 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
283
|
rlm@1
|
284 break;
|
rlm@1
|
285 case 0x4000: // RAM bank select
|
rlm@1
|
286 if (value < 8)
|
rlm@1
|
287 {
|
rlm@1
|
288 if (value == gbDataMBC3.mapperRAMBank)
|
rlm@1
|
289 break;
|
rlm@1
|
290 tmpAddress = value << 13;
|
rlm@1
|
291 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
292 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
293 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
294 gbDataMBC3.mapperRAMBank = value;
|
rlm@1
|
295 gbDataMBC3.mapperRAMAddress = tmpAddress;
|
rlm@1
|
296 }
|
rlm@1
|
297 else
|
rlm@1
|
298 {
|
rlm@1
|
299 if (gbDataMBC3.mapperRAMEnable)
|
rlm@1
|
300 {
|
rlm@1
|
301 gbDataMBC3.mapperRAMBank = -1;
|
rlm@1
|
302
|
rlm@1
|
303 gbDataMBC3.mapperClockRegister = value;
|
rlm@1
|
304 }
|
rlm@1
|
305 }
|
rlm@1
|
306 break;
|
rlm@1
|
307 case 0x6000: // clock latch
|
rlm@1
|
308 if (gbDataMBC3.mapperClockLatch == 0 && value == 1)
|
rlm@1
|
309 {
|
rlm@1
|
310 memoryUpdateMBC3Clock();
|
rlm@1
|
311 gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds;
|
rlm@1
|
312 gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes;
|
rlm@1
|
313 gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours;
|
rlm@1
|
314 gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays;
|
rlm@1
|
315 gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl;
|
rlm@1
|
316 }
|
rlm@1
|
317 if (value == 0x00 || value == 0x01)
|
rlm@1
|
318 gbDataMBC3.mapperClockLatch = value;
|
rlm@1
|
319 break;
|
rlm@1
|
320 }
|
rlm@1
|
321 }
|
rlm@1
|
322
|
rlm@1
|
323 // MBC3 RAM write
|
rlm@1
|
324 void mapperMBC3RAM(u16 address, u8 value)
|
rlm@1
|
325 {
|
rlm@1
|
326 if (gbDataMBC3.mapperRAMEnable)
|
rlm@1
|
327 {
|
rlm@1
|
328 if (gbDataMBC3.mapperRAMBank != -1)
|
rlm@1
|
329 {
|
rlm@1
|
330 if (gbRamSize)
|
rlm@1
|
331 {
|
rlm@1
|
332 gbWriteMemoryQuick(address, value);
|
rlm@1
|
333 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
334 }
|
rlm@1
|
335 }
|
rlm@1
|
336 else
|
rlm@1
|
337 {
|
rlm@1
|
338 time_t tmp; //Small kludge to get it working on some 64 bit systems.
|
rlm@1
|
339 if (VBAMovieActive() || VBAMovieLoading())
|
rlm@1
|
340 gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter()/60;
|
rlm@1
|
341 else {
|
rlm@1
|
342 time(&tmp);
|
rlm@1
|
343 gbDataMBC3.mapperLastTime=(u32)tmp;
|
rlm@1
|
344 }
|
rlm@1
|
345 systemScreenMessage(ctime(&tmp), 4);
|
rlm@1
|
346 gbDataMBC3.mapperLastTime=(u32)tmp;
|
rlm@1
|
347
|
rlm@1
|
348 switch (gbDataMBC3.mapperClockRegister)
|
rlm@1
|
349 {
|
rlm@1
|
350 case 0x08:
|
rlm@1
|
351 gbDataMBC3.mapperSeconds = value;
|
rlm@1
|
352 break;
|
rlm@1
|
353 case 0x09:
|
rlm@1
|
354 gbDataMBC3.mapperMinutes = value;
|
rlm@1
|
355 break;
|
rlm@1
|
356 case 0x0a:
|
rlm@1
|
357 gbDataMBC3.mapperHours = value;
|
rlm@1
|
358 break;
|
rlm@1
|
359 case 0x0b:
|
rlm@1
|
360 gbDataMBC3.mapperDays = value;
|
rlm@1
|
361 break;
|
rlm@1
|
362 case 0x0c:
|
rlm@1
|
363 if (gbDataMBC3.mapperControl & 0x80)
|
rlm@1
|
364 gbDataMBC3.mapperControl = 0x80 | value;
|
rlm@1
|
365 else
|
rlm@1
|
366 gbDataMBC3.mapperControl = value;
|
rlm@1
|
367 break;
|
rlm@1
|
368 }
|
rlm@1
|
369 }
|
rlm@1
|
370 }
|
rlm@1
|
371 }
|
rlm@1
|
372
|
rlm@1
|
373 // MBC3 read RAM
|
rlm@1
|
374 u8 mapperMBC3ReadRAM(u16 address)
|
rlm@1
|
375 {
|
rlm@1
|
376 if (gbDataMBC3.mapperRAMEnable)
|
rlm@1
|
377 {
|
rlm@1
|
378 if (gbDataMBC3.mapperRAMBank != -1)
|
rlm@1
|
379 {
|
rlm@1
|
380 return gbReadMemoryQuick(address);
|
rlm@1
|
381 }
|
rlm@1
|
382
|
rlm@1
|
383 switch (gbDataMBC3.mapperClockRegister)
|
rlm@1
|
384 {
|
rlm@1
|
385 case 0x08:
|
rlm@1
|
386 return gbDataMBC3.mapperLSeconds;
|
rlm@1
|
387 break;
|
rlm@1
|
388 case 0x09:
|
rlm@1
|
389 return gbDataMBC3.mapperLMinutes;
|
rlm@1
|
390 break;
|
rlm@1
|
391 case 0x0a:
|
rlm@1
|
392 return gbDataMBC3.mapperLHours;
|
rlm@1
|
393 break;
|
rlm@1
|
394 case 0x0b:
|
rlm@1
|
395 return gbDataMBC3.mapperLDays;
|
rlm@1
|
396 break;
|
rlm@1
|
397 case 0x0c:
|
rlm@1
|
398 return gbDataMBC3.mapperLControl;
|
rlm@1
|
399 }
|
rlm@1
|
400 }
|
rlm@1
|
401 return 0;
|
rlm@1
|
402 }
|
rlm@1
|
403
|
rlm@1
|
404 void memoryUpdateMapMBC3()
|
rlm@1
|
405 {
|
rlm@1
|
406 int tmpAddress = gbDataMBC3.mapperROMBank << 14;
|
rlm@1
|
407
|
rlm@1
|
408 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
409
|
rlm@1
|
410 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
411 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
412 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
413 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
414
|
rlm@1
|
415 if (gbDataMBC3.mapperRAMBank >= 0 && gbRamSize)
|
rlm@1
|
416 {
|
rlm@1
|
417 tmpAddress = gbDataMBC3.mapperRAMBank << 13;
|
rlm@1
|
418 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
419 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
420 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
421 }
|
rlm@1
|
422 }
|
rlm@1
|
423
|
rlm@1
|
424 mapperMBC5 gbDataMBC5 = {
|
rlm@1
|
425 0, // RAM enable
|
rlm@1
|
426 1, // ROM bank
|
rlm@1
|
427 0, // RAM bank
|
rlm@1
|
428 0, // ROM high address
|
rlm@1
|
429 0, // RAM address
|
rlm@1
|
430 0 // is rumble cartridge?
|
rlm@1
|
431 };
|
rlm@1
|
432
|
rlm@1
|
433 // MBC5 ROM write registers
|
rlm@1
|
434 void mapperMBC5ROM(u16 address, u8 value)
|
rlm@1
|
435 {
|
rlm@1
|
436 int tmpAddress = 0;
|
rlm@1
|
437
|
rlm@1
|
438 switch (address & 0x6000)
|
rlm@1
|
439 {
|
rlm@1
|
440 case 0x0000: // RAM enable register
|
rlm@1
|
441 gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
|
rlm@1
|
442 break;
|
rlm@1
|
443 case 0x2000: // ROM bank select
|
rlm@1
|
444 if (address < 0x3000)
|
rlm@1
|
445 {
|
rlm@1
|
446 value = value & 0xff;
|
rlm@1
|
447 if (value == gbDataMBC5.mapperROMBank)
|
rlm@1
|
448 break;
|
rlm@1
|
449
|
rlm@1
|
450 tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ;
|
rlm@1
|
451
|
rlm@1
|
452 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
453 gbDataMBC5.mapperROMBank = value;
|
rlm@1
|
454 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
455 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
456 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
457 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
458 }
|
rlm@1
|
459 else
|
rlm@1
|
460 {
|
rlm@1
|
461 value = value & 1;
|
rlm@1
|
462 if (value == gbDataMBC5.mapperROMHighAddress)
|
rlm@1
|
463 break;
|
rlm@1
|
464
|
rlm@1
|
465 tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22);
|
rlm@1
|
466
|
rlm@1
|
467 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
468 gbDataMBC5.mapperROMHighAddress = value;
|
rlm@1
|
469 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
470 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
471 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
472 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
473 }
|
rlm@1
|
474 break;
|
rlm@1
|
475 case 0x4000: // RAM bank select
|
rlm@1
|
476 if (gbDataMBC5.isRumbleCartridge)
|
rlm@1
|
477 value &= 0x07;
|
rlm@1
|
478 else
|
rlm@1
|
479 value &= 0x0f;
|
rlm@1
|
480 if (value == gbDataMBC5.mapperRAMBank)
|
rlm@1
|
481 break;
|
rlm@1
|
482 tmpAddress = value << 13;
|
rlm@1
|
483 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
484 if (gbRamSize)
|
rlm@1
|
485 {
|
rlm@1
|
486 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
487 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
488
|
rlm@1
|
489 gbDataMBC5.mapperRAMBank = value;
|
rlm@1
|
490 gbDataMBC5.mapperRAMAddress = tmpAddress;
|
rlm@1
|
491 }
|
rlm@1
|
492 break;
|
rlm@1
|
493 }
|
rlm@1
|
494 }
|
rlm@1
|
495
|
rlm@1
|
496 // MBC5 RAM write
|
rlm@1
|
497 void mapperMBC5RAM(u16 address, u8 value)
|
rlm@1
|
498 {
|
rlm@1
|
499 if (gbDataMBC5.mapperRAMEnable)
|
rlm@1
|
500 {
|
rlm@1
|
501 if (gbRamSize)
|
rlm@1
|
502 {
|
rlm@1
|
503 gbWriteMemoryQuick(address, value);
|
rlm@1
|
504 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
505 }
|
rlm@1
|
506 }
|
rlm@1
|
507 }
|
rlm@1
|
508
|
rlm@1
|
509 void memoryUpdateMapMBC5()
|
rlm@1
|
510 {
|
rlm@1
|
511 int tmpAddress = (gbDataMBC5.mapperROMBank << 14) |
|
rlm@1
|
512 (gbDataMBC5.mapperROMHighAddress << 22) ;
|
rlm@1
|
513
|
rlm@1
|
514 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
515 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
516 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
517 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
518 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
519
|
rlm@1
|
520 if (gbRamSize)
|
rlm@1
|
521 {
|
rlm@1
|
522 tmpAddress = gbDataMBC5.mapperRAMBank << 13;
|
rlm@1
|
523 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
524 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
525 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
526 }
|
rlm@1
|
527 }
|
rlm@1
|
528
|
rlm@1
|
529 mapperMBC7 gbDataMBC7 = {
|
rlm@1
|
530 0, // RAM enable
|
rlm@1
|
531 1, // ROM bank
|
rlm@1
|
532 0, // RAM bank
|
rlm@1
|
533 0, // RAM address
|
rlm@1
|
534 0, // chip select
|
rlm@1
|
535 0, // ??
|
rlm@1
|
536 0, // mapper state
|
rlm@1
|
537 0, // buffer for receiving serial data
|
rlm@1
|
538 0, // idle state
|
rlm@1
|
539 0, // count of bits received
|
rlm@1
|
540 0, // command received
|
rlm@1
|
541 0, // address received
|
rlm@1
|
542 0, // write enable
|
rlm@1
|
543 0, // value to return on ram
|
rlm@1
|
544 };
|
rlm@1
|
545
|
rlm@1
|
546 // MBC7 ROM write registers
|
rlm@1
|
547 void mapperMBC7ROM(u16 address, u8 value)
|
rlm@1
|
548 {
|
rlm@1
|
549 int tmpAddress = 0;
|
rlm@1
|
550
|
rlm@1
|
551 switch (address & 0x6000)
|
rlm@1
|
552 {
|
rlm@1
|
553 case 0x0000:
|
rlm@1
|
554 break;
|
rlm@1
|
555 case 0x2000: // ROM bank select
|
rlm@1
|
556 value = value & 0x7f;
|
rlm@1
|
557 if (value == 0)
|
rlm@1
|
558 value = 1;
|
rlm@1
|
559
|
rlm@1
|
560 if (value == gbDataMBC7.mapperROMBank)
|
rlm@1
|
561 break;
|
rlm@1
|
562
|
rlm@1
|
563 tmpAddress = (value << 14);
|
rlm@1
|
564
|
rlm@1
|
565 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
566 gbDataMBC7.mapperROMBank = value;
|
rlm@1
|
567 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
568 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
569 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
570 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
571 break;
|
rlm@1
|
572 case 0x4000: // RAM bank select/enable
|
rlm@1
|
573 if (value < 8)
|
rlm@1
|
574 {
|
rlm@1
|
575 tmpAddress = (value&3) << 13;
|
rlm@1
|
576 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
577 gbMemoryMap[0x0a] = &gbMemory[0xa000];
|
rlm@1
|
578 gbMemoryMap[0x0b] = &gbMemory[0xb000];
|
rlm@1
|
579
|
rlm@1
|
580 gbDataMBC7.mapperRAMBank = value;
|
rlm@1
|
581 gbDataMBC7.mapperRAMAddress = tmpAddress;
|
rlm@1
|
582 gbDataMBC7.mapperRAMEnable = 0;
|
rlm@1
|
583 }
|
rlm@1
|
584 else
|
rlm@1
|
585 {
|
rlm@1
|
586 gbDataMBC7.mapperRAMEnable = 0;
|
rlm@1
|
587 }
|
rlm@1
|
588 break;
|
rlm@1
|
589 }
|
rlm@1
|
590 }
|
rlm@1
|
591
|
rlm@1
|
592 // MBC7 read RAM
|
rlm@1
|
593 u8 mapperMBC7ReadRAM(u16 address)
|
rlm@1
|
594 {
|
rlm@1
|
595 switch (address & 0xa0f0)
|
rlm@1
|
596 {
|
rlm@1
|
597 case 0xa000:
|
rlm@1
|
598 case 0xa010:
|
rlm@1
|
599 case 0xa060:
|
rlm@1
|
600 case 0xa070:
|
rlm@1
|
601 return 0;
|
rlm@1
|
602 case 0xa020:
|
rlm@1
|
603 // sensor X low byte
|
rlm@1
|
604 return systemGetSensorX() & 255;
|
rlm@1
|
605 case 0xa030:
|
rlm@1
|
606 // sensor X high byte
|
rlm@1
|
607 return systemGetSensorX() >> 8;
|
rlm@1
|
608 case 0xa040:
|
rlm@1
|
609 // sensor Y low byte
|
rlm@1
|
610 return systemGetSensorY() & 255;
|
rlm@1
|
611 case 0xa050:
|
rlm@1
|
612 // sensor Y high byte
|
rlm@1
|
613 return systemGetSensorY() >> 8;
|
rlm@1
|
614 case 0xa080:
|
rlm@1
|
615 return gbDataMBC7.value;
|
rlm@1
|
616 }
|
rlm@1
|
617 return 0xff;
|
rlm@1
|
618 }
|
rlm@1
|
619
|
rlm@1
|
620 // MBC7 RAM write
|
rlm@1
|
621 void mapperMBC7RAM(u16 address, u8 value)
|
rlm@1
|
622 {
|
rlm@1
|
623 if (address == 0xa080)
|
rlm@1
|
624 {
|
rlm@1
|
625 // special processing needed
|
rlm@1
|
626 int oldCs = gbDataMBC7.cs, oldSk = gbDataMBC7.sk;
|
rlm@1
|
627
|
rlm@1
|
628 gbDataMBC7.cs = value>>7;
|
rlm@1
|
629 gbDataMBC7.sk = (value>>6)&1;
|
rlm@1
|
630
|
rlm@1
|
631 if (!oldCs && gbDataMBC7.cs)
|
rlm@1
|
632 {
|
rlm@1
|
633 if (gbDataMBC7.state == 5)
|
rlm@1
|
634 {
|
rlm@1
|
635 if (gbDataMBC7.writeEnable)
|
rlm@1
|
636 {
|
rlm@1
|
637 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2, gbDataMBC7.buffer>>8);
|
rlm@1
|
638 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2+1, gbDataMBC7.buffer&0xff);
|
rlm@1
|
639 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
640 }
|
rlm@1
|
641 gbDataMBC7.state = 0;
|
rlm@1
|
642 gbDataMBC7.value = 1;
|
rlm@1
|
643 }
|
rlm@1
|
644 else
|
rlm@1
|
645 {
|
rlm@1
|
646 gbDataMBC7.idle = true;
|
rlm@1
|
647 gbDataMBC7.state = 0;
|
rlm@1
|
648 }
|
rlm@1
|
649 }
|
rlm@1
|
650
|
rlm@1
|
651 if (!oldSk && gbDataMBC7.sk)
|
rlm@1
|
652 {
|
rlm@1
|
653 if (gbDataMBC7.idle)
|
rlm@1
|
654 {
|
rlm@1
|
655 if (value & 0x02)
|
rlm@1
|
656 {
|
rlm@1
|
657 gbDataMBC7.idle = false;
|
rlm@1
|
658 gbDataMBC7.count = 0;
|
rlm@1
|
659 gbDataMBC7.state = 1;
|
rlm@1
|
660 }
|
rlm@1
|
661 }
|
rlm@1
|
662 else
|
rlm@1
|
663 {
|
rlm@1
|
664 switch (gbDataMBC7.state)
|
rlm@1
|
665 {
|
rlm@1
|
666 case 1:
|
rlm@1
|
667 // receiving command
|
rlm@1
|
668 gbDataMBC7.buffer <<= 1;
|
rlm@1
|
669 gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0;
|
rlm@1
|
670 gbDataMBC7.count++;
|
rlm@1
|
671 if (gbDataMBC7.count == 2)
|
rlm@1
|
672 {
|
rlm@1
|
673 // finished receiving command
|
rlm@1
|
674 gbDataMBC7.state = 2;
|
rlm@1
|
675 gbDataMBC7.count = 0;
|
rlm@1
|
676 gbDataMBC7.code = gbDataMBC7.buffer & 3;
|
rlm@1
|
677 }
|
rlm@1
|
678 break;
|
rlm@1
|
679 case 2:
|
rlm@1
|
680 // receive address
|
rlm@1
|
681 gbDataMBC7.buffer <<= 1;
|
rlm@1
|
682 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
|
rlm@1
|
683 gbDataMBC7.count++;
|
rlm@1
|
684 if (gbDataMBC7.count == 8)
|
rlm@1
|
685 {
|
rlm@1
|
686 // finish receiving
|
rlm@1
|
687 gbDataMBC7.state = 3;
|
rlm@1
|
688 gbDataMBC7.count = 0;
|
rlm@1
|
689 gbDataMBC7.address = gbDataMBC7.buffer&0xff;
|
rlm@1
|
690 if (gbDataMBC7.code == 0)
|
rlm@1
|
691 {
|
rlm@1
|
692 if ((gbDataMBC7.address>>6) == 0)
|
rlm@1
|
693 {
|
rlm@1
|
694 gbDataMBC7.writeEnable = 0;
|
rlm@1
|
695 gbDataMBC7.state = 0;
|
rlm@1
|
696 }
|
rlm@1
|
697 else if ((gbDataMBC7.address>>6) == 3)
|
rlm@1
|
698 {
|
rlm@1
|
699 gbDataMBC7.writeEnable = 1;
|
rlm@1
|
700 gbDataMBC7.state = 0;
|
rlm@1
|
701 }
|
rlm@1
|
702 }
|
rlm@1
|
703 }
|
rlm@1
|
704 break;
|
rlm@1
|
705 case 3:
|
rlm@1
|
706 gbDataMBC7.buffer <<= 1;
|
rlm@1
|
707 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
|
rlm@1
|
708 gbDataMBC7.count++;
|
rlm@1
|
709
|
rlm@1
|
710 switch (gbDataMBC7.code)
|
rlm@1
|
711 {
|
rlm@1
|
712 case 0:
|
rlm@1
|
713 if (gbDataMBC7.count == 16)
|
rlm@1
|
714 {
|
rlm@1
|
715 if ((gbDataMBC7.address>>6) == 0)
|
rlm@1
|
716 {
|
rlm@1
|
717 gbDataMBC7.writeEnable = 0;
|
rlm@1
|
718 gbDataMBC7.state = 0;
|
rlm@1
|
719 }
|
rlm@1
|
720 else if ((gbDataMBC7.address>>6) == 1)
|
rlm@1
|
721 {
|
rlm@1
|
722 if (gbDataMBC7.writeEnable)
|
rlm@1
|
723 {
|
rlm@1
|
724 for (int i = 0; i < 256; i++)
|
rlm@1
|
725 {
|
rlm@1
|
726 gbWriteMemoryQuick(0xa000+i*2, gbDataMBC7.buffer >> 8);
|
rlm@1
|
727 gbWriteMemoryQuick(0xa000+i*2+1, gbDataMBC7.buffer & 0xff);
|
rlm@1
|
728 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
729 }
|
rlm@1
|
730 }
|
rlm@1
|
731 gbDataMBC7.state = 5;
|
rlm@1
|
732 }
|
rlm@1
|
733 else if ((gbDataMBC7.address>>6) == 2)
|
rlm@1
|
734 {
|
rlm@1
|
735 if (gbDataMBC7.writeEnable)
|
rlm@1
|
736 {
|
rlm@1
|
737 for (int i = 0; i < 256; i++)
|
rlm@1
|
738 WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff);
|
rlm@1
|
739 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
740 }
|
rlm@1
|
741 gbDataMBC7.state = 5;
|
rlm@1
|
742 }
|
rlm@1
|
743 else if ((gbDataMBC7.address>>6) == 3)
|
rlm@1
|
744 {
|
rlm@1
|
745 gbDataMBC7.writeEnable = 1;
|
rlm@1
|
746 gbDataMBC7.state = 0;
|
rlm@1
|
747 }
|
rlm@1
|
748 gbDataMBC7.count = 0;
|
rlm@1
|
749 }
|
rlm@1
|
750 break;
|
rlm@1
|
751 case 1:
|
rlm@1
|
752 if (gbDataMBC7.count == 16)
|
rlm@1
|
753 {
|
rlm@1
|
754 gbDataMBC7.count = 0;
|
rlm@1
|
755 gbDataMBC7.state = 5;
|
rlm@1
|
756 gbDataMBC7.value = 0;
|
rlm@1
|
757 }
|
rlm@1
|
758 break;
|
rlm@1
|
759 case 2:
|
rlm@1
|
760 if (gbDataMBC7.count == 1)
|
rlm@1
|
761 {
|
rlm@1
|
762 gbDataMBC7.state = 4;
|
rlm@1
|
763 gbDataMBC7.count = 0;
|
rlm@1
|
764 gbDataMBC7.buffer = (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2)<<8)|
|
rlm@1
|
765 (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2+1));
|
rlm@1
|
766 }
|
rlm@1
|
767 break;
|
rlm@1
|
768 case 3:
|
rlm@1
|
769 if (gbDataMBC7.count == 16)
|
rlm@1
|
770 {
|
rlm@1
|
771 gbDataMBC7.count = 0;
|
rlm@1
|
772 gbDataMBC7.state = 5;
|
rlm@1
|
773 gbDataMBC7.value = 0;
|
rlm@1
|
774 gbDataMBC7.buffer = 0xffff;
|
rlm@1
|
775 }
|
rlm@1
|
776 break;
|
rlm@1
|
777 }
|
rlm@1
|
778 break;
|
rlm@1
|
779 }
|
rlm@1
|
780 }
|
rlm@1
|
781 }
|
rlm@1
|
782
|
rlm@1
|
783 if (oldSk && !gbDataMBC7.sk)
|
rlm@1
|
784 {
|
rlm@1
|
785 if (gbDataMBC7.state == 4)
|
rlm@1
|
786 {
|
rlm@1
|
787 gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000) ? 1 : 0;
|
rlm@1
|
788 gbDataMBC7.buffer <<= 1;
|
rlm@1
|
789 gbDataMBC7.count++;
|
rlm@1
|
790 if (gbDataMBC7.count == 16)
|
rlm@1
|
791 {
|
rlm@1
|
792 gbDataMBC7.count = 0;
|
rlm@1
|
793 gbDataMBC7.state = 0;
|
rlm@1
|
794 }
|
rlm@1
|
795 }
|
rlm@1
|
796 }
|
rlm@1
|
797 }
|
rlm@1
|
798 }
|
rlm@1
|
799
|
rlm@1
|
800 void memoryUpdateMapMBC7()
|
rlm@1
|
801 {
|
rlm@1
|
802 int tmpAddress = (gbDataMBC5.mapperROMBank << 14);
|
rlm@1
|
803
|
rlm@1
|
804 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
805 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
806 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
807 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
808 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
809 }
|
rlm@1
|
810
|
rlm@1
|
811 mapperHuC1 gbDataHuC1 = {
|
rlm@1
|
812 0, // RAM enable
|
rlm@1
|
813 1, // ROM bank
|
rlm@1
|
814 0, // RAM bank
|
rlm@1
|
815 0, // memory model
|
rlm@1
|
816 0, // ROM high address
|
rlm@1
|
817 0 // RAM address
|
rlm@1
|
818 };
|
rlm@1
|
819
|
rlm@1
|
820 // HuC1 ROM write registers
|
rlm@1
|
821 void mapperHuC1ROM(u16 address, u8 value)
|
rlm@1
|
822 {
|
rlm@1
|
823 int tmpAddress = 0;
|
rlm@1
|
824
|
rlm@1
|
825 switch (address & 0x6000)
|
rlm@1
|
826 {
|
rlm@1
|
827 case 0x0000: // RAM enable register
|
rlm@1
|
828 gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
|
rlm@1
|
829 break;
|
rlm@1
|
830 case 0x2000: // ROM bank select
|
rlm@1
|
831 value = value & 0x3f;
|
rlm@1
|
832 if (value == 0)
|
rlm@1
|
833 value = 1;
|
rlm@1
|
834 if (value == gbDataHuC1.mapperROMBank)
|
rlm@1
|
835 break;
|
rlm@1
|
836
|
rlm@1
|
837 tmpAddress = value << 14;
|
rlm@1
|
838
|
rlm@1
|
839 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
840 gbDataHuC1.mapperROMBank = value;
|
rlm@1
|
841 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
842 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
843 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
844 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
845 break;
|
rlm@1
|
846 case 0x4000: // RAM bank select
|
rlm@1
|
847 if (gbDataHuC1.mapperMemoryModel == 1)
|
rlm@1
|
848 {
|
rlm@1
|
849 // 4/32 model, RAM bank switching provided
|
rlm@1
|
850 value = value & 0x03;
|
rlm@1
|
851 if (value == gbDataHuC1.mapperRAMBank)
|
rlm@1
|
852 break;
|
rlm@1
|
853 tmpAddress = value << 13;
|
rlm@1
|
854 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
855 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
856 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
857 gbDataHuC1.mapperRAMBank = value;
|
rlm@1
|
858 gbDataHuC1.mapperRAMAddress = tmpAddress;
|
rlm@1
|
859 }
|
rlm@1
|
860 else
|
rlm@1
|
861 {
|
rlm@1
|
862 // 16/8, set the high address
|
rlm@1
|
863 gbDataHuC1.mapperROMHighAddress = value & 0x03;
|
rlm@1
|
864 tmpAddress = gbDataHuC1.mapperROMBank << 14;
|
rlm@1
|
865 tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19;
|
rlm@1
|
866 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
867 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
868 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
869 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
870 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
871 }
|
rlm@1
|
872 break;
|
rlm@1
|
873 case 0x6000: // memory model select
|
rlm@1
|
874 gbDataHuC1.mapperMemoryModel = value & 1;
|
rlm@1
|
875 break;
|
rlm@1
|
876 }
|
rlm@1
|
877 }
|
rlm@1
|
878
|
rlm@1
|
879 // HuC1 RAM write
|
rlm@1
|
880 void mapperHuC1RAM(u16 address, u8 value)
|
rlm@1
|
881 {
|
rlm@1
|
882 if (gbDataHuC1.mapperRAMEnable)
|
rlm@1
|
883 {
|
rlm@1
|
884 if (gbRamSize)
|
rlm@1
|
885 {
|
rlm@1
|
886 gbWriteMemoryQuick(address, value);
|
rlm@1
|
887 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
888 }
|
rlm@1
|
889 }
|
rlm@1
|
890 }
|
rlm@1
|
891
|
rlm@1
|
892 void memoryUpdateMapHuC1()
|
rlm@1
|
893 {
|
rlm@1
|
894 int tmpAddress = gbDataHuC1.mapperROMBank << 14;
|
rlm@1
|
895
|
rlm@1
|
896 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
897
|
rlm@1
|
898 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
899 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
900 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
901 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
902
|
rlm@1
|
903 if (gbRamSize)
|
rlm@1
|
904 {
|
rlm@1
|
905 tmpAddress = gbDataHuC1.mapperRAMBank << 13;
|
rlm@1
|
906 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
907 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
908 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
909 }
|
rlm@1
|
910 }
|
rlm@1
|
911
|
rlm@1
|
912 mapperHuC3 gbDataHuC3 = {
|
rlm@1
|
913 0, // RAM enable
|
rlm@1
|
914 1, // ROM bank
|
rlm@1
|
915 0, // RAM bank
|
rlm@1
|
916 0, // RAM address
|
rlm@1
|
917 0, // RAM flag
|
rlm@1
|
918 0 // RAM read value
|
rlm@1
|
919 };
|
rlm@1
|
920
|
rlm@1
|
921 // HuC3 ROM write registers
|
rlm@1
|
922 void mapperHuC3ROM(u16 address, u8 value)
|
rlm@1
|
923 {
|
rlm@1
|
924 int tmpAddress = 0;
|
rlm@1
|
925
|
rlm@1
|
926 switch (address & 0x6000)
|
rlm@1
|
927 {
|
rlm@1
|
928 case 0x0000: // RAM enable register
|
rlm@1
|
929 gbDataHuC3.mapperRAMEnable = (value == 0x0a ? 1 : 0);
|
rlm@1
|
930 gbDataHuC3.mapperRAMFlag = value;
|
rlm@1
|
931 if (gbDataHuC3.mapperRAMFlag != 0x0a)
|
rlm@1
|
932 gbDataHuC3.mapperRAMBank = -1;
|
rlm@1
|
933 break;
|
rlm@1
|
934 case 0x2000: // ROM bank select
|
rlm@1
|
935 value = value & 0x7f;
|
rlm@1
|
936 if (value == 0)
|
rlm@1
|
937 value = 1;
|
rlm@1
|
938 if (value == gbDataHuC3.mapperROMBank)
|
rlm@1
|
939 break;
|
rlm@1
|
940
|
rlm@1
|
941 tmpAddress = value << 14;
|
rlm@1
|
942
|
rlm@1
|
943 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
944 gbDataHuC3.mapperROMBank = value;
|
rlm@1
|
945 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
946 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
947 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
948 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
949 break;
|
rlm@1
|
950 case 0x4000: // RAM bank select
|
rlm@1
|
951 value = value & 0x03;
|
rlm@1
|
952 if (value == gbDataHuC3.mapperRAMBank)
|
rlm@1
|
953 break;
|
rlm@1
|
954 tmpAddress = value << 13;
|
rlm@1
|
955 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
956 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
957 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
958 gbDataHuC3.mapperRAMBank = value;
|
rlm@1
|
959 gbDataHuC3.mapperRAMAddress = tmpAddress;
|
rlm@1
|
960 break;
|
rlm@1
|
961 case 0x6000: // nothing to do!
|
rlm@1
|
962 break;
|
rlm@1
|
963 }
|
rlm@1
|
964 }
|
rlm@1
|
965
|
rlm@1
|
966 // HuC3 read RAM
|
rlm@1
|
967 u8 mapperHuC3ReadRAM(u16 address)
|
rlm@1
|
968 {
|
rlm@1
|
969 if (gbDataHuC3.mapperRAMFlag > 0x0b &&
|
rlm@1
|
970 gbDataHuC3.mapperRAMFlag < 0x0e)
|
rlm@1
|
971 {
|
rlm@1
|
972 if (gbDataHuC3.mapperRAMFlag != 0x0c)
|
rlm@1
|
973 return 1;
|
rlm@1
|
974 return gbDataHuC3.mapperRAMValue;
|
rlm@1
|
975 }
|
rlm@1
|
976 else
|
rlm@1
|
977 return gbReadMemoryQuick(address);
|
rlm@1
|
978 }
|
rlm@1
|
979
|
rlm@1
|
980 // HuC3 RAM write
|
rlm@1
|
981 void mapperHuC3RAM(u16 address, u8 value)
|
rlm@1
|
982 {
|
rlm@1
|
983 int32 *p;
|
rlm@1
|
984
|
rlm@1
|
985 if (gbDataHuC3.mapperRAMFlag < 0x0b ||
|
rlm@1
|
986 gbDataHuC3.mapperRAMFlag > 0x0e)
|
rlm@1
|
987 {
|
rlm@1
|
988 if (gbDataHuC3.mapperRAMEnable)
|
rlm@1
|
989 {
|
rlm@1
|
990 if (gbRamSize)
|
rlm@1
|
991 {
|
rlm@1
|
992 gbWriteMemoryQuick(address, value);
|
rlm@1
|
993 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
|
rlm@1
|
994 }
|
rlm@1
|
995 }
|
rlm@1
|
996 }
|
rlm@1
|
997 else
|
rlm@1
|
998 {
|
rlm@1
|
999 if (gbDataHuC3.mapperRAMFlag == 0x0b)
|
rlm@1
|
1000 {
|
rlm@1
|
1001 if (value == 0x62)
|
rlm@1
|
1002 {
|
rlm@1
|
1003 gbDataHuC3.mapperRAMValue = 1;
|
rlm@1
|
1004 }
|
rlm@1
|
1005 else
|
rlm@1
|
1006 {
|
rlm@1
|
1007 switch (value & 0xf0)
|
rlm@1
|
1008 {
|
rlm@1
|
1009 case 0x10:
|
rlm@1
|
1010 p = &gbDataHuC3.mapperRegister2;
|
rlm@1
|
1011 gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++);
|
rlm@1
|
1012 if (gbDataHuC3.mapperRegister1 > 6)
|
rlm@1
|
1013 gbDataHuC3.mapperRegister1 = 0;
|
rlm@1
|
1014 break;
|
rlm@1
|
1015 case 0x30:
|
rlm@1
|
1016 p = &gbDataHuC3.mapperRegister2;
|
rlm@1
|
1017 *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f;
|
rlm@1
|
1018 if (gbDataHuC3.mapperRegister1 > 6)
|
rlm@1
|
1019 gbDataHuC3.mapperRegister1 = 0;
|
rlm@1
|
1020 gbDataHuC3.mapperAddress =
|
rlm@1
|
1021 (gbDataHuC3.mapperRegister6 << 24) |
|
rlm@1
|
1022 (gbDataHuC3.mapperRegister5 << 16) |
|
rlm@1
|
1023 (gbDataHuC3.mapperRegister4 << 8) |
|
rlm@1
|
1024 (gbDataHuC3.mapperRegister3 << 4) |
|
rlm@1
|
1025 (gbDataHuC3.mapperRegister2);
|
rlm@1
|
1026 break;
|
rlm@1
|
1027 case 0x40:
|
rlm@1
|
1028 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) |
|
rlm@1
|
1029 (value & 0x0f);
|
rlm@1
|
1030 gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f);
|
rlm@1
|
1031 gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f);
|
rlm@1
|
1032 gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f);
|
rlm@1
|
1033 gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f);
|
rlm@1
|
1034 gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f);
|
rlm@1
|
1035 gbDataHuC3.mapperRegister7 = 0;
|
rlm@1
|
1036 gbDataHuC3.mapperRegister8 = 0;
|
rlm@1
|
1037 gbDataHuC3.mapperRAMValue = 0;
|
rlm@1
|
1038 break;
|
rlm@1
|
1039 case 0x50:
|
rlm@1
|
1040 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) |
|
rlm@1
|
1041 ((value << 4)&0x0f);
|
rlm@1
|
1042 break;
|
rlm@1
|
1043 default:
|
rlm@1
|
1044 gbDataHuC3.mapperRAMValue = 1;
|
rlm@1
|
1045 break;
|
rlm@1
|
1046 }
|
rlm@1
|
1047 }
|
rlm@1
|
1048 }
|
rlm@1
|
1049 }
|
rlm@1
|
1050 }
|
rlm@1
|
1051
|
rlm@1
|
1052 void memoryUpdateMapHuC3()
|
rlm@1
|
1053 {
|
rlm@1
|
1054 int tmpAddress = gbDataHuC3.mapperROMBank << 14;
|
rlm@1
|
1055
|
rlm@1
|
1056 tmpAddress &= gbRomSizeMask;
|
rlm@1
|
1057 gbMemoryMap[0x04] = &gbRom[tmpAddress];
|
rlm@1
|
1058 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
|
rlm@1
|
1059 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
|
rlm@1
|
1060 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
|
rlm@1
|
1061
|
rlm@1
|
1062 if (gbRamSize)
|
rlm@1
|
1063 {
|
rlm@1
|
1064 tmpAddress = gbDataHuC3.mapperRAMBank << 13;
|
rlm@1
|
1065 tmpAddress &= gbRamSizeMask;
|
rlm@1
|
1066 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
|
rlm@1
|
1067 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
|
rlm@1
|
1068 }
|
rlm@1
|
1069 }
|
rlm@1
|
1070
|