3 #include "rockmacros.h"
14 struct mbc mbc IBSS_ATTR
;
15 struct rom rom IBSS_ATTR
;
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_updatemap(void)
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
;
51 map
[0x8] = lcd
.vbank
[1] - 0x8000;
52 map
[0x9] = lcd
.vbank
[1] - 0x8000;
56 map
[0x8] = lcd
.vbank
[0]/*[R_VBK & 1]*/ - 0x8000;
57 map
[0x9] = lcd
.vbank
[0]/*[R_VBK & 1]*/ - 0x8000;
60 if (mbc
.enableram
&& !(rtc
.sel
&8))
62 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
63 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
65 else map
[0xA] = map
[0xB] = NULL
;
66 map
[0xC] = ram
.ibank
[0] - 0xC000;
68 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
69 map
[0xE] = ram
.ibank
[0] - 0xE000;
73 map
[0x0] = map
[0x1] = map
[0x2] = map
[0x3] = NULL
;
74 map
[0x4] = map
[0x5] = map
[0x6] = map
[0x7] = NULL
;
75 map
[0x8] = map
[0x9] = NULL
;
76 if (mbc
.enableram
&& !(rtc
.sel
&8))
78 map
[0xA] = ram
.sbank
[mbc
.rambank
] - 0xA000;
79 map
[0xB] = ram
.sbank
[mbc
.rambank
] - 0xA000;
81 else map
[0xA] = map
[0xB] = NULL
;
82 map
[0xC] = ram
.ibank
[0] - 0xC000;
84 map
[0xD] = ram
.ibank
[n
?n
:1] - 0xD000;
85 map
[0xE] = ram
.ibank
[0] - 0xE000;
91 * ioreg_write handles output to io registers in the FF00-FF7F,FFFF
92 * range. It takes the register number (low byte of the address) and a
93 * byte value to be written.
96 static void ioreg_write(byte r
, byte b
) ICODE_ATTR
;
97 static void ioreg_write(byte r
, byte b
)
131 if (R_BGP
== b
) break;
132 pal_write_dmg(0, 0, b
);
133 pal_write_dmg(8, 1, b
);
137 if (R_OBP0
== b
) break;
138 pal_write_dmg(64, 2, b
);
142 if (R_OBP1
== b
) break;
143 pal_write_dmg(72, 3, b
);
155 /* FIXME - this is a hack for stupid roms that probe serial */
156 if ((b
& 0x81) == 0x81)
159 hw_interrupt(IF_SERIAL
, IF_SERIAL
);
160 hw_interrupt(0, IF_SERIAL
);
162 R_SC
= b
; /* & 0x7f; */
171 REG(r
) = (REG(r
) & 0x07) | (b
& 0x78);
184 R_BCPD
= lcd
.pal
[b
& 0x3F];
188 R_OCPD
= lcd
.pal
[64 + (b
& 0x3F)];
192 pal_write(R_BCPS
& 0x3F, b
);
193 if (R_BCPS
& 0x80) R_BCPS
= (R_BCPS
+1) & 0xBF;
197 pal_write(64 + (R_OCPS
& 0x3F), b
);
198 if (R_OCPS
& 0x80) R_OCPS
= (R_OCPS
+1) & 0xBF;
208 REG(r
) = (REG(r
) & 0x80) | (b
& 0x01);
229 static byte
ioreg_read(byte r
)
269 if (hw
.cgb
) return REG(r
);
278 * Memory bank controllers typically intercept write attempts to
279 * 0000-7FFF, using the address and byte written as instructions to
280 * change rom or sram banks, control special hardware, etc.
282 * mbc_write takes an address (which should be in the proper range)
283 * and a byte value written to the address.
286 static void mbc_write(int a
, byte b
) ICODE_ATTR
;
287 static void mbc_write(int a
, byte b
)
291 /* printf("mbc %d: rom bank %02X -[%04X:%02X]-> ", mbc.type, mbc.rombank, a, b); */
298 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
301 if ((b
& 0x1F) == 0) b
= 0x01;
302 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
307 mbc
.rambank
= b
& 0x03;
310 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
317 case MBC_MBC2
: /* is this at all right? */
318 if ((a
& 0x0100) == 0x0000)
320 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
323 if ((a
& 0xE100) == 0x2100)
325 mbc
.rombank
= b
& 0x0F;
333 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
336 if ((b
& 0x7F) == 0) b
= 0x01;
337 mbc
.rombank
= b
& 0x7F;
341 mbc
.rambank
= b
& 0x03;
353 /* FIXME - save high bit as rumble state */
354 /* mask off high bit */
364 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
367 if ((b
& 0xFF) == 0) b
= 0x01;
368 mbc
.rombank
= (mbc
.rombank
& 0x100) | (b
& 0xFF);
371 mbc
.rombank
= (mbc
.rombank
& 0xFF) | ((int)(b
&1)<<8);
375 mbc
.rambank
= b
& 0x0f;
379 case MBC_HUC1
: /* FIXME - this is all guesswork -- is it right??? */
383 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
386 if ((b
& 0x1F) == 0) b
= 0x01;
387 mbc
.rombank
= (mbc
.rombank
& 0x60) | (b
& 0x1F);
392 mbc
.rambank
= b
& 0x03;
395 mbc
.rombank
= (mbc
.rombank
& 0x1F) | ((int)(b
&3)<<5);
402 case MBC_HUC3
: /* FIXME - this is all guesswork -- is it right??? */
406 mbc
.enableram
= ((b
& 0x0F) == 0x0A);
415 mbc
.rambank
= b
& 0x03;
425 mbc
.rombank
&= (mbc
.romsize
- 1);
426 mbc
.rambank
&= (mbc
.ramsize
- 1);
432 * mem_write is the basic write function. Although it should only be
433 * called when the write map contains a NULL for the requested address
434 * region, it accepts writes to any address.
437 void mem_write(int a
, byte b
)
440 byte ha
= (a
>>12) & 0xE;
442 /* printf("write to 0x%04X: 0x%02X\n", a, b); */
452 /* if ((R_STAT & 0x03) == 0x03) break; */
453 vram_write(a
& 0x1FFF, b
);
456 if (!mbc
.enableram
) break;
462 ram
.sbank
[mbc
.rambank
][a
& 0x1FFF] = b
;
465 if ((a
& 0xF000) == 0xC000)
467 ram
.ibank
[0][a
& 0x0FFF] = b
;
471 ram
.ibank
[n
?n
:1][a
& 0x0FFF] = b
;
476 mem_write(a
& 0xDFFF, b
);
479 if ((a
& 0xFF00) == 0xFE00)
481 /* if (R_STAT & 0x02) break; */
482 if (a
< 0xFEA0) lcd
.oam
.mem
[a
& 0xFF] = b
;
485 /* return writehi(a & 0xFF, b); */
486 if (a
>= 0xFF10 && a
<= 0xFF3F)
489 sound_write(a
& 0xFF, b
);
492 if ((a
& 0xFF80) == 0xFF80 && a
!= 0xFFFF)
494 ram
.hi
[a
& 0xFF] = b
;
497 ioreg_write(a
& 0xFF, b
);
503 * mem_read is the basic read function...not useful for much anymore
504 * with the read map, but it's still necessary for the final messy
511 byte ha
= (a
>>12) & 0xE;
513 /* printf("read %04x\n", a); */
518 return rom
.bank
[0][a
];
521 return rom
.bank
[mbc
.rombank
][a
& 0x3FFF];
523 /* if ((R_STAT & 0x03) == 0x03) return 0xFF; */
524 return lcd
.vbank
[R_VBK
&1][a
& 0x1FFF];
529 return rtc
.regs
[rtc
.sel
&7];
530 return ram
.sbank
[mbc
.rambank
][a
& 0x1FFF];
532 if ((a
& 0xF000) == 0xC000)
533 return ram
.ibank
[0][a
& 0x0FFF];
535 return ram
.ibank
[n
?n
:1][a
& 0x0FFF];
537 if (a
< 0xFE00) return mem_read(a
& 0xDFFF);
538 if ((a
& 0xFF00) == 0xFE00)
540 /* if (R_STAT & 0x02) return 0xFF; */
541 if (a
< 0xFEA0) return lcd
.oam
.mem
[a
& 0xFF];
544 /* return readhi(a & 0xFF); */
545 if (a
== 0xFFFF) return REG(0xFF);
546 if (a
>= 0xFF10 && a
<= 0xFF3F)
549 return sound_read(a
& 0xFF);
553 if ((a
& 0xFF80) == 0xFF80)
554 return ram
.hi
[a
& 0xFF];
555 return ioreg_read(a
& 0xFF);
557 return 0xff; /* not reached */