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.
37 map
[0x0] = rom
.bank
[0];
38 map
[0x1] = rom
.bank
[0];
39 map
[0x2] = rom
.bank
[0];
40 map
[0x3] = rom
.bank
[0];
41 if (mbc
.rombank
< mbc
.romsize
)
43 map
[0x4] = rom
.bank
[mbc
.rombank
] - 0x4000;
44 map
[0x5] = rom
.bank
[mbc
.rombank
] - 0x4000;
45 map
[0x6] = rom
.bank
[mbc
.rombank
] - 0x4000;
46 map
[0x7] = rom
.bank
[mbc
.rombank
] - 0x4000;
48 else map
[0x4] = map
[0x5] = map
[0x6] = map
[0x7] = NULL
;
49 if (0 && (R_STAT
& 0x03) == 0x03)
56 map
[0x8] = lcd
.vbank
[R_VBK
& 1] - 0x8000;
57 map
[0x9] = lcd
.vbank
[R_VBK
& 1] - 0x8000;
59 if (mbc
.enableram
&& !(rtc
.sel
&8))
61 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
62 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
64 else map
[0xA] = map
[0xB] = NULL
;
65 map
[0xC] = ram
.ibank
[0] - 0xC000;
67 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
68 map
[0xE] = ram
.ibank
[0] - 0xE000;
72 map
[0x0] = map
[0x1] = map
[0x2] = map
[0x3] = NULL
;
73 map
[0x4] = map
[0x5] = map
[0x6] = map
[0x7] = NULL
;
74 map
[0x8] = map
[0x9] = NULL
;
75 if (mbc
.enableram
&& !(rtc
.sel
&8))
77 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
78 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
80 else map
[0xA] = map
[0xB] = NULL
;
81 map
[0xC] = ram
.ibank
[0] - 0xC000;
83 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
84 map
[0xE] = ram
.ibank
[0] - 0xE000;
90 * ioreg_write handles output to io registers in the FF00-FF7F,FFFF
91 * range. It takes the register number (low byte of the address) and a
92 * byte value to be written.
95 void ioreg_write(byte r
, byte b
)
129 if (R_BGP
== b
) break;
130 pal_write_dmg(0, 0, b
);
131 pal_write_dmg(8, 1, b
);
135 if (R_OBP0
== b
) break;
136 pal_write_dmg(64, 2, b
);
140 if (R_OBP1
== b
) break;
141 pal_write_dmg(72, 3, b
);
153 /* FIXME - this is a hack for stupid roms that probe serial */
154 if ((b
& 0x81) == 0x81)
157 hw_interrupt(IF_SERIAL
, IF_SERIAL
);
158 hw_interrupt(0, IF_SERIAL
);
160 R_SC
= b
; /* & 0x7f; */
181 R_BCPD
= lcd
.pal
[b
& 0x3F];
185 R_OCPD
= lcd
.pal
[64 + (b
& 0x3F)];
189 pal_write(R_BCPS
& 0x3F, b
);
190 if (R_BCPS
& 0x80) R_BCPS
= (R_BCPS
+1) & 0xBF;
194 pal_write(64 + (R_OCPS
& 0x3F), b
);
195 if (R_OCPS
& 0x80) R_OCPS
= (R_OCPS
+1) & 0xBF;
205 REG(r
) = (REG(r
) & 0x80) | (b
& 0x01);
228 /* printf("palette reg %02X write %02X at LY=%02X\n", r, b, R_LY); */
234 /* printf("HDMA %d: %02X\n", r - RI_HDMA1 + 1, b); */
237 /* printf("reg %02X => %02X (%02X)\n", r, REG(r), b); */
241 byte
ioreg_read(byte r
)
281 if (hw
.cgb
) return REG(r
);
290 * Memory bank controllers typically intercept write attempts to
291 * 0000-7FFF, using the address and byte written as instructions to
292 * change rom or sram banks, control special hardware, etc.
294 * mbc_write takes an address (which should be in the proper range)
295 * and a byte value written to the address.
298 void mbc_write(int a
, byte b
)
302 /* printf("mbc %d: rom bank %02X -[%04X:%02X]-> ", mbc.type, mbc.rombank, a, b); */
309 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
312 if ((b
& 0x1F) == 0) b
= 0x01;
313 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
318 mbc
.rambank
= b
& 0x03;
321 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
328 case MBC_MBC2
: /* is this at all right? */
329 if ((a
& 0x0100) == 0x0000)
331 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
334 if ((a
& 0xE100) == 0x2100)
336 mbc
.rombank
= b
& 0x0F;
344 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
347 if ((b
& 0x7F) == 0) b
= 0x01;
348 mbc
.rombank
= b
& 0x7F;
352 mbc
.rambank
= b
& 0x03;
364 /* FIXME - save high bit as rumble state */
365 /* mask off high bit */
375 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
378 if ((b
& 0xFF) == 0) b
= 0x01;
379 mbc
.rombank
= (mbc
.rombank
& 0x100) | (b
& 0xFF);
382 mbc
.rombank
= (mbc
.rombank
& 0xFF) | ((int)(b
&1)<<8);
386 mbc
.rambank
= b
& 0x0f;
390 case MBC_HUC1
: /* FIXME - this is all guesswork -- is it right??? */
394 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
397 if ((b
& 0x1F) == 0) b
= 0x01;
398 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
403 mbc
.rambank
= b
& 0x03;
406 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
417 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
421 mbc
.rombank
= b
? b
: 1;
425 mbc
.rambank
= b
& 0x03;
433 mbc
.rombank
&= (mbc
.romsize
- 1);
434 mbc
.rambank
&= (mbc
.ramsize
- 1);
435 /* printf("%02X\n", mbc.rombank); */
441 * mem_write is the basic write function. Although it should only be
442 * called when the write map contains a NULL for the requested address
443 * region, it accepts writes to any address.
446 void mem_write(int a
, byte b
)
449 byte ha
= (a
>>12) & 0xE;
451 /* printf("write to 0x%04X: 0x%02X\n", a, b); */
461 /* if ((R_STAT & 0x03) == 0x03) break; */
462 vram_write(a
& 0x1FFF, b
);
465 if (!mbc
.enableram
) break;
471 ram
.sbank
[mbc
.rambank
][a
& 0x1FFF] = b
;
474 if ((a
& 0xF000) == 0xC000)
476 ram
.ibank
[0][a
& 0x0FFF] = b
;
480 ram
.ibank
[n
?n
:1][a
& 0x0FFF] = b
;
485 mem_write(a
& 0xDFFF, b
);
488 if ((a
& 0xFF00) == 0xFE00)
490 /* if (R_STAT & 0x02) break; */
491 if (a
< 0xFEA0) lcd
.oam
.mem
[a
& 0xFF] = b
;
494 /* return writehi(a & 0xFF, b); */
495 if (a
>= 0xFF10 && a
<= 0xFF3F)
497 sound_write(a
& 0xFF, b
);
500 if ((a
& 0xFF80) == 0xFF80 && a
!= 0xFFFF)
502 ram
.hi
[a
& 0xFF] = b
;
505 ioreg_write(a
& 0xFF, b
);
511 * mem_read is the basic read function...not useful for much anymore
512 * with the read map, but it's still necessary for the final messy
519 byte ha
= (a
>>12) & 0xE;
521 /* printf("read %04x\n", a); */
526 return rom
.bank
[0][a
];
529 return rom
.bank
[mbc
.rombank
][a
& 0x3FFF];
531 /* if ((R_STAT & 0x03) == 0x03) return 0xFF; */
532 return lcd
.vbank
[R_VBK
&1][a
& 0x1FFF];
534 if (!mbc
.enableram
&& mbc
.type
== MBC_HUC3
)
539 return rtc
.regs
[rtc
.sel
&7];
540 return ram
.sbank
[mbc
.rambank
][a
& 0x1FFF];
542 if ((a
& 0xF000) == 0xC000)
543 return ram
.ibank
[0][a
& 0x0FFF];
545 return ram
.ibank
[n
?n
:1][a
& 0x0FFF];
547 if (a
< 0xFE00) return mem_read(a
& 0xDFFF);
548 if ((a
& 0xFF00) == 0xFE00)
550 /* if (R_STAT & 0x02) return 0xFF; */
551 if (a
< 0xFEA0) return lcd
.oam
.mem
[a
& 0xFF];
554 /* return readhi(a & 0xFF); */
555 if (a
== 0xFFFF) return REG(0xFF);
556 if (a
>= 0xFF10 && a
<= 0xFF3F)
557 return sound_read(a
& 0xFF);
558 if ((a
& 0xFF80) == 0xFF80)
559 return ram
.hi
[a
& 0xFF];
560 return ioreg_read(a
& 0xFF);
562 return 0xff; /* not reached */