annotate src/gba/GBAinline.h @ 68:86093f2ce7d1

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