Mercurial > vba-clojure
comparison src/gba/GBAinline.h @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 #ifndef VBA_GBAINLINE_H | |
2 #define VBA_GBAINLINE_H | |
3 | |
4 #if _MSC_VER > 1000 | |
5 #pragma once | |
6 #endif // _MSC_VER > 1000 | |
7 | |
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" | |
15 | |
16 extern bool8 cpuSramEnabled; | |
17 extern bool8 cpuFlashEnabled; | |
18 extern bool8 cpuEEPROMEnabled; | |
19 extern bool8 cpuEEPROMSensorEnabled; | |
20 | |
21 #define CPUReadByteQuick(addr) \ | |
22 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] | |
23 | |
24 #define CPUReadHalfWordQuick(addr) \ | |
25 READ16LE(((u16 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) | |
26 | |
27 #define CPUReadMemoryQuick(addr) \ | |
28 READ32LE(((u32 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) | |
29 | |
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 //} | |
36 | |
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 | |
49 | |
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 | |
65 | |
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 | |
134 | |
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 } | |
150 | |
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 } | |
175 | |
176 extern u32 myROM[]; | |
177 | |
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 | |
190 | |
191 u32 value; | |
192 | |
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 } | |
293 | |
294 if (address & 1) | |
295 { | |
296 value = (value >> 8) | (value << 24); | |
297 } | |
298 | |
299 return value; | |
300 } | |
301 | |
302 inline u16 CPUReadHalfWordSigned(u32 address) | |
303 { | |
304 u16 value = CPUReadHalfWord(address); | |
305 if ((address & 1)) | |
306 value = (s8)value; | |
307 return value; | |
308 } | |
309 | |
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 | |
388 | |
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 } | |
401 | |
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 | |
416 | |
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 } | |
483 | |
484 inline void CPUWriteMemory(u32 address, u32 value) | |
485 { | |
486 CPUWriteMemoryWrapped(address, value); | |
487 CallRegisteredLuaMemHook(address, 4, value, LUAMEMHOOK_WRITE); | |
488 } | |
489 | |
490 #endif // VBA_GBAINLINE_H |