Skip to content

Commit

Permalink
Included initial OrbisOS / R10XX headers
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexAltea committed Apr 10, 2016
1 parent 4d04570 commit 1495301
Show file tree
Hide file tree
Showing 29 changed files with 250 additions and 78 deletions.
7 changes: 7 additions & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ keys.xml

# Logs
*.log

# IDA Pro
*.id0
*.id1
*.id2
*.nam
*.til
8 changes: 0 additions & 8 deletions nucleus/core/core.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\externals\sha1.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\emulator.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\fmt.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\keys.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\loader.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\psf.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\self.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\nucleus.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)config.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)resource.cpp" />
Expand All @@ -37,10 +33,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\endianness.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\feature.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\format.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\keys.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\loader.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\psf.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\self.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\macro.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\nucleus.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\platform.h" />
Expand Down
31 changes: 2 additions & 29 deletions nucleus/core/core.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\externals\sha1.cpp">
<Filter>externals</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\keys.cpp">
<Filter>loader</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\loader.cpp">
<Filter>loader</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\psf.cpp">
<Filter>loader</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\loader\self.cpp">
<Filter>loader</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)..\emulator.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\nucleus.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)resource.cpp" />
Expand All @@ -33,18 +21,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\externals\sha1.h">
<Filter>externals</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\keys.h">
<Filter>loader</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\loader.h">
<Filter>loader</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\psf.h">
<Filter>loader</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\loader\self.h">
<Filter>loader</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\assert.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\common.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\emulator.h" />
Expand All @@ -55,18 +31,15 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\types.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\architecture.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\compiler.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\platform.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)resource.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\target.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\feature.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\platform.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\target.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="externals">
<UniqueIdentifier>{e809ab99-fe03-4cdd-bb7b-b5f8c53f32a4}</UniqueIdentifier>
</Filter>
<Filter Include="loader">
<UniqueIdentifier>{2babb73a-fe6f-43bb-acfc-ef94369243b5}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)resource.inl" />
Expand Down
106 changes: 82 additions & 24 deletions nucleus/emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,76 @@
#include "nucleus/cpu/cell.h"
#include "nucleus/gpu/list.h"
#include "nucleus/filesystem/utils.h"
#include "nucleus/loader/self.h"
#include "nucleus/logger/logger.h"
#include "nucleus/memory/memory.h"
#include "nucleus/system/scei/cellos/lv2.h"
#include "nucleus/system/loader.h"
#include "nucleus/system/scei/self.h"
#include "nucleus/system/list.h"

// Global emulator object
Emulator nucleus;

/**
* Load specific platform
*/
bool Emulator::load_ps3(const std::string& path) {
// Initialize hardware
memory = std::make_shared<mem::Memory>();
cpu = std::make_shared<cpu::Cell>(memory);
gpu = std::make_shared<gpu::RSX>(memory, graphics);
sys = std::make_shared<sys::LV2>(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() != 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) {
// Initialize hardware
gpu = std::make_shared<gpu::R10XX>(graphics);
sys = std::make_shared<sys::OrbisOS>();

// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(path);
sys->vfs.registerDevice(new fs::HostPathDevice("/app0/", 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::OrbisOS*>(sys.get())->proc);
if (self.getMachine() != EM_X86_64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
return false;
}

auto entry = self.getEntry();
static_cast<sys::OrbisOS*>(sys.get())->init(entry);
return true;
}

bool Emulator::initialize(const gfx::BackendParameters& params) {
// Select graphics backend
switch (config.graphicsBackend) {
Expand Down Expand Up @@ -93,33 +155,29 @@ bool Emulator::initialize(const gfx::BackendParameters& params) {
}

bool Emulator::load(const std::string& filepath) {
// Initialize hardware
memory = std::make_shared<mem::Memory>();
cpu = std::make_shared<cpu::Cell>(memory);
gpu = std::make_shared<gpu::RSX>(memory, graphics);
sys = std::make_shared<sys::LV2>(memory, sys::LV2_DEX);

// Initialize application filesystem devices
const fs::Path& processPath = fs::getProcessPath(filepath);
sys->vfs.registerDevice(new fs::HostPathDevice("/app_home/", processPath));

// Load ELF/SELF file
SELFLoader self;
auto file = fs::HostFileSystem::openFile(filepath, fs::Read);
if (!self.open(file.get())) {
logger.error(LOG_COMMON, "Invalid file given.");
// TODO: This is not a good way of detecting a platform
core::Platform platform;
switch (detectFiletype(filepath)) {
case FILETYPE_SELF:
platform = core::PLATFORM_PS3;
break;
case FILETYPE_ELF:
platform = core::PLATFORM_PS4;
break;
default:
logger.error(LOG_COMMON, "Unsupported file");
return false;
}

self.load_elf(static_cast<sys::LV2*>(sys.get())->proc);
if (self.getMachine() != EM_PPC64) {
logger.error(LOG_COMMON, "Only PPC64 executables are allowed");
switch (platform) {
case core::PLATFORM_PS3:
return load_ps3(filepath);
case core::PLATFORM_PS4:
return load_ps4(filepath);
default:
logger.error(LOG_COMMON, "Unsupported platform");
return false;
}

auto entry = self.getEntry();
static_cast<sys::LV2*>(sys.get())->init(entry);
return true;
}

void Emulator::run() {
Expand Down
4 changes: 4 additions & 0 deletions nucleus/emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class Emulator {
EmulatorEvent m_event;
EmulatorStatus m_status;

// Load specific platform
bool load_ps3(const std::string& path);
bool load_ps4(const std::string& path);

public:
std::shared_ptr<audio::Backend> audio;
std::shared_ptr<gfx::IBackend> graphics;
Expand Down
1 change: 1 addition & 0 deletions nucleus/gpu/gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

// Forward declarations
namespace gfx { class Texture; }
namespace gfx { class IBackend; }

namespace gpu {

Expand Down
2 changes: 2 additions & 0 deletions nucleus/gpu/gpu.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)gpu.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)r10xx\r10xx.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)rsx\rsx.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)rsx\rsx_convert.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)rsx\rsx_dma.cpp" />
Expand All @@ -26,6 +27,7 @@
<ClInclude Include="$(MSBuildThisFileDirectory)gpu.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)gpu_hash.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)list.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)r10xx\r10xx.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rsx\rsx.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rsx\rsx_convert.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)rsx\rsx_dma.h" />
Expand Down
6 changes: 6 additions & 0 deletions nucleus/gpu/gpu.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)rsx\rsx_mmio.h">
<Filter>rsx</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)r10xx\r10xx.h">
<Filter>r10xx</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)rsx\rsx_pgraph.cpp">
Expand All @@ -63,6 +66,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)rsx\rsx_convert.cpp">
<Filter>rsx</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)r10xx\r10xx.cpp">
<Filter>r10xx</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)rsx\rsx_methods.inl">
Expand Down
4 changes: 2 additions & 2 deletions nucleus/gpu/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "nucleus/gpu/rsx/rsx.h"
#endif
#ifdef NUCLEUS_PLATFORM_PS4
//#include "nucleus/gpu/r10xx/r10xx.h"
#include "nucleus/gpu/r10xx/r10xx.h"
#endif

namespace gpu {
Expand All @@ -21,7 +21,7 @@ namespace gpu {
using RSX = rsx::RSX;
#endif
#ifdef NUCLEUS_PLATFORM_PS4
//using R10XX = r10xx::R10XX;
using R10XX = r10xx::R10XX;
#endif

} // namespace gpu
19 changes: 19 additions & 0 deletions nucleus/gpu/r10xx/r10xx.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
* Released under GPL v2 license. Read LICENSE for more details.
*/

#include "r10xx.h"

namespace gpu {
namespace r10xx {

R10XX::R10XX(std::shared_ptr<gfx::IBackend> graphics) {
}

gfx::Texture* R10XX::getFrontBuffer() {
return nullptr;
}

} // namespace r10xx
} // namespace gpu
23 changes: 23 additions & 0 deletions nucleus/gpu/r10xx/r10xx.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
* Released under GPL v2 license. Read LICENSE for more details.
*/

#pragma once

#include "nucleus/gpu/gpu.h"

#include <memory>

namespace gpu {
namespace r10xx {

class R10XX : public GPU {
public:
R10XX(std::shared_ptr<gfx::IBackend> graphics);

virtual gfx::Texture* getFrontBuffer() override;
};

} // namespace r10xx
} // namespace gpu
1 change: 0 additions & 1 deletion nucleus/nucleus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ int nucleusInitialize(int argc, char **argv) {

// Start emulator
if (!config.boot.empty()) {

nucleus.load(config.boot);
nucleus.run();
nucleus.idle();
Expand Down
2 changes: 2 additions & 0 deletions nucleus/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
namespace core {

enum Platform {
PLATFORM_UNKNOWN = 0,

PLATFORM_PS3,
PLATFORM_PS4,
PLATFORM_PSP,
Expand Down
File renamed without changes.
File renamed without changes.
28 changes: 28 additions & 0 deletions nucleus/system/list.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
* Released under GPL v2 license. Read LICENSE for more details.
*/

#pragma once

#include "nucleus/common.h"

#ifdef NUCLEUS_PLATFORM_PS3
#include "nucleus/system/scei/cellos/lv1.h"
#include "nucleus/system/scei/cellos/lv2.h"
#endif
#ifdef NUCLEUS_PLATFORM_PS4
#include "nucleus/system/scei/orbisos/orbisos.h"
#endif

namespace sys {

// Shorthands
#ifdef NUCLEUS_PLATFORM_PS3
using LV2 = sys::LV2;
#endif
#ifdef NUCLEUS_PLATFORM_PS4
using OrbisOS = sys::scei::orbis::OrbisOS;
#endif

} // namespace sys
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion nucleus/system/scei/cellos/lv2/sys_prx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include "nucleus/system/scei/cellos/callback.h"
#include "nucleus/system/scei/cellos/lv2.h"
#include "nucleus/system/scei/cellos/lv2/sys_process.h"
#include "nucleus/loader/self.h"
#include "nucleus/system/scei/self.h"

namespace sys {

Expand Down
Loading

8 comments on commit 1495301

@theoldsport
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OrbisOS eh?... Seems ambitious! I understand this is just a foundation, but do you have bigger plans?

@AlexAltea
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theoldsport, Just trying to get PS4 userland emulation à la WINE working. :-)

My main goal is still the PS3, but since all filesystem/graphics/system/etc. libraries are platform-agnostic, even working on the PS4 would result in improvements in backends that the PS3 related frontends use.

@theoldsport
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexAltea, Oh that's interesting, I had no idea the libraries were platform-agnostic.

I've heard the WINE-esque route would be the most practical. Not quite orthodox, but very cool! What do you consider the toughest challenge at this stage? (concerning PS3 or PS4 emulation)

@AlexAltea
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theoldsport,

What do you consider the toughest challenge at this stage? (concerning PS3 or PS4 emulation)

Reverse engineering the kernel and system libraries (takes really a long time), or writing the frontend of the binary translator (it's really easy to do something wrong). But that's just annoying/tiring and not really as "tough" as writing the backends of some of those platform-agnostic libraries, particularly the compilers in /cpu and the backends in /graphics.

I've heard the WINE-esque route would be the most practical. Not quite orthodox, but very cool!

Yeah, going for low-level emulation will be extremely difficult for a long time. So the only choice at the moment is whether doing userland emulation with or without recompiling x86_64 binaries. For now just loading the binaries without recompiling like WINE does should be enough for testing, If it succeeds of course I'll write a x86_64 frontend.

@hlide
Copy link

@hlide hlide commented on 1495301 Apr 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering that PS4 is based on x86-64 AMD "Jaguar", you could think it is a simple matter to run it on our "beloved" intel PC, hence mentioning WINE. Good idea, but I see two issues:

  • use of FS and GS selector may be a trouble to handle : flinux : Foreign LINUX - Run unmodified Linux applications inside Windows. Linux and Windows has a different way to use them. If I recall well, flinux scan the program when loading to patch them.
  • Jaguar has probably some AMD specific instructions to deal with when trying to run on Intel cpu. Jaguar has MMX, SSE, SSE2, SSE3, SSSE3, SSE4a, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE/XSAVEOPT, ABM (POPCNT/LZCNT), and AMD-V. Amongst them, SSE4a, ABM and AMD-V need to be handled as they are AMD specific.

@AlexAltea
Copy link
Owner Author

@AlexAltea AlexAltea commented on 1495301 Apr 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hlide, Oh, I didn't know about flinux, I'll have a look into that, thank you! Yes, I intended to swap FS and GS while loading the ELF/PRX files.

Concerning custom instructions (or stuff like syscall), I would just patch them with jumps to equivalent code. If that's not possible due to lack of bytes in the original instruction, then I would trap the illegal instruction exception [1] and run equivalent code in the handler.

[1] http://blog.ghettoha.xxx/executing-bsd-elfs-in-windows/

@hlide
Copy link

@hlide hlide commented on 1495301 Apr 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexAltea swapping FS and GS won't do:

  • the structures pointed by FS/GS are different between Windows and Linux. I guess it is the same for OrbisOS. So "poking" through FS/GS is the best way to crash your application. Flinux tried to do something like that but had a lot issue so there was no way else avoiding using FS/GS by patching them.
  • 32-bit Windows (I think it is irrelevant for your project) has a GS selector set to null selector whenever a task switch occurs - making the use of GS almost impossible. Not your case because you need to run in 64-bit windows.
  • hackBox (I didn't remember exactly the name) emulator running as a 64-bit process (so GS is used and interrupts would be okay as long as GS is not touched) had a nasty trick to use FS for XBOX (first gen.) OS by running the XBOX cpu in a 32-bit thread. But there is awful price to pay: before going to XBOX code, it saves the windows content of FS to store the XBOX content of FS instead. Whenever you need to call a Windows native function, you must save the XBOX content of FS and restore the original window content of FS back. As you can see, you need to do 4 "memcpy" per XBOX/Windows switch. I was told it was very slow. In your case, even this slow trick won't even work because you're running a 64-bit thread (you cannot do the same with GS selector because of interrupts and stuff like that).

EDIT: good link ! but I'm still unsure it is safe to write fsbase because windows keeps FS for 32-bit threads running on 64-bit windows.

@hlide
Copy link

@hlide hlide commented on 1495301 Apr 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I read the two methods related to FS hack. They look very interesting. I guess they may work as long as there is no attempt to call a function of a 32-bit library inside a 64-bit program.

Please sign in to comment.