Skip to content

Commit

Permalink
Merge branch 'obhq:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
SuchAFuriousDeath committed May 10, 2024
2 parents 3e9dd7e + 4512e9c commit a9d876e
Show file tree
Hide file tree
Showing 76 changed files with 4,220 additions and 1,881 deletions.
27 changes: 4 additions & 23 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"configurations": [
{
"name": "Debug - Main",
"name": "Frontend",
"type": "lldb",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder}",
"windows": {
"program": "${workspaceFolder}/build/src/Debug/Obliteration.exe",
"program": "${workspaceFolder}/build/src/Obliteration.exe",
"env": {
"Path": "${env:Path};${env:CMAKE_PREFIX_PATH}\\bin"
}
Expand All @@ -20,34 +20,15 @@
}
},
{
"name": "Debug - Kernel",
"name": "Kernel | Debug",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/src/target/debug/obkrnl",
"args": ["--debug"],
"cwd": "${workspaceFolder}"
},
{
"name": "Release - Main",
"type": "lldb",
"request": "launch",
"args": [],
"cwd": "${workspaceFolder}",
"windows": {
"program": "${workspaceFolder}/build/src/Release/Obliteration.exe",
"env": {
"Path": "${env:Path};${env:CMAKE_PREFIX_PATH}\\bin"
}
},
"linux": {
"program": "${workspaceFolder}/build/src/obliteration"
},
"osx": {
"program": "${workspaceFolder}/build/src/obliteration.app/Contents/MacOS/obliteration"
}
},
{
"name": "Release - Kernel",
"name": "Kernel | Release",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/src/target/release/obkrnl",
Expand Down
4 changes: 1 addition & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
{
"cmake.configureOnOpen": true,
"cmake.debugConfig": {
"cwd": "${workspaceFolder}"
},
"cmake.skipConfigureIfCachePresent": true,
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"lldb.launch.initCommands": [
"settings set target.x86-disassembly-flavor intel"
],
"rust-analyzer.imports.granularity.group": "module",
"rust-analyzer.imports.group.enable": false,
"[rust]": {
"editor.defaultFormatter": "rust-lang.rust-analyzer",
"editor.formatOnSave": true
}
}
135 changes: 9 additions & 126 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,147 +33,30 @@ We have a Discord server for discussion about Obliteration and its development.

- Windows 10, Linux or macOS 11+.
- x86-64 CPU. We want to support non-x86 but currently we don't have any developers who are willing to work on this.
- CPU with hardware virtualization supports.
- Windows and Linux users may need to enable this feature on the BIOS/UEFI settings.
- A jailbroken PS4 with FTP server that supports SELF decryption.

### Windows-specific requirements

- [Microsoft Visual C++ 2022 Redistributable](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist). If there is an error related to `msvcp140.dll`, `vcruntime140.dll`, or `vcruntime140_1.dll` that means you need to install this manually. It's likely your system already has it, so try to run Obliteration first.
- [Virtual Machine Platform](https://github.com/obhq/obliteration/wiki/Common-Issues)

### Linux-specific requirements

Obliteration supports only 4KB/8KB/16KB pages. Most people should not have any problem with this because 4KB is the default for most distros.

## Building from source
## Building and Development

### Windows prerequisites

- Visual Studio 2022
- `Desktop development with C++` workload is required
- Rust on the latest stable channel
- CMake 3.21+
- Make sure you have `Add CMake to the system PATH` selected when installing
- [Ninja](https://ninja-build.org)
- Make sure Ninja is added to `PATH`

### Linux prerequisites

- GCC 9.4+
- Rust on the latest stable channel
- CMake 3.21+

### macOS prerequisites

- macOS 12+
- Homebrew
- Clang 13+
- Rust on the latest stable channel
- CMake 3.21+

### Install Qt 6

You need to install Qt 6 on your system before you proceed. The minimum version is 6.5. You also need to enable SVG supports when installing.

#### Windows-specific requirements

You need `Qt Online Installer` for open-source to install Qt, downloaded from https://www.qt.io. The installer will ask you to sign in with a Qt account, which you can create for free. You need to check `Custom installation` and do not check `Qt for desktop development` that is using the MinGW toolchain. Make sure you have checked the `MSVC 2019 64-bit` component in the `Select Components` page for the version you wish to install and uncheck all of the other components.

Once installation is completed you need to set the `CMAKE_PREFIX_PATH` environment variable to the full path of the installed version (e.g. `C:\Qt\6.5.1\msvc2019_64`). To set an environment variable:

1. Open a run dialog with <kbd>Win</kbd> + <kbd>R</kbd>.
2. Enter `sysdm.cpl` then click `OK`.
3. Go to the `Advanced` tab then click on `Environment Variables...`.
4. Click `New...` to create a new environment variable. Just create for either `User variables` or `System variables`, not both.
5. Restart your terminal or IDE to load the new PATH.

#### Install Qt with Homebrew (macOS only)

```sh
brew install qt@6
```

### Configure build system

```sh
cmake --preset PRESET .
```

The value of `PRESET` will depend on your platform and the build configuration you want to use. The current available presets are:

- windows-release
- windows-debug
- linux-release
- linux-debug
- mac-release
- mac-debug

If all you want is to use the emulator, choose `[YOUR-PLATFORM]-release` for optimized outputs. But if you want to edit the code, choose `*-debug`.

### Build

```sh
cmake --build --preset PRESET
```

You can use `-j` to enable parallel building (e.g. `cmake --build --preset PRESET -j 2`). Each parallel build on Linux consumes a lot of memory so don't use the number of your CPU cores otherwise your system might crash due to out of memory. On Windows and macOS it seems like it is safe to use the number of your CPU cores.

## Development

Before proceeding, make sure the build preset you are using is `*-debug`. We recommend Visual Studio Code as a code editor with the following extensions:

- CMake Tools ([Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) | [Open VSX](https://open-vsx.org/extension/ms-vscode/cmake-tools))
- clangd ([Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) | [Open VSX](https://open-vsx.org/extension/llvm-vs-code-extensions/vscode-clangd))
- rust-analyzer ([Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) | [Open VSX](https://open-vsx.org/extension/rust-lang/rust-analyzer))
- CodeLLDB ([Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb) | [Open VSX](https://open-vsx.org/extension/vadimcn/vscode-lldb))

Then open this folder with VS Code. It will ask which CMake preset to use and you need to choose the same one that you were using when building. Everything should work out of the box (e.g. code completion, debugging, etc).

### macOS debugging issues

If you can't launch or debug Obliteration from VS Code, try [this](https://github.com/vadimcn/codelldb/discussions/456#discussioncomment-874122) solution.

### Get a homebrew application for testing

If you don't have a PS4 application for testing you can download PS Scene Quiz for free [here](https://pkg-zone.com/details/LAPY10010).

### Rules for Rust sources

- Use unsafe code only when you know what you are doing. When you do try to wrap it in a safe function so other people who are not familiar with unsafe code can have a safe life.
- Don't chain method calls without an intermediate variable if the result code is hard to follow. We encourage code readability as a pleasure when writing so try to make it easy to read and understand for other people.
- Do not blindly cast an integer. Make sure the value can fit in a destination type. We don't have any plans to support non-64-bit systems so the pointer size and its related types like `usize` are always 64-bits.
- Beware of deadlock and memory leak. Rust can protect us from most mistakes, except those two. Deadlock can be happen easily in Rust because Rust requires us to wrap the data we want to protect with a mutex and get a mutable reference through it. The problem with this is it become natural for you to lock the mutex to operate on the inner data, which can easily cause a deadlock if you are not aware when there are another locks being active. The only cases for memory leak you need to aware is when working with `Arc`. Just make sure you don't create a reference cycle that will never be dropped.

### Rules for C++ sources

Just follow how Qt is written (e.g. coding style, etc.). Always prefers Qt classes over `std` when possible so you don't need to handle exceptions. Do not use the Qt `ui` file to design the UI because it will break on a high-DPI screen.

### Starting point

The application consists of 2 binaries:

1. Main application. This is what users will see when they launch Obliteration. Its entry point is inside `src/main.cpp`.
2. Emulator kernel. This is where emulation takes place. Its entry point is inside `src/kernel/src/main.rs`.

### Debugging the kernel

Create `.kernel-debug` in the root of the repository. The contents of this file is YAML and the kernel will deserialize it to the `Args` struct in `src/kernel/src/main.rs` when passing the `--debug` flag to the kernel. See `Args` struct for available options.

We already provide a launch configuration for VS Code so all you need to do is choose `Debug - Kernel` as the configuration and start debugging.

### UI Icons

We use icons from https://materialdesignicons.com for UI (e.g. on the menu and toolbar).

### Additional informations

[PS4 Developer Wiki](https://www.psdevwiki.com/ps4) has a lot of useful information about the PS4 internal. We also have a PS4 reverse engineering [project](https://github.com/obhq/reverse-engineering).

## Code contribution

If you want to make some contributions but don't know what to work on you can look for `TODO` comment or `todo!` macro invocation in the source code. You can also take a look on the unassigned issues.
Information on building Obliteration and preparing to be a developer can be found on our [Wiki.](https://github.com/obhq/obliteration/wiki/Compilation-&-Development)

## License

- `src/ansi_escape.hpp`, `src/ansi_escape.cpp`, `src/log_formatter.hpp` and `src/log_formatter.cpp` are licensed under GPL-3.0 only.
- `src/param`, `src/pfs` and `src/pkg` are licensed under LGPL-3.0 license.
- All other source code is licensed under MIT license.
- All release binaries are under GPL-3.0 license.

### UI Icons

We use icons from https://materialdesignicons.com for UI (e.g. on the menu and toolbar).
5 changes: 4 additions & 1 deletion src/core/src/param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,8 @@ pub unsafe extern "C" fn param_title_id_get(param: &Param, buf: &mut QString) {

#[no_mangle]
pub unsafe extern "C" fn param_version_get(param: &Param, buf: &mut QString) {
buf.set(param.version());
match param.version() {
Some(version) => buf.set(version),
None => buf.set(""),
}
}
24 changes: 16 additions & 8 deletions src/game_models.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "game_models.hpp"
#include "path.hpp"
#include <QFile>

Game::Game(const QString &id, const QString &name, const QString &directory) :
m_id(id),
Expand All @@ -12,23 +13,30 @@ Game::~Game()
{
}

QPixmap Game::icon() const
{
QPixmap Game::icon() const {
if (!m_cachedIcon.isNull()) {
return m_cachedIcon;
}

// Get icon path.
auto dir = joinPath(m_directory, "sce_sys");
auto path = joinPath(dir.c_str(), "icon0.png");

// Construct icon object.
QPixmap icon(path.c_str());
if (QFile::exists(path.c_str())) {
m_cachedIcon.load(path.c_str());
} else {
// Load fallback icon if icon0 doesn't exist.
m_cachedIcon.load(":/resources/fallbackicon0.png");
}

// For games with large icon sizes.
if (icon.width() != 512 || icon.height() != 512) {
icon = icon.scaled(512, 512, Qt::KeepAspectRatio, Qt::SmoothTransformation);
if (m_cachedIcon.width() != 512 || m_cachedIcon.height() != 512) {
m_cachedIcon = m_cachedIcon.scaled(512, 512, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}

icon.setDevicePixelRatio(2.0);
m_cachedIcon.setDevicePixelRatio(2.0);

return icon;
return m_cachedIcon;
}

GameListModel::GameListModel(QObject *parent) :
Expand Down
1 change: 1 addition & 0 deletions src/game_models.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Game final : public QObject {
QString m_id;
QString m_name;
QString m_directory;
mutable QPixmap m_cachedIcon;
};

class GameListModel final : public QAbstractListModel {
Expand Down
4 changes: 3 additions & 1 deletion src/kernel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[package]
name = "kernel"
version = "0.1.0"
description = "Free and open-source alternative PlayStation 4 kernel for Windows, Linux and macOS"
edition = "2021"

[[bin]]
Expand All @@ -11,7 +12,7 @@ path = "src/main.rs"
bitflags = "2.1"
bytemuck = "1.14.0"
byteorder = "1.4"
clap = { version = "4.1", features = ["derive"] }
clap = { version = "4.1", features = ["cargo", "derive"] }
discord-rich-presence = "0.2"
gmtx = { path = "../gmtx" }
iced-x86 = { version = "1.18", features = ["code_asm"] }
Expand Down Expand Up @@ -44,6 +45,7 @@ features = [
"Win32_System_IO",
"Win32_System_Kernel",
"Win32_System_Memory",
"Win32_System_Performance",
"Win32_System_SystemInformation",
"Win32_System_Threading",
"Win32_System_Time",
Expand Down
21 changes: 9 additions & 12 deletions src/kernel/src/budget/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl BudgetManager {
let name = budget.name.clone();
let mut budgets = self.budgets.lock().unwrap();

budgets.alloc_infallible(|_| Entry::new(Some(name), Arc::new(budget), 0x2000))
budgets.alloc(Entry::new(Some(name), Arc::new(budget), 0x2000))
}

fn sys_budget_get_ptype(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
Expand All @@ -34,8 +34,8 @@ impl BudgetManager {

info!("Getting budget process type for process {pid}.");

if td.cred().is_system() || pid == -1 || pid == td.proc().id().get() {
if pid == -1 || pid == td.proc().id().get() {
if td.cred().is_system() || pid == -1 || pid == td.proc().id() {
if pid == -1 || pid == td.proc().id() {
// Lookup budget.
let id = td.proc().budget_id();

Expand Down Expand Up @@ -82,21 +82,18 @@ pub enum BudgetType {
FdIpcSocket = 11,
}

#[allow(dead_code)]
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProcType {
BigApp,
MiniApp,
System, // TODO: Verify this.
BigApp = 0,
#[allow(unused)]
MiniApp = 1,
#[allow(unused)]
System = 2, // TODO: Verify this.
}

impl Into<u32> for ProcType {
fn into(self) -> u32 {
match self {
ProcType::BigApp => 0,
ProcType::MiniApp => 1,
ProcType::System => 2,
}
self as u32
}
}
Loading

0 comments on commit a9d876e

Please sign in to comment.