From ddec111da6e2a822295b5a672f029b5bc2646c26 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 8 Aug 2024 00:23:54 -0300 Subject: [PATCH 1/8] qt_gui: Added feature to toggle (show/hide) game list view "Show Game List" button originally didn't have any action assigned to it, so this PR is supposed to implement the change that would make sense to it (even though I don't think anyone would be using this too much.) --- src/qt_gui/main_window.cpp | 11 +++++++++++ src/qt_gui/main_window.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index b3778be0..fe320bc6 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -162,6 +162,7 @@ void MainWindow::CreateConnects() { connect(ui->mw_searchbar, &QLineEdit::textChanged, this, &MainWindow::SearchGameTable); connect(ui->exitAct, &QAction::triggered, this, &QWidget::close); connect(ui->refreshGameListAct, &QAction::triggered, this, &MainWindow::RefreshGameTable); + connect(ui->showGameListAct, &QAction::triggered, this, &MainWindow::ShowGameList); connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable); connect(ui->sizeSlider, &QSlider::valueChanged, this, [this](int value) { @@ -406,6 +407,16 @@ void MainWindow::SearchGameTable(const QString& text) { } } +void MainWindow::ShowGameList() { + if (ui->showGameListAct->isChecked()){ + RefreshGameTable(); + } + else { + m_game_grid_frame->clearContents(); + m_game_list_frame->clearContents(); + } +}; + void MainWindow::RefreshGameTable() { // m_game_info->m_games.clear(); m_game_info->GetGameInfo(this); diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index d1ef48dc..8bfcda5e 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -44,6 +44,7 @@ private Q_SLOTS: void ConfigureGuiFromSettings(); void SaveWindowState() const; void SearchGameTable(const QString& text); + void ShowGameList(); void RefreshGameTable(); void HandleResize(QResizeEvent* event); From 4375e6fa3afc4109ce3cfce1d176634082cd07ed Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 8 Aug 2024 18:30:58 -0300 Subject: [PATCH 2/8] Fixed if else formatting --- src/qt_gui/main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index fe320bc6..6b732968 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -410,7 +410,7 @@ void MainWindow::SearchGameTable(const QString& text) { void MainWindow::ShowGameList() { if (ui->showGameListAct->isChecked()){ RefreshGameTable(); - } + } else { else { m_game_grid_frame->clearContents(); m_game_list_frame->clearContents(); From 0d56be629b8ed1fa5ee11eb06b7af018f3b8c429 Mon Sep 17 00:00:00 2001 From: Leonardo Date: Thu, 8 Aug 2024 18:33:06 -0300 Subject: [PATCH 3/8] Removed else that duplicated while commiting the typo fixes --- src/qt_gui/main_window.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 6b732968..1273780f 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -411,7 +411,6 @@ void MainWindow::ShowGameList() { if (ui->showGameListAct->isChecked()){ RefreshGameTable(); } else { - else { m_game_grid_frame->clearContents(); m_game_list_frame->clearContents(); } From 14947232a76d88760536494d2ea5d41d774b1515 Mon Sep 17 00:00:00 2001 From: Leonardo <58894431+notgonnaleo@users.noreply.github.com> Date: Fri, 9 Aug 2024 09:24:14 -0300 Subject: [PATCH 4/8] Fixed coding style again on the if brackets --- src/qt_gui/main_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 1273780f..94800828 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -408,7 +408,7 @@ void MainWindow::SearchGameTable(const QString& text) { } void MainWindow::ShowGameList() { - if (ui->showGameListAct->isChecked()){ + if (ui->showGameListAct->isChecked()) { RefreshGameTable(); } else { m_game_grid_frame->clearContents(); From 516a3e71049c5df38d052489b402e9012e6069fa Mon Sep 17 00:00:00 2001 From: bax-cz Date: Mon, 19 Aug 2024 13:14:14 +0200 Subject: [PATCH 5/8] PlayGo: basic implementation, credits to red-prig --- src/core/file_format/playgo_chunk.cpp | 73 ++++++- src/core/file_format/playgo_chunk.h | 117 ++++++++++- src/core/libraries/playgo/playgo.cpp | 288 +++++++++++++++++++++++--- src/core/libraries/playgo/playgo.h | 15 +- src/emulator.cpp | 7 +- 5 files changed, 446 insertions(+), 54 deletions(-) diff --git a/src/core/file_format/playgo_chunk.cpp b/src/core/file_format/playgo_chunk.cpp index 43d8a4de..a9bea4a7 100644 --- a/src/core/file_format/playgo_chunk.cpp +++ b/src/core/file_format/playgo_chunk.cpp @@ -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 false; +} - return true; +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(&chunk_attrs_data[0]); + auto chunk_mchunks = reinterpret_cast(&chunk_mchunks_data[0]); + auto chunk_labels = reinterpret_cast(&chunk_labels_data[0]); + auto mchunk_attrs = + reinterpret_cast(&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( + ((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(&data[0], chunk.length); + return true; + } + } + } + return false; } \ No newline at end of file diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h index d17d24bf..275312b1 100644 --- a/src/core/file_format/playgo_chunk.h +++ b/src/core/file_format/playgo_chunk.h @@ -3,29 +3,128 @@ #pragma once #include -#include "common/types.h" +#include +#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 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; }; \ No newline at end of file diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index af98253f..fbd4ca06 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -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::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::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::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(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::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::Instance(); + auto* playgo = Common::Singleton::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::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::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::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::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::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::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(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::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::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::Instance(); + if (playgo->initialized) { + playgo->initialized = false; + } else { + return ORBIS_PLAYGO_ERROR_NOT_INITIALIZED; + } return ORBIS_OK; } diff --git a/src/core/libraries/playgo/playgo.h b/src/core/libraries/playgo/playgo.h index a6b8c91d..9b77bd7a 100644 --- a/src/core/libraries/playgo/playgo.h +++ b/src/core/libraries/playgo/playgo.h @@ -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, diff --git a/src/emulator.cpp b/src/emulator.cpp index 12e89349..9cc7a130 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -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::Instance(); - playgo->Open(sce_sys_folder.string() + "/playgo-chunk.dat"); + auto* playgo = Common::Singleton::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::Instance(); From 8f7b3c2e8c0e7514b3a84f6e6e29dee0c4ae8e20 Mon Sep 17 00:00:00 2001 From: bax-cz Date: Mon, 19 Aug 2024 20:40:23 +0200 Subject: [PATCH 6/8] clang: fixed formatting --- src/core/file_format/playgo_chunk.cpp | 6 +++--- src/core/file_format/playgo_chunk.h | 6 +++--- src/core/libraries/playgo/playgo.cpp | 18 ++++++++---------- src/core/libraries/playgo/playgo.h | 3 ++- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/core/file_format/playgo_chunk.cpp b/src/core/file_format/playgo_chunk.cpp index a9bea4a7..a430b1ac 100644 --- a/src/core/file_format/playgo_chunk.cpp +++ b/src/core/file_format/playgo_chunk.cpp @@ -27,7 +27,7 @@ bool PlaygoFile::LoadChunks(const Common::FS::IOFile& file) { if (ret) { chunks.resize(playgoHeader.chunk_count); - + auto chunk_attrs = reinterpret_cast(&chunk_attrs_data[0]); auto chunk_mchunks = reinterpret_cast(&chunk_mchunks_data[0]); @@ -61,7 +61,7 @@ bool PlaygoFile::LoadChunks(const Common::FS::IOFile& file) { } bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t& chunk, - std::string& data) { + std::string& data) { if (file.IsOpen()) { if (file.Seek(chunk.offset)) { data.resize(chunk.length); @@ -70,6 +70,6 @@ bool PlaygoFile::load_chunk_data(const Common::FS::IOFile& file, const chunk_t& return true; } } - } + } return false; } \ No newline at end of file diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h index 275312b1..4409d2d1 100644 --- a/src/core/file_format/playgo_chunk.h +++ b/src/core/file_format/playgo_chunk.h @@ -36,8 +36,8 @@ struct PlaygoHeader { chunk_t chunk_attrs; // [0;32000] chunk_t chunk_mchunks; - chunk_t chunk_labels; // [0;16000] - chunk_t mchunk_attrs; // [0;12800] + 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; @@ -67,7 +67,7 @@ struct playgo_chunk_attr_entry_t { u16 mchunk_count; u64 language_mask; u32 mchunks_offset; //<-chunk_mchunks - u32 label_offset; //<-chunk_labels + u32 label_offset; //<-chunk_labels } __attribute__((packed)); struct playgo_chunk_loc_t { diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index fbd4ca06..66422dc2 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -103,7 +103,7 @@ s32 PS4_SYSV_ABI scePlayGoGetInstallSpeed(OrbisPlayGoHandle handle, } } *outSpeed = playgo->speed; - + return ORBIS_OK; } @@ -126,8 +126,8 @@ s32 PS4_SYSV_ABI scePlayGoGetLanguageMask(OrbisPlayGoHandle handle, s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds, uint32_t numberOfEntries, OrbisPlayGoLocus* outLoci) { - LOG_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}", - handle, *chunkIds, numberOfEntries); + LOG_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}", handle, + *chunkIds, numberOfEntries); auto* playgo = Common::Singleton::Instance(); @@ -142,7 +142,7 @@ s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoCh if (playgo->GetPlaygoHeader().file_size == 0) return ORBIS_PLAYGO_ERROR_NOT_SUPPORT_PLAYGO; - for (uint32_t i = 0; i < numberOfEntries; i++) { + for (uint32_t i = 0; i < numberOfEntries; i++) { if (chunkIds[i] <= playgo->chunks.size()) { outLoci[i] = OrbisPlayGoLocusValue::ORBIS_PLAYGO_LOCUS_LOCAL_FAST; } else { @@ -155,8 +155,8 @@ 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_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}", - handle, *chunkIds, numberOfEntries); + LOG_INFO(Lib_PlayGo, "called handle = {}, chunkIds = {}, numberOfEntries = {}", handle, + *chunkIds, numberOfEntries); auto* playgo = Common::Singleton::Instance(); @@ -192,8 +192,7 @@ s32 PS4_SYSV_ABI scePlayGoGetProgress(OrbisPlayGoHandle handle, const OrbisPlayG s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo* outTodoList, u32 numberOfEntries, u32* outEntries) { - LOG_INFO(Lib_PlayGo, "called handle = {} numberOfEntries = {}", handle, - numberOfEntries); + LOG_INFO(Lib_PlayGo, "called handle = {} numberOfEntries = {}", handle, numberOfEntries); auto* playgo = Common::Singleton::Instance(); @@ -233,8 +232,7 @@ s32 PS4_SYSV_ABI scePlayGoInitialize(OrbisPlayGoInitParams* param) { sceSystemServiceParamGetInt(ORBIS_SYSTEM_SERVICE_PARAM_ID_LANG, &systemLang); playgo->langMask = scePlayGoConvertLanguage(systemLang); playgo->initialized = true; - } - else { + } else { return ORBIS_PLAYGO_ERROR_ALREADY_INITIALIZED; } return ORBIS_OK; diff --git a/src/core/libraries/playgo/playgo.h b/src/core/libraries/playgo/playgo.h index 9b77bd7a..f5ae1baa 100644 --- a/src/core/libraries/playgo/playgo.h +++ b/src/core/libraries/playgo/playgo.h @@ -19,7 +19,8 @@ s32 PS4_SYSV_ABI scePlayGoGetChunkId(OrbisPlayGoHandle handle, OrbisPlayGoChunkI 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 scePlayGoGetInstallSpeed(OrbisPlayGoHandle handle, + OrbisPlayGoInstallSpeed* outSpeed); s32 PS4_SYSV_ABI scePlayGoGetLanguageMask(OrbisPlayGoHandle handle, OrbisPlayGoLanguageMask* outLanguageMask); s32 PS4_SYSV_ABI scePlayGoGetLocus(OrbisPlayGoHandle handle, const OrbisPlayGoChunkId* chunkIds, From 0b3356bd1a9175632459cacee4dcace1b861a961 Mon Sep 17 00:00:00 2001 From: bax-cz Date: Tue, 20 Aug 2024 09:28:07 +0200 Subject: [PATCH 7/8] linux build fix --- src/core/file_format/playgo_chunk.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h index 4409d2d1..439e27d0 100644 --- a/src/core/file_format/playgo_chunk.h +++ b/src/core/file_format/playgo_chunk.h @@ -4,6 +4,7 @@ #pragma once #include #include +#include #include "common/io_file.h" #include "core/libraries/playgo/playgo_types.h" @@ -92,7 +93,7 @@ struct PlaygoChunk { u64 language_mask; u64 total_size; std::string label_name; -} __attribute__((packed)); +}; class PlaygoFile { public: @@ -127,4 +128,4 @@ private: private: PlaygoHeader playgoHeader; std::mutex speed_mutex; -}; \ No newline at end of file +}; From c60bfbe2a598ae852a8bd73036f60b057bd923a0 Mon Sep 17 00:00:00 2001 From: kotn3l <32578937+kotn3l@users.noreply.github.com> Date: Tue, 20 Aug 2024 14:39:56 +0200 Subject: [PATCH 8/8] Set game window size based on the config (in windowed mode) (#481) * Set windowed mode size based on config * fix formatting oops * emulator.cpp clang format fix (hopefully?) * formatting fix for real --- src/emulator.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index 9cc7a130..37e227dd 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -34,9 +34,6 @@ Frontend::WindowSDL* g_window = nullptr; namespace Core { -static constexpr s32 WindowWidth = 1280; -static constexpr s32 WindowHeight = 720; - Emulator::Emulator() { // Read configuration file. const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); @@ -117,8 +114,8 @@ void Emulator::Run(const std::filesystem::path& file) { window_title = fmt::format("shadPS4 v{} {} | {}", Common::VERSION, Common::g_scm_desc, game_title); } - window = - std::make_unique(WindowWidth, WindowHeight, controller, window_title); + window = std::make_unique( + Config::getScreenWidth(), Config::getScreenHeight(), controller, window_title); g_window = window.get();