configure.ac: don't add -L /usr/local
[rofl0r-gnuboy.git] / mem.c
blob5d951e1a1a141fdb5a8176f89a506ea79cba7be6
3 #include <stdlib.h>
5 #include "defs.h"
6 #include "hw.h"
7 #include "regs.h"
8 #include "mem.h"
9 #include "rtc.h"
10 #include "lcd.h"
11 #include "lcdc.h"
12 #include "sound.h"
14 struct mbc mbc;
15 struct rom rom;
16 struct ram ram;
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()
33 int n;
34 byte **map;
36 map = mbc.rmap;
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)
51 map[0x8] = NULL;
52 map[0x9] = NULL;
54 else
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;
66 n = R_SVBK & 0x07;
67 map[0xD] = ram.ibank[n?n:1] - 0xD000;
68 map[0xE] = ram.ibank[0] - 0xE000;
69 map[0xF] = NULL;
71 map = mbc.wmap;
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;
82 n = R_SVBK & 0x07;
83 map[0xD] = ram.ibank[n?n:1] - 0xD000;
84 map[0xE] = ram.ibank[0] - 0xE000;
85 map[0xF] = NULL;
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)
97 if (!hw.cgb)
99 switch (r)
101 case RI_VBK:
102 case RI_BCPS:
103 case RI_OCPS:
104 case RI_BCPD:
105 case RI_OCPD:
106 case RI_SVBK:
107 case RI_KEY1:
108 case RI_HDMA1:
109 case RI_HDMA2:
110 case RI_HDMA3:
111 case RI_HDMA4:
112 case RI_HDMA5:
113 return;
117 switch(r)
119 case RI_TIMA:
120 case RI_TMA:
121 case RI_TAC:
122 case RI_SCY:
123 case RI_SCX:
124 case RI_WY:
125 case RI_WX:
126 REG(r) = b;
127 break;
128 case RI_BGP:
129 if (R_BGP == b) break;
130 pal_write_dmg(0, 0, b);
131 pal_write_dmg(8, 1, b);
132 R_BGP = b;
133 break;
134 case RI_OBP0:
135 if (R_OBP0 == b) break;
136 pal_write_dmg(64, 2, b);
137 R_OBP0 = b;
138 break;
139 case RI_OBP1:
140 if (R_OBP1 == b) break;
141 pal_write_dmg(72, 3, b);
142 R_OBP1 = b;
143 break;
144 case RI_IF:
145 case RI_IE:
146 REG(r) = b & 0x1F;
147 break;
148 case RI_P1:
149 REG(r) = b;
150 pad_refresh();
151 break;
152 case RI_SC:
153 /* FIXME - this is a hack for stupid roms that probe serial */
154 if ((b & 0x81) == 0x81)
156 R_SB = 0xff;
157 hw_interrupt(IF_SERIAL, IF_SERIAL);
158 hw_interrupt(0, IF_SERIAL);
160 R_SC = b; /* & 0x7f; */
161 break;
162 case RI_DIV:
163 REG(r) = 0;
164 break;
165 case RI_LCDC:
166 lcdc_change(b);
167 break;
168 case RI_STAT:
169 stat_write(b);
170 break;
171 case RI_LYC:
172 REG(r) = b;
173 stat_trigger();
174 break;
175 case RI_VBK:
176 REG(r) = b | 0xFE;
177 mem_updatemap();
178 break;
179 case RI_BCPS:
180 R_BCPS = b & 0xBF;
181 R_BCPD = lcd.pal[b & 0x3F];
182 break;
183 case RI_OCPS:
184 R_OCPS = b & 0xBF;
185 R_OCPD = lcd.pal[64 + (b & 0x3F)];
186 break;
187 case RI_BCPD:
188 R_BCPD = b;
189 pal_write(R_BCPS & 0x3F, b);
190 if (R_BCPS & 0x80) R_BCPS = (R_BCPS+1) & 0xBF;
191 break;
192 case RI_OCPD:
193 R_OCPD = b;
194 pal_write(64 + (R_OCPS & 0x3F), b);
195 if (R_OCPS & 0x80) R_OCPS = (R_OCPS+1) & 0xBF;
196 break;
197 case RI_SVBK:
198 REG(r) = b & 0x07;
199 mem_updatemap();
200 break;
201 case RI_DMA:
202 hw_dma(b);
203 break;
204 case RI_KEY1:
205 REG(r) = (REG(r) & 0x80) | (b & 0x01);
206 break;
207 case RI_HDMA1:
208 REG(r) = b;
209 break;
210 case RI_HDMA2:
211 REG(r) = b & 0xF0;
212 break;
213 case RI_HDMA3:
214 REG(r) = b & 0x1F;
215 break;
216 case RI_HDMA4:
217 REG(r) = b & 0xF0;
218 break;
219 case RI_HDMA5:
220 hw_hdma_cmd(b);
221 break;
223 switch (r)
225 case RI_BGP:
226 case RI_OBP0:
227 case RI_OBP1:
228 /* printf("palette reg %02X write %02X at LY=%02X\n", r, b, R_LY); */
229 case RI_HDMA1:
230 case RI_HDMA2:
231 case RI_HDMA3:
232 case RI_HDMA4:
233 case RI_HDMA5:
234 /* printf("HDMA %d: %02X\n", r - RI_HDMA1 + 1, b); */
235 break;
237 /* printf("reg %02X => %02X (%02X)\n", r, REG(r), b); */
241 byte ioreg_read(byte r)
243 switch(r)
245 case RI_SC:
246 r = R_SC;
247 R_SC &= 0x7f;
248 return r;
249 case RI_P1:
250 case RI_SB:
251 case RI_DIV:
252 case RI_TIMA:
253 case RI_TMA:
254 case RI_TAC:
255 case RI_LCDC:
256 case RI_STAT:
257 case RI_SCY:
258 case RI_SCX:
259 case RI_LY:
260 case RI_LYC:
261 case RI_BGP:
262 case RI_OBP0:
263 case RI_OBP1:
264 case RI_WY:
265 case RI_WX:
266 case RI_IE:
267 case RI_IF:
268 return REG(r);
269 case RI_VBK:
270 case RI_BCPS:
271 case RI_OCPS:
272 case RI_BCPD:
273 case RI_OCPD:
274 case RI_SVBK:
275 case RI_KEY1:
276 case RI_HDMA1:
277 case RI_HDMA2:
278 case RI_HDMA3:
279 case RI_HDMA4:
280 case RI_HDMA5:
281 if (hw.cgb) return REG(r);
282 default:
283 return 0xff;
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)
300 byte ha = (a>>12);
302 /* printf("mbc %d: rom bank %02X -[%04X:%02X]-> ", mbc.type, mbc.rombank, a, b); */
303 switch (mbc.type)
305 case MBC_MBC1:
306 switch (ha & 0xE)
308 case 0x0:
309 mbc.enableram = ((b & 0x0F) == 0x0A);
310 break;
311 case 0x2:
312 if ((b & 0x1F) == 0) b = 0x01;
313 mbc.rombank = (mbc.rombank & 0x60) | (b & 0x1F);
314 break;
315 case 0x4:
316 if (mbc.model)
318 mbc.rambank = b & 0x03;
319 break;
321 mbc.rombank = (mbc.rombank & 0x1F) | ((int)(b&3)<<5);
322 break;
323 case 0x6:
324 mbc.model = b & 0x1;
325 break;
327 break;
328 case MBC_MBC2: /* is this at all right? */
329 if ((a & 0x0100) == 0x0000)
331 mbc.enableram = ((b & 0x0F) == 0x0A);
332 break;
334 if ((a & 0xE100) == 0x2100)
336 mbc.rombank = b & 0x0F;
337 break;
339 break;
340 case MBC_MBC3:
341 switch (ha & 0xE)
343 case 0x0:
344 mbc.enableram = ((b & 0x0F) == 0x0A);
345 break;
346 case 0x2:
347 if ((b & 0x7F) == 0) b = 0x01;
348 mbc.rombank = b & 0x7F;
349 break;
350 case 0x4:
351 rtc.sel = b & 0x0f;
352 mbc.rambank = b & 0x03;
353 break;
354 case 0x6:
355 rtc_latch(b);
356 break;
358 break;
359 case MBC_RUMBLE:
360 switch (ha & 0xF)
362 case 0x4:
363 case 0x5:
364 /* FIXME - save high bit as rumble state */
365 /* mask off high bit */
366 b &= 0x7;
367 break;
369 /* fall thru */
370 case MBC_MBC5:
371 switch (ha & 0xF)
373 case 0x0:
374 case 0x1:
375 mbc.enableram = ((b & 0x0F) == 0x0A);
376 break;
377 case 0x2:
378 if ((b & 0xFF) == 0) b = 0x01;
379 mbc.rombank = (mbc.rombank & 0x100) | (b & 0xFF);
380 break;
381 case 0x3:
382 mbc.rombank = (mbc.rombank & 0xFF) | ((int)(b&1)<<8);
383 break;
384 case 0x4:
385 case 0x5:
386 mbc.rambank = b & 0x0f;
387 break;
389 break;
390 case MBC_HUC1: /* FIXME - this is all guesswork -- is it right??? */
391 switch (ha & 0xE)
393 case 0x0:
394 mbc.enableram = ((b & 0x0F) == 0x0A);
395 break;
396 case 0x2:
397 if ((b & 0x1F) == 0) b = 0x01;
398 mbc.rombank = (mbc.rombank & 0x60) | (b & 0x1F);
399 break;
400 case 0x4:
401 if (mbc.model)
403 mbc.rambank = b & 0x03;
404 break;
406 mbc.rombank = (mbc.rombank & 0x1F) | ((int)(b&3)<<5);
407 break;
408 case 0x6:
409 mbc.model = b & 0x1;
410 break;
412 break;
413 case MBC_HUC3:
414 switch (ha & 0xE)
416 case 0x0:
417 mbc.enableram = ((b & 0x0F) == 0x0A);
418 break;
419 case 0x2:
420 b &= 0x7F;
421 mbc.rombank = b ? b : 1;
422 break;
423 case 0x4:
424 rtc.sel = b & 0x0f;
425 mbc.rambank = b & 0x03;
426 break;
427 case 0x6:
428 rtc_latch(b);
429 break;
431 break;
433 mbc.rombank &= (mbc.romsize - 1);
434 mbc.rambank &= (mbc.ramsize - 1);
435 /* printf("%02X\n", mbc.rombank); */
436 mem_updatemap();
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)
448 int n;
449 byte ha = (a>>12) & 0xE;
451 /* printf("write to 0x%04X: 0x%02X\n", a, b); */
452 switch (ha)
454 case 0x0:
455 case 0x2:
456 case 0x4:
457 case 0x6:
458 mbc_write(a, b);
459 break;
460 case 0x8:
461 /* if ((R_STAT & 0x03) == 0x03) break; */
462 vram_write(a & 0x1FFF, b);
463 break;
464 case 0xA:
465 if (!mbc.enableram) break;
466 if (rtc.sel&8)
468 rtc_write(b);
469 break;
471 ram.sbank[mbc.rambank][a & 0x1FFF] = b;
472 break;
473 case 0xC:
474 if ((a & 0xF000) == 0xC000)
476 ram.ibank[0][a & 0x0FFF] = b;
477 break;
479 n = R_SVBK & 0x07;
480 ram.ibank[n?n:1][a & 0x0FFF] = b;
481 break;
482 case 0xE:
483 if (a < 0xFE00)
485 mem_write(a & 0xDFFF, b);
486 break;
488 if ((a & 0xFF00) == 0xFE00)
490 /* if (R_STAT & 0x02) break; */
491 if (a < 0xFEA0) lcd.oam.mem[a & 0xFF] = b;
492 break;
494 /* return writehi(a & 0xFF, b); */
495 if (a >= 0xFF10 && a <= 0xFF3F)
497 sound_write(a & 0xFF, b);
498 break;
500 if ((a & 0xFF80) == 0xFF80 && a != 0xFFFF)
502 ram.hi[a & 0xFF] = b;
503 break;
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
513 * region.
516 byte mem_read(int a)
518 int n;
519 byte ha = (a>>12) & 0xE;
521 /* printf("read %04x\n", a); */
522 switch (ha)
524 case 0x0:
525 case 0x2:
526 return rom.bank[0][a];
527 case 0x4:
528 case 0x6:
529 return rom.bank[mbc.rombank][a & 0x3FFF];
530 case 0x8:
531 /* if ((R_STAT & 0x03) == 0x03) return 0xFF; */
532 return lcd.vbank[R_VBK&1][a & 0x1FFF];
533 case 0xA:
534 if (!mbc.enableram && mbc.type == MBC_HUC3)
535 return 0x01;
536 if (!mbc.enableram)
537 return 0xFF;
538 if (rtc.sel&8)
539 return rtc.regs[rtc.sel&7];
540 return ram.sbank[mbc.rambank][a & 0x1FFF];
541 case 0xC:
542 if ((a & 0xF000) == 0xC000)
543 return ram.ibank[0][a & 0x0FFF];
544 n = R_SVBK & 0x07;
545 return ram.ibank[n?n:1][a & 0x0FFF];
546 case 0xE:
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];
552 return 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 */
565 void mbc_reset()
567 mbc.rombank = 1;
568 mbc.rambank = 0;
569 mbc.enableram = 0;
570 mem_updatemap();