mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Implemented LLE Modules Manager (draft)
Improved loader core. Implemented *_thread wrappers. Minor fixes. Temporary disabled ELF Compiler & DisAsm frame.
This commit is contained in:
parent
1d61484992
commit
598d929aba
@ -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,55 +488,77 @@ class be_t
|
||||
return (be_t<Tto>&)res;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
const T& ToBE() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T ToLE() const
|
||||
type ToLE() const
|
||||
{
|
||||
return se_t<T, 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);
|
||||
}
|
||||
|
||||
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<T, 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 _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
|
||||
return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
|
||||
}
|
||||
|
||||
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
|
||||
@ -577,62 +605,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> {};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
thread->GetId();
|
||||
}
|
||||
};
|
@ -8,4 +8,4 @@ u8 PPCDecoder::DecodeMemory(const u32 address)
|
||||
Decode(instr);
|
||||
|
||||
return sizeof(u32);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -146,8 +146,25 @@ 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: return get_time();
|
||||
|
||||
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));
|
||||
@ -163,8 +180,25 @@ 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; break;
|
||||
|
||||
case 0x10C: UNK("WriteSPR: Write to time-based SPR. 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; break;
|
||||
}
|
||||
|
||||
UNK(fmt::Format("WriteSPR error: Unknown SPR 0x%x!", n));
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
*/
|
@ -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();
|
||||
};
|
||||
*/
|
@ -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,24 @@ 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;
|
||||
}
|
@ -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,49 @@ 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
|
||||
{
|
||||
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& run() override
|
||||
{
|
||||
thread->Run();
|
||||
|
||||
static_cast<PPUThread*>(thread)->GPR[3] = argc;
|
||||
static_cast<PPUThread*>(thread)->GPR[4] = argv.addr();
|
||||
static_cast<PPUThread*>(thread)->GPR[5] = envp.addr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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,117 @@ 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 },
|
||||
{ 0x00010000, 0x2FFF0000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc },
|
||||
{ 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc },
|
||||
{ 0x00010000, 0x2FFF0000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc },
|
||||
};
|
||||
|
||||
void close()
|
||||
{
|
||||
Memory.Close();
|
||||
}
|
||||
}
|
@ -1,17 +1,53 @@
|
||||
#pragma once
|
||||
#include "Memory.h"
|
||||
|
||||
namespace vm
|
||||
{
|
||||
enum memory_location
|
||||
{
|
||||
main,
|
||||
stack,
|
||||
sprx,
|
||||
user_space,
|
||||
|
||||
memory_location_count
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
extern location_info g_locations[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* const get_ptr(u64 addr)
|
||||
{
|
||||
return get_ptr<T>((u32)addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& get_ref(u32 addr)
|
||||
@ -19,8 +55,16 @@ namespace vm
|
||||
return *get_ptr<T>(addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& get_ref(u64 addr)
|
||||
{
|
||||
return get_ref<T>((u32)addr);
|
||||
}
|
||||
|
||||
namespace ps3
|
||||
{
|
||||
void init();
|
||||
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)g_base_addr + addr);
|
||||
@ -36,9 +80,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 +97,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 +114,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 +147,8 @@ namespace vm
|
||||
|
||||
namespace psv
|
||||
{
|
||||
void init();
|
||||
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)g_base_addr + addr);
|
||||
@ -138,8 +199,17 @@ 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"
|
||||
#include "vm_var.h"
|
@ -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 = 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,44 @@ 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 [](AT index) const
|
||||
{
|
||||
return get_ref<T>(m_addr + sizeof(T) * index);
|
||||
return vm::get_ref<T>(m_addr + sizeof(AT)* 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 +196,27 @@ namespace vm
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
void set(const AT value)
|
||||
void set(AT value)
|
||||
{
|
||||
m_addr = 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 = 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 +245,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 = 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 = m_addr;
|
||||
return (_ptr_base<const void, 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
@ -286,16 +305,26 @@ 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>
|
||||
@ -335,17 +364,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 = m_addr;
|
||||
return (_ptr_base<RT(*)(T...), 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
@ -356,7 +390,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 = m_addr;
|
||||
return [addr](T... args) -> RT { return make(addr)(args...); };
|
||||
}
|
||||
|
||||
@ -366,7 +400,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 +412,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 +447,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 +459,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 +474,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)
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
@ -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())
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -47,7 +47,8 @@ public:
|
||||
|
||||
proc_param.malloc_pagesize = 0x100000;
|
||||
proc_param.sdk_version = 0x360001;
|
||||
//TODO
|
||||
proc_param.primary_stacksize = 0x100000;
|
||||
proc_param.primary_prio = 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(); }
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
@ -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
|
65
rpcs3/Gui/LLEModulesManager.cpp
Normal file
65
rpcs3/Gui/LLEModulesManager.cpp
Normal 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()
|
||||
{
|
||||
|
||||
}
|
13
rpcs3/Gui/LLEModulesManager.h
Normal file
13
rpcs3/Gui/LLEModulesManager.h
Normal 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();
|
||||
};
|
@ -20,6 +20,7 @@
|
||||
#include "Gui/KernelExplorer.h"
|
||||
#include "Gui/MemoryViewer.h"
|
||||
#include "Gui/RSXDebugger.h"
|
||||
#include "Gui/LLEModulesManager.h"
|
||||
|
||||
#include <wx/dynlib.h>
|
||||
|
||||
@ -44,6 +45,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,
|
||||
@ -98,6 +100,8 @@ MainFrame::MainFrame()
|
||||
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");
|
||||
@ -137,6 +141,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 +678,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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
@ -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();
|
||||
};
|
@ -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_ERROR(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;
|
||||
}
|
||||
}
|
@ -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
@ -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; }
|
||||
};
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
||||
};
|
@ -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])
|
||||
{
|
||||
|
@ -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" />
|
||||
|
@ -356,9 +356,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 +371,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>
|
||||
@ -988,9 +982,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 +997,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>
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user