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