rlm@1: #ifndef VBA_GBAINLINE_H rlm@1: #define VBA_GBAINLINE_H rlm@1: rlm@1: #if _MSC_VER > 1000 rlm@1: #pragma once rlm@1: #endif // _MSC_VER > 1000 rlm@1: rlm@1: #include "../Port.h" rlm@1: #include "../common/System.h" rlm@1: #include "../common/vbalua.h" rlm@1: #include "GBAGlobals.h" rlm@1: #include "EEprom.h" rlm@1: #include "Flash.h" rlm@1: #include "RTC.h" rlm@1: rlm@1: extern bool8 cpuSramEnabled; rlm@1: extern bool8 cpuFlashEnabled; rlm@1: extern bool8 cpuEEPROMEnabled; rlm@1: extern bool8 cpuEEPROMSensorEnabled; rlm@1: rlm@1: #define CPUReadByteQuick(addr) \ rlm@1: map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] rlm@1: rlm@1: #define CPUReadHalfWordQuick(addr) \ rlm@1: READ16LE(((u16 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) rlm@1: rlm@1: #define CPUReadMemoryQuick(addr) \ rlm@1: READ32LE(((u32 *)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) rlm@1: rlm@1: //inline u32 CPUReadMemoryQuick(u32 addr) rlm@1: //{ rlm@1: // u32 addrShift = (addr)>>24; rlm@1: // u32 rt = (addr) & map[addrShift].mask; rlm@1: // return READ32LE(((u32*)&map[addrShift].address[rt])); rlm@1: //} rlm@1: rlm@1: inline u32 CPUReadMemory(u32 address) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (address & 3) rlm@1: { rlm@1: if (systemVerbose & VERBOSE_UNALIGNED_MEMORY) rlm@1: { rlm@1: log("Unaligned word read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: } rlm@1: #endif rlm@1: rlm@1: u32 value; rlm@1: switch (address >> 24) rlm@1: { rlm@1: case 0: rlm@1: if (reg[15].I >> 24) rlm@1: { rlm@1: if (address < 0x4000) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal word read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: rlm@1: value = READ32LE(((u32 *)&biosProtected)); rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: } rlm@1: else rlm@1: value = READ32LE(((u32 *)&bios[address & 0x3FFC])); rlm@1: break; rlm@1: case 2: rlm@1: value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); rlm@1: break; rlm@1: case 3: rlm@1: value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); rlm@1: break; rlm@1: case 4: rlm@1: if ((address < 0x4000400) && ioReadable[address & 0x3fc]) rlm@1: { rlm@1: if (ioReadable[(address & 0x3fc) + 2]) rlm@1: { rlm@1: if (address >= 0x400012d && address <= 0x4000131) rlm@1: GBASystemCounters.lagged = false; rlm@1: value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); rlm@1: } rlm@1: else rlm@1: { rlm@1: if (address >= 0x400012f && address <= 0x4000131) rlm@1: GBASystemCounters.lagged = false; rlm@1: value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); rlm@1: } rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: break; rlm@1: case 5: rlm@1: value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); rlm@1: break; rlm@1: case 6: rlm@1: value = READ32LE(((u32 *)&vram[address & 0x1fffc])); rlm@1: break; rlm@1: case 7: rlm@1: value = READ32LE(((u32 *)&oam[address & 0x3FC])); rlm@1: break; rlm@1: case 8: rlm@1: case 9: rlm@1: case 10: rlm@1: case 11: rlm@1: case 12: rlm@1: value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); rlm@1: break; rlm@1: case 13: rlm@1: if (cpuEEPROMEnabled) rlm@1: // no need to swap this rlm@1: return eepromRead(address); rlm@1: goto unreadable; rlm@1: case 14: rlm@1: if (cpuFlashEnabled | cpuSramEnabled) rlm@1: // no need to swap this rlm@1: return flashRead(address); rlm@1: // default rlm@1: default: rlm@1: unreadable: rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal word read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: rlm@1: // if(ioMem[0x205] & 0x40) { rlm@1: if (armState) rlm@1: { rlm@1: value = CPUReadMemoryQuick(reg[15].I); rlm@1: } rlm@1: else rlm@1: { rlm@1: value = CPUReadHalfWordQuick(reg[15].I) | rlm@1: CPUReadHalfWordQuick(reg[15].I) << 16; rlm@1: } rlm@1: // } else { rlm@1: // value = *((u32 *)&bios[address & 0x3ffc]); rlm@1: // } rlm@1: // return 0xFFFFFFFF; rlm@1: } rlm@1: rlm@1: if (address & 3) rlm@1: { rlm@1: #ifdef C_CORE rlm@1: int shift = (address & 3) << 3; rlm@1: value = (value >> shift) | (value << (32 - shift)); rlm@1: #else rlm@1: #ifdef __GNUC__ rlm@1: asm ("and $3, %%ecx;" rlm@1: "shl $3 ,%%ecx;" rlm@1: "ror %%cl, %0" rlm@1: : "=r" (value) rlm@1: : "r" (value), "c" (address)); rlm@1: #else rlm@1: __asm { rlm@1: mov ecx, address; rlm@1: and ecx, 3; rlm@1: shl ecx, 3; rlm@1: ror [dword ptr value], cl; rlm@1: } rlm@1: #endif rlm@1: #endif rlm@1: } rlm@1: return value; rlm@1: } rlm@1: rlm@1: extern u32 myROM[]; rlm@1: rlm@1: inline u32 CPUReadHalfWord(u32 address) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (address & 1) rlm@1: { rlm@1: if (systemVerbose & VERBOSE_UNALIGNED_MEMORY) rlm@1: { rlm@1: log("Unaligned halfword read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: } rlm@1: #endif rlm@1: rlm@1: u32 value; rlm@1: rlm@1: switch (address >> 24) rlm@1: { rlm@1: case 0: rlm@1: if (reg[15].I >> 24) rlm@1: { rlm@1: if (address < 0x4000) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal halfword read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: value = READ16LE(((u16 *)&biosProtected[address&2])); rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: } rlm@1: else rlm@1: value = READ16LE(((u16 *)&bios[address & 0x3FFE])); rlm@1: break; rlm@1: case 2: rlm@1: value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); rlm@1: break; rlm@1: case 3: rlm@1: value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); rlm@1: break; rlm@1: case 4: rlm@1: if ((address < 0x4000400) && ioReadable[address & 0x3fe]) rlm@1: { rlm@1: if (address >= 0x400012f && address <= 0x4000131) rlm@1: GBASystemCounters.lagged = false; rlm@1: value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: break; rlm@1: case 5: rlm@1: value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); rlm@1: break; rlm@1: case 6: rlm@1: value = READ16LE(((u16 *)&vram[address & 0x1fffe])); rlm@1: break; rlm@1: case 7: rlm@1: value = READ16LE(((u16 *)&oam[address & 0x3fe])); rlm@1: break; rlm@1: case 8: rlm@1: case 9: rlm@1: case 10: rlm@1: case 11: rlm@1: case 12: rlm@1: if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) rlm@1: value = rtcRead(address); rlm@1: else rlm@1: value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); rlm@1: break; rlm@1: case 13: rlm@1: if (cpuEEPROMEnabled) rlm@1: // no need to swap this rlm@1: return eepromRead(address); rlm@1: goto unreadable; rlm@1: case 14: rlm@1: if (cpuFlashEnabled | cpuSramEnabled) rlm@1: // no need to swap this rlm@1: return flashRead(address); rlm@1: // default rlm@1: default: rlm@1: unreadable: rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal halfword read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: extern bool8 cpuDmaHack; rlm@1: extern u32 cpuDmaLast; rlm@1: extern int32 cpuDmaCount; rlm@1: if (cpuDmaHack && cpuDmaCount) rlm@1: { rlm@1: value = (u16)cpuDmaLast; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (armState) rlm@1: { rlm@1: value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); rlm@1: } rlm@1: else rlm@1: { rlm@1: value = CPUReadHalfWordQuick(reg[15].I); rlm@1: } rlm@1: } rlm@1: // return value; rlm@1: // if(address & 1) rlm@1: // value = (value >> 8) | ((value & 0xFF) << 24); rlm@1: // return 0xFFFF; rlm@1: break; rlm@1: } rlm@1: rlm@1: if (address & 1) rlm@1: { rlm@1: value = (value >> 8) | (value << 24); rlm@1: } rlm@1: rlm@1: return value; rlm@1: } rlm@1: rlm@1: inline u16 CPUReadHalfWordSigned(u32 address) rlm@1: { rlm@1: u16 value = CPUReadHalfWord(address); rlm@1: if ((address & 1)) rlm@1: value = (s8)value; rlm@1: return value; rlm@1: } rlm@1: rlm@1: inline u8 CPUReadByte(u32 address) rlm@1: { rlm@1: switch (address >> 24) rlm@1: { rlm@1: case 0: rlm@1: if (reg[15].I >> 24) rlm@1: { rlm@1: if (address < 0x4000) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal byte read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: return biosProtected[address & 3]; rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: } rlm@1: return bios[address & 0x3FFF]; rlm@1: case 2: rlm@1: return workRAM[address & 0x3FFFF]; rlm@1: case 3: rlm@1: return internalRAM[address & 0x7fff]; rlm@1: case 4: rlm@1: if ((address < 0x4000400) && ioReadable[address & 0x3ff]) rlm@1: { rlm@1: if (address == 0x4000130 || address == 0x4000131) rlm@1: GBASystemCounters.lagged = false; rlm@1: return ioMem[address & 0x3ff]; rlm@1: } rlm@1: else rlm@1: goto unreadable; rlm@1: case 5: rlm@1: return paletteRAM[address & 0x3ff]; rlm@1: case 6: rlm@1: return vram[address & 0x1ffff]; rlm@1: case 7: rlm@1: return oam[address & 0x3ff]; rlm@1: case 8: rlm@1: case 9: rlm@1: case 10: rlm@1: case 11: rlm@1: case 12: rlm@1: return rom[address & 0x1FFFFFF]; rlm@1: case 13: rlm@1: if (cpuEEPROMEnabled) rlm@1: return eepromRead(address); rlm@1: goto unreadable; rlm@1: case 14: rlm@1: if (cpuSramEnabled | cpuFlashEnabled) rlm@1: return flashRead(address); rlm@1: if (cpuEEPROMSensorEnabled) rlm@1: { rlm@1: switch (address & 0x00008f00) rlm@1: { rlm@1: case 0x8200: rlm@1: return systemGetSensorX() & 255; rlm@1: case 0x8300: rlm@1: return (systemGetSensorX() >> 8)|0x80; rlm@1: case 0x8400: rlm@1: return systemGetSensorY() & 255; rlm@1: case 0x8500: rlm@1: return systemGetSensorY() >> 8; rlm@1: } rlm@1: } rlm@1: // default rlm@1: default: rlm@1: unreadable: rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_READ) rlm@1: { rlm@1: log("Illegal byte read: %08x at %08x\n", address, armMode ? rlm@1: armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: rlm@1: if (armState) rlm@1: { rlm@1: return CPUReadByteQuick(reg[15].I+(address & 3)); rlm@1: } rlm@1: else rlm@1: { rlm@1: return CPUReadByteQuick(reg[15].I+(address & 1)); rlm@1: } rlm@1: // return 0xFF; rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: inline void CPUWriteMemoryWrapped(u32 address, u32 value) rlm@1: { rlm@1: #ifdef GBA_LOGGING rlm@1: if (address & 3) rlm@1: { rlm@1: if (systemVerbose & VERBOSE_UNALIGNED_MEMORY) rlm@1: { rlm@1: log("Unaliagned word write: %08x to %08x from %08x\n", rlm@1: value, rlm@1: address, rlm@1: armMode ? armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: } rlm@1: #endif rlm@1: rlm@1: switch (address >> 24) rlm@1: { rlm@1: case 0x02: rlm@1: #ifdef SDL rlm@1: if (*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) rlm@1: cheatsWriteMemory((u32 *)&workRAM[address & 0x3FFFC], rlm@1: value, rlm@1: *((u32 *)&freezeWorkRAM[address & 0x3FFFC])); rlm@1: else rlm@1: #endif rlm@1: WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); rlm@1: break; rlm@1: case 0x03: rlm@1: #ifdef SDL rlm@1: if (*((u32 *)&freezeInternalRAM[address & 0x7ffc])) rlm@1: cheatsWriteMemory((u32 *)&internalRAM[address & 0x7FFC], rlm@1: value, rlm@1: *((u32 *)&freezeInternalRAM[address & 0x7ffc])); rlm@1: else rlm@1: #endif rlm@1: WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); rlm@1: break; rlm@1: case 0x04: rlm@1: CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); rlm@1: CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); rlm@1: break; rlm@1: case 0x05: rlm@1: WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); rlm@1: break; rlm@1: case 0x06: rlm@1: if (address & 0x10000) rlm@1: WRITE32LE(((u32 *)&vram[address & 0x17ffc]), value); rlm@1: else rlm@1: WRITE32LE(((u32 *)&vram[address & 0x1fffc]), value); rlm@1: break; rlm@1: case 0x07: rlm@1: WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); rlm@1: break; rlm@1: case 0x0D: rlm@1: if (cpuEEPROMEnabled) rlm@1: { rlm@1: eepromWrite(address, value); rlm@1: break; rlm@1: } rlm@1: goto unwritable; rlm@1: case 0x0E: rlm@1: if (!eepromInUse | cpuSramEnabled | cpuFlashEnabled) rlm@1: { rlm@1: (*cpuSaveGameFunc)(address, (u8)value); rlm@1: break; rlm@1: } rlm@1: // default rlm@1: default: rlm@1: unwritable: rlm@1: #ifdef GBA_LOGGING rlm@1: if (systemVerbose & VERBOSE_ILLEGAL_WRITE) rlm@1: { rlm@1: log("Illegal word write: %08x to %08x from %08x\n", rlm@1: value, rlm@1: address, rlm@1: armMode ? armNextPC - 4 : armNextPC - 2); rlm@1: } rlm@1: #endif rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: inline void CPUWriteMemory(u32 address, u32 value) rlm@1: { rlm@1: CPUWriteMemoryWrapped(address, value); rlm@1: CallRegisteredLuaMemHook(address, 4, value, LUAMEMHOOK_WRITE); rlm@1: } rlm@1: rlm@1: #endif // VBA_GBAINLINE_H