view src/gba/GBAinline.h @ 551:b69a3dba8045

condensed gameboy program into a contigous sequence of bytes.
author Robert McIntyre <rlm@mit.edu>
date Thu, 30 Aug 2012 11:19:52 -0500
parents f9f4f1b99eed
children
line wrap: on
line source
1 #ifndef VBA_GBAINLINE_H
2 #define VBA_GBAINLINE_H
4 #if _MSC_VER > 1000
5 #pragma once
6 #endif // _MSC_VER > 1000
8 #include "../Port.h"
9 #include "../common/System.h"
10 #include "../common/vbalua.h"
11 #include "GBAGlobals.h"
12 #include "EEprom.h"
13 #include "Flash.h"
14 #include "RTC.h"
16 extern bool8 cpuSramEnabled;
17 extern bool8 cpuFlashEnabled;
18 extern bool8 cpuEEPROMEnabled;
19 extern bool8 cpuEEPROMSensorEnabled;
21 #define CPUReadByteQuick(addr) \
22 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
24 #define CPUReadHalfWordQuick(addr) \
25 READ16LE(((u16 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
27 #define CPUReadMemoryQuick(addr) \
28 READ32LE(((u32 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
30 //inline u32 CPUReadMemoryQuick(u32 addr)
31 //{
32 // u32 addrShift = (addr)>>24;
33 // u32 rt = (addr) & map[addrShift].mask;
34 // return READ32LE(((u32*)&map[addrShift].address[rt]));
35 //}
37 inline u32 CPUReadMemory(u32 address)
38 {
39 #ifdef GBA_LOGGING
40 if (address & 3)
41 {
42 if (systemVerbose & VERBOSE_UNALIGNED_MEMORY)
43 {
44 log("Unaligned word read: %08x at %08x\n", address, armMode ?
45 armNextPC - 4 : armNextPC - 2);
46 }
47 }
48 #endif
50 u32 value;
51 switch (address >> 24)
52 {
53 case 0:
54 if (reg[15].I >> 24)
55 {
56 if (address < 0x4000)
57 {
58 #ifdef GBA_LOGGING
59 if (systemVerbose & VERBOSE_ILLEGAL_READ)
60 {
61 log("Illegal word read: %08x at %08x\n", address, armMode ?
62 armNextPC - 4 : armNextPC - 2);
63 }
64 #endif
66 value = READ32LE(((u32 *)&biosProtected));
67 }
68 else
69 goto unreadable;
70 }
71 else
72 value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
73 break;
74 case 2:
75 value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
76 break;
77 case 3:
78 value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
79 break;
80 case 4:
81 if ((address < 0x4000400) && ioReadable[address & 0x3fc])
82 {
83 if (ioReadable[(address & 0x3fc) + 2])
84 {
85 if (address >= 0x400012d && address <= 0x4000131)
86 GBASystemCounters.lagged = false;
87 value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
88 }
89 else
90 {
91 if (address >= 0x400012f && address <= 0x4000131)
92 GBASystemCounters.lagged = false;
93 value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
94 }
95 }
96 else
97 goto unreadable;
98 break;
99 case 5:
100 value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
101 break;
102 case 6:
103 value = READ32LE(((u32 *)&vram[address & 0x1fffc]));
104 break;
105 case 7:
106 value = READ32LE(((u32 *)&oam[address & 0x3FC]));
107 break;
108 case 8:
109 case 9:
110 case 10:
111 case 11:
112 case 12:
113 value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
114 break;
115 case 13:
116 if (cpuEEPROMEnabled)
117 // no need to swap this
118 return eepromRead(address);
119 goto unreadable;
120 case 14:
121 if (cpuFlashEnabled | cpuSramEnabled)
122 // no need to swap this
123 return flashRead(address);
124 // default
125 default:
126 unreadable:
127 #ifdef GBA_LOGGING
128 if (systemVerbose & VERBOSE_ILLEGAL_READ)
129 {
130 log("Illegal word read: %08x at %08x\n", address, armMode ?
131 armNextPC - 4 : armNextPC - 2);
132 }
133 #endif
135 // if(ioMem[0x205] & 0x40) {
136 if (armState)
137 {
138 value = CPUReadMemoryQuick(reg[15].I);
139 }
140 else
141 {
142 value = CPUReadHalfWordQuick(reg[15].I) |
143 CPUReadHalfWordQuick(reg[15].I) << 16;
144 }
145 // } else {
146 // value = *((u32 *)&bios[address & 0x3ffc]);
147 // }
148 // return 0xFFFFFFFF;
149 }
151 if (address & 3)
152 {
153 #ifdef C_CORE
154 int shift = (address & 3) << 3;
155 value = (value >> shift) | (value << (32 - shift));
156 #else
157 #ifdef __GNUC__
158 asm ("and $3, %%ecx;"
159 "shl $3 ,%%ecx;"
160 "ror %%cl, %0"
161 : "=r" (value)
162 : "r" (value), "c" (address));
163 #else
164 __asm {
165 mov ecx, address;
166 and ecx, 3;
167 shl ecx, 3;
168 ror [dword ptr value], cl;
169 }
170 #endif
171 #endif
172 }
173 return value;
174 }
176 extern u32 myROM[];
178 inline u32 CPUReadHalfWord(u32 address)
179 {
180 #ifdef GBA_LOGGING
181 if (address & 1)
182 {
183 if (systemVerbose & VERBOSE_UNALIGNED_MEMORY)
184 {
185 log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
186 armNextPC - 4 : armNextPC - 2);
187 }
188 }
189 #endif
191 u32 value;
193 switch (address >> 24)
194 {
195 case 0:
196 if (reg[15].I >> 24)
197 {
198 if (address < 0x4000)
199 {
200 #ifdef GBA_LOGGING
201 if (systemVerbose & VERBOSE_ILLEGAL_READ)
202 {
203 log("Illegal halfword read: %08x at %08x\n", address, armMode ?
204 armNextPC - 4 : armNextPC - 2);
205 }
206 #endif
207 value = READ16LE(((u16 *)&biosProtected[address&2]));
208 }
209 else
210 goto unreadable;
211 }
212 else
213 value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
214 break;
215 case 2:
216 value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
217 break;
218 case 3:
219 value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
220 break;
221 case 4:
222 if ((address < 0x4000400) && ioReadable[address & 0x3fe])
223 {
224 if (address >= 0x400012f && address <= 0x4000131)
225 GBASystemCounters.lagged = false;
226 value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
227 }
228 else
229 goto unreadable;
230 break;
231 case 5:
232 value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
233 break;
234 case 6:
235 value = READ16LE(((u16 *)&vram[address & 0x1fffe]));
236 break;
237 case 7:
238 value = READ16LE(((u16 *)&oam[address & 0x3fe]));
239 break;
240 case 8:
241 case 9:
242 case 10:
243 case 11:
244 case 12:
245 if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
246 value = rtcRead(address);
247 else
248 value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
249 break;
250 case 13:
251 if (cpuEEPROMEnabled)
252 // no need to swap this
253 return eepromRead(address);
254 goto unreadable;
255 case 14:
256 if (cpuFlashEnabled | cpuSramEnabled)
257 // no need to swap this
258 return flashRead(address);
259 // default
260 default:
261 unreadable:
262 #ifdef GBA_LOGGING
263 if (systemVerbose & VERBOSE_ILLEGAL_READ)
264 {
265 log("Illegal halfword read: %08x at %08x\n", address, armMode ?
266 armNextPC - 4 : armNextPC - 2);
267 }
268 #endif
269 extern bool8 cpuDmaHack;
270 extern u32 cpuDmaLast;
271 extern int32 cpuDmaCount;
272 if (cpuDmaHack && cpuDmaCount)
273 {
274 value = (u16)cpuDmaLast;
275 }
276 else
277 {
278 if (armState)
279 {
280 value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
281 }
282 else
283 {
284 value = CPUReadHalfWordQuick(reg[15].I);
285 }
286 }
287 // return value;
288 // if(address & 1)
289 // value = (value >> 8) | ((value & 0xFF) << 24);
290 // return 0xFFFF;
291 break;
292 }
294 if (address & 1)
295 {
296 value = (value >> 8) | (value << 24);
297 }
299 return value;
300 }
302 inline u16 CPUReadHalfWordSigned(u32 address)
303 {
304 u16 value = CPUReadHalfWord(address);
305 if ((address & 1))
306 value = (s8)value;
307 return value;
308 }
310 inline u8 CPUReadByte(u32 address)
311 {
312 switch (address >> 24)
313 {
314 case 0:
315 if (reg[15].I >> 24)
316 {
317 if (address < 0x4000)
318 {
319 #ifdef GBA_LOGGING
320 if (systemVerbose & VERBOSE_ILLEGAL_READ)
321 {
322 log("Illegal byte read: %08x at %08x\n", address, armMode ?
323 armNextPC - 4 : armNextPC - 2);
324 }
325 #endif
326 return biosProtected[address & 3];
327 }
328 else
329 goto unreadable;
330 }
331 return bios[address & 0x3FFF];
332 case 2:
333 return workRAM[address & 0x3FFFF];
334 case 3:
335 return internalRAM[address & 0x7fff];
336 case 4:
337 if ((address < 0x4000400) && ioReadable[address & 0x3ff])
338 {
339 if (address == 0x4000130 || address == 0x4000131)
340 GBASystemCounters.lagged = false;
341 return ioMem[address & 0x3ff];
342 }
343 else
344 goto unreadable;
345 case 5:
346 return paletteRAM[address & 0x3ff];
347 case 6:
348 return vram[address & 0x1ffff];
349 case 7:
350 return oam[address & 0x3ff];
351 case 8:
352 case 9:
353 case 10:
354 case 11:
355 case 12:
356 return rom[address & 0x1FFFFFF];
357 case 13:
358 if (cpuEEPROMEnabled)
359 return eepromRead(address);
360 goto unreadable;
361 case 14:
362 if (cpuSramEnabled | cpuFlashEnabled)
363 return flashRead(address);
364 if (cpuEEPROMSensorEnabled)
365 {
366 switch (address & 0x00008f00)
367 {
368 case 0x8200:
369 return systemGetSensorX() & 255;
370 case 0x8300:
371 return (systemGetSensorX() >> 8)|0x80;
372 case 0x8400:
373 return systemGetSensorY() & 255;
374 case 0x8500:
375 return systemGetSensorY() >> 8;
376 }
377 }
378 // default
379 default:
380 unreadable:
381 #ifdef GBA_LOGGING
382 if (systemVerbose & VERBOSE_ILLEGAL_READ)
383 {
384 log("Illegal byte read: %08x at %08x\n", address, armMode ?
385 armNextPC - 4 : armNextPC - 2);
386 }
387 #endif
389 if (armState)
390 {
391 return CPUReadByteQuick(reg[15].I+(address & 3));
392 }
393 else
394 {
395 return CPUReadByteQuick(reg[15].I+(address & 1));
396 }
397 // return 0xFF;
398 break;
399 }
400 }
402 inline void CPUWriteMemoryWrapped(u32 address, u32 value)
403 {
404 #ifdef GBA_LOGGING
405 if (address & 3)
406 {
407 if (systemVerbose & VERBOSE_UNALIGNED_MEMORY)
408 {
409 log("Unaliagned word write: %08x to %08x from %08x\n",
410 value,
411 address,
412 armMode ? armNextPC - 4 : armNextPC - 2);
413 }
414 }
415 #endif
417 switch (address >> 24)
418 {
419 case 0x02:
420 #ifdef SDL
421 if (*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
422 cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC],
423 value,
424 *((u32 *)&freezeWorkRAM[address & 0x3FFFC]));
425 else
426 #endif
427 WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
428 break;
429 case 0x03:
430 #ifdef SDL
431 if (*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
432 cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC],
433 value,
434 *((u32 *)&freezeInternalRAM[address & 0x7ffc]));
435 else
436 #endif
437 WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
438 break;
439 case 0x04:
440 CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
441 CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
442 break;
443 case 0x05:
444 WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
445 break;
446 case 0x06:
447 if (address & 0x10000)
448 WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value);
449 else
450 WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value);
451 break;
452 case 0x07:
453 WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
454 break;
455 case 0x0D:
456 if (cpuEEPROMEnabled)
457 {
458 eepromWrite(address, value);
459 break;
460 }
461 goto unwritable;
462 case 0x0E:
463 if (!eepromInUse | cpuSramEnabled | cpuFlashEnabled)
464 {
465 (*cpuSaveGameFunc)(address, (u8)value);
466 break;
467 }
468 // default
469 default:
470 unwritable:
471 #ifdef GBA_LOGGING
472 if (systemVerbose & VERBOSE_ILLEGAL_WRITE)
473 {
474 log("Illegal word write: %08x to %08x from %08x\n",
475 value,
476 address,
477 armMode ? armNextPC - 4 : armNextPC - 2);
478 }
479 #endif
480 break;
481 }
482 }
484 inline void CPUWriteMemory(u32 address, u32 value)
485 {
486 CPUWriteMemoryWrapped(address, value);
487 CallRegisteredLuaMemHook(address, 4, value, LUAMEMHOOK_WRITE);
488 }
490 #endif // VBA_GBAINLINE_H