mirror of
https://github.com/AlexAltea/nucleus.git
synced 2024-06-12 17:27:39 -04:00
Fixed SELF loader issues
This commit is contained in:
parent
ee3e611cc8
commit
cca12b2990
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -40,6 +40,7 @@ UpgradeLog.htm
|
||||||
*.sdf
|
*.sdf
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
|
*.tmp
|
||||||
*.db
|
*.db
|
||||||
|
|
||||||
# CLion files
|
# CLion files
|
||||||
|
|
12
nucleus.sln
12
nucleus.sln
|
@ -80,18 +80,6 @@ Global
|
||||||
nucleus\system\system.vcxitems*{2d4b90ed-c848-4d60-bf54-7d660405b653}*SharedItemsImports = 9
|
nucleus\system\system.vcxitems*{2d4b90ed-c848-4d60-bf54-7d660405b653}*SharedItemsImports = 9
|
||||||
nucleus\debugger\debugger.vcxitems*{30b5f783-76c3-4f96-a9e5-cd221e73b0a2}*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*{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\logger\logger.vcxitems*{5b8b6a6c-001e-4a74-8fba-6b82cfbf12ab}*SharedItemsImports = 9
|
||||||
nucleus\audio\backend\audio-xaudio2.vcxitems*{623f605f-427f-4b3e-93a1-e644a70543aa}*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
|
nucleus\filesystem\filesystem.vcxitems*{7ec60005-180c-4cc7-ae7c-a0c3058f4f26}*SharedItemsImports = 9
|
||||||
|
|
|
@ -11,12 +11,9 @@
|
||||||
#include "nucleus/cpu/cpu_host.h"
|
#include "nucleus/cpu/cpu_host.h"
|
||||||
#include "nucleus/ui/ui.h"
|
#include "nucleus/ui/ui.h"
|
||||||
#include "nucleus/gpu/list.h"
|
#include "nucleus/gpu/list.h"
|
||||||
#include "nucleus/filesystem/utils.h"
|
|
||||||
#include "nucleus/logger/logger.h"
|
#include "nucleus/logger/logger.h"
|
||||||
#include "nucleus/memory/list.h"
|
#include "nucleus/memory/list.h"
|
||||||
#include "nucleus/system/loader.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"
|
#include "nucleus/system/list.h"
|
||||||
|
|
||||||
#if !defined(NUCLEUS_BUILD_TEST)
|
#if !defined(NUCLEUS_BUILD_TEST)
|
||||||
|
@ -25,63 +22,19 @@
|
||||||
* Load specific platform
|
* Load specific platform
|
||||||
*/
|
*/
|
||||||
bool Emulator::load_ps3(const std::string& path) {
|
bool Emulator::load_ps3(const std::string& path) {
|
||||||
// Initialize hardware
|
|
||||||
memory = std::make_shared<mem::GuestVirtualMemory>(4_GB);
|
memory = std::make_shared<mem::GuestVirtualMemory>(4_GB);
|
||||||
cpu = std::make_shared<cpu::GuestCPU>(this, memory.get());
|
cpu = std::make_shared<cpu::GuestCPU>(this, memory.get());
|
||||||
gpu = std::make_shared<gpu::RSX>(this, memory.get(), graphics);
|
gpu = std::make_shared<gpu::RSX>(this, memory.get(), graphics);
|
||||||
sys = std::make_shared<sys::LV2>(this, memory, sys::LV2_DEX);
|
sys = std::make_shared<sys::LV2>(this, memory, sys::LV2_DEX);
|
||||||
|
return sys->start(path);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::load_ps4(const std::string& path) {
|
bool Emulator::load_ps4(const std::string& path) {
|
||||||
// Initialize hardware
|
|
||||||
memory = std::make_shared<mem::HostVirtualMemory>();
|
memory = std::make_shared<mem::HostVirtualMemory>();
|
||||||
cpu = std::make_shared<cpu::HostCPU>(this, memory.get());
|
cpu = std::make_shared<cpu::HostCPU>(this, memory.get());
|
||||||
gpu = std::make_shared<gpu::R10XX>(this, graphics);
|
gpu = std::make_shared<gpu::R10XX>(this, graphics);
|
||||||
sys = std::make_shared<sys::OrbisOS>(this);
|
sys = std::make_shared<sys::OrbisOS>(this);
|
||||||
|
return sys->start(path);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::load(const std::string& filepath) {
|
bool Emulator::load(const std::string& filepath) {
|
||||||
|
|
|
@ -691,6 +691,215 @@ bool Direct3D12Shader::initialize(const ShaderDesc& desc) {
|
||||||
|
|
||||||
std::string source = compile(module);
|
std::string source = compile(module);
|
||||||
// std::cout << source << std::endl;
|
// 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;
|
LPCSTR target;
|
||||||
switch (desc.type) {
|
switch (desc.type) {
|
||||||
|
|
|
@ -111,17 +111,20 @@ void GuestVirtualMemory::write128(U64 addr, U128 value) {
|
||||||
*(U128*)((U64)m_base + addr) = SE128(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) {
|
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
|
} // namespace mem
|
||||||
|
|
|
@ -67,4 +67,25 @@ void HostVirtualMemory::write128(U64 addr, U128 value) {
|
||||||
*reinterpret_cast<U128*>(addr) = 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
|
} // namespace mem
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "nucleus/common.h"
|
||||||
|
|
||||||
#if defined(NUCLEUS_TARGET_LINUX)
|
#if defined(NUCLEUS_TARGET_LINUX)
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#elif defined(NUCLEUS_TARGET_UWP)
|
#elif defined(NUCLEUS_TARGET_UWP)
|
||||||
|
@ -19,12 +21,13 @@ void nucleusInitialize(Display* display, Window window, int width, int height);
|
||||||
#elif defined(NUCLEUS_TARGET_UWP)
|
#elif defined(NUCLEUS_TARGET_UWP)
|
||||||
void nucleusInitialize(IUnknown* window, int width, int height);
|
void nucleusInitialize(IUnknown* window, int width, int height);
|
||||||
#elif defined(NUCLEUS_TARGET_WINDOWS)
|
#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
|
#endif
|
||||||
|
|
||||||
void nucleusConfigure(int argc, char** argv);
|
void nucleusConfigure(int argc, char** argv);
|
||||||
bool nucleusStart();
|
bool nucleusStart();
|
||||||
void nucleusIdle();
|
void nucleusIdle();
|
||||||
|
void nucleusFinalize();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
void nucleusOnWindowSizeChanged(unsigned int width, unsigned int height);
|
void nucleusOnWindowSizeChanged(unsigned int width, unsigned int height);
|
||||||
|
|
116
nucleus/system/elf64_loader.h
Normal file
116
nucleus/system/elf64_loader.h
Normal 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
|
|
@ -4,10 +4,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cellos_loader.h"
|
#include "cellos_loader.h"
|
||||||
|
#include "nucleus/filesystem/filesystem_host.h"
|
||||||
#include "nucleus/logger/logger.h"
|
#include "nucleus/logger/logger.h"
|
||||||
#include "nucleus/system/scei/self.h"
|
|
||||||
#include "nucleus/system/elf64.h"
|
#include "nucleus/system/elf64.h"
|
||||||
#include "nucleus/system/loader.h"
|
#include "nucleus/system/loader.h"
|
||||||
|
#include "cellos_loader_self.h"
|
||||||
|
|
||||||
namespace sys {
|
namespace sys {
|
||||||
namespace scei {
|
namespace scei {
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
#include "nucleus/common.h"
|
#include "nucleus/common.h"
|
||||||
|
|
||||||
#include "nucleus/filesystem/filesystem_host.h"
|
// Forward declarations
|
||||||
|
namespace fs { class File; }
|
||||||
|
|
||||||
namespace sys {
|
namespace sys {
|
||||||
namespace scei {
|
namespace scei {
|
||||||
|
|
|
@ -3,23 +3,29 @@
|
||||||
* Released under GPL v2 license. Read LICENSE for more details.
|
* Released under GPL v2 license. Read LICENSE for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "self.h"
|
#include "cellos_loader_self.h"
|
||||||
#include "nucleus/common.h"
|
#include "nucleus/common.h"
|
||||||
#include "nucleus/core/config.h"
|
#include "nucleus/core/config.h"
|
||||||
#include "nucleus/emulator.h"
|
#include "nucleus/emulator.h"
|
||||||
#include "nucleus/cpu/cpu_guest.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/cpu/frontend/ppu/ppu_decoder.h"
|
||||||
#include "nucleus/system/keys.h"
|
#include "nucleus/system/keys.h"
|
||||||
#include "nucleus/system/loader.h"
|
#include "nucleus/system/loader.h"
|
||||||
#include "nucleus/logger/logger.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/aes.h"
|
||||||
#include "externals/zlib/zlib.h"
|
#include "externals/zlib/zlib.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
using namespace sys;
|
namespace sys {
|
||||||
|
namespace scei {
|
||||||
|
namespace cellos {
|
||||||
|
|
||||||
bool SELFLoader::open(fs::File* file)
|
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) {
|
if (!file) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -55,11 +61,13 @@ bool SELFLoader::open(const std::string& path)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SELFLoader::load_elf(sys::sys_process_t& proc)
|
bool SELFLoader::load_elf(LV2* lv2)
|
||||||
{
|
{
|
||||||
if (elf.empty()) {
|
if (elf.empty()) {
|
||||||
return false;
|
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];
|
const auto& ehdr = (Ehdr&)elf[0];
|
||||||
|
|
||||||
|
@ -73,18 +81,18 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
nucleus.memory->getSegment(mem::SEG_MAIN_MEMORY).allocFixed(phdr.vaddr, phdr.memsz);
|
mem->getSegment(mem::SEG_MAIN_MEMORY).allocFixed(phdr.vaddr, phdr.memsz);
|
||||||
memcpy(nucleus.memory->ptr(phdr.vaddr), &elf[phdr.offset], phdr.filesz);
|
mem->memcpy_h2g(phdr.vaddr, &elf[phdr.offset], phdr.filesz);
|
||||||
if (phdr.flags & PF_X) {
|
if (phdr.flags & PF_X) {
|
||||||
auto module = new cpu::frontend::ppu::Module(nucleus.cpu.get());
|
auto module = new cpu::frontend::ppu::Module(cpu);
|
||||||
module->parent = nucleus.cpu.get();
|
module->parent = cpu;
|
||||||
module->address = phdr.vaddr;
|
module->address = phdr.vaddr;
|
||||||
module->size = phdr.filesz;
|
module->size = phdr.filesz;
|
||||||
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
|
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
|
||||||
module->analyze();
|
module->analyze();
|
||||||
module->recompile();
|
module->recompile();
|
||||||
}
|
}
|
||||||
static_cast<cpu::Cell*>(nucleus.cpu.get())->ppu_modules.push_back(module);
|
cpu->ppu_modules.push_back(module);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -92,20 +100,23 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
|
||||||
// TODO: ?
|
// TODO: ?
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case PT_PROC_PARAM:
|
case PT_PROC_PARAM:
|
||||||
if (!phdr.filesz) {
|
if (!phdr.filesz) {
|
||||||
proc.param.sdk_version = 0xFFFFFFFF;
|
lv2->proc.param.sdk_version = 0xFFFFFFFF;
|
||||||
proc.param.malloc_pagesize = 0x100000;
|
lv2->proc.param.malloc_pagesize = 0x100000;
|
||||||
} else {
|
}
|
||||||
proc.param = (sys::sys_process_param_t&)elf[phdr.offset];
|
else {
|
||||||
|
lv2->proc.param = (sys::sys_process_param_t&)elf[phdr.offset];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PT_PRX_PARAM:
|
case PT_PRX_PARAM:
|
||||||
if (!phdr.filesz) {
|
if (!phdr.filesz) {
|
||||||
logger.error(LOG_LOADER, "Invalid PRX_PARAM segment");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -113,12 +124,15 @@ bool SELFLoader::load_elf(sys::sys_process_t& proc)
|
||||||
return true;
|
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()) {
|
if (elf.empty()) {
|
||||||
return false;
|
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];
|
const auto& ehdr = (Ehdr&)elf[0];
|
||||||
U32 base_addr;
|
U32 base_addr;
|
||||||
|
|
||||||
|
@ -128,8 +142,8 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
|
||||||
|
|
||||||
if (phdr.type == PT_LOAD) {
|
if (phdr.type == PT_LOAD) {
|
||||||
// Allocate memory and copy segment contents
|
// Allocate memory and copy segment contents
|
||||||
const U32 addr = nucleus.memory->getSegment(mem::SEG_MAIN_MEMORY).alloc(phdr.memsz, 0x10000);
|
const U32 addr = mem->getSegment(mem::SEG_MAIN_MEMORY).alloc(phdr.memsz, 0x10000);
|
||||||
memcpy(nucleus.memory->ptr(addr), &elf[phdr.offset], phdr.filesz);
|
mem->memcpy_h2g(addr, &elf[phdr.offset], phdr.filesz);
|
||||||
|
|
||||||
// Add information for PRX Object
|
// Add information for PRX Object
|
||||||
sys::sys_prx_segment_t segment;
|
sys::sys_prx_segment_t segment;
|
||||||
|
@ -226,22 +240,22 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
|
||||||
switch (rel.type.ToLE()) {
|
switch (rel.type.ToLE()) {
|
||||||
case R_PPC64_ADDR32:
|
case R_PPC64_ADDR32:
|
||||||
value = (U32)prx.segments[rel.index_value].addr + rel.ptr;
|
value = (U32)prx.segments[rel.index_value].addr + rel.ptr;
|
||||||
nucleus.memory->write32(addr, value);
|
mem->write32(addr, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC64_ADDR16_LO:
|
case R_PPC64_ADDR16_LO:
|
||||||
value = (U16)rel.ptr;
|
value = (U16)rel.ptr;
|
||||||
nucleus.memory->write16(addr, value);
|
mem->write16(addr, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC64_ADDR16_HI:
|
case R_PPC64_ADDR16_HI:
|
||||||
value = (U16)(prx.segments[rel.index_value].addr >> 16);
|
value = (U16)(prx.segments[rel.index_value].addr >> 16);
|
||||||
nucleus.memory->write16(addr, value);
|
mem->write16(addr, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC64_ADDR16_HA:
|
case R_PPC64_ADDR16_HA:
|
||||||
value = (U16)(prx.segments[1].addr >> 16);
|
value = (U16)(prx.segments[1].addr >> 16);
|
||||||
nucleus.memory->write16(addr, value);
|
mem->write16(addr, value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -262,7 +276,7 @@ bool SELFLoader::load_prx(sys::sys_prx_t& prx)
|
||||||
const sys::sys_prx_library_t* targetLibrary = nullptr;
|
const sys::sys_prx_library_t* targetLibrary = nullptr;
|
||||||
|
|
||||||
// Find library (TODO: This is very inefficient)
|
// 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) {
|
if (object.second->getType() == sys::SYS_PRX_OBJECT) {
|
||||||
const auto* imported_prx = (sys::sys_prx_t*)object.second->getData();
|
const auto* imported_prx = (sys::sys_prx_t*)object.second->getData();
|
||||||
for (const auto& exportedLib : imported_prx->exported_libs) {
|
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) {
|
for (const auto& import : importedLib.exports) {
|
||||||
const U32 fnid = import.first;
|
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
|
// Recompile executable segments
|
||||||
for (auto& prx_segment : prx.segments) {
|
for (auto& prx_segment : prx.segments) {
|
||||||
if (prx_segment.flags & PF_X) {
|
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->address = prx_segment.addr;
|
||||||
segment->size = prx_segment.size_file;
|
segment->size = prx_segment.size_file;
|
||||||
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
|
if (config.ppuTranslator & CPU_TRANSLATOR_MODULE) {
|
||||||
segment->analyze();
|
segment->analyze();
|
||||||
segment->recompile();
|
segment->recompile();
|
||||||
}
|
}
|
||||||
static_cast<cpu::Cell*>(nucleus.cpu.get())->ppu_modules.push_back(segment);
|
cpu->ppu_modules.push_back(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -496,3 +510,35 @@ U64 SELFLoader::getEntry()
|
||||||
const auto& ehdr = (Ehdr&)elf[0];
|
const auto& ehdr = (Ehdr&)elf[0];
|
||||||
return ehdr.entry;
|
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
|
|
@ -6,14 +6,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "nucleus/common.h"
|
#include "nucleus/common.h"
|
||||||
#include "nucleus/filesystem/file.h"
|
#include "nucleus/system/elf64_loader.h"
|
||||||
#include "nucleus/system/elf64.h"
|
|
||||||
#include "nucleus/system/scei/cellos/lv2/sys_process.h"
|
|
||||||
#include "nucleus/system/scei/cellos/lv2/sys_prx.h"
|
#include "nucleus/system/scei/cellos/lv2/sys_prx.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
namespace sys { class LV2; }
|
||||||
|
|
||||||
|
namespace sys {
|
||||||
|
namespace scei {
|
||||||
|
namespace cellos {
|
||||||
|
|
||||||
// ELF ABI
|
// ELF ABI
|
||||||
enum {
|
enum {
|
||||||
ELFOSABI_CELL_LV2 = 0x66,
|
ELFOSABI_CELL_LV2 = 0x66,
|
||||||
|
@ -157,29 +163,39 @@ struct ControlInfo {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class SELFLoader {
|
/**
|
||||||
using Ehdr = sys::Elf64_Ehdr<BE>;
|
* SELF Loader
|
||||||
using Phdr = sys::Elf64_Phdr<BE>;
|
* ============
|
||||||
using Shdr = sys::Elf64_Shdr<BE>;
|
* Parses SELF files.
|
||||||
|
* @tparam E Endianness
|
||||||
|
*/
|
||||||
|
class SELFLoader : public Elf64Loader<BE> {
|
||||||
|
protected:
|
||||||
std::vector<Byte> elf; // Holds the decrypted executable
|
std::vector<Byte> elf; // Holds the decrypted executable
|
||||||
std::vector<Byte> self; // Holds the encrypted 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();
|
bool decryptMetadata();
|
||||||
|
|
||||||
// Returns the size of the ELF file after the SELF decryption/decompression
|
// Returns the size of the ELF file after the SELF decryption/decompression
|
||||||
// by using accessing the SELF's EHDR and decrypted Metadata headers.
|
// by using accessing the SELF's EHDR and decrypted Metadata headers.
|
||||||
U32 getDecryptedElfSize();
|
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:
|
public:
|
||||||
bool open(fs::File* file);
|
bool open(fs::File* file);
|
||||||
bool open(const std::string& path);
|
bool open(LV2* lv2, const std::string& path);
|
||||||
bool load_elf(sys::sys_process_t& proc);
|
bool load_elf(LV2* lv2);
|
||||||
bool load_prx(sys::sys_prx_t& prx);
|
bool load_prx(LV2* lv2, sys::sys_prx_t& prx);
|
||||||
bool decrypt();
|
bool decrypt();
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
U16 getMachine();
|
U16 getMachine();
|
||||||
U64 getEntry();
|
U64 getEntry();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace cellos
|
||||||
|
} // namespace scei
|
||||||
|
} // namespace sys
|
|
@ -6,8 +6,11 @@
|
||||||
#include "lv2.h"
|
#include "lv2.h"
|
||||||
#include "nucleus/emulator.h"
|
#include "nucleus/emulator.h"
|
||||||
#include "nucleus/filesystem/filesystem_app.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/logger/logger.h"
|
||||||
#include "nucleus/system/scei/cellos/callback.h"
|
#include "nucleus/system/scei/cellos/callback.h"
|
||||||
|
#include "cellos_loader_self.h"
|
||||||
|
|
||||||
#include "lv2/sys_cond.h"
|
#include "lv2/sys_cond.h"
|
||||||
#include "lv2/sys_config.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());
|
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
|
} // namespace sys
|
||||||
|
|
|
@ -126,6 +126,8 @@ public:
|
||||||
|
|
||||||
// Get LV2 SysCall ID from the current thread and call it
|
// Get LV2 SysCall ID from the current thread and call it
|
||||||
void call(cpu::frontend::ppu::PPUState& state);
|
void call(cpu::frontend::ppu::PPUState& state);
|
||||||
|
|
||||||
|
bool start(const std::string& path);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sys
|
} // namespace sys
|
||||||
|
|
|
@ -10,13 +10,13 @@
|
||||||
#include "nucleus/core/config.h"
|
#include "nucleus/core/config.h"
|
||||||
#include "nucleus/system/scei/cellos/callback.h"
|
#include "nucleus/system/scei/cellos/callback.h"
|
||||||
#include "nucleus/system/scei/cellos/lv2/sys_process.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"
|
#include "../lv2.h"
|
||||||
|
|
||||||
namespace sys {
|
namespace sys {
|
||||||
|
|
||||||
HLE_FUNCTION(sys_prx_load_module, const S08* path, U64 flags, sys_prx_load_module_option_t* pOpt) {
|
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);
|
auto file = kernel.vfs.openFile(path, fs::Read);
|
||||||
if (!self.open(file)) {
|
if (!self.open(file)) {
|
||||||
return CELL_PRX_ERROR_UNKNOWN_MODULE;
|
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
|
// Load PRX into memory
|
||||||
auto* prx = new sys_prx_t();
|
auto* prx = new sys_prx_t();
|
||||||
if (!self.load_prx(*prx)) {
|
if (!self.load_prx(&kernel, *prx)) {
|
||||||
delete prx;
|
delete prx;
|
||||||
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
|
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,12 +46,6 @@ class SELFLoader {
|
||||||
std::vector<Byte> elf; // Holds the decrypted executable
|
std::vector<Byte> elf; // Holds the decrypted executable
|
||||||
std::vector<Byte> self; // Holds the encrypted 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:
|
public:
|
||||||
bool open(fs::File* file);
|
bool open(fs::File* file);
|
||||||
void* load();
|
void* load();
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "orbisos.h"
|
#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"
|
#include "syscalls/orbis_dynlib.h"
|
||||||
|
|
||||||
|
@ -315,6 +319,31 @@ bool OrbisOS::init(U64 entry) {
|
||||||
return !sys_dynlib_load_prx(nullptr, &args);
|
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 orbis
|
||||||
} // namespace scei
|
} // namespace scei
|
||||||
} // namespace sys
|
} // namespace sys
|
||||||
|
|
|
@ -135,6 +135,8 @@ public:
|
||||||
* @param[in] entry Module entry point
|
* @param[in] entry Module entry point
|
||||||
*/
|
*/
|
||||||
bool init(U64 entry);
|
bool init(U64 entry);
|
||||||
|
|
||||||
|
bool start(const std::string& path);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace orbis
|
} // namespace orbis
|
||||||
|
|
|
@ -25,6 +25,13 @@ public:
|
||||||
* @return Emulator object
|
* @return Emulator object
|
||||||
*/
|
*/
|
||||||
Emulator* getEmulator() const;
|
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
|
} // namespace sys
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
|
||||||
|
<ClInclude Include="$(MSBuildThisFileDirectory)elf64_loader.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)information.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)information.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)keys.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)keys.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\callback.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\callback.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader.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.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv2.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\orbisos\syscalls\orbis_dynlib.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\pkg.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\pkg.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\self.h" />
|
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)system.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)system.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -69,6 +70,7 @@
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)loader.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)loader.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_info.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\cellos_loader.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\hle_module.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\lv1\lv1_gpu.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\cellos\lv2.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\orbisos\syscalls\orbis_dynlib.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\pkg.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\pkg.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp" />
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\self.cpp" />
|
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)system.cpp" />
|
<ClCompile Include="$(MSBuildThisFileDirectory)system.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -124,9 +124,6 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h">
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\psf.h">
|
||||||
<Filter>scei</Filter>
|
<Filter>scei</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\self.h">
|
|
||||||
<Filter>scei</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
|
<ClInclude Include="$(MSBuildThisFileDirectory)elf64.h" />
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.h">
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.h">
|
||||||
|
@ -151,7 +148,9 @@
|
||||||
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv2\sys_lwcond.h">
|
<ClInclude Include="$(MSBuildThisFileDirectory)scei\cellos\lv2\sys_lwcond.h">
|
||||||
<Filter>scei\cellos\lv2</Filter>
|
<Filter>scei\cellos\lv2</Filter>
|
||||||
</ClInclude>
|
</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>
|
<Filter>scei\cellos</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -242,9 +241,6 @@
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp">
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\psf.cpp">
|
||||||
<Filter>scei</Filter>
|
<Filter>scei</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\self.cpp">
|
|
||||||
<Filter>scei</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.cpp">
|
<ClCompile Include="$(MSBuildThisFileDirectory)scei\orbisos\orbis_self.cpp">
|
||||||
<Filter>scei\orbisos</Filter>
|
<Filter>scei\orbisos</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -268,5 +264,8 @@
|
||||||
<Filter>scei\cellos\lv2</Filter>
|
<Filter>scei\cellos\lv2</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="$(MSBuildThisFileDirectory)system.cpp" />
|
<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>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -23,8 +23,9 @@ ScreenEmulator::ScreenEmulator(UI* manager) : Screen(manager) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenEmulator::update() {
|
void ScreenEmulator::update() {
|
||||||
if (nucleus.gpu.get()) {
|
gpu::GPU* gpu = m_emulator->gpu.get();
|
||||||
auto* appTexture = nucleus.gpu->getFrontBuffer();
|
if (gpu) {
|
||||||
|
auto* appTexture = gpu->getFrontBuffer();
|
||||||
app->update(appTexture);
|
app->update(appTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,15 @@
|
||||||
#include "nucleus/ui/screen.h"
|
#include "nucleus/ui/screen.h"
|
||||||
#include "nucleus/ui/widgets/list.h"
|
#include "nucleus/ui/widgets/list.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class Emulator;
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
class ScreenEmulator : public Screen {
|
class ScreenEmulator : public Screen {
|
||||||
|
private:
|
||||||
|
Emulator* m_emulator;
|
||||||
|
|
||||||
WidgetImage* app;
|
WidgetImage* app;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#include "nucleus/ui/transitions.h"
|
#include "nucleus/ui/transitions.h"
|
||||||
#include "nucleus/ui/length.h"
|
#include "nucleus/ui/length.h"
|
||||||
|
|
||||||
|
#include "nucleus/emulator.h"
|
||||||
|
#include "nucleus/nucleus.h"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
ScreenLogo::ScreenLogo(UI* manager) : Screen(manager) {
|
ScreenLogo::ScreenLogo(UI* manager) : Screen(manager) {
|
||||||
|
@ -63,7 +66,7 @@ void ScreenLogo::update() {
|
||||||
// Next screen is loaded
|
// Next screen is loaded
|
||||||
if (dtime > 3000ms) {
|
if (dtime > 3000ms) {
|
||||||
if (bootApp) {
|
if (bootApp) {
|
||||||
manager->pushScreen(std::make_unique<ScreenEmulator>(manager));
|
//manager->pushScreen(std::make_unique<ScreenEmulator>(manager));
|
||||||
} else {
|
} else {
|
||||||
manager->pushScreen(std::make_unique<ScreenMain>(manager));
|
manager->pushScreen(std::make_unique<ScreenMain>(manager));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ void UI::task() {
|
||||||
screens.push_back(std::make_unique<ScreenLogo>(this));
|
screens.push_back(std::make_unique<ScreenLogo>(this));
|
||||||
#endif
|
#endif
|
||||||
while (true) {
|
while (true) {
|
||||||
surface.update(graphics.get());
|
surface.update(graphics);
|
||||||
const gfx::Viewport viewport = { 0, 0, surface.getWidth(), surface.getHeight() };
|
const gfx::Viewport viewport = { 0, 0, surface.getWidth(), surface.getHeight() };
|
||||||
const gfx::Rectangle scissor = { 0, 0, surface.getWidth(), surface.getHeight() };
|
const gfx::Rectangle scissor = { 0, 0, surface.getWidth(), surface.getHeight() };
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
nucleusInitialize(window.hwnd, window.hdc, width, height);
|
nucleusInitialize(window.hwnd, window.hdc, width, height);
|
||||||
auto thread = std::thread([]{
|
auto thread = std::thread([]{
|
||||||
nucleusInitialize();
|
nucleusStart();
|
||||||
});
|
});
|
||||||
|
|
||||||
window.loop();
|
window.loop();
|
||||||
|
@ -31,7 +31,7 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
// Using console
|
// Using console
|
||||||
else {
|
else {
|
||||||
nucleusInitialize();
|
nucleusStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue