rpcsx/rpcs3/Emu/Memory/Memory.h
Peter Tissen c37905e465 initial start to eliminate static func init, not compilable atm
move module initialization into a module manager, still has some issues like stopping not working and debug crashing

add #idef 0 to modules that aren't in the windows project

don't double initialize and don't de-initialize for now, since many modules don't expect it and it leads to many errors

remove duplicate module lists for empty modules and implemented ones, make Module non-copyable but movable

add secondary project, no real use for it now

add some memleak config to the emucore and add asmjit path to rpcs3

small rebase error fixed to get it to compile again

add filters for emucore

re-add the module manager and static file

WIP commit, linker errors abound

some more abstraction layer stuff

fix the remaining linker errors, re-enable platform specific mouse, pad and keyboard handlers

rebasing

fix memset undefined and re() usage of se_t before declaration

Add wxGUI define by default for cmake builds

fix copy constructors of Datetime header

fix copy constructors of other wx interface classes

remove static declarations of global variables

make wxGLCanvas constructor non-ambiguous even with wx2.8. compat mode, fix wrong std::exception constructor calls

remove duplicate definition for FromUTF8 and ToUTF8

temp changes
2014-06-08 23:16:06 +02:00

1139 lines
23 KiB
C++

#pragma once
#include "Emu/SysCalls/Callback.h"
#include "MemoryBlock.h"
#include <vector>
using std::nullptr_t;
enum MemoryType
{
Memory_PS3,
Memory_PSV,
Memory_PSP,
};
class MemoryBase
{
NullMemoryBlock NullMem;
public:
std::vector<MemoryBlock*> MemoryBlocks;
MemoryBlock* UserMemory;
DynamicMemoryBlock MainMem;
DynamicMemoryBlock PRXMem;
DynamicMemoryBlock RSXCMDMem;
DynamicMemoryBlock MmaperMem;
DynamicMemoryBlock RSXFBMem;
DynamicMemoryBlock StackMem;
MemoryBlock SpuRawMem;
MemoryBlock SpuThrMem;
VirtualMemoryBlock RSXIOMem;
struct
{
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Userspace;
} PSVMemory;
struct
{
DynamicMemoryBlockLE Scratchpad;
DynamicMemoryBlockLE VRAM;
DynamicMemoryBlockLE RAM;
DynamicMemoryBlockLE Kernel;
DynamicMemoryBlockLE Userspace;
} PSPMemory;
bool m_inited;
MemoryBase()
{
m_inited = false;
}
~MemoryBase()
{
Close();
}
static __forceinline u16 Reverse16(const u16 val)
{
return _byteswap_ushort(val);
//return ((val >> 8) & 0xff) | ((val << 8) & 0xff00);
}
static __forceinline u32 Reverse32(const u32 val)
{
return _byteswap_ulong(val);
/*
return
((val >> 24) & 0x000000ff) |
((val >> 8) & 0x0000ff00) |
((val << 8) & 0x00ff0000) |
((val << 24) & 0xff000000);
*/
}
static __forceinline u64 Reverse64(const u64 val)
{
return _byteswap_uint64(val);
/*
return
((val >> 56) & 0x00000000000000ff) |
((val >> 40) & 0x000000000000ff00) |
((val >> 24) & 0x0000000000ff0000) |
((val >> 8) & 0x00000000ff000000) |
((val << 8) & 0x000000ff00000000) |
((val << 24) & 0x0000ff0000000000) |
((val << 40) & 0x00ff000000000000) |
((val << 56) & 0xff00000000000000);
*/
}
template<int size> static __forceinline u64 ReverseData(u64 val);
template<typename T> static __forceinline T Reverse(T val)
{
return (T)ReverseData<sizeof(T)>(val);
};
MemoryBlock& GetMemByNum(const u8 num)
{
if(num >= MemoryBlocks.size()) return NullMem;
return *MemoryBlocks[num];
}
MemoryBlock& GetMemByAddr(const u64 addr)
{
for (auto block : MemoryBlocks)
{
if (block->IsMyAddress(addr))
return *block;
}
return NullMem;
}
bool Read8ByAddr(const u64 addr, u8 *value)
{
for (auto block : MemoryBlocks)
{
if (block->Read8(addr, value))
return true;
}
return NullMem.Read8(addr, value);
}
bool Read16ByAddr(const u64 addr, u16 *value)
{
for (auto block : MemoryBlocks)
{
if (block->Read16(addr, value))
return true;
}
return NullMem.Read16(addr, value);
}
bool Read32ByAddr(const u64 addr, u32 *value)
{
for (auto block : MemoryBlocks)
{
if (block->Read32(addr, value))
return true;
}
return NullMem.Read32(addr, value);
}
bool Read64ByAddr(const u64 addr, u64 *value)
{
for (auto block : MemoryBlocks)
{
if (block->Read64(addr, value))
return true;
}
return NullMem.Read64(addr, value);
}
bool Read128ByAddr(const u64 addr, u128 *value)
{
for (auto block : MemoryBlocks)
{
if (block->Read128(addr, value))
return true;
}
return NullMem.Read128(addr, value);
}
u8* GetMemFromAddr(const u64 addr)
{
return GetMemByAddr(addr).GetMemFromAddr(addr);
}
void* VirtualToRealAddr(const u64 vaddr)
{
return GetMemFromAddr(vaddr);
}
u64 RealToVirtualAddr(const void* addr)
{
const u64 raddr = (u64)addr;
for (auto block : MemoryBlocks)
{
MemoryBlock& b = *block;
const u64 baddr = (u64)b.GetMem();
if(raddr >= baddr && raddr < baddr + b.GetSize())
{
return b.GetStartAddr() + (raddr - baddr);
}
}
return 0;
}
bool InitSpuRawMem(const u32 max_spu_raw)
{
//if(SpuRawMem.GetSize()) return false;
MemoryBlocks.push_back(SpuRawMem.SetRange(0xe0000000, 0x100000 * max_spu_raw));
return true;
}
void Init(MemoryType type)
{
if(m_inited) return;
m_inited = true;
ConLog.Write("Initing memory...");
switch(type)
{
case Memory_PS3:
MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000));
MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000));
MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 0x10000000));
MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
//MemoryBlocks.push_back(SpuRawMem.SetRange(0xE0000000, 0x10000000));
//MemoryBlocks.push_back(SpuThrMem.SetRange(0xF0000000, 0x10000000));
break;
case Memory_PSV:
MemoryBlocks.push_back(PSVMemory.RAM.SetRange(0x81000000, 0x10000000));
MemoryBlocks.push_back(UserMemory = PSVMemory.Userspace.SetRange(0x91000000, 0x10000000));
break;
case Memory_PSP:
MemoryBlocks.push_back(PSPMemory.Scratchpad.SetRange(0x00010000, 0x00004000));
MemoryBlocks.push_back(PSPMemory.VRAM.SetRange(0x04000000, 0x00200000));
MemoryBlocks.push_back(PSPMemory.RAM.SetRange(0x08000000, 0x02000000));
MemoryBlocks.push_back(PSPMemory.Kernel.SetRange(0x88000000, 0x00800000));
MemoryBlocks.push_back(UserMemory = PSPMemory.Userspace.SetRange(0x08800000, 0x01800000));
break;
}
ConLog.Write("Memory initialized.");
}
bool IsGoodAddr(const u64 addr)
{
for (auto block : MemoryBlocks)
{
if (block->IsMyAddress(addr))
return true;
}
return false;
}
bool IsGoodAddr(const u64 addr, const u32 size)
{
const u64 end = addr + size - 1;
for (auto block : MemoryBlocks)
{
if (block->IsMyAddress(addr) && block->IsMyAddress(end))
return true;
}
return false;
}
void Close()
{
if(!m_inited) return;
m_inited = false;
ConLog.Write("Closing memory...");
for (auto block : MemoryBlocks)
{
block->Delete();
}
MemoryBlocks.clear();
}
void Write8(const u64 addr, const u8 data);
void Write16(const u64 addr, const u16 data);
void Write32(const u64 addr, const u32 data);
void Write64(const u64 addr, const u64 data);
void Write128(const u64 addr, const u128 data);
bool Write8NN(const u64 addr, const u8 data);
bool Write16NN(const u64 addr, const u16 data);
bool Write32NN(const u64 addr, const u32 data);
bool Write64NN(const u64 addr, const u64 data);
bool Write128NN(const u64 addr, const u128 data);
u8 Read8(const u64 addr);
u16 Read16(const u64 addr);
u32 Read32(const u64 addr);
u64 Read64(const u64 addr);
u128 Read128(const u64 addr);
bool CopyToReal(void* real, u32 from, u32 count) // (4K pages) copy from virtual to real memory
{
if (!count) return true;
u8* to = (u8*)real;
if (u32 frag = from & 4095)
{
if (!IsGoodAddr(from)) return false;
u32 num = 4096 - frag;
if (count < num) num = count;
memcpy(to, GetMemFromAddr(from), num);
to += num;
from += num;
count -= num;
}
for (u32 page = count / 4096; page > 0; page--)
{
if (!IsGoodAddr(from)) return false;
memcpy(to, GetMemFromAddr(from), 4096);
to += 4096;
from += 4096;
count -= 4096;
}
if (count)
{
if (!IsGoodAddr(from)) return false;
memcpy(to, GetMemFromAddr(from), count);
}
return true;
}
bool CopyFromReal(u32 to, const void* real, u32 count) // (4K pages) copy from real to virtual memory
{
if (!count) return true;
const u8* from = (const u8*)real;
if (u32 frag = to & 4095)
{
if (!IsGoodAddr(to)) return false;
u32 num = 4096 - frag;
if (count < num) num = count;
memcpy(GetMemFromAddr(to), from, num);
to += num;
from += num;
count -= num;
}
for (u32 page = count / 4096; page > 0; page--)
{
if (!IsGoodAddr(to)) return false;
memcpy(GetMemFromAddr(to), from, 4096);
to += 4096;
from += 4096;
count -= 4096;
}
if (count)
{
if (!IsGoodAddr(to)) return false;
memcpy(GetMemFromAddr(to), from, count);
}
return true;
}
bool Copy(u32 to, u32 from, u32 count) // (4K pages) copy from virtual to virtual memory through real
{
if (u8* buf = (u8*)malloc(count))
{
if (CopyToReal(buf, from, count))
{
if (CopyFromReal(to, buf, count))
{
free(buf);
return true;
}
else
{
free(buf);
return false;
}
}
else
{
free(buf);
return false;
}
}
else
{
return false;
}
}
void ReadLeft(u8* dst, const u64 addr, const u32 size)
{
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
ConLog.Error("ReadLeft[%d] from null block (0x%llx)", size, addr);
return;
}
for(u32 i=0; i<size; ++i) mem.Read8(addr + i, dst + size - 1 - i);
}
void WriteLeft(const u64 addr, const u32 size, const u8* src)
{
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
ConLog.Error("WriteLeft[%d] to null block (0x%llx)", size, addr);
return;
}
for(u32 i=0; i<size; ++i) mem.Write8(addr + i, src[size - 1 - i]);
}
void ReadRight(u8* dst, const u64 addr, const u32 size)
{
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
ConLog.Error("ReadRight[%d] from null block (0x%llx)", size, addr);
return;
}
for(u32 i=0; i<size; ++i) mem.Read8(addr + (size - 1 - i), dst + i);
}
void WriteRight(const u64 addr, const u32 size, const u8* src)
{
MemoryBlock& mem = GetMemByAddr(addr);
if(mem.IsNULL())
{
ConLog.Error("WriteRight[%d] to null block (0x%llx)", size, addr);
return;
}
for(u32 i=0; i<size; ++i) mem.Write8(addr + (size - 1 - i), src[i]);
}
template<typename T> void WriteData(const u64 addr, const T* data)
{
memcpy(GetMemFromAddr(addr), data, sizeof(T));
}
template<typename T> void WriteData(const u64 addr, const T data)
{
*(T*)GetMemFromAddr(addr) = data;
}
std::string ReadString(const u64 addr, const u64 len)
{
std::string ret((const char *)GetMemFromAddr(addr), len);
return ret;
}
std::string ReadString(const u64 addr)
{
return std::string((const char*)GetMemFromAddr(addr));
}
void WriteString(const u64 addr, const std::string& str)
{
if(!IsGoodAddr(addr, str.length()))
{
ConLog.Error("Memory::WriteString error: bad address (0x%llx)", addr);
return;
}
strcpy((char*)GetMemFromAddr(addr), str.c_str());
}
static u64 AlignAddr(const u64 addr, const u64 align)
{
return (addr + (align-1)) & ~(align-1);
}
u32 GetUserMemTotalSize()
{
return UserMemory->GetSize();
}
u32 GetUserMemAvailSize()
{
return UserMemory->GetSize() - UserMemory->GetUsedSize();
}
u64 Alloc(const u32 size, const u32 align)
{
return UserMemory->AllocAlign(size, align);
}
bool Free(const u64 addr)
{
return UserMemory->Free(addr);
}
bool Lock(const u64 addr, const u32 size)
{
return UserMemory->Lock(addr, size);
}
bool Unlock(const u64 addr, const u32 size)
{
return UserMemory->Unlock(addr, size);
}
bool Map(const u64 dst_addr, const u64 src_addr, const u32 size)
{
if(IsGoodAddr(dst_addr) || !IsGoodAddr(src_addr))
{
return false;
}
MemoryBlocks.push_back((new MemoryMirror())->SetRange(GetMemFromAddr(src_addr), dst_addr, size));
ConLog.Warning("memory mapped 0x%llx to 0x%llx size=0x%x", src_addr, dst_addr, size);
return true;
}
bool Unmap(const u64 addr)
{
bool result = false;
for(uint i=0; i<MemoryBlocks.size(); ++i)
{
if(MemoryBlocks[i]->IsMirror())
{
if(MemoryBlocks[i]->GetStartAddr() == addr)
{
delete MemoryBlocks[i];
MemoryBlocks.erase(MemoryBlocks.begin() + i);
return true;
}
}
}
return false;
}
u8* operator + (const u64 vaddr)
{
u8* ret = GetMemFromAddr(vaddr);
if(ret == nullptr)
throw fmt::Format("GetMemFromAddr(0x%x)", vaddr);
return ret;
}
u8& operator[] (const u64 vaddr)
{
return *(*this + vaddr);
}
};
extern MemoryBase Memory;
template<typename T, typename AT = u32>
class mem_base_t
{
protected:
AT m_addr;
public:
mem_base_t(AT addr) : m_addr(addr)
{
}
__forceinline AT GetAddr() const { return m_addr; }
__forceinline void SetAddr(AT addr) { m_addr = addr; }
__forceinline bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
__forceinline operator bool() const
{
return m_addr != 0;
}
__forceinline bool operator != (nullptr_t) const
{
return m_addr != 0;
}
__forceinline bool operator == (nullptr_t) const
{
return m_addr == 0;
}
bool operator == (const mem_base_t& right) const { return m_addr == right.m_addr; }
bool operator != (const mem_base_t& right) const { return m_addr != right.m_addr; }
bool operator > (const mem_base_t& right) const { return m_addr > right.m_addr; }
bool operator < (const mem_base_t& right) const { return m_addr < right.m_addr; }
bool operator >= (const mem_base_t& right) const { return m_addr >= right.m_addr; }
bool operator <= (const mem_base_t& right) const { return m_addr <= right.m_addr; }
bool operator == (T* right) const { return (T*)&Memory[m_addr] == right; }
bool operator != (T* right) const { return (T*)&Memory[m_addr] != right; }
bool operator > (T* right) const { return (T*)&Memory[m_addr] > right; }
bool operator < (T* right) const { return (T*)&Memory[m_addr] < right; }
bool operator >= (T* right) const { return (T*)&Memory[m_addr] >= right; }
bool operator <= (T* right) const { return (T*)&Memory[m_addr] <= right; }
};
template<typename T, int lvl = 1, typename AT = u32>
class mem_ptr_t : public mem_base_t<AT, AT>
{
public:
mem_ptr_t(AT addr) : mem_base_t<AT, AT>(addr)
{
}
template<typename NT> operator mem_ptr_t<NT, lvl, AT>&() { return (mem_ptr_t<NT, lvl, AT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT, lvl, AT>&() const { return (const mem_ptr_t<NT, lvl, AT>&)*this; }
mem_ptr_t operator++ (int)
{
mem_ptr_t ret(this->m_addr);
this->m_addr += sizeof(AT);
return ret;
}
mem_ptr_t& operator++ ()
{
this->m_addr += sizeof(AT);
return *this;
}
mem_ptr_t operator-- (int)
{
mem_ptr_t ret(this->m_addr);
this->m_addr -= sizeof(AT);
return ret;
}
mem_ptr_t& operator-- ()
{
this->m_addr -= sizeof(AT);
return *this;
}
mem_ptr_t& operator += (uint count)
{
this->m_addr += count * sizeof(AT);
return *this;
}
mem_ptr_t& operator -= (uint count)
{
this->m_addr -= count * sizeof(AT);
return *this;
}
mem_ptr_t operator + (uint count) const
{
return this->m_addr + count * sizeof(AT);
}
mem_ptr_t operator - (uint count) const
{
return this->m_addr - count * sizeof(AT);
}
__forceinline mem_ptr_t<T, lvl - 1, AT>& operator *()
{
return (mem_ptr_t<T, lvl - 1, AT>&)Memory[this->m_addr];
}
__forceinline const mem_ptr_t<T, lvl - 1, AT>& operator *() const
{
return (const mem_ptr_t<T, lvl - 1, AT>&)Memory[this->m_addr];
}
__forceinline mem_ptr_t<T, lvl - 1, AT>& operator [](uint index)
{
return (mem_ptr_t<T, lvl - 1, AT>&)Memory[this->m_addr + sizeof(AT) * index];
}
__forceinline const mem_ptr_t<T, lvl - 1, AT>& operator [](uint index) const
{
return (const mem_ptr_t<T, lvl - 1, AT>&)Memory[this->m_addr + sizeof(AT) * index];
}
bool IsGood() const
{
return (*this)->IsGood() && mem_base_t<T, AT>::IsGood();
}
__forceinline bool IsGoodAddr() const
{
return mem_base_t<T, AT>::IsGood();
}
};
template<typename T, typename AT>
class mem_ptr_t<T, 1, AT> : public mem_base_t<T, AT>
{
public:
mem_ptr_t(AT addr) : mem_base_t<T, AT>(addr)
{
}
template<typename NT> operator mem_ptr_t<NT, 1, AT>&() { return (mem_ptr_t<NT, 1, AT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT, 1, AT>&() const { return (const mem_ptr_t<NT, 1, AT>&)*this; }
__forceinline T* operator -> ()
{
return (T*)&Memory[this->m_addr];
}
__forceinline const T* operator -> () const
{
return (const T*)&Memory[this->m_addr];
}
mem_ptr_t operator++ (int)
{
mem_ptr_t ret(this->m_addr);
this->m_addr += sizeof(T);
return ret;
}
mem_ptr_t& operator++ ()
{
this->m_addr += sizeof(T);
return *this;
}
mem_ptr_t operator-- (int)
{
mem_ptr_t ret(this->m_addr);
this->m_addr -= sizeof(T);
return ret;
}
mem_ptr_t& operator-- ()
{
this->m_addr -= sizeof(T);
return *this;
}
mem_ptr_t& operator += (uint count)
{
this->m_addr += count * sizeof(T);
return *this;
}
mem_ptr_t& operator -= (uint count)
{
this->m_addr -= count * sizeof(T);
return *this;
}
mem_ptr_t operator + (uint count) const
{
return this->m_addr + count * sizeof(T);
}
mem_ptr_t operator - (uint count) const
{
return this->m_addr - count * sizeof(T);
}
__forceinline T& operator *()
{
return (T&)Memory[this->m_addr];
}
__forceinline const T& operator *() const
{
return (T&)Memory[this->m_addr];
}
__forceinline T& operator [](uint index)
{
return (T&)Memory[this->m_addr + sizeof(T) * index];
}
__forceinline const T& operator [](uint index) const
{
return (const T&)Memory[this->m_addr + sizeof(T) * index];
}
};
template<typename AT>
class mem_ptr_t<void, 1, AT> : public mem_base_t<u8, AT>
{
public:
mem_ptr_t(AT addr) : mem_base_t<u8, AT>(addr)
{
}
template<typename NT> operator mem_ptr_t<NT, 1, AT>&() { return (mem_ptr_t<NT, 1, AT>&)*this; }
template<typename NT> operator const mem_ptr_t<NT, 1, AT>&() const { return (const mem_ptr_t<NT, 1, AT>&)*this; }
};
template<typename T, int lvl = 1, typename AT = u32>
class mem_beptr_t : public mem_ptr_t<T, lvl, be_t<AT>> {};
template<typename T, typename AT = u32> class mem_t : public mem_base_t<T, AT>
{
public:
mem_t(AT addr) : mem_base_t<T, AT>(addr)
{
}
mem_t& operator = (T right)
{
(be_t<T>&)Memory[this->m_addr] = right;
return *this;
}
__forceinline T GetValue()
{
return (be_t<T>&)Memory[this->m_addr];
}
operator const T() const
{
return (be_t<T>&)Memory[this->m_addr];
}
mem_t& operator += (T right) { return *this = (*this) + right; }
mem_t& operator -= (T right) { return *this = (*this) - right; }
mem_t& operator *= (T right) { return *this = (*this) * right; }
mem_t& operator /= (T right) { return *this = (*this) / right; }
mem_t& operator %= (T right) { return *this = (*this) % right; }
mem_t& operator &= (T right) { return *this = (*this) & right; }
mem_t& operator |= (T right) { return *this = (*this) | right; }
mem_t& operator ^= (T right) { return *this = (*this) ^ right; }
mem_t& operator <<= (T right) { return *this = (*this) << right; }
mem_t& operator >>= (T right) { return *this = (*this) >> right; }
};
template<typename T, typename AT = u32> class mem_list_ptr_t : public mem_base_t<T, AT>
{
public:
mem_list_ptr_t(u32 addr) : mem_base_t<T>(addr)
{
}
void operator = (T right)
{
(be_t<T>&)Memory[this->m_addr] = right;
}
u32 operator += (T right)
{
*this = right;
this->m_addr += sizeof(T);
return this->m_addr;
}
u32 AppendRawBytes(const u8 *bytes, size_t count)
{
Memory.CopyFromReal(this->m_addr, bytes, count);
this->m_addr += count;
return this->m_addr;
}
u32 Skip(const u32 offset) { return this->m_addr += offset; }
operator be_t<T>*() { return GetPtr(); }
operator void*() { return GetPtr(); }
operator be_t<T>*() const { return GetPtr(); }
operator void*() const { return GetPtr(); }
const char* GetString() const
{
return (const char*)&Memory[this->m_addr];
}
be_t<T>* GetPtr()
{
return (be_t<T>*)&Memory[this->m_addr];
}
const be_t<T>* GetPtr() const
{
return (const be_t<T>*)&Memory[this->m_addr];
}
};
class mem_class_t
{
u32 m_addr;
public:
mem_class_t(u32 addr) : m_addr(addr)
{
}
template<typename T> u32 operator += (T right)
{
mem_t<T>& m((mem_t<T>&)*this);
m = right;
m_addr += sizeof(T);
return m_addr;
}
template<typename T> operator T()
{
mem_t<T>& m((mem_t<T>&)*this);
const T ret = m;
m_addr += sizeof(T);
return ret;
}
u64 GetAddr() const { return m_addr; }
void SetAddr(const u64 addr) { m_addr = addr; }
};
template<typename T>
struct _func_arg
{
__forceinline static u64 get_value(const T& arg)
{
return arg;
}
};
template<typename T>
struct _func_arg<mem_base_t<T, u32>>
{
__forceinline static u64 get_value(const mem_base_t<T, u32> arg)
{
return arg.GetAddr();
}
};
template<typename T, int lvl> struct _func_arg<mem_ptr_t<T, lvl, u32>> : public _func_arg<mem_base_t<T, u32>> {};
template<int lvl> struct _func_arg<mem_ptr_t<void, lvl, u32>> : public _func_arg<mem_base_t<u8, u32>>{};
template<typename T> struct _func_arg<mem_list_ptr_t<T, u32>> : public _func_arg<mem_base_t<T, u32>> {};
template<typename T> struct _func_arg<mem_t<T, u32>> : public _func_arg<mem_base_t<T, u32>> {};
template<typename T>
struct _func_arg<be_t<T>>
{
__forceinline static u64 get_value(const be_t<T>& arg)
{
return arg.ToLE();
}
};
template<typename T, typename AT = u32> class mem_func_ptr_t;
template<typename T, typename AT = u32> class mem_func_beptr_t : public mem_func_ptr_t<T, be_t<AT>> {};
template<typename RT, typename AT>
class mem_func_ptr_t<RT (*)(), AT> : public mem_base_t<u64, AT>
{
__forceinline void call_func(bool is_async)
{
Callback cb;
cb.SetAddr(this->m_addr);
cb.Branch(!is_async);
}
public:
__forceinline void operator()()
{
call_func(false);
}
__forceinline void async()
{
call_func(true);
}
};
template<typename AT, typename RT, typename ...T>
class mem_func_ptr_t<RT(*)(T...), AT> : public mem_base_t<u64, AT>
{
__forceinline void call_func(bool is_async, T... args)
{
Callback cb;
cb.SetAddr(this->m_addr);
cb.Handle(_func_arg<T>::get_value(args)...);
cb.Branch(!is_async);
}
public:
__forceinline void operator()(T... args)
{
call_func(false, args...);
}
__forceinline void async(T... args)
{
call_func(true, args...);
}
};
template<typename T>
class MemoryAllocator
{
u32 m_addr;
u32 m_size;
T* m_ptr;
public:
MemoryAllocator(u32 size = sizeof(T), u32 align = 1)
: m_size(size)
, m_addr(Memory.Alloc(size, align))
, m_ptr((T*)&Memory[m_addr])
{
}
~MemoryAllocator()
{
Memory.Free(m_addr);
}
T* operator -> ()
{
return m_ptr;
}
T* GetPtr()
{
return m_ptr;
}
const T* GetPtr() const
{
return m_ptr;
}
const T* operator -> () const
{
return m_ptr;
}
u32 GetAddr() const
{
return m_addr;
}
u32 GetSize() const
{
return m_size;
}
bool IsGood() const
{
return Memory.IsGoodAddr(m_addr, sizeof(T));
}
template<typename T1>
operator const T1() const
{
return T1(*m_ptr);
}
template<typename T1>
operator T1()
{
return T1(*m_ptr);
}
operator const T&() const
{
return *m_ptr;
}
operator T&()
{
return *m_ptr;
}
operator const T*() const
{
return m_ptr;
}
operator T*()
{
return m_ptr;
}
T operator [](int index)
{
return *(m_ptr + index);
}
template<typename T1>
operator const mem_t<T1>() const
{
return GetAddr();
}
operator const mem_ptr_t<T>() const
{
return GetAddr();
}
template<typename NT>
NT* To(uint offset = 0)
{
return (NT*)(m_ptr + offset);
}
};
typedef mem_t<u8, u32> mem8_t;
typedef mem_t<u16, u32> mem16_t;
typedef mem_t<u32, u32> mem32_t;
typedef mem_t<u64, u32> mem64_t;
/*
typedef mem_ptr_t<be_t<u8>> mem8_ptr_t;
typedef mem_ptr_t<be_t<u16>> mem16_ptr_t;
typedef mem_ptr_t<be_t<u32>> mem32_ptr_t;
typedef mem_ptr_t<be_t<u64>> mem64_ptr_t;
typedef mem_list_ptr_t<u8> mem8_lptr_t;
typedef mem_list_ptr_t<u16> mem16_lptr_t;
typedef mem_list_ptr_t<u32> mem32_lptr_t;
typedef mem_list_ptr_t<u64> mem64_lptr_t;
*/
typedef mem_list_ptr_t<u8, u32> mem8_ptr_t;
typedef mem_list_ptr_t<u16, u32> mem16_ptr_t;
typedef mem_list_ptr_t<u32, u32> mem32_ptr_t;
typedef mem_list_ptr_t<u64, u32> mem64_ptr_t;