Fixed SELF loader issues

This commit is contained in:
Alexandro Sanchez Bach 2017-10-29 15:27:33 +01:00
parent ee3e611cc8
commit cca12b2990
26 changed files with 562 additions and 132 deletions

1
.gitignore vendored
View file

@ -40,6 +40,7 @@ UpgradeLog.htm
*.sdf
*.suo
*.user
*.tmp
*.db
# CLion files

View file

@ -80,18 +80,6 @@ Global
nucleus\system\system.vcxitems*{2d4b90ed-c848-4d60-bf54-7d660405b653}*SharedItemsImports = 9
nucleus\debugger\debugger.vcxitems*{30b5f783-76c3-4f96-a9e5-cd221e73b0a2}*SharedItemsImports = 9
nucleus\audio\audio.vcxitems*{45d41acc-2c3c-43d2-bc10-02aa73ffc7c7}*SharedItemsImports = 9
nucleus\audio\audio.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\core\core.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\cpu\cpu.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\debugger\debugger.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\filesystem\filesystem.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\gpu\gpu.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\graphics\backend\graphics-vulkan.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\graphics\graphics.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\logger\logger.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\memory\memory.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\system\system.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\ui\ui.vcxitems*{5abbef76-750e-453e-8f40-e3f17fb28224}*SharedItemsImports = 4
nucleus\logger\logger.vcxitems*{5b8b6a6c-001e-4a74-8fba-6b82cfbf12ab}*SharedItemsImports = 9
nucleus\audio\backend\audio-xaudio2.vcxitems*{623f605f-427f-4b3e-93a1-e644a70543aa}*SharedItemsImports = 9
nucleus\filesystem\filesystem.vcxitems*{7ec60005-180c-4cc7-ae7c-a0c3058f4f26}*SharedItemsImports = 9

View file

@ -11,12 +11,9 @@
#include "nucleus/cpu/cpu_host.h"
#include "nucleus/ui/ui.h"
#include "nucleus/gpu/list.h"
#include "nucleus/filesystem/utils.h"
#include "nucleus/logger/logger.h"
#include "nucleus/memory/list.h"
#include "nucleus/system/loader.h"
#include "nucleus/system/scei/self.h"
#include "nucleus/system/scei/orbisos/orbis_self.h"
#include "nucleus/system/list.h"
#if !defined(NUCLEUS_BUILD_TEST)
@ -25,63 +22,19 @@
* Load specific platform
*/
bool Emulator::load_ps3(const std::string& path) {
// Initialize hardware
memory = std::make_shared<mem::GuestVirtualMemory>(4_GB);
cpu = std::make_shared<cpu::GuestCPU>(this, memory.get());
gpu = std::make_shared<gpu::RSX>(this, memory.get(), graphics);
sys = std::make_shared<sys::LV2>(this, memory, sys::LV2_DEX);
// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(path);
sys->vfs.registerDevice(new fs::HostPathDevice("/app_home/", processPath));
// Load ELF/SELF file
SELFLoader self;
auto file = fs::HostFileSystem::openFile(path, fs::Read);
if (!self.open(file.get())) {
logger.error(LOG_COMMON, "Invalid file given.");
return false;
}
self.load_elf(static_cast<sys::LV2*>(sys.get())->proc);
if (self.getMachine() != sys::EM_PPC64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}
auto entry = self.getEntry();
static_cast<sys::LV2*>(sys.get())->init(entry);
return true;
return sys->start(path);
}
bool Emulator::load_ps4(const std::string& path) {
// Initialize hardware
memory = std::make_shared<mem::HostVirtualMemory>();
cpu = std::make_shared<cpu::HostCPU>(this, memory.get());
gpu = std::make_shared<gpu::R10XX>(this, graphics);
sys = std::make_shared<sys::OrbisOS>(this);
// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(path);
sys->vfs.registerDevice(new fs::HostPathDevice("/app0/", processPath));
// Load ELF/SELF file
sys::scei::orbis::SELFLoader self;
auto file = fs::HostFileSystem::openFile(path, fs::Read);
if (!self.open(file.get())) {
logger.error(LOG_COMMON, "Invalid file given.");
return false;
}
void* entryBase = self.load();
if (self.getMachine() != sys::EM_X86_64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}
auto entry = reinterpret_cast<uintptr_t>(entryBase) + self.getEntry();
static_cast<sys::OrbisOS*>(sys.get())->init(entry);
return true;
return sys->start(path);
}
bool Emulator::load(const std::string& filepath) {

View file

@ -691,6 +691,215 @@ bool Direct3D12Shader::initialize(const ShaderDesc& desc) {
std::string source = compile(module);
// std::cout << source << std::endl;
static int i = 0;
if (i == 8) {
source = R"(
typedef float4 t6[468U];
struct TInput {
float4 v29 : INPUT0;
};
struct TOutput {
float4 v15 : SV_Position;
float4 v17 : LINK1;
float4 v18 : LINK2;
float4 v19 : LINK6;
float4 v20 : LINK7;
float4 v21 : LINK8;
float4 v22 : LINK9;
float4 v23 : LINK10;
float4 v24 : LINK11;
float4 v25 : LINK12;
float4 v26 : LINK13;
float4 v27 : LINK14;
float4 v28 : LINK15;
};
cbuffer C7 : register(b0) { t6 v7; };
cbuffer C9 : register(b1) { float4x4 v9; };
static uint v5 = 468U;
static int v41 = 467;
static int v101 = 466;
static float4 v34 = float4(0.0, 0.0, 0.0, 0.0);
static float4 v60 = float4(0.0, 0.0, 0.0, 0.0);
TOutput main(TInput input) {
TOutput output = (TOutput)(0);
/*float4 v31 = input.v29;
float4 v32 = float4(v31.x, v31.y, v31.x, v31.x);
float4 v33 = floor(v32);
float4 v36 = v34;
float4 v37 = float4(v33.x, v33.y, v36.z, v36.w);
v34 = v37;
float4 v38 = input.v29;
float4 v39 = float4(v38.w, v38.w, v38.w, v38.z);
float4 v44 = v7[467];
float4 v45 = float4(v44.x, v44.x, v44.x, v44.x);
float4 v47 = v7[467];
float4 v48 = float4(v47.y, v47.y, v47.y, v47.y);
float4 v49 = -(v48);
float4 v50 = v39 * v45;
float4 v51 = v50 + v49;
float4 v52 = v34;
float4 v53 = float4(v52.x, v52.y, v51.z, v51.w);
v34 = v53;
float4 v54 = input.v29;
float4 v55 = float4(v54.x, v54.x, v54.x, v54.y);
float4 v57 = v7[467];
float4 v58 = float4(v57.z, v57.z, v57.z, v57.z);
float4 v59 = v55 * v58;
float4 v61 = v60;
float4 v62 = float4(v61.x, v61.y, v59.z, v59.w);
v60 = v62;
float4 v63 = input.v29;
float4 v64 = float4(v63.y, v63.x, v63.y, v63.y);
float4 v65 = frac(v64);
float4 v66 = v60;
float4 v67 = float4(v65.x, v65.y, v66.z, v66.w);
v60 = v67;
float4 v68 = v60;
float4 v69 = float4(v68.y, v68.x, v68.y, v68.y);
float4 v71 = v7[467];
float4 v72 = float4(v71.x, v71.x, v71.x, v71.x);
float4 v73 = v69 * v72;
float4 v74 = output.v20;
float4 v75 = float4(v73.x, v73.y, v74.z, v74.w);
output.v20 = v75;
float4 v76 = v60;
float4 v77 = float4(v76.w, v76.z, v76.w, v76.w);
float4 v78 = floor(v77);
float4 v79 = v60;
float4 v80 = float4(v78.x, v78.y, v79.z, v79.w);
v60 = v80;
float4 v81 = v34;
float4 v82 = float4(v81.z, v81.z, v81.z, v81.z);
float4 v83 = -(v82);
float4 v84 = output.v15;
float4 v85 = float4(v84.x, v83.y, v84.z, v84.w);
output.v15 = v85;
float4 v86 = v34;
float4 v87 = float4(v86.w, v86.w, v86.w, v86.w);
float4 v88 = output.v15;
float4 v89 = float4(v87.x, v88.y, v88.z, v88.w);
output.v15 = v89;
float4 v90 = v60;
float4 v91 = float4(v90.y, v90.y, v90.y, v90.x);
float4 v93 = v7[467];
float4 v94 = float4(v93.w, v93.w, v93.w, v93.w);
float4 v95 = v91 * v94;
float4 v96 = v34;
float4 v97 = float4(v96.x, v96.y, v95.z, v95.w);
v34 = v97;
float4 v98 = v34;
float4 v99 = float4(v98.z, v98.w, v98.z, v98.z);
float4 v100 = -(v99);
float4 v103 = v7[466];
float4 v104 = float4(v103.x, v103.x, v103.x, v103.x);
float4 v105 = v34;
float4 v106 = float4(v105.x, v105.y, v105.x, v105.x);
float4 v107 = v100 * v104;
float4 v108 = v107 + v106;
float4 v109 = v34;
float4 v110 = float4(v108.x, v108.y, v109.z, v109.w);
v34 = v110;
float4 v111 = v34;
float4 v112 = float4(v111.z, v111.z, v111.z, v111.w);
float4 v113 = output.v17;
float4 v114 = float4(v113.x, v112.y, v113.z, v112.w);
output.v17 = v114;
float4 v115 = v34;
float4 v116 = float4(v115.x, v115.x, v115.y, v115.x);
float4 v118 = v7[467];
float4 v119 = float4(v118.w, v118.w, v118.w, v118.w);
float4 v120 = v116 * v119;
float4 v121 = output.v17;
float4 v122 = float4(v120.x, v121.y, v120.z, v121.w);
output.v17 = v122;
float4 v123 = output.v15;
float4x4 v124 = v9;
float4 v125 = mul(v123, v124);
output.v15 = v125;
output.v15.y *= -1.0f;*/
float4 tmp0 = float4(0., 0., 0., 0.);;
float4 tmp1 = float4(0., 0., 0., 0.);;
float4 dst_reg7 = float4(0.0, 0.0, 0.0, 0.0);
float4 dst_reg0 = float4(0.0f, 0.0f, 0.0f, 1.0f);
float4 dst_reg1 = float4(0.0, 0.0, 0.0, 0.0);
float4 in_pos = input.v29;
tmp0.xy = floor(in_pos.xyxx).xy;
tmp0.zw = (in_pos.wwwz * v7[467].xxxx + -v7[467].yyyy).zw;
tmp1.zw = (in_pos.xxxy * v7[467].zzzz).zw;
tmp1.xy = frac(in_pos.yxyy).xy;
dst_reg7.xy = (tmp1.yxyy * v7[467].xxxx).xy;
tmp1.xy = floor(tmp1.wzww).xy;
dst_reg0.y = -tmp0.zzzz.y;
dst_reg0.x = tmp0.wwww.x;
tmp0.zw = (tmp1.yyyx * v7[467].wwww).zw;
tmp0.xy = (-tmp0.zwzz * v7[466].xxxx + tmp0.xyxx).xy;
dst_reg1.yw = tmp0.zzzw.yw;
dst_reg1.xz = (tmp0.xxyx * v7[467].wwww).xz;
output.v15 = dst_reg0;
output.v17 = dst_reg1;
output.v20 = dst_reg7;
return output;
}
)";
}
if (i == 999) {
source = R"(
struct TInput {
float4 v9 : SV_Position;
float4 v11 : LINK1;
float4 v12 : LINK2;
float4 v22 : LINK6;
float4 v13 : LINK7;
float4 v14 : LINK8;
float4 v15 : LINK9;
float4 v16 : LINK10;
float4 v17 : LINK11;
float4 v18 : LINK12;
float4 v19 : LINK13;
float4 v20 : LINK14;
float4 v21 : LINK15;
};
struct TOutput {
float4 v42 : SV_Target0;
};
Texture2D v24 : register(t0);
SamplerState v24s : register(s0);
static float v32 = 0.000000;
static float v33 = 1.000000;
static float4 v34 = float4(0.000000, 1.000000, 0.000000, 0.000000);
TOutput main(TInput input) {
TOutput output = (TOutput)(0);
/*output.v42 = float4(1.0f, 1.0f, 0.0f, 1.0f);*/
float4 tc0 = In.tc0;
float4 diff_color = In.diff_color;
float4 gl_FragCoord = In.Position;
gl_FragCoord.y = (720 - gl_FragCoord.y);
float4 ssa = is_front_face ? float4(1., 1., 1., 1.) : float4(-1., -1., -1., -1.);
float2 tex0_scale = float2(1., 1.);
r0.w = tex0.Sample(tex0sampler, tc0.xy * tex0_scale).w;
h0 = diff_color;
r0.w = (h0 * r0).w;
r0.xyz = h0.xyz;
return output;
}
)";
}
i++;
LPCSTR target;
switch (desc.type) {

View file

@ -111,17 +111,20 @@ void GuestVirtualMemory::write128(U64 addr, U128 value) {
*(U128*)((U64)m_base + addr) = SE128(value);
}
void GuestVirtualMemory::memcpy_h2g(U64 destination, const void* source, Size num) {
void GuestVirtualMemory::memcpy_h2g(U64 dst, const void* src, Size size) {
::memcpy(ptr(dst), src, size);
}
void GuestVirtualMemory::memcpy_g2h(void* destination, U64 source, Size num) {
void GuestVirtualMemory::memcpy_g2h(void* dst, U64 src, Size size) {
::memcpy(dst, ptr(src), size);
}
void GuestVirtualMemory::memcpy_g2g(U64 dst, U64 src, Size size) {
memcpy(ptr(dst), ptr(src), size);
::memcpy(ptr(dst), ptr(src), size);
}
void GuestVirtualMemory::memset(U64 ptr, int value, Size num) {
void GuestVirtualMemory::memset(U64 addr, int value, Size size) {
::memset(ptr(addr), value, size);
}
} // namespace mem

View file

@ -67,4 +67,25 @@ void HostVirtualMemory::write128(U64 addr, U128 value) {
*reinterpret_cast<U128*>(addr) = value;
}
void HostVirtualMemory::memcpy_h2g(U64 dst, const void* src_ptr, Size size) {
void* dst_ptr = reinterpret_cast<void*>(dst);
::memcpy(dst_ptr, src_ptr, size);
}
void HostVirtualMemory::memcpy_g2h(void* dst_ptr, U64 src, Size size) {
void* src_ptr = reinterpret_cast<void*>(src);
::memcpy(dst_ptr, src_ptr, size);
}
void HostVirtualMemory::memcpy_g2g(U64 dst, U64 src, Size size) {
void* dst_ptr = reinterpret_cast<void*>(dst);
void* src_ptr = reinterpret_cast<void*>(src);
::memcpy(dst_ptr, src_ptr, size);
}
void HostVirtualMemory::memset(U64 addr, int value, Size size) {
void* addr_ptr = reinterpret_cast<void*>(addr);
::memset(addr_ptr, value, size);
}
} // namespace mem

View file

@ -5,6 +5,8 @@
#pragma once
#include "nucleus/common.h"
#if defined(NUCLEUS_TARGET_LINUX)
#include <X11/Xlib.h>
#elif defined(NUCLEUS_TARGET_UWP)
@ -19,12 +21,13 @@ void nucleusInitialize(Display* display, Window window, int width, int height);
#elif defined(NUCLEUS_TARGET_UWP)
void nucleusInitialize(IUnknown* window, int width, int height);
#elif defined(NUCLEUS_TARGET_WINDOWS)
void nucleusInitialize(HWND hwnd, HDC hdc, int width, int height);
bool nucleusInitialize(HWND hwnd, HDC hdc, int width, int height);
#endif
void nucleusConfigure(int argc, char** argv);
bool nucleusStart();
void nucleusIdle();
void nucleusFinalize();
// Events
void nucleusOnWindowSizeChanged(unsigned int width, unsigned int height);

View file

@ -0,0 +1,116 @@
/**
* (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
* Released under GPL v2 license. Read LICENSE for more details.
*/
#pragma once
#include "elf64.h"
#include "system.h"
#include <vector>
// Forward declarations
namespace mem { class Memory; }
namespace sys {
/**
* ELF64 Loader
* ============
* Parses ELF64 files.
* @tparam E Endianness
*/
template <template <typename> typename E>
class Elf64Loader {
protected:
using Ehdr = Elf64_Ehdr<E>;
using Phdr = Elf64_Phdr<E>;
using Shdr = Elf64_Shdr<E>;
// Segment loading
void load_seg_load(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
U64 addr;
if (!phdr.memsz) {
break;
}
if (phdr.vaddr) {
memory->allocFixed(phdr.vaddr, phdr.memsz);
addr = phdr.vaddr;
} else {
addr = memory->alloc(phdr.memsz, phdr.align);
}
memory_h2g(addr, &elf[phdr.offset], phdr.filesz);
if (phdr.flags & PF_X) {
auto module = new cpu::frontend::ppu::Module(nucleus.cpu.get());
module->parent = nucleus.cpu.get();
module->address = phdr.vaddr;
module->size = phdr.filesz;
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
module->analyze();
module->recompile();
}
static_cast<cpu::Cell*>(nucleus.cpu.get())->ppu_modules.push_back(module);
}
break;
}
void load_seg_tls(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
}
void process_seg_custom_os(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
}
void process_seg_custom_proc(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
}
public:
/**
* Load the current ELF64 file into memory.
*/
bool load(System* sys, std::vector<Byte>& data)
{
const Ehdr* ehdr = nullptr;
const Phdr* phdr = nullptr;
const Shdr* shdr = nullptr;
Size ehdr_off = 0;
Size phdr_off = 0;
Size shdr_off = 0;
if (data.size() < sizeof(Ehdr)) {
return false;
}
ehdr = reinterpret_cast<Ehdr*>(&data[ehdr_off]);
for (Size i = 0; i < ehdr.phnum; i++) {
phdr_off = ehdr.phoff + i * sizeof(Phdr);
phdr = reinterpret_cast<Phdr*>(&data[phdr_off]);
Size phdr_type = phdr->type;
switch (phdr_type) {
case PT_LOAD:
process_seg_load(sys, data);
break;
case PT_TLS:
process_seg_tls(sys, data);
break;
}
if (phdr_type >= PT_LOOS && phdr_type <= PT_HIOS) {
process_seg_custom_os(sys, data);
}
if (phdr_type >= PT_LOPROC && phdr_type <= PT_HIPROC) {
process_seg_custom_proc(sys, data);
}
}
}
};
} // namespace sys

View file

@ -4,10 +4,11 @@
*/
#include "cellos_loader.h"
#include "nucleus/filesystem/filesystem_host.h"
#include "nucleus/logger/logger.h"
#include "nucleus/system/scei/self.h"
#include "nucleus/system/elf64.h"
#include "nucleus/system/loader.h"
#include "cellos_loader_self.h"
namespace sys {
namespace scei {

View file

@ -7,7 +7,8 @@
#include "nucleus/common.h"
#include "nucleus/filesystem/filesystem_host.h"
// Forward declarations
namespace fs { class File; }
namespace sys {
namespace scei {

View file

@ -3,23 +3,29 @@
* Released under GPL v2 license. Read LICENSE for more details.
*/
#include "self.h"
#include "cellos_loader_self.h"
#include "nucleus/common.h"
#include "nucleus/core/config.h"
#include "nucleus/emulator.h"
#include "nucleus/cpu/cpu_guest.h"
#include "nucleus/system/scei/cellos/lv2.h"
#include "nucleus/memory/guest_virtual/guest_virtual_memory.h"
#include "nucleus/cpu/frontend/ppu/ppu_decoder.h"
#include "nucleus/system/keys.h"
#include "nucleus/system/loader.h"
#include "nucleus/logger/logger.h"
#include "nucleus/system/scei/cellos/lv2.h"
#include "nucleus/system/scei/cellos/lv2/sys_process.h"
#include "nucleus/system/scei/cellos/lv2/sys_prx.h"
#include "externals/aes.h"
#include "externals/zlib/zlib.h"
#include <cstring>
using namespace sys;
namespace sys {
namespace scei {
namespace cellos {
bool SELFLoader::open(fs::File* file)
{
@ -43,9 +49,9 @@ bool SELFLoader::open(fs::File* file)
}
}
bool SELFLoader::open(const std::string& path)
bool SELFLoader::open(LV2* lv2, const std::string& path)
{
fs::File* file = nucleus.sys->vfs.openFile(path, fs::Read);
fs::File* file = lv2->vfs.openFile(path, fs::Read);
if (!file) {
return false;
}
@ -55,11 +61,13 @@ bool SELFLoader::open(const std::string& path)
return result;
}
bool SELFLoader::load_elf(sys::sys_process_t& proc)
bool SELFLoader::load_elf(LV2* lv2)
{
if (elf.empty()) {
return false;
}
auto* cpu = dynamic_cast<cpu::GuestCPU*>(lv2->getEmulator()->cpu.get());
auto* mem = dynamic_cast<mem::GuestVirtualMemory*>(lv2->getEmulator()->memory.get());
const auto& ehdr = (Ehdr&)elf[0];
@ -73,18 +81,18 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
break;
}
nucleus.memory->getSegment(mem::SEG_MAIN_MEMORY).allocFixed(phdr.vaddr, phdr.memsz);
memcpy(nucleus.memory->ptr(phdr.vaddr), &elf[phdr.offset], phdr.filesz);
mem->getSegment(mem::SEG_MAIN_MEMORY).allocFixed(phdr.vaddr, phdr.memsz);
mem->memcpy_h2g(phdr.vaddr, &elf[phdr.offset], phdr.filesz);
if (phdr.flags & PF_X) {
auto module = new cpu::frontend::ppu::Module(nucleus.cpu.get());
module->parent = nucleus.cpu.get();
auto module = new cpu::frontend::ppu::Module(cpu);
module->parent = cpu;
module->address = phdr.vaddr;
module->size = phdr.filesz;
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
module->analyze();
module->recompile();
}
static_cast<cpu::Cell*>(nucleus.cpu.get())->ppu_modules.push_back(module);
cpu->ppu_modules.push_back(module);
}
break;
@ -92,20 +100,23 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
// TODO: ?
break;
case PT_PROC_PARAM:
if (!phdr.filesz) {
proc.param.sdk_version = 0xFFFFFFFF;
proc.param.malloc_pagesize = 0x100000;
} else {
proc.param = (sys::sys_process_param_t&)elf[phdr.offset];
lv2->proc.param.sdk_version = 0xFFFFFFFF;
lv2->proc.param.malloc_pagesize = 0x100000;
}
else {
lv2->proc.param = (sys::sys_process_param_t&)elf[phdr.offset];
}
break;
case PT_PRX_PARAM:
if (!phdr.filesz) {
logger.error(LOG_LOADER, "Invalid PRX_PARAM segment");
} else {
proc.prx_param = (sys::sys_process_prx_param_t&)elf[phdr.offset];
}
else {
lv2->proc.prx_param = (sys::sys_process_prx_param_t&)elf[phdr.offset];
}
break;
}
@ -113,12 +124,15 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
return true;
}
bool SELFLoader::load_prx(sys::sys_prx_t& prx)
bool SELFLoader::load_prx(LV2* lv2, sys::sys_prx_t& prx)
{
if (elf.empty()) {
return false;
}
auto* cpu = dynamic_cast<cpu::GuestCPU*>(lv2->getEmulator()->cpu.get());
auto* mem = dynamic_cast<mem::GuestVirtualMemory*>(lv2->getEmulator()->memory.get());
const auto& ehdr = (Ehdr&)elf[0];
U32 base_addr;
@ -128,8 +142,8 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
if (phdr.type == PT_LOAD) {
// Allocate memory and copy segment contents
const U32 addr = nucleus.memory->getSegment(mem::SEG_MAIN_MEMORY).alloc(phdr.memsz, 0x10000);
memcpy(nucleus.memory->ptr(addr), &elf[phdr.offset], phdr.filesz);
const U32 addr = mem->getSegment(mem::SEG_MAIN_MEMORY).alloc(phdr.memsz, 0x10000);
mem->memcpy_h2g(addr, &elf[phdr.offset], phdr.filesz);
// Add information for PRX Object
sys::sys_prx_segment_t segment;
@ -226,22 +240,22 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
switch (rel.type.ToLE()) {
case R_PPC64_ADDR32:
value = (U32)prx.segments[rel.index_value].addr + rel.ptr;
nucleus.memory->write32(addr, value);
mem->write32(addr, value);
break;
case R_PPC64_ADDR16_LO:
value = (U16)rel.ptr;
nucleus.memory->write16(addr, value);
mem->write16(addr, value);
break;
case R_PPC64_ADDR16_HI:
value = (U16)(prx.segments[rel.index_value].addr >> 16);
nucleus.memory->write16(addr, value);
mem->write16(addr, value);
break;
case R_PPC64_ADDR16_HA:
value = (U16)(prx.segments[1].addr >> 16);
nucleus.memory->write16(addr, value);
mem->write16(addr, value);
break;
default:
@ -262,7 +276,7 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
const sys::sys_prx_library_t* targetLibrary = nullptr;
// Find library (TODO: This is very inefficient)
for (const auto& object : static_cast<sys::LV2*>(nucleus.sys.get())->objects) {
for (const auto& object : lv2->objects) {
if (object.second->getType() == sys::SYS_PRX_OBJECT) {
const auto* imported_prx = (sys::sys_prx_t*)object.second->getData();
for (const auto& exportedLib : imported_prx->exported_libs) {
@ -280,21 +294,21 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
for (const auto& import : importedLib.exports) {
const U32 fnid = import.first;
nucleus.memory->write32(import.second, targetLibrary->exports.at(fnid));
mem->write32(import.second, targetLibrary->exports.at(fnid));
}
}
// Recompile executable segments
for (auto& prx_segment : prx.segments) {
if (prx_segment.flags & PF_X) {
auto segment = new cpu::frontend::ppu::Module(nucleus.cpu.get());
auto segment = new cpu::frontend::ppu::Module(cpu);
segment->address = prx_segment.addr;
segment->size = prx_segment.size_file;
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
segment->analyze();
segment->recompile();
}
static_cast<cpu::Cell*>(nucleus.cpu.get())->ppu_modules.push_back(segment);
cpu->ppu_modules.push_back(segment);
}
}
return true;
@ -496,3 +510,35 @@ U64 SELFLoader::getEntry()
const auto& ehdr = (Ehdr&)elf[0];
return ehdr.entry;
}
void SELFLoader::process_seg_custom_os(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
auto* lv2 = dynamic_cast<LV2*>(sys);
if (phdr.type == PT_PROC_PARAM) {
if (!phdr.filesz) {
lv2->proc.param.sdk_version = 0xFFFFFFFF;
lv2->proc.param.malloc_pagesize = 0x100000;
}
else {
lv2->proc.param = (sys_process_param_t&)elf[phdr.offset];
}
}
if (phdr.type == PT_PRX_PARAM) {
if (!phdr.filesz) {
logger.error(LOG_LOADER, "Invalid PRX_PARAM segment");
}
else {
lv2->proc.prx_param = (sys_process_prx_param_t&)elf[phdr.offset];
}
}
}
void SELFLoader::process_seg_custom_proc(System* sys, const Phdr& phdr, std::vector<Byte>& data)
{
}
} // namespace cellos
} // namespace scei
} // namespace sys

View file

@ -6,14 +6,20 @@
#pragma once
#include "nucleus/common.h"
#include "nucleus/filesystem/file.h"
#include "nucleus/system/elf64.h"
#include "nucleus/system/scei/cellos/lv2/sys_process.h"
#include "nucleus/system/elf64_loader.h"
#include "nucleus/system/scei/cellos/lv2/sys_prx.h"
#include <string>
#include <vector>
// Forward declaration
namespace sys { class LV2; }
namespace sys {
namespace scei {
namespace cellos {
// ELF ABI
enum {
ELFOSABI_CELL_LV2 = 0x66,
@ -157,29 +163,39 @@ struct ControlInfo {
};
};
class SELFLoader {
using Ehdr = sys::Elf64_Ehdr<BE>;
using Phdr = sys::Elf64_Phdr<BE>;
using Shdr = sys::Elf64_Shdr<BE>;
/**
* SELF Loader
* ============
* Parses SELF files.
* @tparam E Endianness
*/
class SELFLoader : public Elf64Loader<BE> {
protected:
std::vector<Byte> elf; // Holds the decrypted executable
std::vector<Byte> self; // Holds the encrypted executable
// Decrypts the Metadata Info and Headers of a SELF file
// Decrypts the Metadata Info and Headers of a SELF file
bool decryptMetadata();
// Returns the size of the ELF file after the SELF decryption/decompression
// by using accessing the SELF's EHDR and decrypted Metadata headers.
U32 getDecryptedElfSize();
void process_seg_custom_os(System* sys, const Phdr& phdr, std::vector<Byte>& data);
void process_seg_custom_proc(System* sys, const Phdr& phdr, std::vector<Byte>& data);
public:
bool open(fs::File* file);
bool open(const std::string& path);
bool load_elf(sys::sys_process_t& proc);
bool load_prx(sys::sys_prx_t& prx);
bool open(LV2* lv2, const std::string& path);
bool load_elf(LV2* lv2);
bool load_prx(LV2* lv2, sys::sys_prx_t& prx);
bool decrypt();
void close();
U16 getMachine();
U64 getEntry();
};
} // namespace cellos
} // namespace scei
} // namespace sys

View file

@ -6,8 +6,11 @@
#include "lv2.h"
#include "nucleus/emulator.h"
#include "nucleus/filesystem/filesystem_app.h"
#include "nucleus/filesystem/filesystem_host.h"
#include "nucleus/filesystem/utils.h"
#include "nucleus/logger/logger.h"
#include "nucleus/system/scei/cellos/callback.h"
#include "cellos_loader_self.h"
#include "lv2/sys_cond.h"
#include "lv2/sys_config.h"
@ -245,4 +248,29 @@ void LV2::call(cpu::frontend::ppu::PPUState& state) {
syscalls[id].func->call(state, *this, memory->getBaseAddr());
}
bool LV2::start(const std::string& path)
{
// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(path);
vfs.registerDevice(new fs::HostPathDevice("/app_home/", processPath));
// Load ELF/SELF file
scei::cellos::SELFLoader self;
auto file = fs::HostFileSystem::openFile(path, fs::Read);
if (!self.open(file.get())) {
logger.error(LOG_COMMON, "Invalid file given.");
return false;
}
self.load_elf(this);
if (self.getMachine() != EM_PPC64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}
auto entry = self.getEntry();
init(entry);
return true;
}
} // namespace sys

View file

@ -126,6 +126,8 @@ public:
// Get LV2 SysCall ID from the current thread and call it
void call(cpu::frontend::ppu::PPUState& state);
bool start(const std::string& path);
};
} // namespace sys

View file

@ -10,13 +10,13 @@
#include "nucleus/core/config.h"
#include "nucleus/system/scei/cellos/callback.h"
#include "nucleus/system/scei/cellos/lv2/sys_process.h"
#include "nucleus/system/scei/self.h"
#include "nucleus/system/scei/cellos/cellos_loader_self.h"
#include "../lv2.h"
namespace sys {
HLE_FUNCTION(sys_prx_load_module, const S08* path, U64 flags, sys_prx_load_module_option_t* pOpt) {
SELFLoader self;
scei::cellos::SELFLoader self;
auto file = kernel.vfs.openFile(path, fs::Read);
if (!self.open(file)) {
return CELL_PRX_ERROR_UNKNOWN_MODULE;
@ -25,7 +25,7 @@ HLE_FUNCTION(sys_prx_load_module, const S08* path, U64 flags, sys_prx_load_modul
// Load PRX into memory
auto* prx = new sys_prx_t();
if (!self.load_prx(*prx)) {
if (!self.load_prx(&kernel, *prx)) {
delete prx;
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
}

View file

@ -46,12 +46,6 @@ class SELFLoader {
std::vector<Byte> elf; // Holds the decrypted executable
std::vector<Byte> self; // Holds the encrypted executable
/**
* Returns the length of the interval that covers all LOAD segments
* @return Size in bytes
*/
Size getRequiredSize();
public:
bool open(fs::File* file);
void* load();

View file

@ -4,6 +4,10 @@
*/
#include "orbisos.h"
#include "nucleus/logger/logger.h"
#include "nucleus/filesystem/filesystem_host.h"
#include "nucleus/filesystem/utils.h"
#include "nucleus/system/scei/orbisos/orbis_self.h"
#include "syscalls/orbis_dynlib.h"
@ -315,6 +319,31 @@ bool OrbisOS::init(U64 entry) {
return !sys_dynlib_load_prx(nullptr, &args);
}
bool OrbisOS::start(const std::string& path)
{
// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(path);
vfs.registerDevice(new fs::HostPathDevice("/app0/", processPath));
// Load ELF/SELF file
sys::scei::orbis::SELFLoader self;
auto file = fs::HostFileSystem::openFile(path, fs::Read);
if (!self.open(file.get())) {
logger.error(LOG_COMMON, "Invalid file given.");
return false;
}
void* entryBase = self.load();
if (self.getMachine() != sys::EM_X86_64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}
auto entry = reinterpret_cast<uintptr_t>(entryBase) + self.getEntry();
init(entry);
return true;
}
} // namespace orbis
} // namespace scei
} // namespace sys

View file

@ -135,6 +135,8 @@ public:
* @param[in] entry Module entry point
*/
bool init(U64 entry);
bool start(const std::string& path);
};
} // namespace orbis

View file

@ -25,6 +25,13 @@ public:
* @return Emulator object
*/
Emulator* getEmulator() const;
/**
* Start new process from the specified source.
* @param[in] path Executable path
* @return True on success
*/
virtual bool start(const std::string& path) = 0;
};
} // namespace sys

View file

@ -15,6 +15,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)elf64_loader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)information.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)keys.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
@ -23,6 +24,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\callback.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader_self.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv1.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv2.h" />
@ -60,7 +62,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)scei\orbisos\syscalls\orbis_dynlib.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\pkg.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\self.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)system.h" />
</ItemGroup>
<ItemGroup>
@ -69,6 +70,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)loader.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader_self.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\hle_module.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\lv2.cpp" />
@ -102,7 +104,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)scei\orbisos\syscalls\orbis_dynlib.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\pkg.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)scei\self.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)system.cpp" />
</ItemGroup>
</Project>

View file

@ -124,9 +124,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h">
<Filter>scei</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)scei\self.h">
<Filter>scei</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.h">
@ -151,7 +148,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv2\sys_lwcond.h">
<Filter>scei\cellos\lv2</Filter>
</ClInclude>
<ClInclude Include="C:\Users\Alex\Documents\GitHub\nucleus\nucleus\system\scei\cellos\hle_macro.h">
<ClInclude Include="$(MSBuildThisFileDirectory)elf64_loader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\hle_macro.h" />
<ClInclude Include="C:\Users\Alex\Documents\GitHub\nucleus\nucleus\system\scei\cellos\cellos_loader_self.h">
<Filter>scei\cellos</Filter>
</ClInclude>
</ItemGroup>
@ -242,9 +241,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp">
<Filter>scei</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)scei\self.cpp">
<Filter>scei</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.cpp">
<Filter>scei\orbisos</Filter>
</ClCompile>
@ -268,5 +264,8 @@
<Filter>scei\cellos\lv2</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)system.cpp" />
<ClCompile Include="C:\Users\Alex\Documents\GitHub\nucleus\nucleus\system\scei\cellos\cellos_loader_self.cpp">
<Filter>scei\cellos</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -23,8 +23,9 @@ ScreenEmulator::ScreenEmulator(UI* manager) : Screen(manager) {
}
void ScreenEmulator::update() {
if (nucleus.gpu.get()) {
auto* appTexture = nucleus.gpu->getFrontBuffer();
gpu::GPU* gpu = m_emulator->gpu.get();
if (gpu) {
auto* appTexture = gpu->getFrontBuffer();
app->update(appTexture);
}
}

View file

@ -8,9 +8,15 @@
#include "nucleus/ui/screen.h"
#include "nucleus/ui/widgets/list.h"
// Forward declarations
class Emulator;
namespace ui {
class ScreenEmulator : public Screen {
private:
Emulator* m_emulator;
WidgetImage* app;
public:

View file

@ -10,6 +10,9 @@
#include "nucleus/ui/transitions.h"
#include "nucleus/ui/length.h"
#include "nucleus/emulator.h"
#include "nucleus/nucleus.h"
namespace ui {
ScreenLogo::ScreenLogo(UI* manager) : Screen(manager) {
@ -63,7 +66,7 @@ void ScreenLogo::update() {
// Next screen is loaded
if (dtime > 3000ms) {
if (bootApp) {
manager->pushScreen(std::make_unique<ScreenEmulator>(manager));
//manager->pushScreen(std::make_unique<ScreenEmulator>(manager));
} else {
manager->pushScreen(std::make_unique<ScreenMain>(manager));
}

View file

@ -50,7 +50,7 @@ void UI::task() {
screens.push_back(std::make_unique<ScreenLogo>(this));
#endif
while (true) {
surface.update(graphics.get());
surface.update(graphics);
const gfx::Viewport viewport = { 0, 0, surface.getWidth(), surface.getHeight() };
const gfx::Rectangle scissor = { 0, 0, surface.getWidth(), surface.getHeight() };

View file

@ -23,7 +23,7 @@ int main(int argc, char **argv) {
nucleusInitialize(window.hwnd, window.hdc, width, height);
auto thread = std::thread([]{
nucleusInitialize();
nucleusStart();
});
window.loop();
@ -31,7 +31,7 @@ int main(int argc, char **argv) {
// Using console
else {
nucleusInitialize();
nucleusStart();
}
return 0;