remove more unportable ASM, obsoleting C_CORE define
[rofl0r-VisualBoyAdvance.git] / src / GBAinline.h
blob14287bb20657c88bce72dcc2b197663d25fd3276
1 // -*- C++ -*-
2 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
3 // Copyright (C) 1999-2003 Forgotten
4 // Copyright (C) 2005 Forgotten and the VBA development team
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or(at your option)
9 // any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #ifndef VBA_GBAinline_H
21 #define VBA_GBAinline_H
23 #include "System.h"
24 #include "Port.h"
25 #include "RTC.h"
27 extern bool cpuSramEnabled;
28 extern bool cpuFlashEnabled;
29 extern bool cpuEEPROMEnabled;
30 extern bool cpuEEPROMSensorEnabled;
31 extern bool cpuDmaHack;
32 extern u32 cpuDmaLast;
33 extern bool timer0On;
34 extern int timer0Ticks;
35 extern int timer0ClockReload;
36 extern bool timer1On;
37 extern int timer1Ticks;
38 extern int timer1ClockReload;
39 extern bool timer2On;
40 extern int timer2Ticks;
41 extern int timer2ClockReload;
42 extern bool timer3On;
43 extern int timer3Ticks;
44 extern int timer3ClockReload;
45 extern int cpuTotalTicks;
47 #define CPUReadByteQuick(addr) \
48 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
50 #define CPUReadHalfWordQuick(addr) \
51 READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
53 #define CPUReadMemoryQuick(addr) \
54 READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
56 static inline u32 CPUReadMemory(u32 address)
59 #ifdef DEV_VERSION
60 if(address & 3) {
61 if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
62 log("Unaligned word read: %08x at %08x\n", address, armMode ?
63 armNextPC - 4 : armNextPC - 2);
66 #endif
68 u32 value;
69 switch(address >> 24) {
70 case 0:
71 if(reg[15].I >> 24) {
72 if(address < 0x4000) {
73 #ifdef DEV_VERSION
74 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
75 log("Illegal word read: %08x at %08x\n", address, armMode ?
76 armNextPC - 4 : armNextPC - 2);
78 #endif
80 value = READ32LE(((u32 *)&biosProtected));
82 else goto unreadable;
83 } else
84 value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
85 break;
86 case 2:
87 value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
88 break;
89 case 3:
90 value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
91 break;
92 case 4:
93 if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
94 if(ioReadable[(address & 0x3fc) + 2])
95 value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
96 else
97 value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
98 } else goto unreadable;
99 break;
100 case 5:
101 value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
102 break;
103 case 6:
104 address = (address & 0x1fffc);
105 if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
107 value = 0;
108 break;
110 if ((address & 0x18000) == 0x18000)
111 address &= 0x17fff;
112 value = READ32LE(((u32 *)&vram[address]));
113 break;
114 case 7:
115 value = READ32LE(((u32 *)&oam[address & 0x3FC]));
116 break;
117 case 8:
118 case 9:
119 case 10:
120 case 11:
121 case 12:
122 value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
123 break;
124 case 13:
125 if(cpuEEPROMEnabled)
126 // no need to swap this
127 return eepromRead(address);
128 goto unreadable;
129 case 14:
130 if(cpuFlashEnabled | cpuSramEnabled)
131 // no need to swap this
132 return flashRead(address);
133 // default
134 default:
135 unreadable:
136 #ifdef DEV_VERSION
137 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
138 log("Illegal word read: %08x at %08x\n", address, armMode ?
139 armNextPC - 4 : armNextPC - 2);
141 #endif
143 if(cpuDmaHack) {
144 value = cpuDmaLast;
145 } else {
146 if(armState) {
147 value = CPUReadMemoryQuick(reg[15].I);
148 } else {
149 value = CPUReadHalfWordQuick(reg[15].I) |
150 CPUReadHalfWordQuick(reg[15].I) << 16;
155 if(address & 3) {
156 int shift = (address & 3) << 3;
157 value = (value >> shift) | (value << (32 - shift));
159 return value;
162 extern u32 myROM[];
164 static inline u32 CPUReadHalfWord(u32 address)
166 #ifdef DEV_VERSION
167 if(address & 1) {
168 if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
169 log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
170 armNextPC - 4 : armNextPC - 2);
173 #endif
175 u32 value;
177 switch(address >> 24) {
178 case 0:
179 if (reg[15].I >> 24) {
180 if(address < 0x4000) {
181 #ifdef DEV_VERSION
182 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
183 log("Illegal halfword read: %08x at %08x\n", address, armMode ?
184 armNextPC - 4 : armNextPC - 2);
186 #endif
187 value = READ16LE(((u16 *)&biosProtected[address&2]));
188 } else goto unreadable;
189 } else
190 value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
191 break;
192 case 2:
193 value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
194 break;
195 case 3:
196 value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
197 break;
198 case 4:
199 if((address < 0x4000400) && ioReadable[address & 0x3fe])
201 value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
202 if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
204 if (((address & 0x3fe) == 0x100) && timer0On)
205 value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
206 else
207 if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4))
208 value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
209 else
210 if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4))
211 value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
212 else
213 if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4))
214 value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
217 else goto unreadable;
218 break;
219 case 5:
220 value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
221 break;
222 case 6:
223 address = (address & 0x1fffe);
224 if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
226 value = 0;
227 break;
229 if ((address & 0x18000) == 0x18000)
230 address &= 0x17fff;
231 value = READ16LE(((u16 *)&vram[address]));
232 break;
233 case 7:
234 value = READ16LE(((u16 *)&oam[address & 0x3fe]));
235 break;
236 case 8:
237 case 9:
238 case 10:
239 case 11:
240 case 12:
241 if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
242 value = rtcRead(address);
243 else
244 value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
245 break;
246 case 13:
247 if(cpuEEPROMEnabled)
248 // no need to swap this
249 return eepromRead(address);
250 goto unreadable;
251 case 14:
252 if(cpuFlashEnabled | cpuSramEnabled)
253 // no need to swap this
254 return flashRead(address);
255 // default
256 default:
257 unreadable:
258 #ifdef DEV_VERSION
259 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
260 log("Illegal halfword read: %08x at %08x\n", address, armMode ?
261 armNextPC - 4 : armNextPC - 2);
263 #endif
264 if(cpuDmaHack) {
265 value = cpuDmaLast & 0xFFFF;
266 } else {
267 if(armState) {
268 value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
269 } else {
270 value = CPUReadHalfWordQuick(reg[15].I);
273 break;
276 if(address & 1) {
277 value = (value >> 8) | (value << 24);
280 return value;
283 static inline u16 CPUReadHalfWordSigned(u32 address)
285 u16 value = CPUReadHalfWord(address);
286 if((address & 1))
287 value = (s8)value;
288 return value;
291 static inline u8 CPUReadByte(u32 address)
293 switch(address >> 24) {
294 case 0:
295 if (reg[15].I >> 24) {
296 if(address < 0x4000) {
297 #ifdef DEV_VERSION
298 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
299 log("Illegal byte read: %08x at %08x\n", address, armMode ?
300 armNextPC - 4 : armNextPC - 2);
302 #endif
303 return biosProtected[address & 3];
304 } else goto unreadable;
306 return bios[address & 0x3FFF];
307 case 2:
308 return workRAM[address & 0x3FFFF];
309 case 3:
310 return internalRAM[address & 0x7fff];
311 case 4:
312 if((address < 0x4000400) && ioReadable[address & 0x3ff])
313 return ioMem[address & 0x3ff];
314 else goto unreadable;
315 case 5:
316 return paletteRAM[address & 0x3ff];
317 case 6:
318 address = (address & 0x1ffff);
319 if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
320 return 0;
321 if ((address & 0x18000) == 0x18000)
322 address &= 0x17fff;
323 return vram[address];
324 case 7:
325 return oam[address & 0x3ff];
326 case 8:
327 case 9:
328 case 10:
329 case 11:
330 case 12:
331 return rom[address & 0x1FFFFFF];
332 case 13:
333 if(cpuEEPROMEnabled)
334 return eepromRead(address);
335 goto unreadable;
336 case 14:
337 if(cpuSramEnabled | cpuFlashEnabled)
338 return flashRead(address);
339 if(cpuEEPROMSensorEnabled) {
340 switch(address & 0x00008f00) {
341 case 0x8200:
342 return systemGetSensorX() & 255;
343 case 0x8300:
344 return (systemGetSensorX() >> 8)|0x80;
345 case 0x8400:
346 return systemGetSensorY() & 255;
347 case 0x8500:
348 return systemGetSensorY() >> 8;
351 // default
352 default:
353 unreadable:
354 #ifdef DEV_VERSION
355 if(systemVerbose & VERBOSE_ILLEGAL_READ) {
356 log("Illegal byte read: %08x at %08x\n", address, armMode ?
357 armNextPC - 4 : armNextPC - 2);
359 #endif
360 if(cpuDmaHack) {
361 return cpuDmaLast & 0xFF;
362 } else {
363 if(armState) {
364 return CPUReadByteQuick(reg[15].I+(address & 3));
365 } else {
366 return CPUReadByteQuick(reg[15].I+(address & 1));
369 break;
373 static inline void CPUWriteMemory(u32 address, u32 value)
376 #ifdef DEV_VERSION
377 if(address & 3) {
378 if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
379 log("Unaligned word write: %08x to %08x from %08x\n",
380 value,
381 address,
382 armMode ? armNextPC - 4 : armNextPC - 2);
385 #endif
387 switch(address >> 24) {
388 case 0x02:
389 #ifdef BKPT_SUPPORT
390 if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
391 cheatsWriteMemory(address & 0x203FFFC,
392 value);
393 else
394 #endif
395 WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
396 break;
397 case 0x03:
398 #ifdef BKPT_SUPPORT
399 if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
400 cheatsWriteMemory(address & 0x3007FFC,
401 value);
402 else
403 #endif
404 WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
405 break;
406 case 0x04:
407 if(address < 0x4000400) {
408 CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
409 CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
410 } else goto unwritable;
411 break;
412 case 0x05:
413 #ifdef BKPT_SUPPORT
414 if(*((u32 *)&freezePRAM[address & 0x3fc]))
415 cheatsWriteMemory(address & 0x70003FC,
416 value);
417 else
418 #endif
419 WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
420 break;
421 case 0x06:
422 address = (address & 0x1fffc);
423 if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
424 return;
425 if ((address & 0x18000) == 0x18000)
426 address &= 0x17fff;
428 #ifdef BKPT_SUPPORT
429 if(*((u32 *)&freezeVRAM[address]))
430 cheatsWriteMemory(address + 0x06000000, value);
431 else
432 #endif
434 WRITE32LE(((u32 *)&vram[address]), value);
435 break;
436 case 0x07:
437 #ifdef BKPT_SUPPORT
438 if(*((u32 *)&freezeOAM[address & 0x3fc]))
439 cheatsWriteMemory(address & 0x70003FC,
440 value);
441 else
442 #endif
443 WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
444 break;
445 case 0x0D:
446 if(cpuEEPROMEnabled) {
447 eepromWrite(address, value);
448 break;
450 goto unwritable;
451 case 0x0E:
452 if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
453 (*cpuSaveGameFunc)(address, (u8)value);
454 break;
456 // default
457 default:
458 unwritable:
459 #ifdef DEV_VERSION
460 if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
461 log("Illegal word write: %08x to %08x from %08x\n",
462 value,
463 address,
464 armMode ? armNextPC - 4 : armNextPC - 2);
466 #endif
467 break;
471 #endif //VBA_GBAinline_H