Mercurial > vba-clojure
view src/gba/GBAinline.h @ 96:cb487c4ce5c0
added write-memory!, which allows me to write any value to the
gameboy's memory-mapped rom or ram.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sun, 11 Mar 2012 23:27:19 -0500 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #ifndef VBA_GBAINLINE_H2 #define VBA_GBAINLINE_H4 #if _MSC_VER > 10005 #pragma once6 #endif // _MSC_VER > 10008 #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_LOGGING40 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 #endif50 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_LOGGING59 if (systemVerbose & VERBOSE_ILLEGAL_READ)60 {61 log("Illegal word read: %08x at %08x\n", address, armMode ?62 armNextPC - 4 : armNextPC - 2);63 }64 #endif66 value = READ32LE(((u32 *)&biosProtected));67 }68 else69 goto unreadable;70 }71 else72 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 else90 {91 if (address >= 0x400012f && address <= 0x4000131)92 GBASystemCounters.lagged = false;93 value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));94 }95 }96 else97 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 this118 return eepromRead(address);119 goto unreadable;120 case 14:121 if (cpuFlashEnabled | cpuSramEnabled)122 // no need to swap this123 return flashRead(address);124 // default125 default:126 unreadable:127 #ifdef GBA_LOGGING128 if (systemVerbose & VERBOSE_ILLEGAL_READ)129 {130 log("Illegal word read: %08x at %08x\n", address, armMode ?131 armNextPC - 4 : armNextPC - 2);132 }133 #endif135 // if(ioMem[0x205] & 0x40) {136 if (armState)137 {138 value = CPUReadMemoryQuick(reg[15].I);139 }140 else141 {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_CORE154 int shift = (address & 3) << 3;155 value = (value >> shift) | (value << (32 - shift));156 #else157 #ifdef __GNUC__158 asm ("and $3, %%ecx;"159 "shl $3 ,%%ecx;"160 "ror %%cl, %0"161 : "=r" (value)162 : "r" (value), "c" (address));163 #else164 __asm {165 mov ecx, address;166 and ecx, 3;167 shl ecx, 3;168 ror [dword ptr value], cl;169 }170 #endif171 #endif172 }173 return value;174 }176 extern u32 myROM[];178 inline u32 CPUReadHalfWord(u32 address)179 {180 #ifdef GBA_LOGGING181 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 #endif191 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_LOGGING201 if (systemVerbose & VERBOSE_ILLEGAL_READ)202 {203 log("Illegal halfword read: %08x at %08x\n", address, armMode ?204 armNextPC - 4 : armNextPC - 2);205 }206 #endif207 value = READ16LE(((u16 *)&biosProtected[address&2]));208 }209 else210 goto unreadable;211 }212 else213 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 else229 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 else248 value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));249 break;250 case 13:251 if (cpuEEPROMEnabled)252 // no need to swap this253 return eepromRead(address);254 goto unreadable;255 case 14:256 if (cpuFlashEnabled | cpuSramEnabled)257 // no need to swap this258 return flashRead(address);259 // default260 default:261 unreadable:262 #ifdef GBA_LOGGING263 if (systemVerbose & VERBOSE_ILLEGAL_READ)264 {265 log("Illegal halfword read: %08x at %08x\n", address, armMode ?266 armNextPC - 4 : armNextPC - 2);267 }268 #endif269 extern bool8 cpuDmaHack;270 extern u32 cpuDmaLast;271 extern int32 cpuDmaCount;272 if (cpuDmaHack && cpuDmaCount)273 {274 value = (u16)cpuDmaLast;275 }276 else277 {278 if (armState)279 {280 value = CPUReadHalfWordQuick(reg[15].I + (address & 2));281 }282 else283 {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_LOGGING320 if (systemVerbose & VERBOSE_ILLEGAL_READ)321 {322 log("Illegal byte read: %08x at %08x\n", address, armMode ?323 armNextPC - 4 : armNextPC - 2);324 }325 #endif326 return biosProtected[address & 3];327 }328 else329 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 else344 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 // default379 default:380 unreadable:381 #ifdef GBA_LOGGING382 if (systemVerbose & VERBOSE_ILLEGAL_READ)383 {384 log("Illegal byte read: %08x at %08x\n", address, armMode ?385 armNextPC - 4 : armNextPC - 2);386 }387 #endif389 if (armState)390 {391 return CPUReadByteQuick(reg[15].I+(address & 3));392 }393 else394 {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_LOGGING405 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 #endif417 switch (address >> 24)418 {419 case 0x02:420 #ifdef SDL421 if (*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))422 cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC],423 value,424 *((u32 *)&freezeWorkRAM[address & 0x3FFFC]));425 else426 #endif427 WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);428 break;429 case 0x03:430 #ifdef SDL431 if (*((u32 *)&freezeInternalRAM[address & 0x7ffc]))432 cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC],433 value,434 *((u32 *)&freezeInternalRAM[address & 0x7ffc]));435 else436 #endif437 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 else450 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 // default469 default:470 unwritable:471 #ifdef GBA_LOGGING472 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 #endif480 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