20 * In order to make reads and writes efficient, we keep tables
21 * (indexed by the high nibble of the address) specifying which
22 * regions can be read/written without a function call. For such
23 * ranges, the pointer in the map table points to the base of the
24 * region in host system memory. For ranges that require special
25 * processing, the pointer is NULL.
27 * mem_updatemap is called whenever bank changes or other operations
28 * make the old maps potentially invalid.
31 void mem_mapbootrom() {
32 if (!bootrom
.bank
) return;
33 mbc
.rmap
[0x0] = bootrom
.bank
[0];
41 mbc
.rombank
&= (mbc
.romsize
- 1);
42 mbc
.rambank
&= (mbc
.ramsize
- 1);
45 /* don't unmap bootrom unless RI_BOOT was locked */
46 if (REG(RI_BOOT
) & 1) map
[0x0] = rom
.bank
[0];
47 map
[0x1] = rom
.bank
[0];
48 map
[0x2] = rom
.bank
[0];
49 map
[0x3] = rom
.bank
[0];
50 if (mbc
.rombank
< mbc
.romsize
)
52 map
[0x4] = rom
.bank
[mbc
.rombank
] - 0x4000;
53 map
[0x5] = rom
.bank
[mbc
.rombank
] - 0x4000;
54 map
[0x6] = rom
.bank
[mbc
.rombank
] - 0x4000;
55 map
[0x7] = rom
.bank
[mbc
.rombank
] - 0x4000;
57 else map
[0x4] = map
[0x5] = map
[0x6] = map
[0x7] = NULL
;
58 if (0 && (R_STAT
& 0x03) == 0x03)
65 map
[0x8] = lcd
.vbank
[R_VBK
& 1] - 0x8000;
66 map
[0x9] = lcd
.vbank
[R_VBK
& 1] - 0x8000;
68 if (mbc
.enableram
&& !(rtc
.sel
&8))
70 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
71 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
73 else map
[0xA] = map
[0xB] = NULL
;
74 map
[0xC] = ram
.ibank
[0] - 0xC000;
76 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
77 map
[0xE] = ram
.ibank
[0] - 0xE000;
81 map
[0x0] = map
[0x1] = map
[0x2] = map
[0x3] = NULL
;
82 map
[0x4] = map
[0x5] = map
[0x6] = map
[0x7] = NULL
;
83 map
[0x8] = map
[0x9] = NULL
;
84 if (mbc
.enableram
&& !(rtc
.sel
&8))
86 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
87 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
89 else map
[0xA] = map
[0xB] = NULL
;
90 map
[0xC] = ram
.ibank
[0] - 0xC000;
92 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
93 map
[0xE] = ram
.ibank
[0] - 0xE000;
99 * ioreg_write handles output to io registers in the FF00-FF7F,FFFF
100 * range. It takes the register number (low byte of the address) and a
101 * byte value to be written.
104 void ioreg_write(byte r
, byte b
)
138 if (R_BGP
== b
) break;
139 pal_write_dmg(0, 0, b
);
140 pal_write_dmg(8, 1, b
);
144 if (R_OBP0
== b
) break;
145 pal_write_dmg(64, 2, b
);
149 if (R_OBP1
== b
) break;
150 pal_write_dmg(72, 3, b
);
162 /* FIXME - this is a hack for stupid roms that probe serial */
163 if ((b
& 0x81) == 0x81)
166 hw_interrupt(IF_SERIAL
, IF_SERIAL
);
167 hw_interrupt(0, IF_SERIAL
);
169 R_SC
= b
; /* & 0x7f; */
193 R_BCPD
= lcd
.pal
[b
& 0x3F];
197 R_OCPD
= lcd
.pal
[64 + (b
& 0x3F)];
201 pal_write(R_BCPS
& 0x3F, b
);
202 if (R_BCPS
& 0x80) R_BCPS
= (R_BCPS
+1) & 0xBF;
206 pal_write(64 + (R_OCPS
& 0x3F), b
);
207 if (R_OCPS
& 0x80) R_OCPS
= (R_OCPS
+1) & 0xBF;
223 REG(r
) = (REG(r
) & 0x80) | (b
& 0x01);
246 /* printf("palette reg %02X write %02X at LY=%02X\n", r, b, R_LY); */
252 /* printf("HDMA %d: %02X\n", r - RI_HDMA1 + 1, b); */
255 /* printf("reg %02X => %02X (%02X)\n", r, REG(r), b); */
259 byte
ioreg_read(byte r
)
264 return 0xfe | (REG(r
) & 1);
301 if (hw
.cgb
) return REG(r
);
310 * Memory bank controllers typically intercept write attempts to
311 * 0000-7FFF, using the address and byte written as instructions to
312 * change rom or sram banks, control special hardware, etc.
314 * mbc_write takes an address (which should be in the proper range)
315 * and a byte value written to the address.
318 void mbc_write(int a
, byte b
)
322 /* printf("mbc %d: rom bank %02X -[%04X:%02X]-> ", mbc.type, mbc.rombank, a, b); */
329 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
332 if ((b
& 0x1F) == 0) b
= 0x01;
333 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
338 mbc
.rambank
= b
& 0x03;
341 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
348 case MBC_MBC2
: /* is this at all right? */
349 if ((a
& 0x0100) == 0x0000)
351 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
354 if ((a
& 0xE100) == 0x2100)
356 mbc
.rombank
= b
& 0x0F;
364 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
367 if ((b
& 0x7F) == 0) b
= 0x01;
368 mbc
.rombank
= b
& 0x7F;
372 mbc
.rambank
= b
& 0x03;
384 /* FIXME - save high bit as rumble state */
385 /* mask off high bit */
395 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
398 if ((b
& 0xFF) == 0) b
= 0x01;
399 mbc
.rombank
= (mbc
.rombank
& 0x100) | (b
& 0xFF);
402 mbc
.rombank
= (mbc
.rombank
& 0xFF) | ((int)(b
&1)<<8);
406 mbc
.rambank
= b
& 0x0f;
410 case MBC_HUC1
: /* FIXME - this is all guesswork -- is it right??? */
414 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
417 if ((b
& 0x1F) == 0) b
= 0x01;
418 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
423 mbc
.rambank
= b
& 0x03;
426 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
437 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
441 mbc
.rombank
= b
? b
: 1;
445 mbc
.rambank
= b
& 0x03;
453 /* printf("%02X\n", mbc.rombank); */
459 * mem_write is the basic write function. Although it should only be
460 * called when the write map contains a NULL for the requested address
461 * region, it accepts writes to any address.
464 void mem_write(int a
, byte b
)
467 byte ha
= (a
>>12) & 0xE;
469 /* printf("write to 0x%04X: 0x%02X\n", a, b); */
479 /* if ((R_STAT & 0x03) == 0x03) break; */
480 vram_write(a
& 0x1FFF, b
);
483 if (!mbc
.enableram
) break;
489 ram
.sbank
[mbc
.rambank
][a
& 0x1FFF] = b
;
492 if ((a
& 0xF000) == 0xC000)
494 ram
.ibank
[0][a
& 0x0FFF] = b
;
498 ram
.ibank
[n
?n
:1][a
& 0x0FFF] = b
;
503 mem_write(a
& 0xDFFF, b
);
506 if ((a
& 0xFF00) == 0xFE00)
508 /* if (R_STAT & 0x02) break; */
509 if (a
< 0xFEA0) lcd
.oam
.mem
[a
& 0xFF] = b
;
512 /* return writehi(a & 0xFF, b); */
513 if (a
>= 0xFF10 && a
<= 0xFF3F)
515 sound_write(a
& 0xFF, b
);
518 if ((a
& 0xFF80) == 0xFF80 && a
!= 0xFFFF)
520 ram
.hi
[a
& 0xFF] = b
;
523 ioreg_write(a
& 0xFF, b
);
529 * mem_read is the basic read function...not useful for much anymore
530 * with the read map, but it's still necessary for the final messy
537 byte ha
= (a
>>12) & 0xE;
539 /* printf("read %04x\n", a); */
544 return rom
.bank
[0][a
];
547 return rom
.bank
[mbc
.rombank
][a
& 0x3FFF];
549 /* if ((R_STAT & 0x03) == 0x03) return 0xFF; */
550 return lcd
.vbank
[R_VBK
&1][a
& 0x1FFF];
552 if (!mbc
.enableram
&& mbc
.type
== MBC_HUC3
)
557 return rtc
.regs
[rtc
.sel
&7];
558 return ram
.sbank
[mbc
.rambank
][a
& 0x1FFF];
560 if ((a
& 0xF000) == 0xC000)
561 return ram
.ibank
[0][a
& 0x0FFF];
563 return ram
.ibank
[n
?n
:1][a
& 0x0FFF];
565 if (a
< 0xFE00) return mem_read(a
& 0xDFFF);
566 if ((a
& 0xFF00) == 0xFE00)
568 /* if (R_STAT & 0x02) return 0xFF; */
569 if (a
< 0xFEA0) return lcd
.oam
.mem
[a
& 0xFF];
572 /* return readhi(a & 0xFF); */
573 if (a
== 0xFFFF) return REG(0xFF);
574 if (a
>= 0xFF10 && a
<= 0xFF3F)
575 return sound_read(a
& 0xFF);
576 if ((a
& 0xFF80) == 0xFF80)
577 return ram
.hi
[a
& 0xFF];
578 return ioreg_read(a
& 0xFF);
580 return 0xff; /* not reached */
591 const char* mbc_to_string(int mbc_type
) {
593 case MBC_NONE
: return "NONE";
594 case MBC_MBC1
: return "MBC1";
595 case MBC_MBC2
: return "MBC2";
596 case MBC_MBC3
: return "MBC3";
597 case MBC_MBC5
: return "MBC5";
598 case MBC_RUMBLE
: return "RUMBL";
599 case MBC_HUC1
: return "HUC1";
600 case MBC_HUC3
: return "HUC3";
601 default: return "UNKN";