Merge remote-tracking branch 'upstream/master'

Conflicts:
	rpcs3/Emu/Cell/PPUInterpreter.h
This commit is contained in:
S Gopal Rajagopal 2014-11-25 23:26:16 +05:30
commit 631675fdd6
65 changed files with 3095 additions and 2945 deletions

View File

@ -451,7 +451,13 @@ template<typename T, typename T2 = T>
class be_t
{
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
T m_data;
public:
typedef typename std::remove_cv<T>::type type;
static const bool is_le_machine = true;
private:
type m_data;
template<typename Tto, typename Tfrom, int mode>
struct _convert
@ -482,54 +488,77 @@ class be_t
return (be_t<Tto>&)res;
}
};
public:
typedef T type;
const T& ToBE() const
const type& ToBE() const
{
return m_data;
}
T ToLE() const
type ToLE() const
{
return se_t<T, sizeof(T2)>::func(m_data);
return se_t<type, sizeof(T2)>::func(m_data);
}
void FromBE(const T& value)
void FromBE(const type& value)
{
m_data = value;
}
void FromLE(const T& value)
void FromLE(const type& value)
{
m_data = se_t<T, sizeof(T2)>::func(value);
m_data = se_t<type, sizeof(T2)>::func(value);
}
static be_t make(const T value)
static be_t MakeFromLE(const type value)
{
T data = se_t<T, sizeof(T2)>::func(value);
type data = se_t<type, sizeof(T2)>::func(value);
return (be_t&)data;
}
//template<typename T1>
operator const T() const
static be_t MakeFromBE(const type value)
{
return ToLE();
return (be_t&)value;
}
//make be_t from current machine byte ordering
static be_t make(const type value)
{
return is_le_machine ? MakeFromLE(value) : MakeFromBE(value);
}
//get value in current machine byte ordering
__forceinline type value() const
{
return is_le_machine ? ToLE() : ToBE();
}
//be_t() = default;
//be_t(const be_t& value) = default;
//be_t(type value)
//{
// m_data = se_t<type, sizeof(T2)>::func(value);
//}
be_t& operator = (const be_t& value) = default;
be_t& operator = (T value)
be_t& operator = (type value)
{
m_data = se_t<T, sizeof(T2)>::func(value);
m_data = se_t<type, sizeof(T2)>::func(value);
return *this;
}
operator type() const
{
return value();
}
template<typename T1>
operator const be_t<T1>() const
{
return be_t<T1>::make(ToLE());
return be_t<T1>::make(value());
//return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
}
@ -577,62 +606,6 @@ public:
be_t& operator-- () { *this -= 1; return *this; }
};
template<typename T, typename T2>
class be_t<const T, T2>
{
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
const T m_data;
public:
typedef const T type;
const T& ToBE() const
{
return m_data;
}
const T ToLE() const
{
return se_t<const T, sizeof(T2)>::func(m_data);
}
static be_t make(const T value)
{
const T data = se_t<const T, sizeof(T2)>::func(value);
return (be_t&)data;
}
//template<typename T1>
operator const T() const
{
return ToLE();
}
template<typename T1>
operator const be_t<T1>() const
{
return be_t<T1>::make(ToLE());
}
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; }
template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; }
template<typename T1> bool operator != (T1 right) const { return !(*this == right); }
template<typename T1> bool operator > (T1 right) const { return (T1)ToLE() > right; }
template<typename T1> bool operator < (T1 right) const { return (T1)ToLE() < right; }
template<typename T1> bool operator >= (T1 right) const { return (T1)ToLE() >= right; }
template<typename T1> bool operator <= (T1 right) const { return (T1)ToLE() <= right; }
template<typename T1> bool operator == (const be_t<T1>& right) const { return ToBE() == right.ToBE(); }
template<typename T1> bool operator != (const be_t<T1>& right) const { return !(*this == right); }
template<typename T1> bool operator > (const be_t<T1>& right) const { return (T1)ToLE() > right.ToLE(); }
template<typename T1> bool operator < (const be_t<T1>& right) const { return (T1)ToLE() < right.ToLE(); }
template<typename T1> bool operator >= (const be_t<T1>& right) const { return (T1)ToLE() >= right.ToLE(); }
template<typename T1> bool operator <= (const be_t<T1>& right) const { return (T1)ToLE() <= right.ToLE(); }
};
template<typename T, typename T2 = T>
struct is_be_t : public std::integral_constant<bool, false> {};
@ -672,6 +645,8 @@ public:
//be_t<T, size> if need swap endianes, T otherwise
typedef typename _be_type_selector< T, T2, value >::type type;
typedef typename _be_type_selector< T, T2, !is_be_t<T, T2>::value >::type forced_type;
};
template<typename T>
@ -799,3 +774,51 @@ template<typename T> __forceinline static void Write64(T& f, const u64 data)
{
Write64LE(f, re64(data));
}
template<typename Tto, typename Tfrom>
struct convert_le_be_t
{
static Tto func(Tfrom&& value)
{
return (Tto)value;
}
};
template<typename Tt, typename Tt1, typename Tfrom>
struct convert_le_be_t<be_t<Tt, Tt1>, Tfrom>
{
static be_t<Tt, Tt1> func(Tfrom&& value)
{
return be_t<Tt, Tt1>::make(value);
}
};
template<typename Tt, typename Tt1, typename Tf, typename Tf1>
struct convert_le_be_t<be_t<Tt, Tt1>, be_t<Tf, Tf1>>
{
static be_t<Tt, Tt1> func(be_t<Tf, Tf1>&& value)
{
return value;
}
};
template<typename Tto, typename Tf, typename Tf1>
struct convert_le_be_t<Tto, be_t<Tf, Tf1>>
{
static Tto func(be_t<Tf, Tf1>&& value)
{
return value.value();
}
};
template<typename Tto, typename Tfrom>
__forceinline Tto convert_le_be(Tfrom&& value)
{
return convert_le_be_t<Tto, Tfrom>::func(value);
}
template<typename Tto, typename Tfrom>
__forceinline void convert_le_be(Tto& dst, Tfrom&& src)
{
dst = convert_le_be_t<Tto, Tfrom>::func(src);
}

View File

@ -10,6 +10,101 @@
#include <wx/mstream.h>
#include <wx/zstream.h>
void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write64(f, ehdr.e_entry);
Write64(f, ehdr.e_phoff);
Write64(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(rFile& f, Elf64_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_flags);
Write64(f, phdr.p_offset);
Write64(f, phdr.p_vaddr);
Write64(f, phdr.p_paddr);
Write64(f, phdr.p_filesz);
Write64(f, phdr.p_memsz);
Write64(f, phdr.p_align);
}
void WriteShdr(rFile& f, Elf64_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write64(f, shdr.sh_flags);
Write64(f, shdr.sh_addr);
Write64(f, shdr.sh_offset);
Write64(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write64(f, shdr.sh_addralign);
Write64(f, shdr.sh_entsize);
}
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write32(f, ehdr.e_entry);
Write32(f, ehdr.e_phoff);
Write32(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(rFile& f, Elf32_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_offset);
Write32(f, phdr.p_vaddr);
Write32(f, phdr.p_paddr);
Write32(f, phdr.p_filesz);
Write32(f, phdr.p_memsz);
Write32(f, phdr.p_flags);
Write32(f, phdr.p_align);
}
void WriteShdr(rFile& f, Elf32_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write32(f, shdr.sh_flags);
Write32(f, shdr.sh_addr);
Write32(f, shdr.sh_offset);
Write32(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write32(f, shdr.sh_addralign);
Write32(f, shdr.sh_entsize);
}
void AppInfo::Load(vfsStream& f)
{
authid = Read64(f);

View File

@ -1,6 +1,5 @@
#pragma once
#include "Loader/SELF.h"
#include "Loader/ELF64.h"
#include "Loader/ELF32.h"
#include "key_vault.h"
@ -142,7 +141,8 @@ struct MetadataSectionHeader
void Show();
};
struct SectionHash {
struct SectionHash
{
u8 sha1[20];
u8 padding[12];
u8 hmac_key[64];
@ -183,6 +183,291 @@ struct SelfSection
void Load(vfsStream& f);
};
struct Elf32_Ehdr
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
void Show() {}
bool IsLittleEndian() const
{
return e_data == 1;
}
void Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
if (IsLittleEndian())
{
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
else
{
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
}
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u32 GetEntry() const { return e_entry; }
};
struct Elf32_Shdr
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
void Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read32(f);
sh_addr = Read32(f);
sh_offset = Read32(f);
sh_size = Read32(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read32(f);
sh_entsize = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {}
};
struct Elf32_Phdr
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
void Load(vfsStream& f)
{
p_type = Read32(f);
p_offset = Read32(f);
p_vaddr = Read32(f);
p_paddr = Read32(f);
p_filesz = Read32(f);
p_memsz = Read32(f);
p_flags = Read32(f);
p_align = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {}
};
struct Elf64_Ehdr
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u64 e_entry;
u64 e_phoff;
u64 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
void Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read64(f);
e_phoff = Read64(f);
e_shoff = Read64(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
void Show() {}
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u64 GetEntry() const { return e_entry; }
};
struct Elf64_Shdr
{
u32 sh_name;
u32 sh_type;
u64 sh_flags;
u64 sh_addr;
u64 sh_offset;
u64 sh_size;
u32 sh_link;
u32 sh_info;
u64 sh_addralign;
u64 sh_entsize;
void Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read64(f);
sh_addr = Read64(f);
sh_offset = Read64(f);
sh_size = Read64(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read64(f);
sh_entsize = Read64(f);
}
void Show(){}
};
struct Elf64_Phdr
{
u32 p_type;
u32 p_flags;
u64 p_offset;
u64 p_vaddr;
u64 p_paddr;
u64 p_filesz;
u64 p_memsz;
u64 p_align;
void Load(vfsStream& f)
{
p_type = Read32(f);
p_flags = Read32(f);
p_offset = Read64(f);
p_vaddr = Read64(f);
p_paddr = Read64(f);
p_filesz = Read64(f);
p_memsz = Read64(f);
p_align = Read64(f);
}
void Show(){}
};
struct SceHeader
{
u32 se_magic;
u32 se_hver;
u16 se_flags;
u16 se_type;
u32 se_meta;
u64 se_hsize;
u64 se_esize;
void Load(vfsStream& f)
{
se_magic = Read32(f);
se_hver = Read32(f);
se_flags = Read16(f);
se_type = Read16(f);
se_meta = Read32(f);
se_hsize = Read64(f);
se_esize = Read64(f);
}
void Show(){}
bool CheckMagic() const { return se_magic == 0x53434500; }
};
struct SelfHeader
{
u64 se_htype;
u64 se_appinfooff;
u64 se_elfoff;
u64 se_phdroff;
u64 se_shdroff;
u64 se_secinfoff;
u64 se_sceveroff;
u64 se_controloff;
u64 se_controlsize;
u64 pad;
void Load(vfsStream& f)
{
se_htype = Read64(f);
se_appinfooff = Read64(f);
se_elfoff = Read64(f);
se_phdroff = Read64(f);
se_shdroff = Read64(f);
se_secinfoff = Read64(f);
se_sceveroff = Read64(f);
se_controloff = Read64(f);
se_controlsize = Read64(f);
pad = Read64(f);
}
void Show(){}
};
class SELFDecrypter
{
// Main SELF file stream.

View File

@ -3,6 +3,7 @@
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "ARMv7Thread.h"
#include "ARMv7Decoder.h"
@ -100,3 +101,15 @@ void ARMv7Thread::DoStop()
void ARMv7Thread::DoCode()
{
}
arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}

View File

@ -138,3 +138,48 @@ protected:
virtual void DoCode();
};
class arm7_thread : cpu_thread
{
static const u32 stack_align = 0x10;
vm::ptr<u64> argv;
u32 argc;
vm::ptr<u64> envp;
public:
arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
cpu_thread& args(std::initializer_list<std::string> values) override
{
if (!values.size())
return *this;
assert(argc == 0);
envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main));
*envp = 0;
argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main));
for (auto &arg : values)
{
u32 arg_size = align(u32(arg.size() + 1), stack_align);
u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main);
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
argv[argc++] = arg_addr;
}
return *this;
}
cpu_thread& run() override
{
thread->Run();
static_cast<ARMv7Thread*>(thread)->GPR[3] = argc;
static_cast<ARMv7Thread*>(thread)->GPR[4] = argv.addr();
static_cast<ARMv7Thread*>(thread)->GPR[5] = envp.addr();
return *this;
}
};

View File

@ -340,7 +340,7 @@ public:
, m_args_count(source.m_args_count)
, m_args(source.m_args_count ? new CodeFieldBase*[source.m_args_count] : nullptr)
{
for(int i = 0; i < source.m_args_count; ++i)
for(uint i = 0; i < source.m_args_count; ++i)
m_args[i] = source.m_args[i];
}

View File

@ -228,13 +228,13 @@ public:
m_call_stack.erase((res + 1).base(), m_call_stack.end());
return;
}
//add a new entry otherwise
CallStackItem new_item;
new_item.branch_pc = pc;
new_item.pc = PC;
m_call_stack.push_back(new_item);
}
@ -256,3 +256,42 @@ protected:
};
CPUThread* GetCurrentCPUThread();
class cpu_thread
{
protected:
CPUThread* thread;
public:
u32 get_entry() const
{
return thread->entry;
}
virtual cpu_thread& args(std::initializer_list<std::string> values) = 0;
virtual cpu_thread& run() = 0;
u64 join()
{
if (!joinable())
throw "thread must be joinable for join";
thread->SetJoinable(false);
while (thread->IsRunning())
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return thread->GetExitStatus();
}
bool joinable() const
{
return thread->IsJoinable();
}
u32 get_id() const
{
return thread->GetId();
}
};

View File

@ -8,4 +8,4 @@ u8 PPCDecoder::DecodeMemory(const u32 address)
Decode(instr);
return sizeof(u32);
}
}

View File

@ -9,7 +9,7 @@ public:
virtual std::string GetThreadName() const
{
return (GetFName() + fmt::Format("[0x%08llx]", PC));
return (GetFName() + fmt::Format("[0x%08x]", PC));
}
protected:

File diff suppressed because it is too large Load Diff

View File

@ -146,9 +146,26 @@ private:
case 0x001: return CPU.XER.XER;
case 0x008: return CPU.LR;
case 0x009: return CPU.CTR;
case 0x100: return CPU.USPRG0;
case 0x100:
case 0x101:
case 0x102:
case 0x103:
case 0x104:
case 0x105:
case 0x106:
case 0x107: return CPU.USPRG[n - 0x100];
case 0x10C: CPU.TB = get_time(); return CPU.TB;
case 0x10D: CPU.TB = get_time(); return CPU.TBH;
case 0x110:
case 0x111:
case 0x112:
case 0x113:
case 0x114:
case 0x115:
case 0x116:
case 0x117: return CPU.SPRG[n - 0x110];
}
UNK(fmt::Format("ReadSPR error: Unknown SPR 0x%x!", n));
@ -164,9 +181,26 @@ private:
case 0x001: CPU.XER.XER = value; return;
case 0x008: CPU.LR = value; return;
case 0x009: CPU.CTR = value; return;
case 0x100: CPU.USPRG0 = value; return;
case 0x100:
case 0x101:
case 0x102:
case 0x103:
case 0x104:
case 0x105:
case 0x106:
case 0x107: CPU.USPRG[n - 0x100] = value; return;
case 0x10C: UNK("WriteSPR: Write to time-based SPR. Report this to a developer!"); return;
case 0x10D: UNK("WriteSPR: Write to time-based SPR upper. Report this to a developer!"); return;
case 0x110:
case 0x111:
case 0x112:
case 0x113:
case 0x114:
case 0x115:
case 0x116:
case 0x117: CPU.SPRG[n - 0x110] = value; return;
}
UNK(fmt::Format("WriteSPR error: Unknown SPR 0x%x!", n));

View File

@ -4836,14 +4836,14 @@ void Compiler::SetXerSo(Value * so) {
}
Value * Compiler::GetUsprg0() {
auto usrpg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG0));
auto usrpg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG));
auto usprg0_i64_ptr = m_ir_builder->CreateBitCast(usrpg0_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(usprg0_i64_ptr, 8);
}
void Compiler::SetUsprg0(Value * val_x64) {
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
auto usprg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG0));
auto usprg0_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, USPRG));
auto usprg0_i64_ptr = m_ir_builder->CreateBitCast(usprg0_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i64, usprg0_i64_ptr, 8);
}
@ -5139,7 +5139,7 @@ void Compiler::WriteMemory(Value * addr_i64, Value * val_ix, u32 alignment, bool
val_else_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), val_else_i32);
}
Call<void>("vm.write32", (void(*)(u64, u32))vm::write32, addr_i64, val_else_i32);
Call<void>("vm.write32", (void(*)(u32, u32))vm::write32, addr_i64, val_else_i32);
m_ir_builder->CreateBr(merge_bb);
m_ir_builder->SetInsertPoint(merge_bb);
@ -5227,7 +5227,8 @@ std::shared_ptr<RecompilationEngine> RecompilationEngine::s_the_instance = nullp
RecompilationEngine::RecompilationEngine()
: ThreadBase("PPU Recompilation Engine")
, m_next_ordinal(0)
, m_compiler(*this, ExecutionEngine::ExecuteFunction, ExecutionEngine::ExecuteTillReturn) {
, m_compiler(*this, ExecutionEngine::ExecuteFunction, ExecutionEngine::ExecuteTillReturn)
, m_log(nullptr) {
m_compiler.RunAllTests();
}

View File

@ -1,7 +1,7 @@
#include "stdafx_gui.h"
#include "PPUProgramCompiler.h"
#include "Utilities/rFile.h"
/*
using namespace PPU_instr;
template<typename TO, typename T>
@ -78,10 +78,10 @@ SectionInfo::SectionInfo(const std::string& _name)
section_name_offs += name.length() + 1;
}
void SectionInfo::SetDataSize(u32 size, u32 align)
void SectionInfo::SetDataSize(u32 size, u32 addralign)
{
if(align) shdr.sh_addralign = align;
if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign);
if (addralign) shdr.sh_addralign = addralign;
if (shdr.sh_addralign) size = align(size, shdr.sh_addralign);
if(!code.empty())
{
@ -985,7 +985,7 @@ void CompilePPUProgram::Compile()
elf_info.e_shnum = 15;
elf_info.e_shstrndx = elf_info.e_shnum - 1;
elf_info.e_phoff = elf_info.e_ehsize;
u32 section_offset = AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
u32 section_offset = align(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
static const u32 sceStub_text_block = 8 * 4;
@ -1143,7 +1143,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sceStub_text;
memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr));
s_sceStub_text.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_sceStub_text.sh_addralign);
section_offset = align(section_offset, s_sceStub_text.sh_addralign);
s_sceStub_text.sh_type = 1;
s_sceStub_text.sh_offset = section_offset;
s_sceStub_text.sh_addr = section_offset + 0x10000;
@ -1167,7 +1167,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_stub_top;
memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr));
s_lib_stub_top.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_lib_stub_top.sh_addralign);
section_offset = align(section_offset, s_lib_stub_top.sh_addralign);
s_lib_stub_top.sh_type = 1;
s_lib_stub_top.sh_name = section_name_offset;
s_lib_stub_top.sh_offset = section_offset;
@ -1186,7 +1186,7 @@ void CompilePPUProgram::Compile()
s_lib_stub.sh_offset = section_offset;
s_lib_stub.sh_addr = section_offset + 0x10000;
s_lib_stub.sh_flags = 2;
s_lib_stub.sh_size = sizeof(Elf64_StubHeader) * modules.size();
s_lib_stub.sh_size = sizeof(sys_stub) * modules.size();
sections_names.push_back(".lib.stub");
section_name_offset += std::string(".lib.stub").length() + 1;
section_offset += s_lib_stub.sh_size;
@ -1207,7 +1207,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceFNID;
memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr));
s_rodata_sceFNID.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign);
section_offset = align(section_offset, s_rodata_sceFNID.sh_addralign);
s_rodata_sceFNID.sh_type = 1;
s_rodata_sceFNID.sh_name = section_name_offset;
s_rodata_sceFNID.sh_offset = section_offset;
@ -1221,7 +1221,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceResident;
memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr));
s_rodata_sceResident.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_rodata_sceResident.sh_addralign);
section_offset = align(section_offset, s_rodata_sceResident.sh_addralign);
s_rodata_sceResident.sh_type = 1;
s_rodata_sceResident.sh_name = section_name_offset;
s_rodata_sceResident.sh_offset = section_offset;
@ -1232,7 +1232,7 @@ void CompilePPUProgram::Compile()
{
s_rodata_sceResident.sh_size += module.m_name.length() + 1;
}
s_rodata_sceResident.sh_size = AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
s_rodata_sceResident.sh_size = align(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
sections_names.push_back(".rodata.sceResident");
section_name_offset += std::string(".rodata.sceResident").length() + 1;
section_offset += s_rodata_sceResident.sh_size;
@ -1240,7 +1240,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_ent_top;
memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr));
s_lib_ent_top.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_lib_ent_top.sh_addralign);
section_offset = align(section_offset, s_lib_ent_top.sh_addralign);
s_lib_ent_top.sh_size = 4;
s_lib_ent_top.sh_flags = 2;
s_lib_ent_top.sh_type = 1;
@ -1267,7 +1267,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sys_proc_prx_param;
memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr));
s_sys_proc_prx_param.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign);
section_offset = align(section_offset, s_sys_proc_prx_param.sh_addralign);
s_sys_proc_prx_param.sh_type = 1;
s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param);
s_sys_proc_prx_param.sh_name = section_name_offset;
@ -1280,14 +1280,14 @@ void CompilePPUProgram::Compile()
const u32 prog_load_0_end = section_offset;
section_offset = AlignAddr(section_offset + 0x10000, 0x10000);
section_offset = align(section_offset + 0x10000, 0x10000);
const u32 prog_load_1_start = section_offset;
Elf64_Shdr s_data_sceFStub;
memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr));
s_data_sceFStub.sh_name = section_name_offset;
s_data_sceFStub.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_data_sceFStub.sh_addralign);
section_offset = align(section_offset, s_data_sceFStub.sh_addralign);
s_data_sceFStub.sh_flags = 3;
s_data_sceFStub.sh_type = 1;
s_data_sceFStub.sh_offset = section_offset;
@ -1300,7 +1300,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_tbss;
memset(&s_tbss, 0, sizeof(Elf64_Shdr));
s_tbss.sh_addralign = 4;
section_offset = AlignAddr(section_offset, s_tbss.sh_addralign);
section_offset = align(section_offset, s_tbss.sh_addralign);
s_tbss.sh_size = 4;
s_tbss.sh_flags = 0x403;
s_tbss.sh_type = 8;
@ -1314,7 +1314,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_opd;
memset(&s_opd, 0, sizeof(Elf64_Shdr));
s_opd.sh_addralign = 8;
section_offset = AlignAddr(section_offset, s_opd.sh_addralign);
section_offset = align(section_offset, s_opd.sh_addralign);
s_opd.sh_size = 2*4;
s_opd.sh_type = 1;
s_opd.sh_offset = section_offset;
@ -1475,7 +1475,7 @@ void CompilePPUProgram::Compile()
if(!m_file_path.empty() && !m_analyze && !m_error)
{
s_opd.sh_size = AlignAddr(s_opd.sh_size, s_opd.sh_addralign);
s_opd.sh_size = align(s_opd.sh_size, s_opd.sh_addralign);
section_offset += s_opd.sh_size;
const u32 prog_load_1_end = section_offset;
@ -1483,7 +1483,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_shstrtab;
memset(&s_shstrtab, 0, sizeof(Elf64_Shdr));
s_shstrtab.sh_addralign = 1;
section_offset = AlignAddr(section_offset, s_shstrtab.sh_addralign);
section_offset = align(section_offset, s_shstrtab.sh_addralign);
s_shstrtab.sh_name = section_name_offset;
s_shstrtab.sh_type = 3;
s_shstrtab.sh_offset = section_offset;
@ -1505,7 +1505,7 @@ void CompilePPUProgram::Compile()
elf_info.e_machine = MACHINE_PPC64; //PowerPC64
elf_info.e_version = 1; //ver 1
elf_info.e_flags = 0x0;
elf_info.e_shoff = AlignAddr(section_offset, 4);
elf_info.e_shoff = align(section_offset, 4);
u8* opd_data = new u8[s_opd.sh_size];
u32 entry_point = s_text.sh_addr;
@ -1523,14 +1523,14 @@ void CompilePPUProgram::Compile()
sys_proc_prx_param prx_param;
memset(&prx_param, 0, sizeof(sys_proc_prx_param));
prx_param.size = re32(0x40);
prx_param.magic = re32(0x1b434cec);
prx_param.version = re32(0x4);
prx_param.libentstart = re32(s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size);
prx_param.libentend = re32(s_lib_ent_btm.sh_addr);
prx_param.libstubstart = re32(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size);
prx_param.libstubend = re32(s_lib_stub_btm.sh_addr);
prx_param.ver = re16(0x101);
prx_param.size = 0x40;
prx_param.magic = 0x1b434cec;
prx_param.version = 0x4;
prx_param.libentstart = s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size;
prx_param.libentend = s_lib_ent_btm.sh_addr;
prx_param.libstubstart = vm::bptr<sys_stub>::make(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size);
prx_param.libstubend = vm::bptr<sys_stub>::make(s_lib_stub_btm.sh_addr);
prx_param.ver = 0x101;
elf_info.e_entry = s_opd.sh_addr;
@ -1588,20 +1588,20 @@ void CompilePPUProgram::Compile()
f.Seek(s_lib_stub.sh_offset);
for(u32 i=0, nameoffs=4, dataoffs=0; i<modules.size(); ++i)
{
Elf64_StubHeader stub;
memset(&stub, 0, sizeof(Elf64_StubHeader));
sys_stub stub;
memset(&stub, 0, sizeof(sys_stub));
stub.s_size = 0x2c;
stub.s_version = re16(0x1);
stub.s_unk1 = re16(0x9);
stub.s_modulename = re32(s_rodata_sceResident.sh_addr + nameoffs);
stub.s_nid = re32(s_rodata_sceFNID.sh_addr + dataoffs);
stub.s_text = re32(s_data_sceFStub.sh_addr + dataoffs);
stub.s_imports = re16(modules[i].m_imports.size());
stub.s_modulename = vm::bptr<const char>::make(s_rodata_sceResident.sh_addr + nameoffs);
stub.s_nid = vm::bptr<u32>::make(s_rodata_sceFNID.sh_addr + dataoffs);
stub.s_text = vm::bptr<u32>::make(s_data_sceFStub.sh_addr + dataoffs);
stub.s_imports = modules[i].m_imports.size();
dataoffs += modules[i].m_imports.size() * 4;
f.Write(&stub, sizeof(Elf64_StubHeader));
f.Write(&stub, sizeof(sys_stub));
nameoffs += modules[i].m_name.length() + 1;
}
@ -1732,3 +1732,4 @@ void CompilePPUProgram::Compile()
system("make_fself.cmd");
}
}
*/

View File

@ -1,7 +1,7 @@
#pragma once
#include "PPUInstrTable.h"
#include "Loader/ELF64.h"
/*
enum ArgType
{
ARG_ERR = 0,
@ -189,3 +189,4 @@ protected:
public:
void Compile();
};
*/

View File

@ -10,6 +10,8 @@
#include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPULLVMRecompiler.h"
//#include "Emu/Cell/PPURecompiler.h"
#include "Emu/CPU/CPUThreadManager.h"
PPUThread& GetCurrentPPUThread()
{
@ -39,11 +41,11 @@ void PPUThread::DoReset()
memset(FPR, 0, sizeof(FPR));
memset(GPR, 0, sizeof(GPR));
memset(SPRG, 0, sizeof(SPRG));
memset(USPRG, 0, sizeof(USPRG));
CR.CR = 0;
LR = 0;
CTR = 0;
USPRG0 = 0;
TB = 0;
XER.XER = 0;
FPSCR.FPSCR = 0;
@ -84,8 +86,10 @@ void PPUThread::InitRegs()
}
*/
GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200;
GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200;
GPR[2] = rtoc;
//GPR[11] = entry;
//GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
LR = Emu.GetPPUThreadExit();
@ -122,6 +126,8 @@ void PPUThread::DoRun()
#endif
break;
//case 3: m_dec = new PPURecompiler(*this); break;
default:
LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
Emu.Pause();
@ -218,12 +224,68 @@ void PPUThread::FastStop()
void PPUThread::Task()
{
if (m_custom_task)
if (custom_task)
{
m_custom_task(*this);
custom_task(*this);
}
else
{
CPUThread::Task();
}
}
ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}
cpu_thread& ppu_thread::args(std::initializer_list<std::string> values)
{
if (!values.size())
return *this;
assert(argc == 0);
envp.set(vm::alloc(align((u32)sizeof(*envp), stack_align), vm::main));
*envp = 0;
argv.set(vm::alloc(sizeof(*argv) * values.size(), vm::main));
for (auto &arg : values)
{
u32 arg_size = align(u32(arg.size() + 1), stack_align);
u32 arg_addr = vm::alloc(arg_size, vm::main);
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
argv[argc++] = arg_addr;
}
return *this;
}
cpu_thread& ppu_thread::run()
{
thread->Run();
gpr(3, argc);
gpr(4, argv.addr());
gpr(5, envp.addr());
return *this;
}
ppu_thread& ppu_thread::gpr(uint index, u64 value)
{
assert(index < 32);
static_cast<PPUThread*>(thread)->GPR[index] = value;
return *this;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "Emu/Cell/PPCThread.h"
#include "Emu/Memory/vm.h"
enum
{
@ -530,11 +531,8 @@ public:
u64 LR; //SPR 0x008 : Link Register
u64 CTR; //SPR 0x009 : Count Register
union
{
u64 USPRG0; //SPR 0x100 : User-SPR General-Purpose Register 0
u64 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers
};
u64 USPRG[8]; //SPR 0x100 - 0x107: User-SPR General-Purpose Registers
u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers
//TBR : Time-Base Registers
union
@ -554,7 +552,7 @@ public:
u64 R_VALUE; // reservation value (BE)
u32 owned_mutexes;
std::function<void(PPUThread& CPU)> m_custom_task;
std::function<void(PPUThread& CPU)> custom_task;
public:
PPUThread();
@ -799,3 +797,18 @@ protected:
};
PPUThread& GetCurrentPPUThread();
class ppu_thread : cpu_thread
{
static const u32 stack_align = 0x10;
vm::ptr<u64> argv;
u32 argc;
vm::ptr<u64> envp;
public:
ppu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
cpu_thread& args(std::initializer_list<std::string> values) override;
cpu_thread& run() override;
ppu_thread& gpr(uint index, u64 value);
};

View File

@ -1163,7 +1163,6 @@ void SPUThread::StopAndSignal(u32 code)
}
default:
{
if (!SPU.Out_MBox.GetCount())
{
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
@ -1175,5 +1174,16 @@ void SPUThread::StopAndSignal(u32 code)
Emu.Pause();
break;
}
}
}
spu_thread::spu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_SPU);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}

View File

@ -583,3 +583,49 @@ protected:
};
SPUThread& GetCurrentSPUThread();
class spu_thread : cpu_thread
{
static const u32 stack_align = 0x10;
vm::ptr<u64> argv;
u32 argc;
vm::ptr<u64> envp;
public:
spu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
cpu_thread& args(std::initializer_list<std::string> values) override
{
if (!values.size())
return *this;
assert(argc == 0);
envp.set(Memory.MainMem.AllocAlign((u32)sizeof(envp), stack_align));
*envp = 0;
argv.set(Memory.MainMem.AllocAlign(u32(sizeof(argv)* values.size()), stack_align));
for (auto &arg : values)
{
u32 arg_size = align(u32(arg.size() + 1), stack_align);
u32 arg_addr = Memory.MainMem.AllocAlign(arg_size, stack_align);
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
argv[argc++] = arg_addr;
}
return *this;
}
cpu_thread& run() override
{
thread->Run();
static_cast<SPUThread*>(thread)->GPR[3].from64(argc);
static_cast<SPUThread*>(thread)->GPR[4].from64(argv.addr());
static_cast<SPUThread*>(thread)->GPR[5].from64(envp.addr());
return *this;
}
};

View File

@ -108,9 +108,9 @@ void MemoryBase::Init(MemoryType type)
memset(RawSPUMem, 0, sizeof(RawSPUMem));
#ifdef _WIN32
if (!g_base_addr)
if (!vm::g_base_addr)
#else
if ((s64)g_base_addr == (s64)-1)
if ((s64)vm::g_base_addr == (s64)-1)
#endif
{
LOG_ERROR(MEMORY, "Initializing memory failed");
@ -119,7 +119,7 @@ void MemoryBase::Init(MemoryType type)
}
else
{
LOG_NOTICE(MEMORY, "Initializing memory: m_base_addr = 0x%llx", (u64)g_base_addr);
LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr);
}
switch (type)
@ -128,6 +128,8 @@ void MemoryBase::Init(MemoryType type)
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(SPRXMem.SetRange(0x50000000, 0x10000000));
MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
break;
@ -217,6 +219,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
}
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size);
return true;
}
@ -412,12 +415,6 @@ void DynamicMemoryBlockBase::Delete()
bool DynamicMemoryBlockBase::AllocFixed(u64 addr, u32 size)
{
if (!MemoryBlock::GetStartAddr())
{
LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocFixed(addr=0x%llx, size=0x%x): memory block not initialized", addr, size);
return false;
}
size = PAGE_4K(size + (addr & 4095)); // align size
addr &= ~4095; // align start address
@ -452,7 +449,7 @@ u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align)
LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align);
return 0;
}
size = PAGE_4K(size);
u32 exsize;
@ -579,9 +576,9 @@ bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size)
bool VirtualMemoryBlock::IsMyAddress(const u64 addr)
{
for(u32 i=0; i<m_mapped_memory.size(); ++i)
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if(addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
{
return true;
}
@ -620,7 +617,7 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size)
bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
{
if(!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1)))
if (!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1)))
return false;
m_mapped_memory.emplace_back(addr, realaddr, size);
@ -629,9 +626,9 @@ bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr, u32& size)
{
for(u32 i=0; i<m_mapped_memory.size(); ++i)
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if(m_mapped_memory[i].realAddress == realaddr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
if (m_mapped_memory[i].realAddress == realaddr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
{
size = m_mapped_memory[i].size;
m_mapped_memory.erase(m_mapped_memory.begin() + i);
@ -644,9 +641,9 @@ bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr, u32& size)
bool VirtualMemoryBlock::UnmapAddress(u64 addr, u32& size)
{
for(u32 i=0; i<m_mapped_memory.size(); ++i)
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if(m_mapped_memory[i].addr == addr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
if (m_mapped_memory[i].addr == addr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
{
size = m_mapped_memory[i].size;
m_mapped_memory.erase(m_mapped_memory.begin() + i);
@ -669,7 +666,7 @@ bool VirtualMemoryBlock::Read32(const u64 addr, u32* value)
bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
{
u64 realAddr;
if(!getRealAddr(addr, realAddr))
if (!getRealAddr(addr, realAddr))
return false;
vm::write32(realAddr, value);
return true;
@ -677,9 +674,9 @@ bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result)
{
for(u32 i=0; i<m_mapped_memory.size(); ++i)
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if(addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
{
result = m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr);
return true;
@ -691,9 +688,9 @@ bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result)
u64 VirtualMemoryBlock::getMappedAddress(u64 realAddress)
{
for(u32 i=0; i<m_mapped_memory.size(); ++i)
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if(realAddress >= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size)
if (realAddress >= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size)
{
return m_mapped_memory[i].addr + (realAddress - m_mapped_memory[i].realAddress);
}
@ -711,7 +708,7 @@ void VirtualMemoryBlock::Delete()
bool VirtualMemoryBlock::Reserve(u32 size)
{
if(size + GetReservedAmount() > GetEndAddr() - GetStartAddr())
if (size + GetReservedAmount() > GetEndAddr() - GetStartAddr())
return false;
m_reserve_size += size;
@ -720,7 +717,7 @@ bool VirtualMemoryBlock::Reserve(u32 size)
bool VirtualMemoryBlock::Unreserve(u32 size)
{
if(size > GetReservedAmount())
if (size > GetReservedAmount())
return false;
m_reserve_size -= size;
@ -730,4 +727,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size)
u32 VirtualMemoryBlock::GetReservedAmount()
{
return m_reserve_size;
}
}

View File

@ -7,8 +7,6 @@ using std::nullptr_t;
#define safe_delete(x) do {delete (x);(x)=nullptr;} while(0)
#define safe_free(x) do {free(x);(x)=nullptr;} while(0)
extern void* const g_base_addr;
enum MemoryType
{
Memory_PS3,
@ -24,6 +22,11 @@ enum : u32
RAW_SPU_PROB_OFFSET = 0x00040000,
};
namespace vm
{
extern void* const g_base_addr;
}
class MemoryBase
{
std::vector<MemoryBlock*> MemoryBlocks;
@ -33,8 +36,10 @@ public:
MemoryBlock* UserMemory;
DynamicMemoryBlock MainMem;
DynamicMemoryBlock SPRXMem;
DynamicMemoryBlock PRXMem;
DynamicMemoryBlock RSXCMDMem;
DynamicMemoryBlock MmaperMem;
DynamicMemoryBlock RSXFBMem;
DynamicMemoryBlock StackMem;
MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET];
@ -69,7 +74,7 @@ public:
static void* const GetBaseAddr()
{
return g_base_addr;
return vm::g_base_addr;
}
__noinline void InvalidAddress(const char* func, const u64 addr);

View File

@ -1,23 +1,22 @@
#include "stdafx.h"
#include "Memory.h"
#ifdef _WIN32
#include <Windows.h>
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
#else
#include <sys/mman.h>
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
void* const g_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
namespace vm
{
#ifdef _WIN32
#include <Windows.h>
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
#else
#include <sys/mman.h>
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
bool check_addr(u32 addr)
{
// Checking address before using it is unsafe.
@ -28,20 +27,120 @@ namespace vm
//TODO
bool map(u32 addr, u32 size, u32 flags)
{
return false;
return Memory.Map(addr, size);
}
bool unmap(u32 addr, u32 size, u32 flags)
{
return false;
return Memory.Unmap(addr);
}
u32 alloc(u32 size)
u32 alloc(u32 addr, u32 size, memory_location location)
{
return 0;
return g_locations[location].fixed_allocator(addr, size);
}
void unalloc(u32 addr)
u32 alloc(u32 size, memory_location location)
{
return g_locations[location].allocator(size);
}
void dealloc(u32 addr, memory_location location)
{
return g_locations[location].deallocator(addr);
}
namespace ps3
{
u32 main_alloc(u32 size)
{
return Memory.MainMem.AllocAlign(size, 1);
}
u32 main_fixed_alloc(u32 addr, u32 size)
{
return Memory.MainMem.AllocFixed(addr, size) ? addr : 0;
}
void main_dealloc(u32 addr)
{
Memory.MainMem.Free(addr);
}
u32 g_stack_offset = 0;
u32 stack_alloc(u32 size)
{
return Memory.StackMem.AllocAlign(size, 0x10);
}
u32 stack_fixed_alloc(u32 addr, u32 size)
{
return Memory.StackMem.AllocFixed(addr, size) ? addr : 0;
}
void stack_dealloc(u32 addr)
{
Memory.StackMem.Free(addr);
}
u32 sprx_alloc(u32 size)
{
return Memory.SPRXMem.AllocAlign(size, 1);
}
u32 sprx_fixed_alloc(u32 addr, u32 size)
{
return Memory.SPRXMem.AllocFixed(Memory.SPRXMem.GetStartAddr() + addr, size) ? Memory.SPRXMem.GetStartAddr() + addr : 0;
}
void sprx_dealloc(u32 addr)
{
Memory.SPRXMem.Free(addr);
}
u32 user_space_alloc(u32 size)
{
return Memory.PRXMem.AllocAlign(size, 1);
}
u32 user_space_fixed_alloc(u32 addr, u32 size)
{
return Memory.PRXMem.AllocFixed(addr, size) ? addr : 0;
}
void user_space_dealloc(u32 addr)
{
Memory.PRXMem.Free(addr);
}
void init()
{
Memory.Init(Memory_PS3);
}
}
namespace psv
{
void init()
{
Memory.Init(Memory_PSV);
}
}
namespace psp
{
void init()
{
Memory.Init(Memory_PSP);
}
}
location_info g_locations[memory_location_count] =
{
{ 0x00010000, 0x2FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc },
{ 0xD0000000, 0x10000000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc },
//remove me
{ 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc },
{ 0x30000000, 0x10000000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc },
};
void close()
{
Memory.Close();
}
}

View File

@ -1,18 +1,37 @@
#pragma once
#include "Memory.h"
namespace vm
{
enum memory_location : uint
{
main,
stack,
//remove me
sprx,
user_space,
memory_location_count
};
static void set_stack_size(u32 size) {}
static void initialize_stack() {}
extern void* const g_base_addr;
bool map(u32 addr, u32 size, u32 flags);
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
u32 alloc(u32 size);
void unalloc(u32 addr);
u32 alloc(u32 size, memory_location location = user_space);
u32 alloc(u32 addr, u32 size, memory_location location = user_space);
void dealloc(u32 addr, memory_location location = user_space);
template<typename T>
template<typename T = void>
T* const get_ptr(u32 addr)
{
return (T*)((u8*)g_base_addr + addr);
}
template<typename T>
T& get_ref(u32 addr)
{
@ -21,6 +40,8 @@ namespace vm
namespace ps3
{
void init();
static u8 read8(u32 addr)
{
return *((u8*)g_base_addr + addr);
@ -36,9 +57,9 @@ namespace vm
return re16(*(u16*)((u8*)g_base_addr + addr));
}
static void write16(u32 addr, u16 value)
static void write16(u32 addr, be_t<u16> value)
{
*(u16*)((u8*)g_base_addr + addr) = re16(value);
*(be_t<u16>*)((u8*)g_base_addr + addr) = value;
}
static u32 read32(u32 addr)
@ -53,11 +74,11 @@ namespace vm
}
}
static void write32(u32 addr, u32 value)
static void write32(u32 addr, be_t<u32> value)
{
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
{
*(u32*)((u8*)g_base_addr + addr) = re32(value);
*(be_t<u32>*)((u8*)g_base_addr + addr) = value;
}
else
{
@ -70,9 +91,24 @@ namespace vm
return re64(*(u64*)((u8*)g_base_addr + addr));
}
static void write64(u32 addr, be_t<u64> value)
{
*(be_t<u64>*)((u8*)g_base_addr + addr) = value;
}
static void write16(u32 addr, u16 value)
{
write16(addr, be_t<u16>::make(value));
}
static void write32(u32 addr, u32 value)
{
write32(addr, be_t<u32>::make(value));
}
static void write64(u32 addr, u64 value)
{
*(u64*)((u8*)g_base_addr + addr) = re64(value);
write64(addr, be_t<u64>::make(value));
}
static u128 read128(u32 addr)
@ -88,6 +124,8 @@ namespace vm
namespace psv
{
void init();
static u8 read8(u32 addr)
{
return *((u8*)g_base_addr + addr);
@ -138,8 +176,47 @@ namespace vm
*(u128*)((u8*)g_base_addr + addr) = value;
}
}
namespace psp
{
using namespace psv;
void init();
}
void close();
}
#include "vm_ref.h"
#include "vm_ptr.h"
#include "vm_var.h"
namespace vm
{
struct location_info
{
u32 addr_offset;
u32 size;
u32(*allocator)(u32 size);
u32(*fixed_allocator)(u32 addr, u32 size);
void(*deallocator)(u32 addr);
u32 alloc_offset;
template<typename T = char>
ptr<T> alloc(u32 count) const
{
return ptr<T>::make(allocator(count * sizeof(T)));
}
};
extern location_info g_locations[memory_location_count];
template<memory_location location = main>
location_info& get()
{
assert(location < memory_location_count);
return g_locations[location];
}
}

View File

@ -10,7 +10,7 @@ namespace vm
AT m_addr;
public:
typedef T type;
typedef typename std::remove_cv<T>::type type;
_ptr_base operator++ (int)
{
@ -38,49 +38,49 @@ namespace vm
return *this;
}
_ptr_base& operator += (int count)
_ptr_base& operator += (AT count)
{
m_addr += count * sizeof(AT);
return *this;
}
_ptr_base& operator -= (int count)
_ptr_base& operator -= (AT count)
{
m_addr -= count * sizeof(AT);
return *this;
}
_ptr_base operator + (int count) const
{
return make(m_addr + count * sizeof(AT));
}
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
_ptr_base operator - (int count) const
{
return make(m_addr - count * sizeof(AT));
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator *() const
{
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr);
}
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator [](int index) const
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator [](AT index) const
{
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr + sizeof(AT)* index);
}
operator bool() const
{
return m_addr != 0;
}
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<T, lvl, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<T, lvl, AT2>&)addr;
}
@ -108,6 +108,8 @@ namespace vm
AT m_addr;
public:
typedef typename std::remove_cv<T>::type type;
__forceinline T* const operator -> () const
{
return vm::get_ptr<T>(m_addr);
@ -139,38 +141,49 @@ namespace vm
return *this;
}
_ptr_base& operator += (int count)
_ptr_base& operator += (AT count)
{
m_addr += count * sizeof(T);
return *this;
}
_ptr_base& operator -= (int count)
_ptr_base& operator -= (AT count)
{
m_addr -= count * sizeof(T);
return *this;
}
_ptr_base operator + (int count) const
{
return make(m_addr + count * sizeof(T));
}
_ptr_base operator - (int count) const
{
return make(m_addr - count * sizeof(T));
}
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
__forceinline T& operator *() const
{
return get_ref<T>(m_addr);
return vm::get_ref<T>(m_addr);
}
__forceinline T& operator [](int index) const
__forceinline T& operator [](typename remove_be_t<AT>::type index) const
{
return get_ref<T>(m_addr + sizeof(T) * index);
return vm::get_ref<T>(m_addr + sizeof(T)* index);
}
__forceinline T& operator [](typename to_be_t<AT>::forced_type index) const
{
return vm::get_ref<T>(m_addr + sizeof(T)* index);
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
explicit operator T*() const { return get_ptr(); }
/*
operator _ref_base<T, AT>()
{
@ -188,26 +201,28 @@ namespace vm
return m_addr;
}
void set(const AT value)
template<typename U>
void set(U&& value)
{
m_addr = value;
m_addr = convert_le_be<AT>(value);
}
operator bool() const
/*
operator T*() const
{
return m_addr != 0;
return get_ptr();
}
*/
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<T, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<T, 1, AT2>&)addr;
}
T* const get_ptr() const
T* get_ptr() const
{
return vm::get_ptr<T>(m_addr);
}
@ -236,29 +251,39 @@ namespace vm
m_addr = value;
}
void* const get_ptr() const
void* get_ptr() const
{
return vm::get_ptr<void>(m_addr);
}
operator bool() const
explicit operator void*() const
{
return m_addr != 0;
return get_ptr();
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<void, 1, AT2>&)addr;
}
template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<const void, 1, AT2>&)addr;
}
@ -286,22 +311,32 @@ namespace vm
m_addr = value;
}
const void* const get_ptr() const
const void* get_ptr() const
{
return vm::get_ptr<const void>(m_addr);
}
operator bool() const
explicit operator const void*() const
{
return m_addr != 0;
return get_ptr();
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<const void, 1, AT2>&)addr;
}
@ -335,17 +370,22 @@ namespace vm
m_addr = value;
}
operator bool() const
{
return m_addr != 0;
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<RT(*)(T...), 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<RT(*)(T...), 1, AT2>&)addr;
}
@ -356,7 +396,7 @@ namespace vm
operator const std::function<RT(T...)>() const
{
typename std::remove_const<AT>::type addr; addr = m_addr;
typename std::remove_const<AT>::type addr = convert_le_be<AT>(m_addr);
return [addr](T... args) -> RT { return make(addr)(args...); };
}
@ -366,7 +406,7 @@ namespace vm
//BE pointer to LE data
template<typename T, int lvl = 1, typename AT = u32> struct bptrl : public _ptr_base<T, lvl, typename to_be_t<AT>::type>
{
static bptrl make(typename to_be_t<AT>::type addr)
static bptrl make(AT addr)
{
return (bptrl&)addr;
}
@ -378,7 +418,7 @@ namespace vm
//BE pointer to BE data
template<typename T, int lvl = 1, typename AT = u32> struct bptrb : public _ptr_base<typename to_be_t<T>::type, lvl, typename to_be_t<AT>::type>
{
static bptrb make(typename to_be_t<AT>::type addr)
static bptrb make(AT addr)
{
return (bptrb&)addr;
}
@ -413,7 +453,7 @@ namespace vm
namespace ps3
{
//default pointer for HLE functions (LE ptrerence to BE data)
//default pointer for HLE functions (LE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrb<T, lvl, AT>
{
static ptr make(AT addr)
@ -425,10 +465,10 @@ namespace vm
//using lptrb<T, lvl, AT>::operator const _ptr_base<typename to_be_t<T>::type, lvl, AT>;
};
//default pointer for HLE structures (BE ptrerence to BE data)
//default pointer for HLE structures (BE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> struct bptr : public bptrb<T, lvl, AT>
{
static bptr make(typename to_be_t<AT>::type addr)
static bptr make(AT addr)
{
return (bptr&)addr;
}
@ -440,7 +480,7 @@ namespace vm
namespace psv
{
//default pointer for HLE functions & structures (LE ptrerence to LE data)
//default pointer for HLE functions & structures (LE pointer to LE data)
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrl<T, lvl, AT>
{
static ptr make(AT addr)

View File

@ -10,6 +10,8 @@ class ModuleManager
std::vector<ModuleFunc *> m_modules_funcs_list;
std::vector<Module> m_mod_init; //owner of Module
bool initialized;
std::unordered_map<u32, u32> m_registered_functions;
public:
ModuleManager();
~ModuleManager();
@ -24,4 +26,20 @@ public:
u32 GetFuncNumById(u32 id);
Module* GetModuleByName(const std::string& name);
Module* GetModuleById(u16 id);
void register_function(u32 fnid, u32 fstub)
{
m_registered_functions[fnid] = fstub;
}
bool get_function_stub(u32 fnid, be_t<u32>& res)
{
auto f = m_registered_functions.find(fnid);
if (f == m_registered_functions.end())
return false;
res = f->second;
return true;
}
};

View File

@ -179,7 +179,7 @@ void fix_import(Module* module, u32 func, u32 addr)
vm::ptr<u32>& ptr = (vm::ptr<u32>&)addr;
*ptr++ = LIS(11, func >> 16);
*ptr++ = ADDIS(11, 0, func >> 16);
*ptr++ = ORI(11, 11, func & 0xffff);
*ptr++ = NOP();
++ptr;

View File

@ -16,15 +16,16 @@ int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr<float> screenSize)
{
cellAvconfExt->Warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize_addr=0x%x)", videoOut, screenSize.addr());
if (videoOut != CELL_VIDEO_OUT_PRIMARY)
if (!videoOut == CELL_VIDEO_OUT_PRIMARY)
return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT;
//TODO: Use virtual screen size
#ifdef _WIN32
HDC screen = GetDC(NULL);
float diagonal = roundf(sqrtf((powf(GetDeviceCaps(screen, HORZSIZE), 2) + powf(GetDeviceCaps(screen, VERTSIZE), 2))) * 0.0393);
float diagonal = round(sqrt((pow(GetDeviceCaps(screen, HORZSIZE), 2) + pow(GetDeviceCaps(screen, VERTSIZE), 2))) * 0.0393);
#else
// TODO: Linux implementation, without using wx
// float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393);
// float diagonal = round(sqrt((pow(wxGetDisplaySizeMM().GetWidth(), 2) + pow(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393);
#endif
if (Ini.GS3DTV.GetValue())

View File

@ -900,7 +900,7 @@ int cellDmuxEnableEs(u32 demuxerHandle, vm::ptr<const CellCodecEsFilterId> esFil
*esHandle = id;
cellDmux->Warning("*** New ES(dmux=%d, addr=0x%x, size=0x%x, filter(0x%x, 0x%x, 0x%x, 0x%x), cb=0x%x(arg=0x%x), spec=0x%x): id = %d",
demuxerHandle, es->memAddr, es->memSize, es->fidMajor, es->fidMinor, es->sup1, es->sup2, (u32)esCb->cbEsMsgFunc, es->cbArg, es->spec, id);
demuxerHandle, es->memAddr, es->memSize, es->fidMajor, es->fidMinor, es->sup1, es->sup2, esCb->cbEsMsgFunc.addr(), es->cbArg, es->spec, id);
DemuxerTask task(dmuxEnableEs);
task.es.es = id;

View File

@ -180,6 +180,12 @@ int cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm:
{
cellGame->Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)",
contentInfoPath.addr(), usrdirPath.addr());
if (!contentInfoPath && !usrdirPath)
{
cellGame->Warning("cellGameContentPermit(): CELL_GAME_ERROR_PARAM");
return CELL_GAME_ERROR_PARAM;
}
if (contentInfo == "" && usrdir == "")
{

View File

@ -77,16 +77,14 @@ int pamfStreamTypeToEsFilterId(u8 type, u8 ch, vm::ptr<CellCodecEsFilterId> pEsF
u8 pamfGetStreamType(vm::ptr<CellPamfReader> pSelf, u8 stream)
{
//TODO: get stream type correctly
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
switch (pAddr->stream_headers[stream].type)
switch (pSelf->pAddr->stream_headers[stream].type)
{
case 0x1b: return CELL_PAMF_STREAM_TYPE_AVC;
case 0xdc: return CELL_PAMF_STREAM_TYPE_ATRAC3PLUS;
case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM;
case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA;
default:
cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pAddr->stream_headers[stream].type);
cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type);
return 0;
}
}
@ -94,18 +92,18 @@ u8 pamfGetStreamType(vm::ptr<CellPamfReader> pSelf, u8 stream)
u8 pamfGetStreamChannel(vm::ptr<CellPamfReader> pSelf, u8 stream)
{
//TODO: get stream channel correctly
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
switch (pAddr->stream_headers[stream].type)
switch (pSelf->pAddr->stream_headers[stream].type)
{
case 0x1b:
if ((pAddr->stream_headers[stream].stream_id >= 0xe0) && (pAddr->stream_headers[stream].stream_id <= 0xef))
if ((pSelf->pAddr->stream_headers[stream].stream_id >= 0xe0) && (pSelf->pAddr->stream_headers[stream].stream_id <= 0xef))
{
return pAddr->stream_headers[stream].stream_id - 0xe0;
return pSelf->pAddr->stream_headers[stream].stream_id - 0xe0;
}
else
{
cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x", pAddr->stream_headers[stream].type, pAddr->stream_headers[stream].stream_id);
cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x",
pSelf->pAddr->stream_headers[stream].type, pSelf->pAddr->stream_headers[stream].stream_id);
return 0;
}
case 0xdc:
@ -118,7 +116,7 @@ u8 pamfGetStreamChannel(vm::ptr<CellPamfReader> pSelf, u8 stream)
cellPamf->Todo("pamfGetStreamChannel: CELL_PAMF_STREAM_TYPE_USER_DATA");
return 0;
default:
cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pAddr->stream_headers[stream].type);
cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type);
return 0;
}
@ -200,10 +198,8 @@ int cellPamfReaderGetPresentationStartTime(vm::ptr<CellPamfReader> pSelf, vm::pt
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
const u32 upper = (u16)pAddr->start_pts_high;
pTimeStamp->upper = upper;
pTimeStamp->lower = pAddr->start_pts_low;
pTimeStamp->upper = (u32)(u16)pSelf->pAddr->start_pts_high;
pTimeStamp->lower = pSelf->pAddr->start_pts_low;
return CELL_OK;
}
@ -215,10 +211,8 @@ int cellPamfReaderGetPresentationEndTime(vm::ptr<CellPamfReader> pSelf, vm::ptr<
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
const u32 upper = (u16)pAddr->end_pts_high;
pTimeStamp->upper = upper;
pTimeStamp->lower = pAddr->end_pts_low;
pTimeStamp->upper = (u32)(u16)pSelf->pAddr->end_pts_high;
pTimeStamp->lower = pSelf->pAddr->end_pts_low;
return CELL_OK;
}
@ -230,8 +224,7 @@ int cellPamfReaderGetMuxRateBound(vm::ptr<CellPamfReader> pSelf)
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
return pAddr->mux_rate_max;
return pSelf->pAddr->mux_rate_max;
}
int cellPamfReaderGetNumberOfStreams(vm::ptr<CellPamfReader> pSelf)
@ -242,8 +235,7 @@ int cellPamfReaderGetNumberOfStreams(vm::ptr<CellPamfReader> pSelf)
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
return pAddr->stream_count;
return pSelf->pAddr->stream_count;
}
int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr<CellPamfReader> pSelf, u8 streamType)
@ -254,11 +246,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr<CellPamfReader> pSelf, u8 s
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
int counts[6] = {0, 0, 0, 0, 0, 0};
for (u8 i = 0; i < pAddr->stream_count; i++)
for (u8 i = 0; i < pSelf->pAddr->stream_count; i++)
{
counts[pamfGetStreamType(pSelf, i)]++;
}
@ -289,18 +279,14 @@ int cellPamfReaderSetStreamWithIndex(vm::ptr<CellPamfReader> pSelf, u8 streamInd
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
if (streamIndex < pAddr->stream_count)
if (streamIndex < pSelf->pAddr->stream_count)
{
pSelf->stream = streamIndex;
return CELL_OK;
}
else
{
cellPamf->Error("cellPamfReaderSetStreamWithIndex: CELL_PAMF_ERROR_INVALID_ARG");
return CELL_PAMF_ERROR_INVALID_ARG;
}
cellPamf->Error("cellPamfReaderSetStreamWithIndex: CELL_PAMF_ERROR_INVALID_ARG");
return CELL_PAMF_ERROR_INVALID_ARG;
}
int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr<CellPamfReader> pSelf, u8 streamType, u8 ch)
@ -311,8 +297,6 @@ int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr<CellPamfReader> pSelf, u8
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
if (streamType > 5)
{
cellPamf->Error("cellPamfReaderSetStreamWithTypeAndChannel: invalid stream type(%d)", streamType);
@ -320,7 +304,7 @@ int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr<CellPamfReader> pSelf, u8
return CELL_PAMF_ERROR_INVALID_ARG;
}
for (u8 i = 0; i < pAddr->stream_count; i++)
for (u8 i = 0; i < pSelf->pAddr->stream_count; i++)
{
if (pamfGetStreamType(pSelf, i) == streamType)
{
@ -343,11 +327,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr<CellPamfReader> pSelf, u8 st
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
u32 found = 0;
for (u8 i = 0; i < pAddr->stream_count; i++)
for (u8 i = 0; i < pSelf->pAddr->stream_count; i++)
{
const u8 type = pamfGetStreamType(pSelf, i);
@ -426,8 +408,6 @@ int cellPamfReaderGetStreamInfo(vm::ptr<CellPamfReader> pSelf, u32 pInfo_addr, u
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
memset(vm::get_ptr<void>(pInfo_addr), 0, size);
switch (pamfGetStreamType(pSelf, pSelf->stream))
@ -486,7 +466,7 @@ int cellPamfReaderGetStreamInfo(vm::ptr<CellPamfReader> pSelf, u32 pInfo_addr, u
case CELL_PAMF_STREAM_TYPE_AC3:
{
auto pInfo = vm::ptr<CellPamfAc3Info>::make(pInfo_addr);
auto pAudio = vm::ptr<PamfStreamHeader_Audio>::make(pSelf->pAddr + 0x98 + pSelf->stream * 0x30);
auto pAudio = vm::ptr<PamfStreamHeader_Audio>::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30);
if (size != sizeof(CellPamfAc3Info))
{
@ -501,7 +481,7 @@ int cellPamfReaderGetStreamInfo(vm::ptr<CellPamfReader> pSelf, u32 pInfo_addr, u
case CELL_PAMF_STREAM_TYPE_PAMF_LPCM:
{
auto pInfo = vm::ptr<CellPamfLpcmInfo>::make(pInfo_addr);
auto pAudio = vm::ptr<PamfStreamHeader_Audio>::make(pSelf->pAddr + 0x98 + pSelf->stream * 0x30);
auto pAudio = vm::ptr<PamfStreamHeader_Audio>::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30);
if (size != sizeof(CellPamfLpcmInfo))
{
@ -537,8 +517,7 @@ int cellPamfReaderGetNumberOfEp(vm::ptr<CellPamfReader> pSelf)
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
return pAddr->stream_headers[pSelf->stream].ep_num;
return pSelf->pAddr->stream_headers[pSelf->stream].ep_num;
}
int cellPamfReaderGetEpIteratorWithIndex(vm::ptr<CellPamfReader> pSelf, u32 epIndex, vm::ptr<CellPamfEpIterator> pIt)
@ -549,7 +528,6 @@ int cellPamfReaderGetEpIteratorWithIndex(vm::ptr<CellPamfReader> pSelf, u32 epIn
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
//TODO:
return CELL_OK;
}
@ -562,8 +540,6 @@ int cellPamfReaderGetEpIteratorWithTimeStamp(vm::ptr<CellPamfReader> pSelf, vm::
return CELL_PAMF_ERROR_INVALID_PAMF;
}
vm::ptr<const PamfHeader> pAddr(pSelf->pAddr);
//TODO:
return CELL_OK;

View File

@ -1691,7 +1691,7 @@ s64 cellSpursGetWorkloadFlag(vm::ptr<CellSpurs> spurs, vm::ptr<vm::bptr<CellSpur
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
flag->set(be_t<u32>::make(Memory.RealToVirtualAddr(&spurs->m.wklFlag)));
flag->set(Memory.RealToVirtualAddr(&spurs->m.wklFlag));
return CELL_OK;
}

View File

@ -290,7 +290,7 @@ s32 syncRwmInitialize(vm::ptr<CellSyncRwm> rwm, vm::ptr<void> buffer, u32 buffer
}
// prx: zeroize first u16 and second u16, write buffer_size in second u32, write buffer_addr in second u64 and sync
rwm->m_size = buffer_size;
rwm->m_size = be_t<u32>::make(buffer_size);
rwm->m_buffer = buffer;
rwm->data.exchange({});
return CELL_OK;
@ -479,9 +479,9 @@ s32 syncQueueInitialize(vm::ptr<CellSyncQueue> queue, vm::ptr<u8> buffer, u32 si
}
// prx: zeroize first u64, write size in third u32, write depth in fourth u32, write address in third u64 and sync
queue->m_size = size;
queue->m_depth = depth;
queue->m_buffer = buffer;
queue->m_size = be_t<u32>::make(size);
queue->m_depth = be_t<u32>::make(depth);
queue->m_buffer.set(buffer.addr());
queue->data.exchange({});
return CELL_OK;
}
@ -855,7 +855,7 @@ void syncLFQueueInit(vm::ptr<CellSyncLFQueue> queue, vm::ptr<u8> buffer, u32 siz
{
queue->pop1.write_relaxed({});
queue->push1.write_relaxed({});
queue->m_buffer.set(queue->m_buffer.addr() | be_t<u64>::make(1));
queue->m_buffer.set(queue->m_buffer.addr() | 1);
queue->m_bs[0] = -1;
queue->m_bs[1] = -1;
//m_bs[2]

View File

@ -14,7 +14,7 @@
#include "Emu/SysCalls/lv2/sys_time.h"
#include "Emu/SysCalls/lv2/sys_mmapper.h"
#include "Emu/SysCalls/lv2/sys_lwcond.h"
#include "Loader/ELF.h"
#include "Loader/ELF32.h"
#include "Crypto/unself.h"
#include "Emu/Cell/RawSPUThread.h"
#include "sysPrxForUser.h"
@ -130,11 +130,10 @@ int sys_raw_spu_load(s32 id, vm::ptr<const char> path, vm::ptr<u32> entry)
f.Seek(0);
ELFLoader l(f);
l.LoadInfo();
l.LoadData(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id);
u32 _entry;
LoadSpuImage(f, _entry, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id);
*entry = l.GetEntry();
*entry = _entry;
return CELL_OK;
}

View File

@ -96,7 +96,7 @@ int sys_net_accept(s32 s, vm::ptr<sys_net_sockaddr> addr, vm::ptr<pck_len_t> pad
{
sys_net->Warning("accept(s=%d, family_addr=0x%x, paddrlen=0x%x)", s, addr.addr(), paddrlen.addr());
if (!addr) {
int ret = accept(s, NULL, NULL);
int ret = accept(s, nullptr, nullptr);
*g_lastError = getLastError();
return ret;
}

View File

@ -15,7 +15,7 @@ s32 lwcond_create(sys_lwcond_t& lwcond, sys_lwmutex_t& lwmutex, u64 name_u64)
u32 id = sys_lwcond.GetNewId(new Lwcond(name_u64), TYPE_LWCOND);
u32 addr = Memory.RealToVirtualAddr(&lwmutex);
lwcond.lwmutex.set(be_t<u32>::make(addr));
lwcond.lwmutex.set(addr);
lwcond.lwcond_queue = id;
std::string name((const char*)&name_u64, 8);

View File

@ -24,13 +24,13 @@ s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_a
{
default:
case SYS_MEMORY_PAGE_SIZE_1M:
if(AlignAddr(size, alignment) & 0xfffff)
if(align(size, alignment) & 0xfffff)
return CELL_EALIGN;
addr = (u32)Memory.Alloc(size, 0x100000);
break;
case SYS_MEMORY_PAGE_SIZE_64K:
if(AlignAddr(size, alignment) & 0xffff)
if (align(size, alignment) & 0xffff)
return CELL_EALIGN;
addr = (u32)Memory.Alloc(size, 0x10000);
break;

View File

@ -160,11 +160,11 @@ PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool i
new_thread.m_has_interrupt = false;
new_thread.m_is_interrupt = is_interrupt;
new_thread.SetName(name);
new_thread.m_custom_task = task;
new_thread.custom_task = task;
sys_ppu_thread.Notice("*** New PPU Thread [%s] (%s, entry=0x%x): id = %d", name.c_str(),
is_interrupt ? "interrupt" :
(is_joinable ? "joinable" : "non-joinable"), entry, id);
(is_joinable ? "joinable" : "detached"), entry, id);
if (!is_interrupt)
{
@ -194,15 +194,13 @@ s32 sys_ppu_thread_create(vm::ptr<u64> thread_id, u32 entry, u64 arg, s32 prio,
{
case 0: break;
case SYS_PPU_THREAD_CREATE_JOINABLE:
{
is_joinable = true;
break;
}
case SYS_PPU_THREAD_CREATE_INTERRUPT:
{
is_interrupt = true;
break;
}
default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM;
}

View File

@ -34,10 +34,10 @@ s32 sys_prx_load_module(vm::ptr<const char> path, u64 flags, vm::ptr<sys_prx_loa
sys_prx_t* prx = new sys_prx_t();
prx->size = (u32)f.GetSize();
prx->address = (u32)Memory.Alloc(prx->size, 4);
prx->path = path;
prx->path = (const char*)path;
// Load the PRX into memory
f.Read(vm::get_ptr<void>(prx->address), prx->size);
f.Read(vm::get_ptr(prx->address), prx->size);
u32 id = sys_prx.GetNewId(prx, TYPE_PRX);
return id;

View File

@ -28,11 +28,74 @@ enum
CELL_PRX_ERROR_ELF_IS_REGISTERED = 0x80011910, // Fixed ELF is already registered
};
// Information about imported or exported libraries in PRX modules
struct sys_prx_library_info_t
{
u8 size;
u8 unk0;
be_t<u16> version;
be_t<u16> attributes;
be_t<u16> num_func;
be_t<u16> num_var;
be_t<u16> num_tlsvar;
u8 info_hash;
u8 info_tlshash;
u8 unk1[2];
be_t<u32> name_addr;
be_t<u32> fnid_addr;
be_t<u32> fstub_addr;
be_t<u32> unk4;
be_t<u32> unk5;
be_t<u32> unk6;
be_t<u32> unk7;
};
// ELF file headers
struct sys_prx_param_t
{
be_t<u32> size;
be_t<u32> magic;
be_t<u32> version;
be_t<u32> unk0;
be_t<u32> libentstart;
be_t<u32> libentend;
vm::bptr<sys_prx_library_info_t> libstubstart;
vm::bptr<sys_prx_library_info_t> libstubend;
be_t<u16> ver;
be_t<u16> unk1;
be_t<u32> unk2;
};
// PRX file headers
struct sys_prx_module_info_t
{
be_t<u16> attributes;
be_t<u16> version;
s8 name[28];
be_t<u32> toc;
vm::bptr<sys_prx_library_info_t> exports_start;
vm::bptr<sys_prx_library_info_t> exports_end;
be_t<u32> imports_start;
be_t<u32> imports_end;
};
// Relocation information of the SCE_PPURELA segment
struct sys_prx_relocation_info_t
{
be_t<u64> offset;
be_t<u16> unk0;
u8 index_value;
u8 index_addr;
be_t<u32> type;
vm::bptr<void, 1, u64> ptr;
};
// Data types
struct sys_prx_load_module_option_t
{
be_t<u64> size;
be_t<u32> base_addr; // void*
vm::bptr<void> base_addr;
};
struct sys_prx_start_module_option_t

View File

@ -7,20 +7,26 @@
#include "Emu/Cell/RawSPUThread.h"
#include "Emu/FS/vfsStreamMemory.h"
#include "Emu/FS/vfsFile.h"
#include "Loader/ELF.h"
#include "Loader/ELF32.h"
#include "Crypto/unself.h"
#include "sys_spu.h"
static SysCallBase sys_spu("sys_spu");
void LoadSpuImage(vfsStream& stream, u32& spu_ep, u32 addr)
{
loader::handlers::elf32 h;
h.init(stream);
h.load_data(addr);
spu_ep = h.m_ehdr.data_be.e_entry;
}
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep)
{
ELFLoader l(stream);
l.LoadInfo();
const u32 alloc_size = 256 * 1024;
u32 spu_offset = (u32)Memory.MainMem.AllocAlign(alloc_size);
l.LoadData(spu_offset);
spu_ep = l.GetEntry();
u32 spu_offset = (u32)vm::alloc(alloc_size, vm::main);
LoadSpuImage(stream, spu_ep, spu_offset);
return spu_offset;
}

View File

@ -90,7 +90,7 @@ struct sys_spu_segment
union
{
be_t<u32> addr; // address or fill value
be_t<u32> addr; // address or fill value
u64 pad;
};
};
@ -154,6 +154,10 @@ struct SpuGroupInfo
};
class SPUThread;
struct vfsStream;
void LoadSpuImage(vfsStream& stream, u32& spu_ep, u32 addr);
u32 LoadSpuImage(vfsStream& stream, u32& spu_ep);
// Aux
s32 spu_image_import(sys_spu_image& img, u32 src, u32 type);

View File

@ -57,6 +57,8 @@ Emulator::Emulator()
, m_sync_prim_manager(new SyncPrimManager())
, m_vfs(new VFS())
{
m_loader.register_handler(new loader::handlers::elf32);
m_loader.register_handler(new loader::handlers::elf64);
}
Emulator::~Emulator()
@ -235,78 +237,13 @@ void Emulator::Load()
return;
}
bool is_error;
Loader l(f);
try
if (!m_loader.load(f))
{
if(!(is_error = !l.Analyze()))
{
switch(l.GetMachine())
{
case MACHINE_SPU:
Memory.Init(Memory_PS3);
Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr(), 0x40000);
break;
case MACHINE_PPC64:
Memory.Init(Memory_PS3);
break;
case MACHINE_MIPS:
Memory.Init(Memory_PSP);
break;
case MACHINE_ARM:
Memory.Init(Memory_PSV);
break;
default:
throw std::string("Unknown machine!");
}
is_error = !l.Load();
}
}
catch(const std::string& e)
{
LOG_ERROR(LOADER, "%s", e.c_str());
is_error = true;
}
catch(...)
{
LOG_ERROR(LOADER, "Unhandled loader error.");
is_error = true;
}
CPUThreadType thread_type;
if(!is_error)
{
switch(l.GetMachine())
{
case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break;
case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break;
case MACHINE_ARM: thread_type = CPU_THREAD_ARMv7; break;
default:
LOG_ERROR(LOADER, "Unimplemented thread type for machine.");
is_error = true;
break;
}
}
if(is_error)
{
Memory.Close();
Stop();
LOG_ERROR(LOADER, "Loading '%s' failed", m_elf_path.c_str());
vm::close();
return;
}
// setting default values
Emu.m_sdk_version = -1; // possibly "unknown" value
// trying to load some info from PARAM.SFO
vfsFile f2("/app_home/PARAM.SFO");
if (f2.IsOpened())
@ -326,83 +263,6 @@ void Emulator::Load()
LoadPoints(BreakPointsDBName);
CPUThread& thread = GetCPU().AddThread(thread_type);
switch(l.GetMachine())
{
case MACHINE_SPU:
LOG_NOTICE(LOADER, "offset = 0x%llx", Memory.MainMem.GetStartAddr());
LOG_NOTICE(LOADER, "max addr = 0x%x", l.GetMaxAddr());
thread.SetOffset(Memory.MainMem.GetStartAddr());
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
thread.Run();
break;
case MACHINE_PPC64:
{
m_rsx_callback = (u32)Memory.MainMem.AllocAlign(4 * 4) + 4;
vm::write32(m_rsx_callback - 4, m_rsx_callback);
auto callback_data = vm::ptr<u32>::make(m_rsx_callback);
callback_data[0] = ADDI(11, 0, 0x3ff);
callback_data[1] = SC(2);
callback_data[2] = BCLR(0x10 | 0x04, 0, 0, 0);
m_ppu_thr_exit = (u32)Memory.MainMem.AllocAlign(4 * 4);
auto ppu_thr_exit_data = vm::ptr<u32>::make(m_ppu_thr_exit);
//ppu_thr_exit_data += ADDI(3, 0, 0); // why it kills return value (GPR[3]) ?
ppu_thr_exit_data[0] = ADDI(11, 0, 41);
ppu_thr_exit_data[1] = SC(2);
ppu_thr_exit_data[2] = BCLR(0x10 | 0x04, 0, 0, 0);
m_ppu_thr_stop = (u32)Memory.MainMem.AllocAlign(2 * 4);
auto ppu_thr_stop_data = vm::ptr<u32>::make(m_ppu_thr_stop);
ppu_thr_stop_data[0] = SC(4);
ppu_thr_stop_data[1] = BCLR(0x10 | 0x04, 0, 0, 0);
vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE);
thread.SetEntry(l.GetEntry());
thread.SetStackSize(0x10000);
thread.SetPrio(0x50);
thread.Run();
u32 arg1 = Memory.MainMem.AllocAlign(m_elf_path.size() + 1 + 0x20, 0x10) + 0x20;
memcpy(vm::get_ptr<char>(arg1), m_elf_path.c_str(), m_elf_path.size() + 1);
u32 argv = arg1 - 0x20;
vm::write64(argv, arg1);
static_cast<PPUThread&>(thread).GPR[3] = 1; // arg count
static_cast<PPUThread&>(thread).GPR[4] = argv; // probably, args**
static_cast<PPUThread&>(thread).GPR[5] = argv + 0x10; // unknown
static_cast<PPUThread&>(thread).GPR[6] = 0; // unknown
static_cast<PPUThread&>(thread).GPR[12] = Emu.GetMallocPageSize(); // ???
//thread.AddArgv("-emu");
}
break;
case MACHINE_ARM:
{
u32 entry = l.GetEntry();
auto code = vm::psv::ptr<const u32>::make(entry & ~3);
// evil way to find entry point in .sceModuleInfo.rodata
while (code[0] != 0xffffffffu)
{
entry = code[0] + 0x81000000;
code++;
}
thread.SetEntry(entry & ~1);
thread.Run();
break;
}
}
m_status = Ready;
GetGSManager().Init();
@ -415,7 +275,6 @@ void Emulator::Load()
void Emulator::Run()
{
if(!IsReady())
{
Load();

View File

@ -45,9 +45,10 @@ public:
SetTLSData(0, 0, 0);
memset(&proc_param, 0, sizeof(sys_process_param_info));
proc_param.malloc_pagesize = 0x100000;
proc_param.sdk_version = 0x360001;
//TODO
proc_param.malloc_pagesize = be_t<u32>::make(0x100000);
proc_param.sdk_version = be_t<u32>::make(0x360001);
proc_param.primary_stacksize = be_t<u32>::make(0x100000);
proc_param.primary_prio = be_t<s32>::make(0x50);
}
void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz)
@ -106,6 +107,7 @@ class Emulator
VFS* m_vfs;
EmuInfo m_info;
loader::loader m_loader;
public:
std::string m_path;
@ -121,6 +123,11 @@ public:
void SetPath(const std::string& path, const std::string& elf_path = "");
void SetTitleID(const std::string& id);
std::string GetPath() const
{
return m_elf_path;
}
std::recursive_mutex& GetCoreMutex() { return m_core_mutex; }
CPUThreadManager& GetCPU() { return *m_thread_manager; }
@ -149,6 +156,21 @@ public:
m_info.SetTLSData(addr, filesz, memsz);
}
void SetRSXCallback(u32 addr)
{
m_rsx_callback = addr;
}
void SetPPUThreadExit(u32 addr)
{
m_ppu_thr_exit = addr;
}
void SetPPUThreadStop(u32 addr)
{
m_ppu_thr_stop = addr;
}
EmuInfo& GetInfo() { return m_info; }
u64 GetTLSAddr() const { return m_info.GetTLSAddr(); }

View File

@ -421,5 +421,5 @@ void CompilerELF::SetOpStyle(const std::string& text, const wxColour& color, boo
void CompilerELF::DoAnalyzeCode(bool compile)
{
CompilePPUProgram(fmt::ToUTF8(asm_list->GetValue()), "compiled.elf", asm_list, hex_list, err_list, !compile).Compile();
// CompilePPUProgram(fmt::ToUTF8(asm_list->GetValue()), "compiled.elf", asm_list, hex_list, err_list, !compile).Compile();
}

View File

@ -1,4 +1,5 @@
#include "stdafx_gui.h"
#if 0
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
@ -512,3 +513,4 @@ void DisAsmFrame::MouseWheel(wxMouseEvent& event)
event.Skip();
}
#endif

View File

@ -1,5 +1,5 @@
#pragma once
#if 0
class PPCThread;
class DisAsmFrame : public wxFrame
@ -31,4 +31,6 @@ public:
}
virtual void AddLine(const wxString line);
};
};
#endif

View File

@ -0,0 +1,65 @@
#include "stdafx_gui.h"
#include "Utilities/Log.h"
#include "Loader/ELF64.h"
#include "Emu/FS/vfsDir.h"
#include "Emu/FS/vfsFile.h"
#include "LLEModulesManager.h"
#include "Emu/System.h"
#include "Emu/FS/VFS.h"
LLEModulesManagerFrame::LLEModulesManagerFrame(wxWindow* parent) : FrameBase(parent, wxID_ANY, "", "LLEModulesManagerFrame", wxSize(800, 600))
{
wxBoxSizer *s_panel = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *s_p_panel = new wxBoxSizer(wxVERTICAL);
wxPanel *p_main = new wxPanel(this);
m_check_list = new wxCheckListBox(p_main, wxID_ANY);
s_p_panel->Add(m_check_list, 0, wxEXPAND | wxALL, 5);
p_main->SetSizerAndFit(s_p_panel);
s_panel->Add(p_main, 0, wxEXPAND | wxALL, 5);
SetSizerAndFit(s_panel);
Refresh();
//Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent& event) { UpdateSelection(); });
Bind(wxEVT_SIZE, [p_main, this](wxSizeEvent& event) { p_main->SetSize(GetClientSize()); m_check_list->SetSize(p_main->GetClientSize() - wxSize(10, 10)); });
}
void LLEModulesManagerFrame::Refresh()
{
m_check_list->Clear();
std::string path = "/dev_flash/sys/external/";
Emu.GetVFS().Init(path);
vfsDir dir(path);
loader::handlers::elf64 sprx_loader;
for (const DirEntryInfo* info = dir.Read(); info; info = dir.Read())
{
if (info->flags & DirEntry_TypeFile)
{
vfsFile f(path + info->name);
if (sprx_loader.init(f) != loader::handler::ok)
{
continue;
}
if (!sprx_loader.is_sprx())
{
continue;
}
sprx_loader.load();
m_check_list->Check(m_check_list->Append(sprx_loader.sprx_get_module_name() +
" v" + std::to_string((int)sprx_loader.m_sprx_module_info.version[0]) + "." + std::to_string((int)sprx_loader.m_sprx_module_info.version[1])));
}
}
Emu.GetVFS().UnMountAll();
}
void LLEModulesManagerFrame::UpdateSelection()
{
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "Gui/FrameBase.h"
#include <wx/checklst.h>
class LLEModulesManagerFrame : public FrameBase
{
wxCheckListBox *m_check_list;
public:
LLEModulesManagerFrame(wxWindow *parent);
void Refresh();
void UpdateSelection();
};

View File

@ -20,6 +20,7 @@
#include "Gui/KernelExplorer.h"
#include "Gui/MemoryViewer.h"
#include "Gui/RSXDebugger.h"
#include "Gui/LLEModulesManager.h"
#include <wx/dynlib.h>
@ -33,7 +34,8 @@ enum IDs
{
id_boot_elf = 0x555,
id_boot_game,
id_install_pkg,
id_boot_install_pkg,
id_boot_exit,
id_sys_pause,
id_sys_stop,
id_sys_send_open_menu,
@ -44,6 +46,7 @@ enum IDs
id_config_vhdd_manager,
id_config_autopause_manager,
id_config_savedata_manager,
id_config_lle_modules_manager,
id_tools_compiler,
id_tools_kernel_explorer,
id_tools_memory_viewer,
@ -74,41 +77,45 @@ MainFrame::MainFrame()
wxMenuBar* menubar = new wxMenuBar();
wxMenu* menu_boot = new wxMenu();
menubar->Append(menu_boot, "Boot");
menu_boot->Append(id_boot_elf, "Boot ELF / SELF file");
menu_boot->Append(id_boot_game, "Boot game");
menubar->Append(menu_boot, "&Boot");
menu_boot->Append(id_boot_elf, "Boot &ELF / SELF file");
menu_boot->Append(id_boot_game, "Boot &game");
menu_boot->AppendSeparator();
menu_boot->Append(id_install_pkg, "Install PKG");
menu_boot->Append(id_boot_install_pkg, "&Install PKG");
menu_boot->AppendSeparator();
menu_boot->Append(id_boot_exit, "&Exit");
wxMenu* menu_sys = new wxMenu();
menubar->Append(menu_sys, "System");
menu_sys->Append(id_sys_pause, "Pause")->Enable(false);
menu_sys->Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false);
menubar->Append(menu_sys, "&System");
menu_sys->Append(id_sys_pause, "&Pause")->Enable(false);
menu_sys->Append(id_sys_stop, "&Stop\tCtrl + S")->Enable(false);
menu_sys->AppendSeparator();
menu_sys->Append(id_sys_send_open_menu, "Send open system menu cmd")->Enable(false);
menu_sys->Append(id_sys_send_exit, "Send exit cmd")->Enable(false);
menu_sys->Append(id_sys_send_open_menu, "Send &open system menu cmd")->Enable(false);
menu_sys->Append(id_sys_send_exit, "Send &exit cmd")->Enable(false);
wxMenu* menu_conf = new wxMenu();
menubar->Append(menu_conf, "Config");
menu_conf->Append(id_config_emu, "Settings");
menu_conf->Append(id_config_pad, "PAD Settings");
menubar->Append(menu_conf, "&Config");
menu_conf->Append(id_config_emu, "&Settings");
menu_conf->Append(id_config_pad, "&PAD Settings");
menu_conf->AppendSeparator();
menu_conf->Append(id_config_autopause_manager, "Auto Pause Settings");
menu_conf->Append(id_config_autopause_manager, "&Auto Pause Settings");
menu_conf->AppendSeparator();
menu_conf->Append(id_config_vfs_manager, "Virtual File System Manager");
menu_conf->Append(id_config_vhdd_manager, "Virtual HDD Manager");
menu_conf->Append(id_config_savedata_manager, "Save Data Utility");
menu_conf->Append(id_config_vfs_manager, "Virtual &File System Manager");
menu_conf->Append(id_config_vhdd_manager, "Virtual &HDD Manager");
menu_conf->Append(id_config_savedata_manager, "Save &Data Utility");
menu_conf->Append(id_config_lle_modules_manager, "&LLE Modules Manager");
wxMenu* menu_tools = new wxMenu();
menubar->Append(menu_tools, "Tools");
menu_tools->Append(id_tools_compiler, "ELF Compiler");
menu_tools->Append(id_tools_kernel_explorer, "Kernel Explorer")->Enable(false);
menu_tools->Append(id_tools_memory_viewer, "Memory Viewer")->Enable(false);
menu_tools->Append(id_tools_rsx_debugger, "RSX Debugger")->Enable(false);
menubar->Append(menu_tools, "&Tools");
menu_tools->Append(id_tools_compiler, "&ELF Compiler");
menu_tools->Append(id_tools_kernel_explorer, "&Kernel Explorer")->Enable(false);
menu_tools->Append(id_tools_memory_viewer, "&Memory Viewer")->Enable(false);
menu_tools->Append(id_tools_rsx_debugger, "&RSX Debugger")->Enable(false);
wxMenu* menu_help = new wxMenu();
menubar->Append(menu_help, "Help");
menu_help->Append(id_help_about, "About...");
menubar->Append(menu_help, "&Help");
menu_help->Append(id_help_about, "&About...");
SetMenuBar(menubar);
@ -124,7 +131,8 @@ MainFrame::MainFrame()
// Events
Bind(wxEVT_MENU, &MainFrame::BootElf, this, id_boot_elf);
Bind(wxEVT_MENU, &MainFrame::BootGame, this, id_boot_game);
Bind(wxEVT_MENU, &MainFrame::InstallPkg, this, id_install_pkg);
Bind(wxEVT_MENU, &MainFrame::InstallPkg, this, id_boot_install_pkg);
Bind(wxEVT_MENU, [](wxCommandEvent&){ wxGetApp().Exit(); }, id_boot_exit);
Bind(wxEVT_MENU, &MainFrame::Pause, this, id_sys_pause);
Bind(wxEVT_MENU, &MainFrame::Stop, this, id_sys_stop);
@ -137,6 +145,7 @@ MainFrame::MainFrame()
Bind(wxEVT_MENU, &MainFrame::ConfigVHDD, this, id_config_vhdd_manager);
Bind(wxEVT_MENU, &MainFrame::ConfigAutoPause, this, id_config_autopause_manager);
Bind(wxEVT_MENU, &MainFrame::ConfigSaveData, this, id_config_savedata_manager);
Bind(wxEVT_MENU, &MainFrame::ConfigLLEModules, this, id_config_lle_modules_manager);
Bind(wxEVT_MENU, &MainFrame::OpenELFCompiler, this, id_tools_compiler);
Bind(wxEVT_MENU, &MainFrame::OpenKernelExplorer, this, id_tools_kernel_explorer);
@ -673,6 +682,11 @@ void MainFrame::ConfigSaveData(wxCommandEvent& event)
SaveDataListDialog(this, true).ShowModal();
}
void MainFrame::ConfigLLEModules(wxCommandEvent& event)
{
(new LLEModulesManagerFrame(this))->Show();
}
void MainFrame::OpenELFCompiler(wxCommandEvent& WXUNUSED(event))
{
(new CompilerELF(this)) -> Show();
@ -775,7 +789,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
// Emulation
wxMenuItem& pause = *menubar.FindItem( id_sys_pause );
wxMenuItem& stop = *menubar.FindItem( id_sys_stop );
pause.SetItemLabel(is_running ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + E" : "Resume\tCtrl + E");
pause.SetItemLabel(is_running ? "&Pause\tCtrl + P" : is_ready ? "&Start\tCtrl + E" : "&Resume\tCtrl + E");
pause.Enable(!is_stopped);
stop.Enable(!is_stopped);
@ -783,7 +797,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit );
wxMenuItem& send_open_menu = *menubar.FindItem( id_sys_send_open_menu );
bool enable_commands = !is_stopped;
send_open_menu.SetItemLabel(wxString::Format("Send %s system menu cmd", (m_sys_menu_opened ? "close" : "open")));
send_open_menu.SetItemLabel(wxString::Format("Send &%s system menu cmd", (m_sys_menu_opened ? "close" : "open")));
send_open_menu.Enable(enable_commands);
send_exit.Enable(enable_commands);

View File

@ -40,6 +40,7 @@ private:
void ConfigVHDD(wxCommandEvent& event);
void ConfigAutoPause(wxCommandEvent& event);
void ConfigSaveData(wxCommandEvent& event);
void ConfigLLEModules(wxCommandEvent& event);
void OpenELFCompiler(wxCommandEvent& evt);
void OpenKernelExplorer(wxCommandEvent& evt);
void OpenMemoryViewer(wxCommandEvent& evt);

View File

@ -1,63 +0,0 @@
#include "stdafx.h"
#include "Emu/FS/vfsStream.h"
#include "ELF.h"
#include "ELF64.h"
#include "ELF32.h"
void Elf_Ehdr::Show()
{
}
void Elf_Ehdr::Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
}
ELFLoader::ELFLoader(vfsStream& f)
: m_elf_file(f)
, LoaderBase()
, m_loader(nullptr)
{
}
bool ELFLoader::LoadInfo()
{
if(!m_elf_file.IsOpened())
return false;
m_elf_file.Seek(0);
ehdr.Load(m_elf_file);
if(!ehdr.CheckMagic())
return false;
switch(ehdr.GetClass())
{
case CLASS_ELF32:
m_loader = new ELF32Loader(m_elf_file);
break;
case CLASS_ELF64:
m_loader = new ELF64Loader(m_elf_file);
break;
}
if(!(m_loader && m_loader->LoadInfo()))
return false;
entry = m_loader->GetEntry();
machine = m_loader->GetMachine();
return true;
}
bool ELFLoader::LoadData(u64 offset)
{
return m_loader && m_loader->LoadData(offset);
}
bool ELFLoader::Close()
{
delete m_loader;
m_loader = nullptr;
return m_elf_file.Close();
}

View File

@ -1,53 +0,0 @@
#pragma once
#include "Loader.h"
struct vfsStream;
enum ElfClass
{
CLASS_Unknown,
CLASS_ELF32,
CLASS_ELF64,
};
struct Elf_Ehdr
{
u32 e_magic;
u8 e_class;
virtual void Show();
virtual void Load(vfsStream& f);
bool CheckMagic() const { return e_magic == 0x7F454C46; }
ElfClass GetClass() const
{
switch(e_class)
{
case 1: return CLASS_ELF32;
case 2: return CLASS_ELF64;
}
return CLASS_Unknown;
}
};
class ELFLoader : public LoaderBase
{
vfsStream& m_elf_file;
LoaderBase* m_loader;
public:
Elf_Ehdr ehdr;
ELFLoader(vfsStream& f);
virtual ~ELFLoader()
{
Close();
}
virtual bool LoadInfo();
virtual bool LoadData(u64 offset = 0);
virtual bool Close();
};

View File

@ -3,623 +3,127 @@
#include "Utilities/rFile.h"
#include "Emu/FS/vfsStream.h"
#include "Emu/Memory/Memory.h"
#include "Emu/ARMv7/PSVFuncList.h"
#include "ELF32.h"
#include "Emu/Cell/SPUThread.h"
#include "Emu/ARMv7/ARMv7Thread.h"
#include "Emu/System.h"
//#define LOADER_DEBUG
void Elf32_Ehdr::Show()
namespace loader
{
#ifdef LOADER_DEBUG
LOG_NOTICE(LOADER, "Magic: %08x", e_magic);
LOG_NOTICE(LOADER, "Class: %s", "ELF32");
LOG_NOTICE(LOADER, "Data: %s", Ehdr_DataToString(e_data).c_str());
LOG_NOTICE(LOADER, "Current Version: %d", e_curver);
LOG_NOTICE(LOADER, "OS/ABI: %s", Ehdr_OS_ABIToString(e_os_abi).c_str());
LOG_NOTICE(LOADER, "ABI version: %lld", e_abi_ver);
LOG_NOTICE(LOADER, "Type: %s", Ehdr_TypeToString(e_type).c_str());
LOG_NOTICE(LOADER, "Machine: %s", Ehdr_MachineToString(e_machine).c_str());
LOG_NOTICE(LOADER, "Version: %d", e_version);
LOG_NOTICE(LOADER, "Entry point address: 0x%x", e_entry);
LOG_NOTICE(LOADER, "Program headers offset: 0x%08x", e_phoff);
LOG_NOTICE(LOADER, "Section headers offset: 0x%08x", e_shoff);
LOG_NOTICE(LOADER, "Flags: 0x%x", e_flags);
LOG_NOTICE(LOADER, "Size of this header: %d", e_ehsize);
LOG_NOTICE(LOADER, "Size of program headers: %d", e_phentsize);
LOG_NOTICE(LOADER, "Number of program headers: %d", e_phnum);
LOG_NOTICE(LOADER, "Size of section headers: %d", e_shentsize);
LOG_NOTICE(LOADER, "Number of section headers: %d", e_shnum);
LOG_NOTICE(LOADER, "Section header string table index: %d", e_shstrndx);
#endif
}
void Elf32_Ehdr::Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
if(IsLittleEndian())
namespace handlers
{
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
else
{
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
}
void Elf32_Desc::Load(vfsStream& f)
{
revision = Read32(f);
ls_size = Read32(f);
stack_size = Read32(f);
flags = Read32(f);
}
void Elf32_Desc::LoadLE(vfsStream& f)
{
revision = Read32LE(f);
ls_size = Read32LE(f);
stack_size = Read32LE(f);
flags = Read32LE(f);
}
void Elf32_Note::Load(vfsStream& f)
{
namesz = Read32(f);
descsz = Read32(f);
type = Read32(f);
f.Read(name, 8);
if (descsz == 32)
{
f.Read(desc_text, descsz);
}
else
{
desc.Load(f);
}
}
void Elf32_Note::LoadLE(vfsStream& f)
{
namesz = Read32LE(f);
descsz = Read32LE(f);
type = Read32LE(f);
f.Read(name, 8);
if (descsz == 32)
{
f.Read(desc_text, descsz);
}
else
{
desc.Load(f);
}
}
void Elf32_Shdr::Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read32(f);
sh_addr = Read32(f);
sh_offset = Read32(f);
sh_size = Read32(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read32(f);
sh_entsize = Read32(f);
}
void Elf32_Shdr::LoadLE(vfsStream& f)
{
sh_name = Read32LE(f);
sh_type = Read32LE(f);
sh_flags = Read32LE(f);
sh_addr = Read32LE(f);
sh_offset = Read32LE(f);
sh_size = Read32LE(f);
sh_link = Read32LE(f);
sh_info = Read32LE(f);
sh_addralign = Read32LE(f);
sh_entsize = Read32LE(f);
}
void Elf32_Shdr::Show()
{
#ifdef LOADER_DEBUG
LOG_NOTICE(LOADER, "Name offset: 0x%x", sh_name);
LOG_NOTICE(LOADER, "Type: 0x%d", sh_type);
LOG_NOTICE(LOADER, "Addr: 0x%x", sh_addr);
LOG_NOTICE(LOADER, "Offset: 0x%x", sh_offset);
LOG_NOTICE(LOADER, "Size: 0x%x", sh_size);
LOG_NOTICE(LOADER, "EntSize: %d", sh_entsize);
LOG_NOTICE(LOADER, "Flags: 0x%x", sh_flags);
LOG_NOTICE(LOADER, "Link: 0x%x", sh_link);
LOG_NOTICE(LOADER, "Info: %d", sh_info);
LOG_NOTICE(LOADER, "Address align: 0x%x", sh_addralign);
#endif
}
void Elf32_Phdr::Load(vfsStream& f)
{
p_type = Read32(f);
p_offset = Read32(f);
p_vaddr = Read32(f);
p_paddr = Read32(f);
p_filesz = Read32(f);
p_memsz = Read32(f);
p_flags = Read32(f);
p_align = Read32(f);
}
void Elf32_Phdr::LoadLE(vfsStream& f)
{
p_type = Read32LE(f);
p_offset = Read32LE(f);
p_vaddr = Read32LE(f);
p_paddr = Read32LE(f);
p_filesz = Read32LE(f);
p_memsz = Read32LE(f);
p_flags = Read32LE(f);
p_align = Read32LE(f);
}
void Elf32_Phdr::Show()
{
#ifdef LOADER_DEBUG
LOG_NOTICE(LOADER, "Type: %s", Phdr_TypeToString(p_type).c_str());
LOG_NOTICE(LOADER, "Offset: 0x%08x", p_offset);
LOG_NOTICE(LOADER, "Virtual address: 0x%08x", p_vaddr);
LOG_NOTICE(LOADER, "Physical address: 0x%08x", p_paddr);
LOG_NOTICE(LOADER, "File size: 0x%08x", p_filesz);
LOG_NOTICE(LOADER, "Memory size: 0x%08x", p_memsz);
LOG_NOTICE(LOADER, "Flags: %s", Phdr_FlagsToString(p_flags).c_str());
LOG_NOTICE(LOADER, "Align: 0x%x", p_align);
#endif
}
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write32(f, ehdr.e_entry);
Write32(f, ehdr.e_phoff);
Write32(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(rFile& f, Elf32_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_offset);
Write32(f, phdr.p_vaddr);
Write32(f, phdr.p_paddr);
Write32(f, phdr.p_filesz);
Write32(f, phdr.p_memsz);
Write32(f, phdr.p_flags);
Write32(f, phdr.p_align);
}
void WriteShdr(rFile& f, Elf32_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write32(f, shdr.sh_flags);
Write32(f, shdr.sh_addr);
Write32(f, shdr.sh_offset);
Write32(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write32(f, shdr.sh_addralign);
Write32(f, shdr.sh_entsize);
}
ELF32Loader::ELF32Loader(vfsStream& f)
: elf32_f(f)
, LoaderBase()
{
}
bool ELF32Loader::LoadInfo()
{
if(!elf32_f.IsOpened()) return false;
if(!LoadEhdrInfo()) return false;
if(!LoadPhdrInfo()) return false;
if(!LoadShdrInfo()) return false;
return true;
}
bool ELF32Loader::LoadData(u64 offset)
{
if(!elf32_f.IsOpened()) return false;
if(!LoadEhdrData(offset)) return false;
if(!LoadPhdrData(offset)) return false;
if(!LoadShdrData(offset)) return false;
return true;
}
bool ELF32Loader::Close()
{
return elf32_f.Close();
}
bool ELF32Loader::LoadEhdrInfo()
{
elf32_f.Seek(0);
ehdr.Load(elf32_f);
if(!ehdr.CheckMagic()) return false;
if(ehdr.IsLittleEndian())
LOG_WARNING(LOADER, "ELF32 LE");
switch(ehdr.e_machine)
{
case MACHINE_MIPS:
case MACHINE_PPC64:
case MACHINE_SPU:
case MACHINE_ARM:
machine = (Elf_Machine)ehdr.e_machine;
break;
default:
machine = MACHINE_Unknown;
LOG_ERROR(LOADER, "Unknown elf32 machine: 0x%x", ehdr.e_machine);
return false;
}
entry = ehdr.GetEntry();
if(entry == 0)
{
LOG_ERROR(LOADER, "elf32 error: entry is null!");
return false;
}
return true;
}
bool ELF32Loader::LoadPhdrInfo()
{
if(ehdr.e_phoff == 0 && ehdr.e_phnum)
{
LOG_ERROR(LOADER, "LoadPhdr32 error: Program header offset is null!");
return false;
}
elf32_f.Seek(ehdr.e_phoff);
for(uint i=0; i<ehdr.e_phnum; ++i)
{
phdr_arr.emplace_back();
if(ehdr.IsLittleEndian())
phdr_arr.back().LoadLE(elf32_f);
else
phdr_arr.back().Load(elf32_f);
}
if (machine == MACHINE_ARM)
{
entry = (entry & ~0x3) + 0x81000000;
}
else if(entry & 0x3)
{
//entry is physical, convert to virtual
entry &= ~0x3;
for(size_t i=0; i<phdr_arr.size(); ++i)
handler::error_code elf32::init(vfsStream& stream)
{
if(phdr_arr[i].p_paddr >= entry && entry < phdr_arr[i].p_paddr + phdr_arr[i].p_memsz)
error_code res = handler::init(stream);
if (res != ok)
return res;
m_stream->Read(&m_ehdr, sizeof(ehdr));
if (!m_ehdr.check())
{
entry += phdr_arr[i].p_vaddr;
LOG_WARNING(LOADER, "virtual entry = 0x%x", entry);
break;
}
}
}
return true;
}
bool ELF32Loader::LoadShdrInfo()
{
elf32_f.Seek(ehdr.e_shoff);
for(u32 i=0; i<ehdr.e_shnum; ++i)
{
shdr_arr.emplace_back();
if(ehdr.IsLittleEndian())
shdr_arr.back().LoadLE(elf32_f);
else
shdr_arr.back().Load(elf32_f);
}
if(ehdr.e_shstrndx >= shdr_arr.size())
{
LOG_WARNING(LOADER, "LoadShdr32 error: shstrndx too big!");
return true;
}
for(u32 i=0; i<shdr_arr.size(); ++i)
{
elf32_f.Seek(shdr_arr[ehdr.e_shstrndx].sh_offset + shdr_arr[i].sh_name);
std::string name;
while(!elf32_f.Eof())
{
char c;
elf32_f.Read(&c, 1);
if(c == 0) break;
name.push_back(c);
}
shdr_name_arr.push_back(name);
}
return true;
}
bool ELF32Loader::LoadEhdrData(u64 offset)
{
#ifdef LOADER_DEBUG
LOG_NOTICE(LOADER, "");
ehdr.Show();
LOG_NOTICE(LOADER, "");
#endif
return true;
}
bool ELF32Loader::LoadPhdrData(u64 _offset)
{
const u64 offset = machine == MACHINE_SPU ? _offset : 0;
for(u32 i=0; i<phdr_arr.size(); ++i)
{
phdr_arr[i].Show();
if(phdr_arr[i].p_type == 0x00000001) //LOAD
{
if(phdr_arr[i].p_vaddr < min_addr)
{
min_addr = phdr_arr[i].p_vaddr;
return bad_file;
}
if(phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz > max_addr)
if (m_ehdr.data_le.e_phnum && (m_ehdr.is_le() ? m_ehdr.data_le.e_phentsize : m_ehdr.data_be.e_phentsize) != sizeof(phdr))
{
max_addr = phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz;
return broken_file;
}
if(phdr_arr[i].p_vaddr != phdr_arr[i].p_paddr)
if (m_ehdr.data_le.e_shnum && (m_ehdr.is_le() ? m_ehdr.data_le.e_shentsize : m_ehdr.data_be.e_shentsize) != sizeof(shdr))
{
LOG_WARNING
(
LOADER,
"LoadPhdr32 different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x",
phdr_arr[i].p_paddr, phdr_arr[i].p_vaddr
);
return broken_file;
}
switch(machine)
LOG_WARNING(LOADER, "m_ehdr.e_type = 0x%x", (u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_type : m_ehdr.data_be.e_type));
if (m_ehdr.data_le.e_phnum)
{
case MACHINE_SPU: break;
case MACHINE_MIPS: Memory.PSP.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
case MACHINE_ARM: Memory.PSV.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break;
default:
continue;
}
elf32_f.Seek(phdr_arr[i].p_offset);
elf32_f.Read(vm::get_ptr<void>(phdr_arr[i].p_vaddr + offset), phdr_arr[i].p_filesz);
}
else if(phdr_arr[i].p_type == 0x00000004)
{
elf32_f.Seek(phdr_arr[i].p_offset);
Elf32_Note note;
if(ehdr.IsLittleEndian()) note.LoadLE(elf32_f);
else note.Load(elf32_f);
if(note.type != 1)
{
LOG_ERROR(LOADER, "ELF32: Bad NOTE type (%d)", note.type);
break;
}
if(note.namesz != sizeof(note.name))
{
LOG_ERROR(LOADER, "ELF32: Bad NOTE namesz (%d)", note.namesz);
break;
}
if(note.descsz != sizeof(note.desc) && note.descsz != 32)
{
LOG_ERROR(LOADER, "ELF32: Bad NOTE descsz (%d)", note.descsz);
break;
}
//if(note.desc.flags)
//{
// LOG_ERROR(LOADER, "ELF32: Bad NOTE flags (0x%x)", note.desc.flags);
// break;
//}
if(note.descsz == sizeof(note.desc))
{
LOG_WARNING(LOADER, "name = %s", std::string((const char *)note.name, 8).c_str());
LOG_WARNING(LOADER, "ls_size = %d", note.desc.ls_size);
LOG_WARNING(LOADER, "stack_size = %d", note.desc.stack_size);
m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum);
m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_phoff : m_ehdr.data_be.e_phoff));
size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr);
if (m_stream->Read(m_phdrs.data(), size) != size)
return broken_file;
}
else
m_phdrs.clear();
if (m_ehdr.data_le.e_shnum)
{
LOG_WARNING(LOADER, "desc = '%s'", std::string(note.desc_text, 32).c_str());
m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum);
m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_shoff : m_ehdr.data_be.e_shoff));
size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr);
if (m_stream->Read(m_shdrs.data(), size) != size)
return broken_file;
}
}
#ifdef LOADER_DEBUG
LOG_NOTICE(LOADER, "");
#endif
}
else
m_shdrs.clear();
return true;
}
bool ELF32Loader::LoadShdrData(u64 offset)
{
u32 fnid_addr = 0;
for(u32 i=0; i<shdr_arr.size(); ++i)
{
Elf32_Shdr& shdr = shdr_arr[i];
#ifdef LOADER_DEBUG
if(i < shdr_name_arr.size()) LOG_NOTICE(LOADER, "Name: %s", shdr_name_arr[i].c_str());
shdr.Show();
LOG_NOTICE(LOADER, "");
#endif
if((shdr.sh_type == SHT_RELA) || (shdr.sh_type == SHT_REL))
{
LOG_ERROR(LOADER, "ELF32 ERROR: Relocation");
continue;
}
if((shdr.sh_flags & SHF_ALLOC) != SHF_ALLOC) continue;
if(shdr.sh_addr < min_addr)
{
min_addr = shdr.sh_addr;
return ok;
}
if(shdr.sh_addr + shdr.sh_size > max_addr)
handler::error_code elf32::load()
{
max_addr = shdr.sh_addr + shdr.sh_size;
}
// probably should be in LoadPhdrData()
if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceFNID.rodata"))
{
fnid_addr = shdr.sh_addr;
}
else if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceFStub.rodata"))
{
list_known_psv_modules();
auto fnid = vm::psv::ptr<const u32>::make(fnid_addr);
auto fstub = vm::psv::ptr<const u32>::make(shdr.sh_addr);
for (u32 j = 0; j < shdr.sh_size / 4; j++)
Elf_Machine machine;
switch (machine = (Elf_Machine)(u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_machine : m_ehdr.data_be.e_machine))
{
u32 nid = fnid[j];
u32 addr = fstub[j];
case MACHINE_MIPS: vm::psp::init(); break;
case MACHINE_ARM: vm::psv::init(); break;
case MACHINE_SPU: vm::ps3::init(); break;
if (auto func = get_psv_func_by_nid(nid))
default:
return bad_version;
}
error_code res = load_data(0);
if (res != ok)
return res;
switch (machine)
{
case MACHINE_MIPS: break;
case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break;
case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break;
}
return ok;
}
handler::error_code elf32::load_data(u32 offset)
{
for (auto &phdr : m_phdrs)
{
u32 memsz = m_ehdr.is_le() ? phdr.data_le.p_memsz : phdr.data_be.p_memsz;
u32 filesz = m_ehdr.is_le() ? phdr.data_le.p_filesz : phdr.data_be.p_filesz;
u32 vaddr = offset + (m_ehdr.is_le() ? phdr.data_le.p_vaddr : phdr.data_be.p_vaddr);
u32 offset = m_ehdr.is_le() ? phdr.data_le.p_offset : phdr.data_be.p_offset;
switch (m_ehdr.is_le() ? phdr.data_le.p_type : phdr.data_be.p_type)
{
if (func->module)
func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr);
else
LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr);
case 0x00000001: //LOAD
if (phdr.data_le.p_memsz)
{
if (!vm::alloc(vaddr, memsz, vm::main))
{
LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz);
// writing Thumb code (temporarily, because it should be ARM)
vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function)
vm::psv::write16(addr + 2, (u16)get_psv_func_index(func));
vm::psv::write16(addr + 4, 0x4770); // BX LR
vm::psv::write16(addr + 6, 0); // null
}
else
{
LOG_ERROR(LOADER, "Unimplemented function 0x%08x (addr=0x%x)", nid, addr);
return loading_error;
}
vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function)
vm::psv::write16(addr + 2, 0x0000); // (zero index)
vm::psv::write16(addr + 4, 0x4770); // BX LR
vm::psv::write16(addr + 6, 0); // null
if (filesz)
{
m_stream->Seek(handler::get_stream_offset() + offset);
m_stream->Read(vm::get_ptr(vaddr), filesz);
}
}
break;
}
}
}
else if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceRefs.rodata"))
{
auto code = vm::psv::ptr<const u32>::make(shdr.sh_addr);
u32 data = 0;
for (; code.addr() < shdr.sh_addr + shdr.sh_size; code++)
{
switch (*code)
{
case 0x000000ff:
{
// save address for future use
data = *++code;
break;
}
case 0x0000002f:
{
// movw r12,# instruction will be replaced
const u32 addr = *++code;
vm::psv::write16(addr + 0, 0xf240 | (data & 0x800) >> 1 | (data & 0xf000) >> 12); // MOVW
vm::psv::write16(addr + 2, 0x0c00 | (data & 0x700) << 4 | (data & 0xff));
break;
}
case 0x00000030:
{
// movt r12,# instruction will be replaced
const u32 addr = *++code;
vm::psv::write16(addr + 0, 0xf2c0 | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); // MOVT
vm::psv::write16(addr + 2, 0x0c00 | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16);
break;
}
case 0x00000000:
{
// probably, no operation
break;
}
default: LOG_NOTICE(LOADER, "sceRefs: unknown code found (0x%08x)", *code);
}
}
return ok;
}
}
//TODO
return true;
}
}

View File

@ -4,135 +4,137 @@
struct vfsStream;
class rFile;
struct Elf32_Ehdr
namespace loader
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
void Show();
bool IsLittleEndian() const
namespace handlers
{
return e_data == 1;
class elf32 : public handler
{
public:
struct ehdr
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
union
{
struct
{
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u16 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
} data_le;
struct
{
be_t<u64> e_abi_ver;
be_t<u16> e_type;
be_t<u16> e_machine;
be_t<u32> e_version;
be_t<u16> e_entry;
be_t<u32> e_phoff;
be_t<u32> e_shoff;
be_t<u32> e_flags;
be_t<u16> e_ehsize;
be_t<u16> e_phentsize;
be_t<u16> e_phnum;
be_t<u16> e_shentsize;
be_t<u16> e_shnum;
be_t<u16> e_shstrndx;
} data_be;
};
bool is_le() const { return e_data == 1; }
bool check() const { return e_magic == 0x7F454C46; }
};
struct shdr
{
union
{
struct
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
} data_le;
struct
{
be_t<u32> sh_name;
be_t<u32> sh_type;
be_t<u32> sh_flags;
be_t<u32> sh_addr;
be_t<u32> sh_offset;
be_t<u32> sh_size;
be_t<u32> sh_link;
be_t<u32> sh_info;
be_t<u32> sh_addralign;
be_t<u32> sh_entsize;
} data_be;
};
};
struct phdr
{
union
{
struct
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
} data_le;
struct
{
be_t<u32> p_type;
be_t<u32> p_offset;
be_t<u32> p_vaddr;
be_t<u32> p_paddr;
be_t<u32> p_filesz;
be_t<u32> p_memsz;
be_t<u32> p_flags;
be_t<u32> p_align;
} data_be;
};
};
ehdr m_ehdr;
std::vector<phdr> m_phdrs;
std::vector<shdr> m_shdrs;
error_code init(vfsStream& stream) override;
error_code load() override;
error_code load_data(u32 offset);
virtual ~elf32() = default;
};
}
void Load(vfsStream& f);
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u32 GetEntry() const { return e_entry; }
};
struct Elf32_Desc
{
u32 revision;
u32 ls_size;
u32 stack_size;
u32 flags;
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
};
struct Elf32_Note
{
u32 namesz;
u32 descsz;
u32 type;
u8 name[8];
union
{
Elf32_Desc desc;
char desc_text[32];
};
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
};
struct Elf32_Shdr
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
void Show();
};
struct Elf32_Phdr
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
void Load(vfsStream& f);
void LoadLE(vfsStream& f);
void Show();
};
class ELF32Loader : public LoaderBase
{
vfsStream& elf32_f;
public:
Elf32_Ehdr ehdr;
std::vector<std::string> shdr_name_arr;
std::vector<Elf32_Shdr> shdr_arr;
std::vector<Elf32_Phdr> phdr_arr;
ELF32Loader(vfsStream& f);
~ELF32Loader() {Close();}
virtual bool LoadInfo();
virtual bool LoadData(u64 offset);
virtual bool Close();
private:
bool LoadEhdrInfo();
bool LoadPhdrInfo();
bool LoadShdrInfo();
bool LoadEhdrData(u64 offset);
bool LoadPhdrData(u64 offset);
bool LoadShdrData(u64 offset);
};
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr);
void WritePhdr(rFile& f, Elf32_Phdr& phdr);
void WriteShdr(rFile& f, Elf32_Shdr& shdr);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +1,157 @@
#pragma once
#include "Loader.h"
#include <unordered_map>
struct vfsStream;
class rFile;
struct Elf64_Ehdr
namespace loader
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u64 e_entry;
u64 e_phoff;
u64 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
namespace handlers
{
class elf64 : public handler
{
public:
struct ehdr
{
be_t<u32> e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
be_t<u64> e_abi_ver;
be_t<u16> e_type;
be_t<u16> e_machine;
be_t<u32> e_version;
be_t<u64> e_entry;
be_t<u64> e_phoff;
be_t<u64> e_shoff;
be_t<u32> e_flags;
be_t<u16> e_ehsize;
be_t<u16> e_phentsize;
be_t<u16> e_phnum;
be_t<u16> e_shentsize;
be_t<u16> e_shnum;
be_t<u16> e_shstrndx;
void Load(vfsStream& f);
bool check() const { return e_magic.ToBE() == se32(0x7F454C46); }
} m_ehdr;
void Show();
struct phdr
{
be_t<u32> p_type;
be_t<u32> p_flags;
be_t<u64> p_offset;
bptr<void, 1, u64> p_vaddr;
bptr<void, 1, u64> p_paddr;
be_t<u64> p_filesz;
be_t<u64> p_memsz;
be_t<u64> p_align;
};
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u64 GetEntry() const { return e_entry; }
};
struct shdr
{
be_t<u32> sh_name;
be_t<u32> sh_type;
be_t<u64> sh_flags;
bptr<void, 1, u64> sh_addr;
be_t<u64> sh_offset;
be_t<u64> sh_size;
be_t<u32> sh_link;
be_t<u32> sh_info;
be_t<u64> sh_addralign;
be_t<u64> sh_entsize;
};
struct Elf64_Shdr
{
u32 sh_name;
u32 sh_type;
u64 sh_flags;
u64 sh_addr;
u64 sh_offset;
u64 sh_size;
u32 sh_link;
u32 sh_info;
u64 sh_addralign;
u64 sh_entsize;
struct sprx_module_info
{
be_t<u16> attr;
u8 version[2];
char name[28];
be_t<u32> toc_addr;
be_t<u32> export_start;
be_t<u32> export_end;
be_t<u32> import_start;
be_t<u32> import_end;
} m_sprx_module_info;
void Load(vfsStream& f);
struct sprx_export_info
{
u8 size;
u8 padding;
be_t<u16> version;
be_t<u16> attr;
be_t<u16> func_count;
be_t<u16> vars_count;
be_t<u16> tls_vars_count;
be_t<u16> hash_info;
be_t<u16> tls_hash_info;
u8 reserved[2];
be_t<u32> lib_name_offset;
be_t<u32> nid_offset;
be_t<u32> stub_offset;
};
void Show();
};
struct sprx_import_info
{
u8 size;
u8 unused;
be_t<u16> version;
be_t<u16> attr;
be_t<u16> func_count;
be_t<u16> vars_count;
be_t<u16> tls_vars_count;
u8 reserved[4];
be_t<u32> lib_name_offset;
be_t<u32> nid_offset;
be_t<u32> stub_offset;
//...
};
struct Elf64_Phdr
{
u32 p_type;
u32 p_flags;
u64 p_offset;
u64 p_vaddr;
u64 p_paddr;
u64 p_filesz;
u64 p_memsz;
u64 p_align;
struct sprx_function_info
{
be_t<u32> name_table_offset;
be_t<u32> entry_table_offset;
be_t<u32> padding;
} m_sprx_function_info;
void Load(vfsStream& f);
struct sprx_lib_info
{
std::string name;
};
void Show();
};
struct sprx_segment_info
{
vm::ptr<void> begin;
u32 size;
u32 size_file;
vm::ptr<void> initial_addr;
std::vector<sprx_module_info> modules;
};
class ELF64Loader : public LoaderBase
{
vfsStream& elf64_f;
struct sprx_info
{
std::unordered_map<u32, u32> exports;
std::unordered_map<u32, u32> imports;
std::vector<sprx_segment_info> segments;
};
public:
Elf64_Ehdr ehdr;
std::vector<std::string> shdr_name_arr;
std::vector<Elf64_Shdr> shdr_arr;
std::vector<Elf64_Phdr> phdr_arr;
std::vector<phdr> m_phdrs;
std::vector<shdr> m_shdrs;
ELF64Loader(vfsStream& f);
~ELF64Loader() {Close();}
std::vector<sprx_segment_info> m_sprx_segments_info;
std::vector<sprx_import_info> m_sprx_import_info;
std::vector<sprx_export_info> m_sprx_export_info;
virtual bool LoadInfo();
virtual bool LoadData(u64 offset = 0);
virtual bool Close();
public:
virtual ~elf64() = default;
bool LoadEhdrInfo(s64 offset=-1);
bool LoadPhdrInfo(s64 offset=-1);
bool LoadShdrInfo(s64 offset=-1);
private:
bool LoadEhdrData(u64 offset);
bool LoadPhdrData(u64 offset);
bool LoadShdrData(u64 offset);
//bool LoadImports();
};
void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr);
void WritePhdr(rFile& f, Elf64_Phdr& phdr);
void WriteShdr(rFile& f, Elf64_Shdr& shdr);
error_code init(vfsStream& stream) override;
error_code load() override;
error_code load_data(u64 offset);
error_code load_sprx(sprx_info& info);
bool is_sprx() const { return m_ehdr.e_type == 0xffa4; }
std::string sprx_get_module_name() const { return m_sprx_module_info.name; }
};
}
}

View File

@ -1,11 +1,38 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Loader.h"
#include "ELF.h"
#include "SELF.h"
#include "PSF.h"
#include "Emu/FS/vfsLocalFile.h"
namespace loader
{
bool loader::load(vfsStream& stream)
{
for (auto i : m_handlers)
{
if (i->init(stream) == handler::ok)
{
if (i->load() == handler::ok)
{
return true;
}
}
stream.Seek(i->get_stream_offset());
}
return false;
}
handler::error_code handler::init(vfsStream& stream)
{
m_stream_offset = stream.Tell();
m_stream = &stream;
return ok;
}
};
static const u64 g_spu_offset = 0x10000;
const std::string Ehdr_DataToString(const u8 data)
@ -13,7 +40,7 @@ const std::string Ehdr_DataToString(const u8 data)
if(data > 1) return fmt::Format("%d's complement, big endian", data);
if(data < 1) return "Data is not found";
return fmt::Format("%d's complement, small endian", data);
return fmt::Format("%d's complement, little endian", data);
}
const std::string Ehdr_TypeToString(const u16 type)
@ -35,7 +62,7 @@ const std::string Ehdr_OS_ABIToString(const u8 os_abi)
case 0x66: return "Cell OS LV-2";
};
return fmt::Format("Unknown (0x%x)", os_abi);
return fmt::Format("Unknown (%x)", os_abi);
}
const std::string Ehdr_MachineToString(const u16 machine)
@ -48,7 +75,7 @@ const std::string Ehdr_MachineToString(const u16 machine)
case MACHINE_ARM: return "ARM";
};
return fmt::Format("Unknown (0x%x)", machine);
return fmt::Format("Unknown (%x)", machine);
}
const std::string Phdr_FlagsToString(u32 flags)
@ -73,7 +100,7 @@ const std::string Phdr_FlagsToString(u32 flags)
flags &= ~spu << 0x14;
flags &= ~rsx << 0x18;
if(flags != 0) return fmt::Format("Unknown %s PPU[0x%x] SPU[0x%x] RSX[0x%x]", ret.c_str(), ppu, spu, rsx);
if(flags != 0) return fmt::Format("Unknown %s PPU[%x] SPU[%x] RSX[%x]", ret.c_str(), ppu, spu, rsx);
ret += "PPU[" + FLAGS_TO_STRING(ppu) + "] ";
ret += "SPU[" + FLAGS_TO_STRING(spu) + "] ";
@ -93,94 +120,5 @@ const std::string Phdr_TypeToString(const u32 type)
case 0x60000002: return "LOOS+2";
};
return fmt::Format("Unknown (0x%x)", type);
}
Loader::Loader()
: m_stream(nullptr)
, m_loader(nullptr)
{
}
Loader::Loader(vfsFileBase& stream)
: m_stream(&stream)
, m_loader(nullptr)
{
}
Loader::~Loader()
{
delete m_loader;
m_loader = nullptr;
}
void Loader::Open(vfsFileBase& stream)
{
m_stream = &stream;
}
LoaderBase* Loader::SearchLoader()
{
if(!m_stream)
return nullptr;
LoaderBase* l = new ELFLoader(*m_stream);
if(l->LoadInfo())
return l;
delete l;
l = new SELFLoader(*m_stream);
if(l->LoadInfo())
return l;
delete l;
return nullptr;
}
bool Loader::Analyze()
{
delete m_loader;
m_loader = SearchLoader();
if(!m_loader)
{
LOG_ERROR(LOADER, "Unknown file type");
return false;
}
machine = m_loader->GetMachine();
entry = m_loader->GetMachine() == MACHINE_SPU ? m_loader->GetEntry() + g_spu_offset : m_loader->GetEntry();
return true;
}
bool Loader::Load()
{
if(!m_loader)
return false;
if(!m_loader->LoadData(m_loader->GetMachine() == MACHINE_SPU ? g_spu_offset : 0))
{
LOG_ERROR(LOADER, "Broken file");
return false;
}
/*
const std::string& root = fmt::ToUTF8(wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath());
std::string ps3_path;
const std::string& psf_path = root + "/" + "PARAM.SFO";
vfsFile f(psf_path);
if(f.IsOpened())
{
PSFLoader psf_l(f);
if(psf_l.Load())
{
CurGameInfo = psf_l.m_info;
CurGameInfo.root = root;
psf_l.Close();
}
}
*/
return true;
return fmt::Format("Unknown (%x)", type);
}

View File

@ -1,6 +1,8 @@
#pragma once
#include "Emu/Memory/vm.h"
struct vfsFileBase;
struct vfsStream;
class rFile;
#ifdef _DEBUG
@ -65,22 +67,7 @@ struct sys_process_param
sys_process_param_info info;
};
struct sys_proc_prx_param
{
be_t<u32> size;
be_t<u32> magic;
be_t<u32> version;
be_t<u32> pad0;
be_t<u32> libentstart;
be_t<u32> libentend;
be_t<u32> libstubstart;
be_t<u32> libstubend;
be_t<u16> ver;
be_t<u16> pad1;
be_t<u32> pad2;
};
struct Elf64_StubHeader
struct sys_stub
{
u8 s_size; // = 0x2c
u8 s_unk0;
@ -89,59 +76,80 @@ struct Elf64_StubHeader
be_t<u16> s_imports;
be_t<u32> s_unk2; // = 0x0
be_t<u32> s_unk3; // = 0x0
be_t<u32> s_modulename;
be_t<u32> s_nid;
be_t<u32> s_text;
vm::bptr<const char> s_modulename;
vm::bptr<u32> s_nid;
vm::bptr<u32> s_text;
be_t<u32> s_unk4; // = 0x0
be_t<u32> s_unk5; // = 0x0
be_t<u32> s_unk6; // = 0x0
be_t<u32> s_unk7; // = 0x0
};
class LoaderBase
struct sys_proc_prx_param
{
protected:
u32 entry;
u32 min_addr;
u32 max_addr;
Elf_Machine machine;
LoaderBase()
: machine(MACHINE_Unknown)
, entry(0)
, min_addr(0)
, max_addr(0)
{
}
public:
virtual ~LoaderBase() = default;
virtual bool LoadInfo() { return false; }
virtual bool LoadData(u64 offset = 0) { return false; }
Elf_Machine GetMachine() const { return machine; }
u32 GetEntry() const { return entry; }
u32 GetMinAddr() const { return min_addr; }
u32 GetMaxAddr() const { return max_addr; }
be_t<u32> size;
be_t<u32> magic;
be_t<u32> version;
be_t<u32> pad0;
be_t<u32> libentstart;
be_t<u32> libentend;
vm::bptr<sys_stub> libstubstart;
vm::bptr<sys_stub> libstubend;
be_t<u16> ver;
be_t<u16> pad1;
be_t<u32> pad2;
};
class Loader : public LoaderBase
namespace loader
{
vfsFileBase* m_stream;
LoaderBase* m_loader;
class handler
{
u64 m_stream_offset;
public:
Loader();
Loader(vfsFileBase& stream);
virtual ~Loader();
protected:
vfsStream* m_stream;
void Open(const std::string& path);
void Open(vfsFileBase& stream);
bool Analyze();
public:
enum error_code
{
bad_version = -1,
bad_file = -2,
broken_file = -3,
loading_error = -4,
bad_relocation_type = -5,
ok = 0,
};
bool Load();
virtual ~handler() = default;
private:
LoaderBase* SearchLoader();
};
virtual error_code init(vfsStream& stream);
virtual error_code load() = 0;
u64 get_stream_offset() const
{
return m_stream_offset;
}
};
class loader
{
std::vector<handler*> m_handlers;
public:
~loader()
{
for (auto &h : m_handlers)
{
delete h;
}
}
void register_handler(handler* handler)
{
m_handlers.push_back(handler);
}
bool load(vfsStream& stream);
};
using namespace vm;
}

View File

@ -1,99 +0,0 @@
#include "stdafx.h"
#include "Utilities/Log.h"
#include "Emu/FS/vfsStream.h"
#include "SELF.h"
#include "ELF64.h"
void SceHeader::Load(vfsStream& f)
{
se_magic = Read32(f);
se_hver = Read32(f);
se_flags = Read16(f);
se_type = Read16(f);
se_meta = Read32(f);
se_hsize = Read64(f);
se_esize = Read64(f);
}
void SceHeader::Show()
{
LOG_NOTICE(LOADER, "Magic: %08x", se_magic);
LOG_NOTICE(LOADER, "Class: %s", "SELF");
LOG_NOTICE(LOADER, "hver: 0x%08x", se_hver);
LOG_NOTICE(LOADER, "flags: 0x%04x", se_flags);
LOG_NOTICE(LOADER, "type: 0x%04x", se_type);
LOG_NOTICE(LOADER, "meta: 0x%08x", se_meta);
LOG_NOTICE(LOADER, "hsize: 0x%llx", se_hsize);
LOG_NOTICE(LOADER, "esize: 0x%llx", se_esize);
}
void SelfHeader::Load(vfsStream& f)
{
se_htype = Read64(f);
se_appinfooff = Read64(f);
se_elfoff = Read64(f);
se_phdroff = Read64(f);
se_shdroff = Read64(f);
se_secinfoff = Read64(f);
se_sceveroff = Read64(f);
se_controloff = Read64(f);
se_controlsize = Read64(f);
pad = Read64(f);
}
void SelfHeader::Show()
{
LOG_NOTICE(LOADER, "header type: 0x%llx", se_htype);
LOG_NOTICE(LOADER, "app info offset: 0x%llx", se_appinfooff);
LOG_NOTICE(LOADER, "elf offset: 0x%llx", se_elfoff);
LOG_NOTICE(LOADER, "program header offset: 0x%llx", se_phdroff);
LOG_NOTICE(LOADER, "section header offset: 0x%llx", se_shdroff);
LOG_NOTICE(LOADER, "section info offset: 0x%llx", se_secinfoff);
LOG_NOTICE(LOADER, "sce version offset: 0x%llx", se_sceveroff);
LOG_NOTICE(LOADER, "control info offset: 0x%llx", se_controloff);
LOG_NOTICE(LOADER, "control info size: 0x%llx", se_controlsize);
}
SELFLoader::SELFLoader(vfsStream& f)
: self_f(f)
, LoaderBase()
{
}
bool SELFLoader::LoadInfo()
{
if(!self_f.IsOpened()) return false;
self_f.Seek(0);
sce_hdr.Load(self_f);
self_hdr.Load(self_f);
if(!sce_hdr.CheckMagic()) return false;
return true;
}
bool SELFLoader::LoadData(u64 offset)
{
if(!self_f.IsOpened()) return false;
sce_hdr.Show();
self_hdr.Show();
ELF64Loader l(self_f);
if( !l.LoadEhdrInfo(self_hdr.se_elfoff) ||
!l.LoadPhdrInfo(self_hdr.se_phdroff) ||
!l.LoadShdrInfo(self_hdr.se_shdroff) ||
!l.LoadData(self_hdr.se_appinfooff) )
{
LOG_ERROR(LOADER, "Broken SELF file.");
return false;
}
machine = l.GetMachine();
entry = l.GetEntry();
return true;
LOG_ERROR(LOADER, "Boot SELF not supported yet!");
return false;
}

View File

@ -1,53 +0,0 @@
#pragma once
#include "Loader.h"
struct vfsStream;
struct SceHeader
{
u32 se_magic;
u32 se_hver;
u16 se_flags;
u16 se_type;
u32 se_meta;
u64 se_hsize;
u64 se_esize;
void Load(vfsStream& f);
void Show();
bool CheckMagic() const { return se_magic == 0x53434500; }
};
struct SelfHeader
{
u64 se_htype;
u64 se_appinfooff;
u64 se_elfoff;
u64 se_phdroff;
u64 se_shdroff;
u64 se_secinfoff;
u64 se_sceveroff;
u64 se_controloff;
u64 se_controlsize;
u64 pad;
void Load(vfsStream& f);
void Show();
};
class SELFLoader : public LoaderBase
{
vfsStream& self_f;
SceHeader sce_hdr;
SelfHeader self_hdr;
public:
SELFLoader(vfsStream& f);
virtual bool LoadInfo();
virtual bool LoadData(u64 offset = 0);
};

View File

@ -133,7 +133,7 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con
{
if (n->GetName() == "trophy")
{
u32 trophy_id = atoi(n->GetAttribute("id").c_str());
u32 trophy_id = std::atoi(n->GetAttribute("id").c_str());
u32 trophy_grade;
switch (((const char *)n->GetAttribute("ttype").c_str())[0])
{

View File

@ -239,13 +239,11 @@
<ClCompile Include="Emu\SysCalls\SysCalls.cpp" />
<ClCompile Include="Emu\System.cpp" />
<ClCompile Include="Ini.cpp" />
<ClCompile Include="Loader\ELF.cpp" />
<ClCompile Include="Loader\ELF32.cpp" />
<ClCompile Include="Loader\ELF64.cpp" />
<ClCompile Include="Loader\Loader.cpp" />
<ClCompile Include="Loader\PKG.cpp" />
<ClCompile Include="Loader\PSF.cpp" />
<ClCompile Include="Loader\SELF.cpp" />
<ClCompile Include="Loader\TROPUSR.cpp" />
<ClCompile Include="Loader\TRP.cpp" />
<ClCompile Include="Emu\Cell\PPULLVMRecompiler.cpp">
@ -459,13 +457,11 @@
<ClInclude Include="Emu\SysCalls\SysCalls.h" />
<ClInclude Include="Emu\System.h" />
<ClInclude Include="Ini.h" />
<ClInclude Include="Loader\ELF.h" />
<ClInclude Include="Loader\ELF32.h" />
<ClInclude Include="Loader\ELF64.h" />
<ClInclude Include="Loader\Loader.h" />
<ClInclude Include="Loader\PKG.h" />
<ClInclude Include="Loader\PSF.h" />
<ClInclude Include="Loader\SELF.h" />
<ClInclude Include="Loader\TROPUSR.h" />
<ClInclude Include="Loader\TRP.h" />
<ClInclude Include="restore_new.h" />

View File

@ -33,15 +33,9 @@
<Filter Include="Emu\HDD">
<UniqueIdentifier>{28902cf4-4fa6-428b-ab94-6b410fd5077f}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Cell">
<UniqueIdentifier>{13d20086-2188-425a-9856-0440fe6f79f2}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\CPU">
<UniqueIdentifier>{037247b4-0370-4193-a25d-bc9d075bf0a7}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\ARMv7">
<UniqueIdentifier>{93b1cff1-0158-4327-a437-e9abcac8d724}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Audio">
<UniqueIdentifier>{5a18e5b1-2632-4849-ba94-e7a2ea0b78fa}</UniqueIdentifier>
</Filter>
@ -60,24 +54,33 @@
<Filter Include="Utilities\SimpleIni">
<UniqueIdentifier>{84c34dd1-4c49-4ecf-8ee2-4165c14f24be}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\RSX">
<UniqueIdentifier>{fadb4b36-57af-4583-891d-d22ff369e266}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\RSX\Null">
<UniqueIdentifier>{4adca4fa-b90f-4662-9eb0-1d29cf3cd2eb}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\RSX\GL">
<UniqueIdentifier>{6f1da5b2-52c5-416b-9b5c-b9897bc1b300}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\Io\Null">
<UniqueIdentifier>{fcac6852-b45f-4cf2-afee-cf56bcea14e5}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\SysCalls\currently_unused">
<UniqueIdentifier>{ead7494f-a872-4b4d-a864-1a61c3b6012f}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\ARMv7\Modules">
<Filter Include="Emu\CPU\Cell">
<UniqueIdentifier>{13d20086-2188-425a-9856-0440fe6f79f2}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\CPU\ARMv7">
<UniqueIdentifier>{93b1cff1-0158-4327-a437-e9abcac8d724}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\CPU\ARMv7\Modules">
<UniqueIdentifier>{1d9e6fc4-9a79-4329-a8b5-081e24822aaa}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\GPU">
<UniqueIdentifier>{6674e2ab-90cd-47de-a852-d21643ab18c2}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\GPU\RSX">
<UniqueIdentifier>{fadb4b36-57af-4583-891d-d22ff369e266}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\GPU\RSX\Null">
<UniqueIdentifier>{4adca4fa-b90f-4662-9eb0-1d29cf3cd2eb}</UniqueIdentifier>
</Filter>
<Filter Include="Emu\GPU\RSX\GL">
<UniqueIdentifier>{6f1da5b2-52c5-416b-9b5c-b9897bc1b300}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Crypto\aes.cpp">
@ -309,28 +312,28 @@
<Filter>Emu\HDD</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\MFC.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPCDecoder.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPCThread.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPUThread.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\RawSPUThread.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\SPURecompilerCore.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\SPURSManager.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\SPUThread.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\CPU\CPUThread.cpp">
<Filter>Emu\CPU</Filter>
@ -339,7 +342,7 @@
<Filter>Emu\CPU</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClCompile>
<ClCompile Include="Emu\Audio\AudioManager.cpp">
<Filter>Emu\Audio</Filter>
@ -356,9 +359,6 @@
<ClCompile Include="Emu\Memory\vm.cpp">
<Filter>Emu\Memory</Filter>
</ClCompile>
<ClCompile Include="Loader\ELF.cpp">
<Filter>Loader</Filter>
</ClCompile>
<ClCompile Include="Loader\ELF32.cpp">
<Filter>Loader</Filter>
</ClCompile>
@ -374,9 +374,6 @@
<ClCompile Include="Loader\PSF.cpp">
<Filter>Loader</Filter>
</ClCompile>
<ClCompile Include="Loader\SELF.cpp">
<Filter>Loader</Filter>
</ClCompile>
<ClCompile Include="Loader\TROPUSR.cpp">
<Filter>Loader</Filter>
</ClCompile>
@ -561,37 +558,37 @@
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLProgram.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLProgramBuffer.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLVertexProgram.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\OpenGL.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLBuffers.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLFragmentProgram.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GL\GLGSRender.cpp">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GSManager.cpp">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\GSRender.cpp">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\RSXThread.cpp">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\SysCalls\lv2\sys_event_flag.cpp">
<Filter>Emu\SysCalls\lv2</Filter>
@ -630,31 +627,31 @@
<Filter>Emu\SysCalls\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPULLVMRecompiler.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\PPULLVMRecompilerTests.cpp">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\PSVFuncList.cpp">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\Modules\sceLibc.cpp">
<Filter>Emu\ARMv7\Modules</Filter>
<Filter>Emu\CPU\ARMv7\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\Modules\sceLibstdcxx.cpp">
<Filter>Emu\ARMv7\Modules</Filter>
<Filter>Emu\CPU\ARMv7\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\Modules\sceLibKernel.cpp">
<Filter>Emu\ARMv7\Modules</Filter>
<Filter>Emu\CPU\ARMv7\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\ARMv7\Modules\sceLibm.cpp">
<Filter>Emu\ARMv7\Modules</Filter>
<Filter>Emu\CPU\ARMv7\Modules</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -884,64 +881,64 @@
<Filter>Emu\HDD</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\MFC.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPCDecoder.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPCDisAsm.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPCInstrTable.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPCThread.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUDecoder.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUDisAsm.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUInstrTable.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUInterpreter.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUOpcodes.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPUThread.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\RawSPUThread.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUDecoder.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUDisAsm.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUInstrTable.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUInterpreter.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUOpcodes.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPURecompiler.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPURSManager.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\SPUThread.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\CPU\CPUDecoder.h">
<Filter>Emu\CPU</Filter>
@ -959,19 +956,19 @@
<Filter>Emu\CPU</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\ARMv7Decoder.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\ARMv7DisAsm.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\ARMv7Thread.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
<ClInclude Include="Emu\Audio\AudioDumper.h">
<Filter>Emu\Audio</Filter>
@ -988,9 +985,6 @@
<ClInclude Include="Emu\Memory\MemoryBlock.h">
<Filter>Emu\Memory</Filter>
</ClInclude>
<ClInclude Include="Loader\ELF.h">
<Filter>Loader</Filter>
</ClInclude>
<ClInclude Include="Loader\ELF32.h">
<Filter>Loader</Filter>
</ClInclude>
@ -1006,9 +1000,6 @@
<ClInclude Include="Loader\PSF.h">
<Filter>Loader</Filter>
</ClInclude>
<ClInclude Include="Loader\SELF.h">
<Filter>Loader</Filter>
</ClInclude>
<ClInclude Include="Loader\TROPUSR.h">
<Filter>Loader</Filter>
</ClInclude>
@ -1133,58 +1124,58 @@
<Filter>Emu\SysCalls</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\Null\NullGSRender.h">
<Filter>Emu\RSX\Null</Filter>
<Filter>Emu\GPU\RSX\Null</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLGSRender.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLProcTable.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLProgram.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLProgramBuffer.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLShaderParam.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLVertexProgram.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\OpenGL.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLBuffers.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GL\GLFragmentProgram.h">
<Filter>Emu\RSX\GL</Filter>
<Filter>Emu\GPU\RSX\GL</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GSManager.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GSRender.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\RSXFragmentProgram.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\RSXTexture.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\RSXThread.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\RSXVertexProgram.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\sysutil_video.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\GCM.h">
<Filter>Emu\RSX</Filter>
<Filter>Emu\GPU\RSX</Filter>
</ClInclude>
<ClInclude Include="Emu\SysCalls\lv2\sys_event_flag.h">
<Filter>Emu\SysCalls\lv2</Filter>
@ -1265,10 +1256,10 @@
<Filter>Emu\SysCalls\Modules</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\PPULLVMRecompiler.h">
<Filter>Emu\Cell</Filter>
<Filter>Emu\CPU\Cell</Filter>
</ClInclude>
<ClInclude Include="Emu\ARMv7\PSVFuncList.h">
<Filter>Emu\ARMv7</Filter>
<Filter>Emu\CPU\ARMv7</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -173,6 +173,7 @@
<ClCompile Include="Gui\GSFrame.cpp" />
<ClCompile Include="Gui\InterpreterDisAsm.cpp" />
<ClCompile Include="Gui\KernelExplorer.cpp" />
<ClCompile Include="Gui\LLEModulesManager.cpp" />
<ClCompile Include="Gui\MainFrame.cpp" />
<ClCompile Include="Gui\MemoryViewer.cpp" />
<ClCompile Include="Gui\MsgDialog.cpp" />
@ -212,6 +213,7 @@
<ClInclude Include="Gui\InstructionEditor.h" />
<ClInclude Include="Gui\InterpreterDisAsm.h" />
<ClInclude Include="Gui\KernelExplorer.h" />
<ClInclude Include="Gui\LLEModulesManager.h" />
<ClInclude Include="Gui\MainFrame.h" />
<ClInclude Include="Gui\MemoryViewer.h" />
<ClInclude Include="Gui\MsgDialog.h" />

View File

@ -90,6 +90,9 @@
<ClCompile Include="Gui\MsgDialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="Gui\LLEModulesManager.cpp">
<Filter>Gui</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="rpcs3.rc" />
@ -185,5 +188,8 @@
<ClInclude Include="Gui\InstructionEditor.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="Gui\LLEModulesManager.h">
<Filter>Gui</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -50,7 +50,10 @@ typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#define AlignAddr(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1))
template<typename T> __forceinline T align(const T addr, int align)
{
return (addr + (align - 1)) & ~(align - 1);
}
#include "Utilities/StrFmt.h"
#include "Utilities/BEType.h"