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)
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
27 extern bool cpuSramEnabled
;
28 extern bool cpuFlashEnabled
;
29 extern bool cpuEEPROMEnabled
;
30 extern bool cpuEEPROMSensorEnabled
;
31 extern bool cpuDmaHack
;
32 extern u32 cpuDmaLast
;
34 extern int timer0Ticks
;
35 extern int timer0ClockReload
;
37 extern int timer1Ticks
;
38 extern int timer1ClockReload
;
40 extern int timer2Ticks
;
41 extern int timer2ClockReload
;
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
)
61 if(systemVerbose
& VERBOSE_UNALIGNED_MEMORY
) {
62 log("Unaligned word read: %08x at %08x\n", address
, armMode
?
63 armNextPC
- 4 : armNextPC
- 2);
69 switch(address
>> 24) {
72 if(address
< 0x4000) {
74 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
75 log("Illegal word read: %08x at %08x\n", address
, armMode
?
76 armNextPC
- 4 : armNextPC
- 2);
80 value
= READ32LE(((u32
*)&biosProtected
));
84 value
= READ32LE(((u32
*)&bios
[address
& 0x3FFC]));
87 value
= READ32LE(((u32
*)&workRAM
[address
& 0x3FFFC]));
90 value
= READ32LE(((u32
*)&internalRAM
[address
& 0x7ffC]));
93 if((address
< 0x4000400) && ioReadable
[address
& 0x3fc]) {
94 if(ioReadable
[(address
& 0x3fc) + 2])
95 value
= READ32LE(((u32
*)&ioMem
[address
& 0x3fC]));
97 value
= READ16LE(((u16
*)&ioMem
[address
& 0x3fc]));
98 } else goto unreadable
;
101 value
= READ32LE(((u32
*)&paletteRAM
[address
& 0x3fC]));
104 address
= (address
& 0x1fffc);
105 if (((DISPCNT
& 7) >2) && ((address
& 0x1C000) == 0x18000))
110 if ((address
& 0x18000) == 0x18000)
112 value
= READ32LE(((u32
*)&vram
[address
]));
115 value
= READ32LE(((u32
*)&oam
[address
& 0x3FC]));
122 value
= READ32LE(((u32
*)&rom
[address
&0x1FFFFFC]));
126 // no need to swap this
127 return eepromRead(address
);
130 if(cpuFlashEnabled
| cpuSramEnabled
)
131 // no need to swap this
132 return flashRead(address
);
137 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
138 log("Illegal word read: %08x at %08x\n", address
, armMode
?
139 armNextPC
- 4 : armNextPC
- 2);
147 value
= CPUReadMemoryQuick(reg
[15].I
);
149 value
= CPUReadHalfWordQuick(reg
[15].I
) |
150 CPUReadHalfWordQuick(reg
[15].I
) << 16;
156 int shift
= (address
& 3) << 3;
157 value
= (value
>> shift
) | (value
<< (32 - shift
));
164 static inline u32
CPUReadHalfWord(u32 address
)
168 if(systemVerbose
& VERBOSE_UNALIGNED_MEMORY
) {
169 log("Unaligned halfword read: %08x at %08x\n", address
, armMode
?
170 armNextPC
- 4 : armNextPC
- 2);
177 switch(address
>> 24) {
179 if (reg
[15].I
>> 24) {
180 if(address
< 0x4000) {
182 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
183 log("Illegal halfword read: %08x at %08x\n", address
, armMode
?
184 armNextPC
- 4 : armNextPC
- 2);
187 value
= READ16LE(((u16
*)&biosProtected
[address
&2]));
188 } else goto unreadable
;
190 value
= READ16LE(((u16
*)&bios
[address
& 0x3FFE]));
193 value
= READ16LE(((u16
*)&workRAM
[address
& 0x3FFFE]));
196 value
= READ16LE(((u16
*)&internalRAM
[address
& 0x7ffe]));
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
);
207 if (((address
& 0x3fe) == 0x104) && timer1On
&& !(TM1CNT
& 4))
208 value
= 0xFFFF - ((timer1Ticks
-cpuTotalTicks
) >> timer1ClockReload
);
210 if (((address
& 0x3fe) == 0x108) && timer2On
&& !(TM2CNT
& 4))
211 value
= 0xFFFF - ((timer2Ticks
-cpuTotalTicks
) >> timer2ClockReload
);
213 if (((address
& 0x3fe) == 0x10C) && timer3On
&& !(TM3CNT
& 4))
214 value
= 0xFFFF - ((timer3Ticks
-cpuTotalTicks
) >> timer3ClockReload
);
217 else goto unreadable
;
220 value
= READ16LE(((u16
*)&paletteRAM
[address
& 0x3fe]));
223 address
= (address
& 0x1fffe);
224 if (((DISPCNT
& 7) >2) && ((address
& 0x1C000) == 0x18000))
229 if ((address
& 0x18000) == 0x18000)
231 value
= READ16LE(((u16
*)&vram
[address
]));
234 value
= READ16LE(((u16
*)&oam
[address
& 0x3fe]));
241 if(address
== 0x80000c4 || address
== 0x80000c6 || address
== 0x80000c8)
242 value
= rtcRead(address
);
244 value
= READ16LE(((u16
*)&rom
[address
& 0x1FFFFFE]));
248 // no need to swap this
249 return eepromRead(address
);
252 if(cpuFlashEnabled
| cpuSramEnabled
)
253 // no need to swap this
254 return flashRead(address
);
259 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
260 log("Illegal halfword read: %08x at %08x\n", address
, armMode
?
261 armNextPC
- 4 : armNextPC
- 2);
265 value
= cpuDmaLast
& 0xFFFF;
268 value
= CPUReadHalfWordQuick(reg
[15].I
+ (address
& 2));
270 value
= CPUReadHalfWordQuick(reg
[15].I
);
277 value
= (value
>> 8) | (value
<< 24);
283 static inline u16
CPUReadHalfWordSigned(u32 address
)
285 u16 value
= CPUReadHalfWord(address
);
291 static inline u8
CPUReadByte(u32 address
)
293 switch(address
>> 24) {
295 if (reg
[15].I
>> 24) {
296 if(address
< 0x4000) {
298 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
299 log("Illegal byte read: %08x at %08x\n", address
, armMode
?
300 armNextPC
- 4 : armNextPC
- 2);
303 return biosProtected
[address
& 3];
304 } else goto unreadable
;
306 return bios
[address
& 0x3FFF];
308 return workRAM
[address
& 0x3FFFF];
310 return internalRAM
[address
& 0x7fff];
312 if((address
< 0x4000400) && ioReadable
[address
& 0x3ff])
313 return ioMem
[address
& 0x3ff];
314 else goto unreadable
;
316 return paletteRAM
[address
& 0x3ff];
318 address
= (address
& 0x1ffff);
319 if (((DISPCNT
& 7) >2) && ((address
& 0x1C000) == 0x18000))
321 if ((address
& 0x18000) == 0x18000)
323 return vram
[address
];
325 return oam
[address
& 0x3ff];
331 return rom
[address
& 0x1FFFFFF];
334 return eepromRead(address
);
337 if(cpuSramEnabled
| cpuFlashEnabled
)
338 return flashRead(address
);
339 if(cpuEEPROMSensorEnabled
) {
340 switch(address
& 0x00008f00) {
342 return systemGetSensorX() & 255;
344 return (systemGetSensorX() >> 8)|0x80;
346 return systemGetSensorY() & 255;
348 return systemGetSensorY() >> 8;
355 if(systemVerbose
& VERBOSE_ILLEGAL_READ
) {
356 log("Illegal byte read: %08x at %08x\n", address
, armMode
?
357 armNextPC
- 4 : armNextPC
- 2);
361 return cpuDmaLast
& 0xFF;
364 return CPUReadByteQuick(reg
[15].I
+(address
& 3));
366 return CPUReadByteQuick(reg
[15].I
+(address
& 1));
373 static inline void CPUWriteMemory(u32 address
, u32 value
)
378 if(systemVerbose
& VERBOSE_UNALIGNED_MEMORY
) {
379 log("Unaligned word write: %08x to %08x from %08x\n",
382 armMode
? armNextPC
- 4 : armNextPC
- 2);
387 switch(address
>> 24) {
390 if(*((u32
*)&freezeWorkRAM
[address
& 0x3FFFC]))
391 cheatsWriteMemory(address
& 0x203FFFC,
395 WRITE32LE(((u32
*)&workRAM
[address
& 0x3FFFC]), value
);
399 if(*((u32
*)&freezeInternalRAM
[address
& 0x7ffc]))
400 cheatsWriteMemory(address
& 0x3007FFC,
404 WRITE32LE(((u32
*)&internalRAM
[address
& 0x7ffC]), value
);
407 if(address
< 0x4000400) {
408 CPUUpdateRegister((address
& 0x3FC), value
& 0xFFFF);
409 CPUUpdateRegister((address
& 0x3FC) + 2, (value
>> 16));
410 } else goto unwritable
;
414 if(*((u32
*)&freezePRAM
[address
& 0x3fc]))
415 cheatsWriteMemory(address
& 0x70003FC,
419 WRITE32LE(((u32
*)&paletteRAM
[address
& 0x3FC]), value
);
422 address
= (address
& 0x1fffc);
423 if (((DISPCNT
& 7) >2) && ((address
& 0x1C000) == 0x18000))
425 if ((address
& 0x18000) == 0x18000)
429 if(*((u32
*)&freezeVRAM
[address
]))
430 cheatsWriteMemory(address
+ 0x06000000, value
);
434 WRITE32LE(((u32
*)&vram
[address
]), value
);
438 if(*((u32
*)&freezeOAM
[address
& 0x3fc]))
439 cheatsWriteMemory(address
& 0x70003FC,
443 WRITE32LE(((u32
*)&oam
[address
& 0x3fc]), value
);
446 if(cpuEEPROMEnabled
) {
447 eepromWrite(address
, value
);
452 if(!eepromInUse
| cpuSramEnabled
| cpuFlashEnabled
) {
453 (*cpuSaveGameFunc
)(address
, (u8
)value
);
460 if(systemVerbose
& VERBOSE_ILLEGAL_WRITE
) {
461 log("Illegal word write: %08x to %08x from %08x\n",
464 armMode
? armNextPC
- 4 : armNextPC
- 2);
471 #endif //VBA_GBAinline_H