mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-06-09 08:04:58 -06:00
269 lines
7.6 KiB
C++
269 lines
7.6 KiB
C++
#pragma once
|
|
|
|
void memory_init();
|
|
void memory_mapForCurrentTitle();
|
|
void memory_unmapForCurrentTitle();
|
|
void memory_logModifiedMemoryRanges();
|
|
|
|
void memory_enableOverlayArena();
|
|
void memory_enableHBLELFCodeArea();
|
|
uint32 memory_getVirtualOffsetFromPointer(void* ptr);
|
|
uint8* memory_getPointerFromVirtualOffset(uint32 virtualOffset);
|
|
uint8* memory_getPointerFromVirtualOffsetAllowNull(uint32 virtualOffset);
|
|
|
|
uint8* memory_getPointerFromPhysicalOffset(uint32 physicalOffset);
|
|
|
|
uint32 memory_virtualToPhysical(uint32 virtualOffset);
|
|
uint32 memory_physicalToVirtual(uint32 physicalOffset);
|
|
|
|
extern uint8* memory_base; // points to base of PowerPC address space
|
|
|
|
enum class MMU_MEM_AREA_ID
|
|
{
|
|
CODE_LOW0,
|
|
CODE_TRAMPOLINE,
|
|
CODE_CAVE,
|
|
CODE_MAIN,
|
|
MEM2_DATA,
|
|
FGBUCKET,
|
|
TILING_APERATURE,
|
|
OVERLAY,
|
|
MAPABLE_SPACE,
|
|
MEM1,
|
|
RPLLOADER,
|
|
SHAREDDATA,
|
|
|
|
CPU_LC0,
|
|
CPU_LC1,
|
|
CPU_LC2,
|
|
CPU_PER_CORE,
|
|
|
|
CEMU_PRIVATE,
|
|
};
|
|
|
|
struct MMURange
|
|
{
|
|
enum MFLAG
|
|
{
|
|
FLAG_OPTIONAL = (1 << 0), // allocate only on explicit request
|
|
FLAG_MAP_EARLY = (1 << 1), // map at Cemu launch, normally memory is mapped when a game is loaded
|
|
};
|
|
|
|
MMURange(const uint32 baseAddress, const uint32 size, MMU_MEM_AREA_ID areaId, const std::string_view name, MFLAG flags = (MFLAG)0);
|
|
|
|
void mapMem();
|
|
void unmapMem();
|
|
|
|
uint8* getPtr() const
|
|
{
|
|
cemu_assert_debug(m_isMapped);
|
|
return memory_base + baseAddress;
|
|
}
|
|
|
|
uint32 getBase() const
|
|
{
|
|
return baseAddress;
|
|
}
|
|
|
|
// reset to initial parameters
|
|
void resetConfig()
|
|
{
|
|
size = initSize;
|
|
}
|
|
|
|
void setEnd(uint32 endAddress)
|
|
{
|
|
cemu_assert_debug(!m_isMapped);
|
|
cemu_assert_debug((endAddress & 0xFFF) == 0);
|
|
size = endAddress - baseAddress;
|
|
}
|
|
|
|
// returns offset of last byte + 1 (base + size)
|
|
uint32 getEnd() const
|
|
{
|
|
return baseAddress + size;
|
|
}
|
|
|
|
uint32 getSize() const
|
|
{
|
|
return size;
|
|
}
|
|
|
|
uint32 getInitSize() const
|
|
{
|
|
return initSize;
|
|
}
|
|
|
|
std::string_view getName() const
|
|
{
|
|
return name;
|
|
}
|
|
|
|
bool containsAddress(uint32 addr) const
|
|
{
|
|
return addr >= getBase() && addr < getEnd();
|
|
}
|
|
|
|
bool isMapped() const { return m_isMapped; };
|
|
bool isOptional() const { return (flags & MFLAG::FLAG_OPTIONAL) != 0; };
|
|
bool isMappedEarly() const { return (flags & MFLAG::FLAG_MAP_EARLY) != 0; };
|
|
|
|
const uint32 baseAddress;
|
|
const uint32 initSize; // initial size
|
|
const std::string name;
|
|
const MFLAG flags;
|
|
const MMU_MEM_AREA_ID areaId;
|
|
// runtime parameters
|
|
uint32 size;
|
|
bool m_isMapped{};
|
|
};
|
|
|
|
|
|
extern MMURange mmuRange_LOW0;
|
|
extern MMURange mmuRange_TRAMPOLINE_AREA;
|
|
extern MMURange mmuRange_CODECAVE;
|
|
extern MMURange mmuRange_TEXT_AREA;
|
|
extern MMURange mmuRange_MEM2;
|
|
extern MMURange mmuRange_CEMU_AREA;
|
|
extern MMURange mmuRange_OVERLAY_AREA;
|
|
extern MMURange mmuRange_FGBUCKET;
|
|
extern MMURange mmuRange_TILINGAPERTURE;
|
|
extern MMURange mmuRange_MEM1;
|
|
extern MMURange mmuRange_RPLLOADER;
|
|
extern MMURange mmuRange_SHARED_AREA;
|
|
extern MMURange mmuRange_CORE0_LC;
|
|
extern MMURange mmuRange_CORE1_LC;
|
|
extern MMURange mmuRange_CORE2_LC;
|
|
std::vector<MMURange*> memory_getMMURanges();
|
|
MMURange* memory_getMMURangeByAddress(MPTR address);
|
|
|
|
bool memory_isAddressRangeAccessible(MPTR virtualAddress, uint32 size);
|
|
|
|
#define MEMORY_CODELOW0_ADDR (0x00010000)
|
|
#define MEMORY_CODELOW0_SIZE (0x000F0000) // ~1MB
|
|
|
|
#define MEMORY_CODE_TRAMPOLINE_AREA_ADDR (0x00E00000) // code area for trampolines and imports
|
|
#define MEMORY_CODE_TRAMPOLINE_AREA_SIZE (0x00200000) // 2MB
|
|
|
|
#define MEMORY_CODECAVEAREA_ADDR (0x01800000)
|
|
#define MEMORY_CODECAVEAREA_SIZE (0x00400000) // 4MB
|
|
|
|
#define MEMORY_CODEAREA_ADDR (0x02000000)
|
|
#define MEMORY_CODEAREA_SIZE (0x0E000000) // 224MB
|
|
|
|
#define MEMORY_DATA_AREA_ADDR (0x10000000)
|
|
#define MEMORY_DATA_AREA_SIZE (0x40000000)
|
|
|
|
#define MEMORY_FGBUCKET_AREA_ADDR (0xE0000000) // actual offset is 0xE0000000 according to PPC kernel
|
|
#define MEMORY_FGBUCKET_AREA_SIZE (0x04000000) // 64MB split up into multiple subareas, size is verified with value from PPC kernel
|
|
|
|
#define MEMORY_TILINGAPERTURE_AREA_ADDR (0xE8000000)
|
|
#define MEMORY_TILINGAPERTURE_AREA_SIZE (0x02000000) // 32MB
|
|
|
|
#define MEMORY_OVERLAY_AREA_OFFSET (0xA0000000)
|
|
#define MEMORY_OVERLAY_AREA_SIZE (448*1024*1024) // 448MB (recycled background app memory)
|
|
|
|
#define MEMORY_MEM1_AREA_ADDR (0xF4000000)
|
|
#define MEMORY_MEM1_AREA_SIZE (0x02000000) // 32MB
|
|
|
|
#define MEMORY_RPLLOADER_AREA_ADDR (0xF6000000) // workarea for RPLLoader (normally this is kernel workspace)
|
|
#define MEMORY_RPLLOADER_AREA_SIZE (0x02000000) // 32MB
|
|
|
|
#define MEMORY_SHAREDDATA_AREA_ADDR (0xF8000000)
|
|
#define MEMORY_SHAREDDATA_AREA_SIZE (0x02000000) // 32MB
|
|
|
|
#if BOOST_OS_WINDOWS
|
|
#define CPU_swapEndianU64(_v) _byteswap_uint64((uint64)(_v))
|
|
#define CPU_swapEndianU32(_v) _byteswap_ulong((uint32)(_v))
|
|
#define CPU_swapEndianU16(_v) _byteswap_ushort((uint16)(_v))
|
|
#elif BOOST_OS_LINUX
|
|
#define CPU_swapEndianU64(_v) bswap_64((uint64)(_v))
|
|
#define CPU_swapEndianU32(_v) bswap_32((uint32)(_v))
|
|
#define CPU_swapEndianU16(_v) bswap_16((uint16)(_v))
|
|
#elif BOOST_OS_MACOS
|
|
#define CPU_swapEndianU64(_v) OSSwapInt64((uint64)(_v))
|
|
#define CPU_swapEndianU32(_v) OSSwapInt32((uint32)(_v))
|
|
#define CPU_swapEndianU16(_v) OSSwapInt16((uint16)(_v))
|
|
#endif
|
|
|
|
// C-style memory access, deprecated. Use memory_read<> and memory_write<> templates instead
|
|
void memory_writeDouble(uint32 address, double vf);
|
|
void memory_writeFloat(uint32 address, float vf);
|
|
void memory_writeU32(uint32 address, uint32 v);
|
|
void memory_writeU16(uint32 address, uint16 v);
|
|
void memory_writeU8(uint32 address, uint8 v);
|
|
void memory_writeU64(uint32 address, uint64 v);
|
|
|
|
double memory_readDouble(uint32 address);
|
|
float memory_readFloat(uint32 address);
|
|
uint64 memory_readU64(uint32 address);
|
|
uint32 memory_readU32(uint32 address);
|
|
uint16 memory_readU16(uint32 address);
|
|
uint8 memory_readU8(uint32 address);
|
|
|
|
void memory_createDump();
|
|
|
|
template<size_t count>
|
|
void memory_readBytes(VAddr address, std::array<uint8, count>& buffer)
|
|
{
|
|
memcpy(buffer.data(), memory_getPointerFromVirtualOffset(address), count);
|
|
}
|
|
|
|
template <typename T> inline T memory_read(VAddr address)
|
|
{
|
|
return *(betype<T>*)(memory_base + address);
|
|
}
|
|
|
|
template <typename T> inline void memory_write(VAddr address, T value)
|
|
{
|
|
*(betype<T>*)(memory_base + address) = value;
|
|
}
|
|
|
|
// LLE implementation
|
|
void memory_initPhysicalLayout();
|
|
|
|
namespace MMU
|
|
{
|
|
using MMIOFuncWrite32 = void (*)(PAddr addr, uint32 value);
|
|
using MMIOFuncWrite16 = void (*)(PAddr addr, uint16 value);
|
|
|
|
using MMIOFuncRead32 = uint32(*)(PAddr addr);
|
|
using MMIOFuncRead16 = uint16(*)(PAddr addr);
|
|
|
|
enum class MMIOInterface
|
|
{
|
|
INTERFACE_0C000000,
|
|
INTERFACE_0D000000,
|
|
//INTERFACE_0D000000,
|
|
};
|
|
|
|
void RegisterMMIO_W16(MMIOInterface interfaceLocation, uint32 relativeAddress, MMIOFuncWrite16 ptr);
|
|
void RegisterMMIO_W32(MMIOInterface interfaceLocation, uint32 relativeAddress, MMIOFuncWrite32 ptr);
|
|
void RegisterMMIO_R32(MMIOInterface interfaceLocation, uint32 relativeAddress, MMIOFuncRead32 ptr);
|
|
void RegisterMMIO_R16(MMIOInterface interfaceLocation, uint32 relativeAddress, MMIOFuncRead16 ptr);
|
|
|
|
template<typename TRegType, auto TReadFunc, auto TWriteFunc>
|
|
void RegisterMMIO_32(MMIOInterface interfaceLocation, uint32 relativeAddress)
|
|
{
|
|
RegisterMMIO_W32(interfaceLocation, relativeAddress,
|
|
[](PAddr addr, uint32 value) -> void
|
|
{
|
|
TRegType temp;
|
|
temp.setFromRaw(value);
|
|
TWriteFunc(addr, temp);
|
|
});
|
|
RegisterMMIO_R32(interfaceLocation, relativeAddress,
|
|
[](PAddr addr) -> uint32
|
|
{
|
|
return TReadFunc(addr).getRawValue();
|
|
});
|
|
}
|
|
|
|
void WriteMMIO_32(PAddr address, uint32 value);
|
|
void WriteMMIO_16(PAddr address, uint16 value);
|
|
uint16 ReadMMIO_32(PAddr address);
|
|
uint16 ReadMMIO_16(PAddr address);
|
|
|
|
}
|
|
|
|
#define MMU_IsInPPCMemorySpace(__ptr) ((const uint8*)(__ptr) >= memory_base && (const uint8*)(__ptr) < (memory_base + 0x100000000)) |