From b4916ef2cab28ad77e4157fb5eb3d5a70a271f7b Mon Sep 17 00:00:00 2001
From: georgemoralis <giorgosmrls@gmail.com>
Date: Wed, 24 Jul 2024 19:02:22 +0300
Subject: [PATCH] some fixup to playgo  , makes Worms go further

---
 CMakeLists.txt                        |  2 ++
 src/core/file_format/playgo_chunk.cpp | 16 ++++++++++++++
 src/core/file_format/playgo_chunk.h   | 31 +++++++++++++++++++++++++++
 src/core/libraries/playgo/playgo.cpp  | 18 +++++++++++-----
 4 files changed, 62 insertions(+), 5 deletions(-)
 create mode 100644 src/core/file_format/playgo_chunk.cpp
 create mode 100644 src/core/file_format/playgo_chunk.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8ec7cd54..880d1cf5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -308,6 +308,8 @@ set(CORE src/core/aerolib/stubs.cpp
          src/core/file_format/pkg_type.h
          src/core/file_format/psf.cpp
          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.h
          src/core/file_format/splash.h
diff --git a/src/core/file_format/playgo_chunk.cpp b/src/core/file_format/playgo_chunk.cpp
new file mode 100644
index 00000000..43d8a4de
--- /dev/null
+++ b/src/core/file_format/playgo_chunk.cpp
@@ -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;
+}
\ No newline at end of file
diff --git a/src/core/file_format/playgo_chunk.h b/src/core/file_format/playgo_chunk.h
new file mode 100644
index 00000000..d17d24bf
--- /dev/null
+++ b/src/core/file_format/playgo_chunk.h
@@ -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;
+};
\ No newline at end of file
diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp
index e029413e..a3af8b4c 100644
--- a/src/core/libraries/playgo/playgo.cpp
+++ b/src/core/libraries/playgo/playgo.cpp
@@ -1,6 +1,7 @@
 // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
 // SPDX-License-Identifier: GPL-2.0-or-later
 
+#include <core/file_format/playgo_chunk.h>
 #include "common/logging/log.h"
 #include "common/singleton.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) {
     LOG_ERROR(Lib_PlayGo, "(STUBBED)called 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,
-              OrbisPlayGoLocusValue::ORBIS_PLAYGO_LOCUS_LOCAL_FAST);
+
+    auto* playgo = Common::Singleton<PlaygoChunk>::Instance();
+
+    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;
 }
 
@@ -68,7 +76,7 @@ s32 PS4_SYSV_ABI scePlayGoGetProgress(OrbisPlayGoHandle handle, const OrbisPlayG
 s32 PS4_SYSV_ABI scePlayGoGetToDoList(OrbisPlayGoHandle handle, OrbisPlayGoToDo* outTodoList,
                                       u32 numberOfEntries, u32* outEntries) {
     LOG_ERROR(Lib_PlayGo, "(STUBBED)called");
-    if (handle != shadMagic)
+    if (handle != 1)
         return ORBIS_PLAYGO_ERROR_BAD_HANDLE;
     if (outTodoList == nullptr)
         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) {
-    *outHandle = shadMagic;
+    *outHandle = 1;
     LOG_INFO(Lib_PlayGo, "(STUBBED)called");
     return ORBIS_OK;
 }