PlayGo: basic implementation, credits to red-prig
This commit is contained in:
parent
138c9ce787
commit
516a3e7104
|
@ -1,16 +1,75 @@
|
|||
// 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) {
|
||||
bool PlaygoFile::Open(const std::filesystem::path& filepath) {
|
||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
||||
if (!file.IsOpen()) {
|
||||
return false;
|
||||
if (file.IsOpen()) {
|
||||
file.Read(playgoHeader);
|
||||
if (LoadChunks(file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
file.Read(playgoHeader);
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlaygoFile::LoadChunks(const Common::FS::IOFile& file) {
|
||||
if (file.IsOpen()) {
|
||||
if (playgoHeader.magic == PLAYGO_MAGIC) {
|
||||
bool ret = true;
|
||||
|
||||
std::string chunk_attrs_data, chunk_mchunks_data, chunk_labels_data, mchunk_attrs_data;
|
||||
ret = ret && load_chunk_data(file, playgoHeader.chunk_attrs, chunk_attrs_data);
|
||||
ret = ret && load_chunk_data(file, playgoHeader.chunk_mchunks, chunk_mchunks_data);
|
||||
ret = ret && load_chunk_data(file, playgoHeader.chunk_labels, chunk_labels_data);
|
||||
ret = ret && load_chunk_data(file, playgoHeader.mchunk_attrs, mchunk_attrs_data);
|
||||
|
||||
if (ret) {
|
||||
chunks.resize(playgoHeader.chunk_count);
|
||||
|
||||
auto chunk_attrs =
|
||||
reinterpret_cast<playgo_chunk_attr_entry_t*>(&chunk_attrs_data[0]);
|
||||
auto chunk_mchunks = reinterpret_cast<u16*>(&chunk_mchunks_data[0]);
|
||||
auto chunk_labels = reinterpret_cast<char*>(&chunk_labels_data[0]);
|
||||
auto mchunk_attrs =
|
||||
reinterpret_cast<playgo_mchunk_attr_entry_t*>(&mchunk_attrs_data[0]);
|
||||
|
||||
for (u16 i = 0; i < playgoHeader.chunk_count; i++) {
|
||||
chunks[i].req_locus = chunk_attrs[i].req_locus;
|
||||
chunks[i].language_mask = chunk_attrs[i].language_mask;
|
||||
chunks[i].label_name = std::string(chunk_labels + chunk_attrs[i].label_offset);
|
||||
|
||||
u64 total_size = 0;
|
||||
u16 mchunk_count = chunk_attrs[i].mchunk_count;
|
||||
if (mchunk_count != 0) {
|
||||
auto mchunks = reinterpret_cast<u16*>(
|
||||
((u8*)chunk_mchunks + chunk_attrs[i].mchunks_offset));
|
||||
for (u16 j = 0; j < mchunk_count; j++) {
|
||||
u16 mchunk_id = mchunks[j];
|
||||
total_size += mchunk_attrs[mchunk_id].size.size;
|
||||
}
|
||||
}
|
||||
chunks[i].total_size = total_size;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk,
|
||||
std::string& data) {
|
||||
if (file.IsOpen()) {
|
||||
if (file.Seek(chunk.offset)) {
|
||||
data.resize(chunk.length);
|
||||
if (data.size() == chunk.length) {
|
||||
file.ReadRaw<char>(&data[0], chunk.length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -3,29 +3,128 @@
|
|||
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
#include "common/types.h"
|
||||
#include <mutex>
|
||||
#include "common/io_file.h"
|
||||
#include "core/libraries/playgo/playgo_types.h"
|
||||
|
||||
constexpr u32 PLAYGO_MAGIC = 0x6F676C70;
|
||||
|
||||
struct chunk_t {
|
||||
u32 offset;
|
||||
u32 length;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PlaygoHeader {
|
||||
u32 magic;
|
||||
|
||||
u16 version_major;
|
||||
u16 version_minor;
|
||||
u16 image_count;
|
||||
u16 image_count; // [0;1]
|
||||
u16 chunk_count; // [0;1000]
|
||||
u16 mchunk_count; // [0;8000]
|
||||
u16 scenario_count; // [0;32]
|
||||
|
||||
u32 file_size;
|
||||
u16 default_scenario_id;
|
||||
u16 attrib;
|
||||
u32 sdk_version;
|
||||
u16 disc_count; // [0;2] (if equals to 0 then disc count = 1)
|
||||
u16 layer_bmp;
|
||||
|
||||
u8 reserved[32];
|
||||
char content_id[128];
|
||||
|
||||
chunk_t chunk_attrs; // [0;32000]
|
||||
chunk_t chunk_mchunks;
|
||||
chunk_t chunk_labels; // [0;16000]
|
||||
chunk_t mchunk_attrs; // [0;12800]
|
||||
chunk_t scenario_attrs; // [0;1024]
|
||||
chunk_t scenario_chunks;
|
||||
chunk_t scenario_labels;
|
||||
chunk_t inner_mchunk_attrs; // [0;12800]
|
||||
} __attribute__((packed));
|
||||
|
||||
struct playgo_scenario_attr_entry_t {
|
||||
u8 _type;
|
||||
u8 _unk[19];
|
||||
u16 initial_chunk_count;
|
||||
u16 chunk_count;
|
||||
u32 chunks_offset; //<-scenario_chunks
|
||||
u32 label_offset; //<-scenario_labels
|
||||
} __attribute__((packed));
|
||||
|
||||
struct image_disc_layer_no_t {
|
||||
u8 layer_no : 2;
|
||||
u8 disc_no : 2;
|
||||
u8 image_no : 4;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct playgo_chunk_attr_entry_t {
|
||||
u8 flag;
|
||||
image_disc_layer_no_t image_disc_layer_no;
|
||||
u8 req_locus;
|
||||
u8 unk[11];
|
||||
u16 mchunk_count;
|
||||
u16 scenario_count;
|
||||
// TODO fill the rest
|
||||
};
|
||||
class PlaygoChunk {
|
||||
u64 language_mask;
|
||||
u32 mchunks_offset; //<-chunk_mchunks
|
||||
u32 label_offset; //<-chunk_labels
|
||||
} __attribute__((packed));
|
||||
|
||||
struct playgo_chunk_loc_t {
|
||||
u64 offset : 48;
|
||||
u64 _align1 : 8;
|
||||
u64 image_no : 4;
|
||||
u64 _align2 : 4;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct playgo_chunk_size_t {
|
||||
u64 size : 48;
|
||||
u64 _align : 16;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct playgo_mchunk_attr_entry_t {
|
||||
playgo_chunk_loc_t loc;
|
||||
playgo_chunk_size_t size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PlaygoChunk {
|
||||
u64 req_locus;
|
||||
u64 language_mask;
|
||||
u64 total_size;
|
||||
std::string label_name;
|
||||
} __attribute__((packed));
|
||||
|
||||
class PlaygoFile {
|
||||
public:
|
||||
PlaygoChunk() = default;
|
||||
~PlaygoChunk() = default;
|
||||
bool initialized;
|
||||
OrbisPlayGoHandle handle;
|
||||
OrbisPlayGoChunkId id;
|
||||
OrbisPlayGoLocus locus;
|
||||
OrbisPlayGoInstallSpeed speed;
|
||||
s64 speed_tick;
|
||||
OrbisPlayGoEta eta;
|
||||
OrbisPlayGoLanguageMask langMask;
|
||||
std::vector<PlaygoChunk> chunks;
|
||||
|
||||
public:
|
||||
PlaygoFile()
|
||||
: initialized(false), handle(0), id(0), locus(0), speed(ORBIS_PLAYGO_INSTALL_SPEED_TRICKLE),
|
||||
speed_tick(0), eta(0), langMask(0), playgoHeader{0} {}
|
||||
~PlaygoFile() = default;
|
||||
|
||||
bool Open(const std::filesystem::path& filepath);
|
||||
PlaygoHeader GetPlaygoHeader() {
|
||||
bool LoadChunks(const Common::FS::IOFile& file);
|
||||
PlaygoHeader& GetPlaygoHeader() {
|
||||
return playgoHeader;
|
||||
}
|
||||
std::mutex& GetSpeedMutex() {
|
||||
return speed_mutex;
|
||||
}
|
||||
|
||||
private:
|
||||
bool load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk, std::string& data);
|
||||
|
||||
private:
|
||||
PlaygoHeader playgoHeader;
|
||||
std::mutex speed_mutex;
|
||||
};
|
|
@ -6,6 +6,7 @@
|
|||
#include "common/singleton.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/system/systemservice.h"
|
||||
#include "playgo.h"
|
||||
|
||||
namespace Libraries::PlayGo {
|
||||
|
@ -20,42 +21,129 @@ s32 PS4_SYSV_ABI sceDbgPlayGoSnapshot() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoClose() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoClose(OrbisPlayGoHandle handle) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetChunkId() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoGetChunkId(OrbisPlayGoHandle handle, OrbisPlayGoChunkId* outChunkIdList,
|
||||
u32 numberOfEntries, u32* outEntries) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (outEntries == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (outChunkIdList != nullptr && numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
|
||||
if (playgo->GetPlaygoHeader().file_size == 0) {
|
||||
*outEntries = 0;
|
||||
} else {
|
||||
if (outChunkIdList == nullptr) {
|
||||
*outEntries = playgo->chunks.size();
|
||||
} else {
|
||||
if (numberOfEntries > playgo->chunks.size()) {
|
||||
numberOfEntries = playgo->chunks.size();
|
||||
}
|
||||
|
||||
if (numberOfEntries != 0) {
|
||||
for (u32 i = 0; i < numberOfEntries; i++) {
|
||||
outChunkIdList[i] = i;
|
||||
}
|
||||
*outEntries = numberOfEntries;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetEta() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoGetEta(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
u32 numberOfEntries, OrbisPlayGoEta* outEta) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (chunkIds == nullptr || outEta == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
|
||||
*outEta = 0; // all is loaded
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetInstallSpeed() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoGetInstallSpeed(OrbisPlayGoHandle handle,
|
||||
OrbisPlayGoInstallSpeed* outSpeed) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (outSpeed == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
|
||||
std::scoped_lock lk{playgo->GetSpeedMutex()};
|
||||
|
||||
if (playgo->speed == 0) {
|
||||
using namespace std::chrono;
|
||||
if ((duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count() -
|
||||
playgo->speed_tick) > 30 * 1000) { // 30sec
|
||||
playgo->speed = ORBIS_PLAYGO_INSTALL_SPEED_TRICKLE;
|
||||
}
|
||||
}
|
||||
*outSpeed = playgo->speed;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetLanguageMask(OrbisPlayGoHandle handle,
|
||||
OrbisPlayGoLanguageMask* languageMask) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
*languageMask = 1; // En, todo;
|
||||
OrbisPlayGoLanguageMask* outLanguageMask) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (outLanguageMask == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
|
||||
*outLanguageMask = playgo->langMask;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
uint32_t numberOfEntries, OrbisPlayGoLocus* outLoci) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
||||
LOG_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
||||
handle, *chunkIds, numberOfEntries);
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoChunk>::Instance();
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
for (uint32_t i = 0; i < numberOfEntries; i++) {
|
||||
if (chunkIds[i] <= playgo->GetPlaygoHeader().mchunk_count) {
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (chunkIds == nullptr || outLoci == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
if (playgo->GetPlaygoHeader().file_size == 0)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_SUPPORT_PLAYGO;
|
||||
|
||||
for (uint32_t i = 0; i < numberOfEntries; i++) {
|
||||
if (chunkIds[i] <= playgo->chunks.size()) {
|
||||
outLoci[i] = OrbisPlayGoLocusValue::ORBIS_PLAYGO_LOCUS_LOCAL_FAST;
|
||||
} else {
|
||||
outLoci[i] = ORBIS_PLAYGO_LOCUS_NOT_DOWNLOADED;
|
||||
|
@ -67,64 +155,204 @@ s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoCh
|
|||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetProgress(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
uint32_t numberOfEntries, OrbisPlayGoProgress* outProgress) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
||||
LOG_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}",
|
||||
handle, *chunkIds, numberOfEntries);
|
||||
outProgress->progressSize = 0x10000; // todo?
|
||||
outProgress->totalSize = 0x10000;
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (chunkIds == nullptr || outProgress == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
if (playgo->GetPlaygoHeader().file_size == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
|
||||
outProgress->progressSize = 0;
|
||||
outProgress->totalSize = 0;
|
||||
|
||||
u64 total_size = 0;
|
||||
for (u32 i = 0; i < numberOfEntries; i++) {
|
||||
u32 chunk_id = chunkIds[i];
|
||||
if (chunk_id < playgo->chunks.size()) {
|
||||
total_size += playgo->chunks[chunk_id].total_size;
|
||||
} else {
|
||||
return ORBIS_PLAYGO_ERROR_BAD_CHUNK_ID;
|
||||
}
|
||||
}
|
||||
|
||||
outProgress->progressSize = total_size;
|
||||
outProgress->totalSize = total_size;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo* outTodoList,
|
||||
u32 numberOfEntries, u32* outEntries) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called handle = {} numberOfEntries = {}", handle,
|
||||
LOG_INFO(Lib_PlayGo, "called handle = {} numberOfEntries = {}", handle,
|
||||
numberOfEntries);
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (outTodoList == nullptr)
|
||||
if (outTodoList == nullptr || outEntries == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
*outEntries = 0; // nothing to do
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int scePlayGoConvertLanguage(int systemLang) {
|
||||
if (systemLang >= 0 && systemLang < 48) {
|
||||
return (1 << (64 - systemLang - 1));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoInitialize(OrbisPlayGoInitParams* param) {
|
||||
LOG_INFO(Lib_PlayGo, "called, bufSize = {}", param->bufSize);
|
||||
if (param->bufAddr == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (param->bufSize < 0x200000)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
LOG_INFO(Lib_PlayGo, "(STUBBED)called, bufSize = {}", param->bufSize);
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (!playgo->initialized) {
|
||||
using namespace SystemService;
|
||||
// get system lang
|
||||
int systemLang = 0;
|
||||
sceSystemServiceParamGetInt(ORBIS_SYSTEM_SERVICE_PARAM_ID_LANG, &systemLang);
|
||||
playgo->langMask = scePlayGoConvertLanguage(systemLang);
|
||||
playgo->initialized = true;
|
||||
}
|
||||
else {
|
||||
return ORBIS_PLAYGO_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoOpen(OrbisPlayGoHandle* outHandle, const void* param) {
|
||||
*outHandle = 1;
|
||||
LOG_INFO(Lib_PlayGo, "(STUBBED)called");
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (outHandle == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (param)
|
||||
return ORBIS_PLAYGO_ERROR_INVALID_ARGUMENT;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
if (playgo->GetPlaygoHeader().file_size == 0)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_SUPPORT_PLAYGO;
|
||||
|
||||
playgo->handle = *outHandle = 1;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoPrefetch() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoPrefetch(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
u32 numberOfEntries, OrbisPlayGoLocus minimumLocus) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (chunkIds == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
|
||||
switch (minimumLocus) {
|
||||
case ORBIS_PLAYGO_LOCUS_NOT_DOWNLOADED:
|
||||
case ORBIS_PLAYGO_LOCUS_LOCAL_SLOW:
|
||||
case ORBIS_PLAYGO_LOCUS_LOCAL_FAST:
|
||||
break;
|
||||
default:
|
||||
return ORBIS_PLAYGO_ERROR_BAD_LOCUS;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoSetInstallSpeed() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
s32 PS4_SYSV_ABI scePlayGoSetInstallSpeed(OrbisPlayGoHandle handle, OrbisPlayGoInstallSpeed speed) {
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
|
||||
switch (speed) {
|
||||
case ORBIS_PLAYGO_INSTALL_SPEED_SUSPENDED:
|
||||
case ORBIS_PLAYGO_INSTALL_SPEED_TRICKLE:
|
||||
case ORBIS_PLAYGO_INSTALL_SPEED_FULL:
|
||||
break;
|
||||
default:
|
||||
return ORBIS_PLAYGO_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
std::scoped_lock lk{playgo->GetSpeedMutex()};
|
||||
|
||||
using namespace std::chrono;
|
||||
playgo->speed = speed;
|
||||
playgo->speed_tick =
|
||||
duration_cast<milliseconds>(steady_clock::now().time_since_epoch()).count();
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoSetLanguageMask(OrbisPlayGoHandle handle,
|
||||
OrbisPlayGoLanguageMask languageMask) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
|
||||
playgo->langMask = languageMask;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoSetToDoList(OrbisPlayGoHandle handle, const OrbisPlayGoToDo* todoList,
|
||||
uint32_t numberOfEntries) {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
|
||||
if (handle != 1)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
|
||||
if (todoList == nullptr)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_POINTER;
|
||||
if (numberOfEntries == 0)
|
||||
return ORBIS_PLAYGO_ERROR_BAD_SIZE;
|
||||
if (!playgo->initialized)
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI scePlayGoTerminate() {
|
||||
LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
|
||||
LOG_INFO(Lib_PlayGo, "called");
|
||||
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
if (playgo->initialized) {
|
||||
playgo->initialized = false;
|
||||
} else {
|
||||
return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,12 @@ constexpr int shadMagic = 0x53484144;
|
|||
|
||||
s32 PS4_SYSV_ABI sceDbgPlayGoRequestNextChunk();
|
||||
s32 PS4_SYSV_ABI sceDbgPlayGoSnapshot();
|
||||
s32 PS4_SYSV_ABI scePlayGoClose();
|
||||
s32 PS4_SYSV_ABI scePlayGoGetChunkId();
|
||||
s32 PS4_SYSV_ABI scePlayGoGetEta();
|
||||
s32 PS4_SYSV_ABI scePlayGoGetInstallSpeed();
|
||||
s32 PS4_SYSV_ABI scePlayGoClose(OrbisPlayGoHandle handle);
|
||||
s32 PS4_SYSV_ABI scePlayGoGetChunkId(OrbisPlayGoHandle handle, OrbisPlayGoChunkId* outChunkIdList,
|
||||
u32 numberOfEntries, u32* outEntries);
|
||||
s32 PS4_SYSV_ABI scePlayGoGetEta(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
u32 numberOfEntries, OrbisPlayGoEta* outEta);
|
||||
s32 PS4_SYSV_ABI scePlayGoGetInstallSpeed(OrbisPlayGoHandle handle, OrbisPlayGoInstallSpeed* outSpeed);
|
||||
s32 PS4_SYSV_ABI scePlayGoGetLanguageMask(OrbisPlayGoHandle handle,
|
||||
OrbisPlayGoLanguageMask* outLanguageMask);
|
||||
s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
|
@ -28,8 +30,9 @@ s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo*
|
|||
u32 numberOfEntries, u32* outEntries);
|
||||
s32 PS4_SYSV_ABI scePlayGoInitialize(OrbisPlayGoInitParams* param);
|
||||
s32 PS4_SYSV_ABI scePlayGoOpen(OrbisPlayGoHandle* outHandle, const void* param);
|
||||
s32 PS4_SYSV_ABI scePlayGoPrefetch();
|
||||
s32 PS4_SYSV_ABI scePlayGoSetInstallSpeed();
|
||||
s32 PS4_SYSV_ABI scePlayGoPrefetch(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds,
|
||||
u32 numberOfEntries, OrbisPlayGoLocus minimumLocus);
|
||||
s32 PS4_SYSV_ABI scePlayGoSetInstallSpeed(OrbisPlayGoHandle handle, OrbisPlayGoInstallSpeed speed);
|
||||
s32 PS4_SYSV_ABI scePlayGoSetLanguageMask(OrbisPlayGoHandle handle,
|
||||
OrbisPlayGoLanguageMask languageMask);
|
||||
s32 PS4_SYSV_ABI scePlayGoSetToDoList(OrbisPlayGoHandle handle, const OrbisPlayGoToDo* todoList,
|
||||
|
|
|
@ -91,8 +91,11 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||
app_version = param_sfo->GetString("APP_VER");
|
||||
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");
|
||||
auto* playgo = Common::Singleton<PlaygoFile>::Instance();
|
||||
auto filepath = sce_sys_folder / "playgo-chunk.dat";
|
||||
if (!playgo->Open(filepath)) {
|
||||
LOG_ERROR(Loader, "PlayGo: unable to open file");
|
||||
}
|
||||
} else if (entry.path().filename() == "pic0.png" ||
|
||||
entry.path().filename() == "pic1.png") {
|
||||
auto* splash = Common::Singleton<Splash>::Instance();
|
||||
|
|
Loading…
Reference in New Issue