commit
14e78591e8
|
@ -308,6 +308,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||||
src/core/file_format/pkg_type.h
|
src/core/file_format/pkg_type.h
|
||||||
src/core/file_format/psf.cpp
|
src/core/file_format/psf.cpp
|
||||||
src/core/file_format/psf.h
|
src/core/file_format/psf.h
|
||||||
|
src/core/file_format/playgo_chunk.cpp
|
||||||
|
src/core/file_format/playgo_chunk.h
|
||||||
src/core/file_format/trp.cpp
|
src/core/file_format/trp.cpp
|
||||||
src/core/file_format/trp.h
|
src/core/file_format/trp.h
|
||||||
src/core/file_format/splash.h
|
src/core/file_format/splash.h
|
||||||
|
|
|
@ -220,7 +220,7 @@ void load(const std::filesystem::path& path) {
|
||||||
auto general = generalResult.unwrap();
|
auto general = generalResult.unwrap();
|
||||||
|
|
||||||
isNeo = toml::find_or<toml::boolean>(general, "isPS4Pro", false);
|
isNeo = toml::find_or<toml::boolean>(general, "isPS4Pro", false);
|
||||||
isFullscreen = toml::find_or<toml::boolean>(general, "Fullscreen", true);
|
isFullscreen = toml::find_or<toml::boolean>(general, "Fullscreen", false);
|
||||||
logFilter = toml::find_or<toml::string>(general, "logFilter", "");
|
logFilter = toml::find_or<toml::string>(general, "logFilter", "");
|
||||||
logType = toml::find_or<toml::string>(general, "logType", "sync");
|
logType = toml::find_or<toml::string>(general, "logType", "sync");
|
||||||
isShowSplash = toml::find_or<toml::boolean>(general, "showSplash", true);
|
isShowSplash = toml::find_or<toml::boolean>(general, "showSplash", true);
|
||||||
|
|
|
@ -72,6 +72,7 @@ static auto UserPaths = [] {
|
||||||
create_path(PathType::GameDataDir, user_dir / GAMEDATA_DIR);
|
create_path(PathType::GameDataDir, user_dir / GAMEDATA_DIR);
|
||||||
create_path(PathType::TempDataDir, user_dir / TEMPDATA_DIR);
|
create_path(PathType::TempDataDir, user_dir / TEMPDATA_DIR);
|
||||||
create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR);
|
create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR);
|
||||||
|
create_path(PathType::DownloadDir, user_dir / DOWNLOAD_DIR);
|
||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}();
|
}();
|
||||||
|
|
|
@ -18,6 +18,7 @@ enum class PathType {
|
||||||
TempDataDir, // Where game temp data is stored.
|
TempDataDir, // Where game temp data is stored.
|
||||||
GameDataDir, // Where game data is stored.
|
GameDataDir, // Where game data is stored.
|
||||||
SysModuleDir, // Where system modules are stored.
|
SysModuleDir, // Where system modules are stored.
|
||||||
|
DownloadDir, // Where downloads/temp files are stored.
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto PORTABLE_DIR = "user";
|
constexpr auto PORTABLE_DIR = "user";
|
||||||
|
@ -31,6 +32,7 @@ constexpr auto SAVEDATA_DIR = "savedata";
|
||||||
constexpr auto GAMEDATA_DIR = "data";
|
constexpr auto GAMEDATA_DIR = "data";
|
||||||
constexpr auto TEMPDATA_DIR = "temp";
|
constexpr auto TEMPDATA_DIR = "temp";
|
||||||
constexpr auto SYSMODULES_DIR = "sys_modules";
|
constexpr auto SYSMODULES_DIR = "sys_modules";
|
||||||
|
constexpr auto DOWNLOAD_DIR = "download";
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
constexpr auto LOG_FILE = "shad_log.txt";
|
constexpr auto LOG_FILE = "shad_log.txt";
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/io_file.h"
|
||||||
|
|
||||||
|
#include "playgo_chunk.h"
|
||||||
|
|
||||||
|
bool PlaygoChunk::Open(const std::filesystem::path& filepath) {
|
||||||
|
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
file.Read(playgoHeader);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <filesystem>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
struct PlaygoHeader {
|
||||||
|
u32 magic;
|
||||||
|
|
||||||
|
u16 version_major;
|
||||||
|
u16 version_minor;
|
||||||
|
u16 image_count;
|
||||||
|
u16 chunk_count;
|
||||||
|
u16 mchunk_count;
|
||||||
|
u16 scenario_count;
|
||||||
|
// TODO fill the rest
|
||||||
|
};
|
||||||
|
class PlaygoChunk {
|
||||||
|
public:
|
||||||
|
PlaygoChunk() = default;
|
||||||
|
~PlaygoChunk() = default;
|
||||||
|
|
||||||
|
bool Open(const std::filesystem::path& filepath);
|
||||||
|
PlaygoHeader GetPlaygoHeader() {
|
||||||
|
return playgoHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PlaygoHeader playgoHeader;
|
||||||
|
};
|
|
@ -26,23 +26,27 @@ void MntPoints::UnmountAll() {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) {
|
std::filesystem::path MntPoints::GetHostPath(const std::string& guest_directory) {
|
||||||
const MntPair* mount = GetMount(guest_directory);
|
// Evil games like Turok2 pass double slashes e.g /app0//game.kpf
|
||||||
|
auto corrected_path = guest_directory;
|
||||||
|
size_t pos = corrected_path.find("//");
|
||||||
|
while (pos != std::string::npos) {
|
||||||
|
corrected_path.replace(pos, 2, "/");
|
||||||
|
pos = corrected_path.find("//", pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const MntPair* mount = GetMount(corrected_path);
|
||||||
if (!mount) {
|
if (!mount) {
|
||||||
return guest_directory;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing to do if getting the mount itself.
|
// Nothing to do if getting the mount itself.
|
||||||
if (guest_directory == mount->mount) {
|
if (corrected_path == mount->mount) {
|
||||||
return mount->host_path;
|
return mount->host_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove device (e.g /app0) from path to retrieve relative path.
|
// Remove device (e.g /app0) from path to retrieve relative path.
|
||||||
u32 pos = mount->mount.size() + 1;
|
pos = mount->mount.size() + 1;
|
||||||
// Evil games like Turok2 pass double slashes e.g /app0//game.kpf
|
const auto rel_path = std::string_view(corrected_path).substr(pos);
|
||||||
if (guest_directory[pos] == '/') {
|
|
||||||
pos++;
|
|
||||||
}
|
|
||||||
const auto rel_path = std::string_view(guest_directory).substr(pos);
|
|
||||||
const auto host_path = mount->host_path / rel_path;
|
const auto host_path = mount->host_path / rel_path;
|
||||||
if (!NeedsCaseInsensiveSearch) {
|
if (!NeedsCaseInsensiveSearch) {
|
||||||
return host_path;
|
return host_path;
|
||||||
|
|
|
@ -198,13 +198,9 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataMount() {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOption option,
|
int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOption option,
|
||||||
OrbisAppContentMountPoint* mountPoint) {
|
OrbisAppContentMountPoint* mountPoint) {
|
||||||
if (std::string_view(mountPoint->data).empty()) // causing issues with save_data.
|
if (mountPoint == nullptr)
|
||||||
return ORBIS_APP_CONTENT_ERROR_PARAMETER;
|
return ORBIS_APP_CONTENT_ERROR_PARAMETER;
|
||||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
strncpy(mountPoint->data, "/temp0", 16);
|
||||||
std::string id(param_sfo->GetString("CONTENT_ID"), 7, 9);
|
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::TempDataDir) / id;
|
|
||||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
|
||||||
mnt->Mount(mount_dir, mountPoint->data);
|
|
||||||
LOG_INFO(Lib_AppContent, "sceAppContentTemporaryDataMount2: option = {}, mountPoint = {}",
|
LOG_INFO(Lib_AppContent, "sceAppContentTemporaryDataMount2: option = {}, mountPoint = {}",
|
||||||
option, mountPoint->data);
|
option, mountPoint->data);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
|
|
@ -53,6 +53,9 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
||||||
if (std::string_view{path} == "/dev/stdout") {
|
if (std::string_view{path} == "/dev/stdout") {
|
||||||
return 2002;
|
return 2002;
|
||||||
}
|
}
|
||||||
|
if (std::string_view{path} == "/dev/urandom") {
|
||||||
|
return 2003;
|
||||||
|
}
|
||||||
u32 handle = h->CreateHandle();
|
u32 handle = h->CreateHandle();
|
||||||
auto* file = h->GetFile(handle);
|
auto* file = h->GetFile(handle);
|
||||||
if (directory) {
|
if (directory) {
|
||||||
|
@ -113,6 +116,9 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
|
||||||
if (d < 3) { // d probably hold an error code
|
if (d < 3) { // d probably hold an error code
|
||||||
return ORBIS_KERNEL_ERROR_EPERM;
|
return ORBIS_KERNEL_ERROR_EPERM;
|
||||||
}
|
}
|
||||||
|
if (d == 2003) { // dev/urandom case
|
||||||
|
return SCE_OK;
|
||||||
|
}
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* file = h->GetFile(d);
|
auto* file = h->GetFile(d);
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
|
@ -223,6 +229,13 @@ s64 PS4_SYSV_ABI posix_lseek(int d, s64 offset, int whence) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
|
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
|
||||||
|
if (d == 2003) // dev urandom case
|
||||||
|
{
|
||||||
|
auto rbuf = static_cast<char*>(buf);
|
||||||
|
for (size_t i = 0; i < nbytes; i++)
|
||||||
|
rbuf[i] = std::rand() & 0xFF;
|
||||||
|
return nbytes;
|
||||||
|
}
|
||||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||||
auto* file = h->GetFile(d);
|
auto* file = h->GetFile(d);
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
|
@ -460,6 +473,7 @@ s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
std::srand(std::time(nullptr));
|
||||||
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
|
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
|
||||||
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
|
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
|
||||||
LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose);
|
LIB_FUNCTION("UK2Tl2DWUns", "libkernel", 1, "libkernel", 1, 1, sceKernelClose);
|
||||||
|
|
|
@ -228,7 +228,8 @@ int PS4_SYSV_ABI sceKernelGetDirectMemoryType(u64 addr, int* directMemoryTypeOut
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, int numEntries,
|
s32 PS4_SYSV_ABI sceKernelBatchMap(OrbisKernelBatchMapEntry* entries, int numEntries,
|
||||||
int* numEntriesOut) {
|
int* numEntriesOut) {
|
||||||
return sceKernelBatchMap2(entries, numEntries, numEntriesOut, 0x10); // 0x10 : Fixed / 0x410
|
return sceKernelBatchMap2(entries, numEntries, numEntriesOut,
|
||||||
|
MemoryFlags::SCE_KERNEL_MAP_FIXED); // 0x10, 0x410?
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len);
|
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len);
|
||||||
|
@ -243,7 +244,7 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
|
||||||
break; // break and assign a value to numEntriesOut.
|
break; // break and assign a value to numEntriesOut.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entries[i].operation == 0) { // MAP_DIRECT
|
if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_MAP_DIRECT) {
|
||||||
result = sceKernelMapNamedDirectMemory(&entries[i].start, entries[i].length,
|
result = sceKernelMapNamedDirectMemory(&entries[i].start, entries[i].length,
|
||||||
entries[i].protection, flags,
|
entries[i].protection, flags,
|
||||||
static_cast<s64>(entries[i].offset), 0, "");
|
static_cast<s64>(entries[i].offset), 0, "");
|
||||||
|
@ -256,7 +257,7 @@ s32 PS4_SYSV_ABI sceKernelBatchMap2(OrbisKernelBatchMapEntry* entries, int numEn
|
||||||
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
processed++;
|
processed++;
|
||||||
} else if (entries[i].operation == 1) {
|
} else if (entries[i].operation == MemoryOpTypes::ORBIS_KERNEL_MAP_OP_UNMAP) {
|
||||||
result = sceKernelMunmap(entries[i].start, entries[i].length);
|
result = sceKernelMunmap(entries[i].start, entries[i].length);
|
||||||
LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
|
LOG_INFO(Kernel_Vmm, "BatchMap: entry = {}, operation = {}, len = {:#x}, result = {}",
|
||||||
i, entries[i].operation, entries[i].length, result);
|
i, entries[i].operation, entries[i].length, result);
|
||||||
|
|
|
@ -31,6 +31,14 @@ enum MemoryProtection : u32 {
|
||||||
SCE_KERNEL_PROT_GPU_RW = 0x30 // Permit reads/writes from the GPU
|
SCE_KERNEL_PROT_GPU_RW = 0x30 // Permit reads/writes from the GPU
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum MemoryOpTypes : u32 {
|
||||||
|
ORBIS_KERNEL_MAP_OP_MAP_DIRECT = 0,
|
||||||
|
ORBIS_KERNEL_MAP_OP_UNMAP = 1,
|
||||||
|
ORBIS_KERNEL_MAP_OP_PROTECT = 2,
|
||||||
|
ORBIS_KERNEL_MAP_OP_MAP_FLEXIBLE = 3,
|
||||||
|
ORBIS_KERNEL_MAP_OP_TYPE_PROTECT = 4
|
||||||
|
};
|
||||||
|
|
||||||
struct OrbisQueryInfo {
|
struct OrbisQueryInfo {
|
||||||
uintptr_t start;
|
uintptr_t start;
|
||||||
uintptr_t end;
|
uintptr_t end;
|
||||||
|
|
|
@ -1336,10 +1336,23 @@ int PS4_SYSV_ABI posix_sem_wait(sem_t* sem) {
|
||||||
return sem_wait(sem);
|
return sem_wait(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_sem_timedwait(sem_t* sem, const timespec* t) {
|
||||||
|
#ifndef __APPLE__
|
||||||
|
return sem_timedwait(sem, t);
|
||||||
|
#else
|
||||||
|
LOG_ERROR(Kernel_Pthread, "Apple doesn't support sem_timedwait yet");
|
||||||
|
return 0; // unsupported for apple yet
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_sem_post(sem_t* sem) {
|
int PS4_SYSV_ABI posix_sem_post(sem_t* sem) {
|
||||||
return sem_post(sem);
|
return sem_post(sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_sem_destroy(sem_t* sem) {
|
||||||
|
return sem_destroy(sem);
|
||||||
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) {
|
int PS4_SYSV_ABI posix_sem_getvalue(sem_t* sem, int* sval) {
|
||||||
return sem_getvalue(sem, sval);
|
return sem_getvalue(sem, sval);
|
||||||
}
|
}
|
||||||
|
@ -1403,6 +1416,26 @@ int PS4_SYSV_ABI posix_pthread_condattr_setclock(ScePthreadCondattr* attr, clock
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_getschedparam(ScePthread thread, int* policy,
|
||||||
|
SceKernelSchedParam* param) {
|
||||||
|
return scePthreadGetschedparam(thread, policy, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_setschedparam(ScePthread thread, int policy,
|
||||||
|
const SceKernelSchedParam* param) {
|
||||||
|
return scePthreadSetschedparam(thread, policy, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_attr_getschedpolicy(const ScePthreadAttr* attr, int* policy) {
|
||||||
|
return scePthreadAttrGetschedpolicy(attr, policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI scePthreadRename(ScePthread thread, const char* name) {
|
||||||
|
thread->name = name;
|
||||||
|
LOG_INFO(Kernel_Pthread, "scePthreadRename: name = {}", thread->name);
|
||||||
|
return SCE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate);
|
LIB_FUNCTION("lZzFeSxPl08", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setcancelstate);
|
||||||
LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init);
|
LIB_FUNCTION("0TyVk4MSLt0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_cond_init);
|
||||||
|
@ -1427,6 +1460,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid);
|
LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid);
|
||||||
LIB_FUNCTION("1tKyG7RlMJo", "libkernel", 1, "libkernel", 1, 1, scePthreadGetprio);
|
LIB_FUNCTION("1tKyG7RlMJo", "libkernel", 1, "libkernel", 1, 1, scePthreadGetprio);
|
||||||
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, scePthreadSetprio);
|
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, scePthreadSetprio);
|
||||||
|
LIB_FUNCTION("GBUY7ywdULE", "libkernel", 1, "libkernel", 1, 1, scePthreadRename);
|
||||||
|
|
||||||
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf);
|
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
||||||
|
@ -1498,6 +1532,8 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("EjllaAqAPZo", "libScePosix", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("EjllaAqAPZo", "libScePosix", 1, "libkernel", 1, 1,
|
||||||
posix_pthread_condattr_setclock);
|
posix_pthread_condattr_setclock);
|
||||||
LIB_FUNCTION("Z4QosVuAsA0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_once);
|
||||||
|
LIB_FUNCTION("RtLRV-pBTTY", "libScePosix", 1, "libkernel", 1, 1,
|
||||||
|
posix_pthread_attr_getschedpolicy);
|
||||||
|
|
||||||
// openorbis weird functions
|
// openorbis weird functions
|
||||||
LIB_FUNCTION("7H0iTOciTLo", "libkernel", 1, "libkernel", 1, 1, posix_pthread_mutex_lock);
|
LIB_FUNCTION("7H0iTOciTLo", "libkernel", 1, "libkernel", 1, 1, posix_pthread_mutex_lock);
|
||||||
|
@ -1512,9 +1548,13 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("+U1R4WtXvoc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_detach);
|
LIB_FUNCTION("+U1R4WtXvoc", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_detach);
|
||||||
LIB_FUNCTION("CBNtXOoef-E", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_max);
|
LIB_FUNCTION("CBNtXOoef-E", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_max);
|
||||||
LIB_FUNCTION("m0iS6jNsXds", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_min);
|
LIB_FUNCTION("m0iS6jNsXds", "libScePosix", 1, "libkernel", 1, 1, posix_sched_get_priority_min);
|
||||||
|
LIB_FUNCTION("FIs3-UQT9sg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_getschedparam);
|
||||||
|
LIB_FUNCTION("Xs9hdiD7sAA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setschedparam);
|
||||||
LIB_FUNCTION("pDuPEf3m4fI", "libScePosix", 1, "libkernel", 1, 1, posix_sem_init);
|
LIB_FUNCTION("pDuPEf3m4fI", "libScePosix", 1, "libkernel", 1, 1, posix_sem_init);
|
||||||
LIB_FUNCTION("YCV5dGGBcCo", "libScePosix", 1, "libkernel", 1, 1, posix_sem_wait);
|
LIB_FUNCTION("YCV5dGGBcCo", "libScePosix", 1, "libkernel", 1, 1, posix_sem_wait);
|
||||||
|
LIB_FUNCTION("w5IHyvahg-o", "libScePosix", 1, "libkernel", 1, 1, posix_sem_timedwait);
|
||||||
LIB_FUNCTION("IKP8typ0QUk", "libScePosix", 1, "libkernel", 1, 1, posix_sem_post);
|
LIB_FUNCTION("IKP8typ0QUk", "libScePosix", 1, "libkernel", 1, 1, posix_sem_post);
|
||||||
|
LIB_FUNCTION("cDW233RAwWo", "libScePosix", 1, "libkernel", 1, 1, posix_sem_destroy);
|
||||||
LIB_FUNCTION("Bq+LRV-N6Hk", "libScePosix", 1, "libkernel", 1, 1, posix_sem_getvalue);
|
LIB_FUNCTION("Bq+LRV-N6Hk", "libScePosix", 1, "libkernel", 1, 1, posix_sem_getvalue);
|
||||||
// libs
|
// libs
|
||||||
RwlockSymbolsRegister(sym);
|
RwlockSymbolsRegister(sym);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <core/file_format/playgo_chunk.h>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
|
@ -50,9 +51,16 @@ s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoCh
|
||||||
uint32_t numberOfEntries, OrbisPlayGoLocus* outLoci) {
|
uint32_t numberOfEntries, OrbisPlayGoLocus* outLoci) {
|
||||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
LOG_ERROR(Lib_PlayGo, "(STUBBED)called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
||||||
handle, *chunkIds, numberOfEntries);
|
handle, *chunkIds, numberOfEntries);
|
||||||
// assign all now so that scePlayGoGetLocus is not called again for every single entry
|
|
||||||
std::fill(outLoci, outLoci + numberOfEntries,
|
auto* playgo = Common::Singleton<PlaygoChunk>::Instance();
|
||||||
OrbisPlayGoLocusValue::ORBIS_PLAYGO_LOCUS_LOCAL_FAST);
|
|
||||||
|
for (uint32_t i = 0; i < numberOfEntries; i++) {
|
||||||
|
if (chunkIds[i] <= playgo->GetPlaygoHeader().mchunk_count) {
|
||||||
|
outLoci[i] = OrbisPlayGoLocusValue::ORBIS_PLAYGO_LOCUS_LOCAL_FAST;
|
||||||
|
} else {
|
||||||
|
return ORBIS_PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +76,7 @@ s32 PS4_SYSV_ABI scePlayGoGetProgress(OrbisPlayGoHandle handle, const OrbisPlayG
|
||||||
s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo* outTodoList,
|
s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo* outTodoList,
|
||||||
u32 numberOfEntries, u32* outEntries) {
|
u32 numberOfEntries, u32* outEntries) {
|
||||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||||
if (handle != shadMagic)
|
if (handle != 1)
|
||||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||||
if (outTodoList == nullptr)
|
if (outTodoList == nullptr)
|
||||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||||
|
@ -86,7 +94,7 @@ s32 PS4_SYSV_ABI scePlayGoInitialize(OrbisPlayGoInitParams* param) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI scePlayGoOpen(OrbisPlayGoHandle* outHandle, const void* param) {
|
s32 PS4_SYSV_ABI scePlayGoOpen(OrbisPlayGoHandle* outHandle, const void* param) {
|
||||||
*outHandle = shadMagic;
|
*outHandle = 1;
|
||||||
LOG_INFO(Lib_PlayGo, "(STUBBED)called");
|
LOG_INFO(Lib_PlayGo, "(STUBBED)called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,21 +186,23 @@ int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond*
|
||||||
if (!mount_dir.empty() && std::filesystem::exists(mount_dir)) {
|
if (!mount_dir.empty() && std::filesystem::exists(mount_dir)) {
|
||||||
if (cond->dirName == nullptr) { // look for all dirs if no dir is provided.
|
if (cond->dirName == nullptr) { // look for all dirs if no dir is provided.
|
||||||
for (int i = 0; const auto& entry : std::filesystem::directory_iterator(mount_dir)) {
|
for (int i = 0; const auto& entry : std::filesystem::directory_iterator(mount_dir)) {
|
||||||
if (std::filesystem::is_directory(entry.path())) {
|
if (std::filesystem::is_directory(entry.path()) &&
|
||||||
|
entry.path().filename().string() != "sdmemory") {
|
||||||
|
// sceSaveDataDirNameSearch does not search for dataMemory1/2 dirs.
|
||||||
i++;
|
i++;
|
||||||
result->dirNamesNum = 0; // why is it 1024? is it max?
|
result->dirNamesNum = 0; // why is it 1024? is it max?
|
||||||
// copy dir name to be used by sceSaveDataMount in read mode.
|
// copy dir name to be used by sceSaveDataMount in read mode.
|
||||||
strncpy(result->dirNames[i].data, entry.path().filename().string().c_str(), 32);
|
strncpy(result->dirNames[i].data, entry.path().filename().string().c_str(), 32);
|
||||||
result->hitNum = i + 1;
|
result->hitNum = i + 1;
|
||||||
result->dirNamesNum = i + 1; // to confirm
|
result->dirNamesNum = i + 1;
|
||||||
result->setNum = i + 1; // to confirm
|
result->setNum = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else { // Need a game to test.
|
} else { // Need a game to test.
|
||||||
strncpy(result->dirNames[0].data, cond->dirName->data, 32);
|
strncpy(result->dirNames[0].data, cond->dirName->data, 32);
|
||||||
result->hitNum = 1;
|
result->hitNum = 1;
|
||||||
result->dirNamesNum = 1; // to confirm
|
result->dirNamesNum = 1;
|
||||||
result->setNum = 1; // to confirm
|
result->setNum = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
result->hitNum = 0;
|
result->hitNum = 0;
|
||||||
|
@ -321,7 +323,7 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataCount() {
|
||||||
int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize,
|
int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize,
|
||||||
const int64_t offset) {
|
const int64_t offset) {
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(userId) / game_serial / "save_mem1.sav";
|
std::to_string(userId) / game_serial / "sdmemory/save_mem1.sav";
|
||||||
|
|
||||||
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read);
|
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read);
|
||||||
if (!file.IsOpen()) {
|
if (!file.IsOpen()) {
|
||||||
|
@ -336,7 +338,7 @@ int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) {
|
int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getParam) {
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(getParam->userId) / game_serial;
|
std::to_string(getParam->userId) / game_serial / "sdmemory";
|
||||||
if (getParam == nullptr)
|
if (getParam == nullptr)
|
||||||
return ORBIS_SAVE_DATA_ERROR_PARAMETER;
|
return ORBIS_SAVE_DATA_ERROR_PARAMETER;
|
||||||
if (getParam->data != nullptr) {
|
if (getParam->data != nullptr) {
|
||||||
|
@ -604,7 +606,7 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf,
|
||||||
const size_t bufSize, const int64_t offset) {
|
const size_t bufSize, const int64_t offset) {
|
||||||
LOG_INFO(Lib_SaveData, "called");
|
LOG_INFO(Lib_SaveData, "called");
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(userId) / game_serial / "save_mem1.sav";
|
std::to_string(userId) / game_serial / "sdmemory/save_mem1.sav";
|
||||||
|
|
||||||
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write);
|
||||||
file.Seek(offset);
|
file.Seek(offset);
|
||||||
|
@ -616,7 +618,7 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf,
|
||||||
int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) {
|
int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* setParam) {
|
||||||
LOG_INFO(Lib_SaveData, "called: dataNum = {}, slotId= {}", setParam->dataNum, setParam->slotId);
|
LOG_INFO(Lib_SaveData, "called: dataNum = {}, slotId= {}", setParam->dataNum, setParam->slotId);
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(setParam->userId) / game_serial;
|
std::to_string(setParam->userId) / game_serial / "sdmemory";
|
||||||
if (setParam->data != nullptr) {
|
if (setParam->data != nullptr) {
|
||||||
Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Write);
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen())
|
||||||
|
@ -644,7 +646,7 @@ int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory(u32 userId, size_t memorySize,
|
||||||
LOG_INFO(Lib_SaveData, "called:userId = {}, memorySize = {}", userId, memorySize);
|
LOG_INFO(Lib_SaveData, "called:userId = {}, memorySize = {}", userId, memorySize);
|
||||||
|
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(userId) / game_serial;
|
std::to_string(userId) / game_serial / "sdmemory";
|
||||||
|
|
||||||
if (std::filesystem::exists(mount_dir)) {
|
if (std::filesystem::exists(mount_dir)) {
|
||||||
return ORBIS_SAVE_DATA_ERROR_EXISTS;
|
return ORBIS_SAVE_DATA_ERROR_EXISTS;
|
||||||
|
@ -663,7 +665,7 @@ int PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetup2
|
||||||
LOG_INFO(Lib_SaveData, "called");
|
LOG_INFO(Lib_SaveData, "called");
|
||||||
// if (setupParam->option == 1) { // check this later.
|
// if (setupParam->option == 1) { // check this later.
|
||||||
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
|
||||||
std::to_string(setupParam->userId) / game_serial;
|
std::to_string(setupParam->userId) / game_serial / "sdmemory";
|
||||||
if (std::filesystem::exists(mount_dir) &&
|
if (std::filesystem::exists(mount_dir) &&
|
||||||
std::filesystem::exists(mount_dir / "save_mem2.sav")) {
|
std::filesystem::exists(mount_dir / "save_mem2.sav")) {
|
||||||
Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read);
|
Common::FS::IOFile file(mount_dir / "save_mem2.sav", Common::FS::FileAccessMode::Read);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <common/logging/log.h>
|
#include <common/logging/log.h>
|
||||||
|
#include <core/file_format/playgo_chunk.h>
|
||||||
#include <core/file_format/psf.h>
|
#include <core/file_format/psf.h>
|
||||||
#include <core/file_format/splash.h>
|
#include <core/file_format/splash.h>
|
||||||
#include <core/libraries/disc_map/disc_map.h>
|
#include <core/libraries/disc_map/disc_map.h>
|
||||||
|
@ -51,9 +52,6 @@ Emulator::Emulator() {
|
||||||
memory = Core::Memory::Instance();
|
memory = Core::Memory::Instance();
|
||||||
controller = Common::Singleton<Input::GameController>::Instance();
|
controller = Common::Singleton<Input::GameController>::Instance();
|
||||||
linker = Common::Singleton<Core::Linker>::Instance();
|
linker = Common::Singleton<Core::Linker>::Instance();
|
||||||
window = std::make_unique<Frontend::WindowSDL>(WindowWidth, WindowHeight, controller);
|
|
||||||
|
|
||||||
g_window = window.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Emulator::~Emulator() {
|
Emulator::~Emulator() {
|
||||||
|
@ -68,6 +66,8 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||||
|
|
||||||
// Loading param.sfo file if exists
|
// Loading param.sfo file if exists
|
||||||
std::string id;
|
std::string id;
|
||||||
|
std::string title;
|
||||||
|
std::string app_version;
|
||||||
std::filesystem::path sce_sys_folder = file.parent_path() / "sce_sys";
|
std::filesystem::path sce_sys_folder = file.parent_path() / "sce_sys";
|
||||||
if (std::filesystem::is_directory(sce_sys_folder)) {
|
if (std::filesystem::is_directory(sce_sys_folder)) {
|
||||||
for (const auto& entry : std::filesystem::directory_iterator(sce_sys_folder)) {
|
for (const auto& entry : std::filesystem::directory_iterator(sce_sys_folder)) {
|
||||||
|
@ -75,11 +75,14 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
||||||
param_sfo->open(sce_sys_folder.string() + "/param.sfo", {});
|
param_sfo->open(sce_sys_folder.string() + "/param.sfo", {});
|
||||||
id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9);
|
id = std::string(param_sfo->GetString("CONTENT_ID"), 7, 9);
|
||||||
std::string title(param_sfo->GetString("TITLE"));
|
title = param_sfo->GetString("TITLE");
|
||||||
LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
|
LOG_INFO(Loader, "Game id: {} Title: {}", id, title);
|
||||||
u32 fw_version = param_sfo->GetInteger("SYSTEM_VER");
|
u32 fw_version = param_sfo->GetInteger("SYSTEM_VER");
|
||||||
std::string app_version = param_sfo->GetString("APP_VER");
|
app_version = param_sfo->GetString("APP_VER");
|
||||||
LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version);
|
LOG_INFO(Loader, "Fw: {:#x} App Version: {}", fw_version, app_version);
|
||||||
|
} else if (entry.path().filename() == "playgo-chunk.dat") {
|
||||||
|
auto* playgo = Common::Singleton<PlaygoChunk>::Instance();
|
||||||
|
playgo->Open(sce_sys_folder.string() + "/playgo-chunk.dat");
|
||||||
} else if (entry.path().filename() == "pic0.png" ||
|
} else if (entry.path().filename() == "pic0.png" ||
|
||||||
entry.path().filename() == "pic1.png") {
|
entry.path().filename() == "pic1.png") {
|
||||||
auto* splash = Common::Singleton<Splash>::Instance();
|
auto* splash = Common::Singleton<Splash>::Instance();
|
||||||
|
@ -92,6 +95,12 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string game_title = fmt::format("{} - {} <{}>", id, title, app_version);
|
||||||
|
|
||||||
|
window =
|
||||||
|
std::make_unique<Frontend::WindowSDL>(WindowWidth, WindowHeight, controller, game_title);
|
||||||
|
|
||||||
|
g_window = window.get();
|
||||||
|
|
||||||
const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
const auto& mount_data_dir = Common::FS::GetUserPath(Common::FS::PathType::GameDataDir) / id;
|
||||||
if (!std::filesystem::exists(mount_data_dir)) {
|
if (!std::filesystem::exists(mount_data_dir)) {
|
||||||
|
@ -104,6 +113,13 @@ void Emulator::Run(const std::filesystem::path& file) {
|
||||||
}
|
}
|
||||||
mnt->Mount(mount_temp_dir, "/temp0"); // called in app_content ==> stat/mkdir
|
mnt->Mount(mount_temp_dir, "/temp0"); // called in app_content ==> stat/mkdir
|
||||||
|
|
||||||
|
const auto& mount_download_dir =
|
||||||
|
Common::FS::GetUserPath(Common::FS::PathType::DownloadDir) / id;
|
||||||
|
if (!std::filesystem::exists(mount_download_dir)) {
|
||||||
|
std::filesystem::create_directory(mount_download_dir);
|
||||||
|
}
|
||||||
|
mnt->Mount(mount_download_dir, "/download0");
|
||||||
|
|
||||||
// Initialize kernel and library facilities.
|
// Initialize kernel and library facilities.
|
||||||
Libraries::Kernel::init_pthreads();
|
Libraries::Kernel::init_pthreads();
|
||||||
Libraries::InitHLELibs(&linker->GetHLESymbols());
|
Libraries::InitHLELibs(&linker->GetHLESymbols());
|
||||||
|
|
|
@ -18,14 +18,15 @@
|
||||||
|
|
||||||
namespace Frontend {
|
namespace Frontend {
|
||||||
|
|
||||||
WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_)
|
WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameController* controller_,
|
||||||
|
std::string_view game_title)
|
||||||
: width{width_}, height{height_}, controller{controller_} {
|
: width{width_}, height{height_}, controller{controller_} {
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
UNREACHABLE_MSG("Failed to initialize SDL video subsystem: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
|
||||||
const std::string title = "shadPS4 v" + std::string(Common::VERSION);
|
const std::string title = fmt::format("shadPS4 v{} | {}", Common::VERSION, game_title);
|
||||||
SDL_PropertiesID props = SDL_CreateProperties();
|
SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
|
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, title.c_str());
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
|
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
struct SDL_Window;
|
struct SDL_Window;
|
||||||
|
@ -40,7 +41,8 @@ struct WindowSystemInfo {
|
||||||
|
|
||||||
class WindowSDL {
|
class WindowSDL {
|
||||||
public:
|
public:
|
||||||
explicit WindowSDL(s32 width, s32 height, Input::GameController* controller);
|
explicit WindowSDL(s32 width, s32 height, Input::GameController* controller,
|
||||||
|
std::string_view game_title);
|
||||||
~WindowSDL();
|
~WindowSDL();
|
||||||
|
|
||||||
s32 getWidth() const {
|
s32 getWidth() const {
|
||||||
|
|
Loading…
Reference in New Issue