From 5ff462ebcae3d47e9942899becb4cba06f05095b Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Sun, 6 Apr 2025 20:02:06 +0200 Subject: [PATCH 01/70] Fixing include misunderstanding --- Core/ELF/ElfReader.h | 2 +- Core/ELF/{ElfTypes.h => _ElfTypes.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename Core/ELF/{ElfTypes.h => _ElfTypes.h} (100%) diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index ff10e5d31a0f..965dcbfc21d2 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -19,7 +19,7 @@ #include #include "Common/CommonTypes.h" -#include "Core/ELF/ElfTypes.h" +#include "Core/ELF/_ElfTypes.h" enum { R_MIPS_NONE, diff --git a/Core/ELF/ElfTypes.h b/Core/ELF/_ElfTypes.h similarity index 100% rename from Core/ELF/ElfTypes.h rename to Core/ELF/_ElfTypes.h From aa7b5b3b4a8dac3e124e7046fd9ab57c8cb1addf Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Sun, 6 Apr 2025 20:53:02 +0200 Subject: [PATCH 02/70] Deparalleliing initialization --- Core/FileLoaders/LocalFileLoader.cpp | 1 + Core/System.cpp | 96 +++++++++++++--------------- libretro/libretro.cpp | 1 - 3 files changed, 44 insertions(+), 54 deletions(-) diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 89b0fe4ce949..3abd59300360 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -57,6 +57,7 @@ void LocalFileLoader::DetectSizeFd() { LocalFileLoader::LocalFileLoader(const Path &filename) : filesize_(0), filename_(filename) { + if (filename.empty()) { ERROR_LOG(Log::FileSystem, "LocalFileLoader can't load empty filenames"); return; diff --git a/Core/System.cpp b/Core/System.cpp index ba7d498aeebd..c7c7b04fada9 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -85,7 +85,6 @@ CoreParameter g_CoreParameter; static FileLoader *g_loadedFile; // For background loading thread. static std::mutex loadingLock; -static std::thread g_loadingThread; bool coreCollectDebugStats = false; static int coreCollectDebugStatsCounter = 0; @@ -529,65 +528,60 @@ bool PSP_InitStart(const CoreParameter &coreParam) { INFO_LOG(Log::System, "Starting loader thread..."); - _dbg_assert_(!g_loadingThread.joinable()); + SetCurrentThreadName("ExecLoader"); + AndroidJNIThreadContext jniContext; - g_loadingThread = std::thread([error_string]() { - SetCurrentThreadName("ExecLoader"); + NOTICE_LOG(Log::Boot, "PPSSPP %s", PPSSPP_GIT_VERSION); - AndroidJNIThreadContext jniContext; + Core_NotifyLifecycle(CoreLifecycle::STARTING); - NOTICE_LOG(Log::Boot, "PPSSPP %s", PPSSPP_GIT_VERSION); - - Core_NotifyLifecycle(CoreLifecycle::STARTING); - - Path filename = g_CoreParameter.fileToStart; - FileLoader *loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename)); - - IdentifiedFileType type = Identify_File(loadedFile, &g_CoreParameter.errorString); - g_CoreParameter.fileType = type; + Path filename = g_CoreParameter.fileToStart; + FileLoader *loadedFile = ResolveFileLoaderTarget(ConstructFileLoader(filename)); + IdentifiedFileType type = Identify_File(loadedFile, &g_CoreParameter.errorString); + g_CoreParameter.fileType = type; - if (System_GetPropertyBool(SYSPROP_ENOUGH_RAM_FOR_FULL_ISO)) { - if (g_Config.bCacheFullIsoInRam) { - switch (g_CoreParameter.fileType) { - case IdentifiedFileType::PSP_ISO: - case IdentifiedFileType::PSP_ISO_NP: - loadedFile = new RamCachingFileLoader(loadedFile); - break; - default: - INFO_LOG(Log::System, "RAM caching is on, but file is not an ISO, so ignoring"); - break; - } + if (System_GetPropertyBool(SYSPROP_ENOUGH_RAM_FOR_FULL_ISO)) { + if (g_Config.bCacheFullIsoInRam) { + switch (g_CoreParameter.fileType) { + case IdentifiedFileType::PSP_ISO: + case IdentifiedFileType::PSP_ISO_NP: + loadedFile = new RamCachingFileLoader(loadedFile); + break; + default: + INFO_LOG(Log::System, "RAM caching is on, but file is not an ISO, so ignoring"); + break; } } + } - if (g_Config.bAchievementsEnable) { - std::string errorString; - Achievements::SetGame(filename, type, loadedFile); - } + if (g_Config.bAchievementsEnable) { + std::string errorString; + Achievements::SetGame(filename, type, loadedFile); + } - // TODO: The reason we pass in g_CoreParameter.errorString here is that it's persistent - - // it gets written to from the loader thread that gets spawned. - if (!CPU_Init(loadedFile, type, &g_CoreParameter.errorString)) { - CPU_Shutdown(false); - coreState = CORE_BOOT_ERROR; - g_CoreParameter.fileToStart.clear(); - *error_string = g_CoreParameter.errorString; - if (error_string->empty()) { - *error_string = "Failed initializing CPU/Memory"; - } - g_bootState = BootState::Failed; - return; + // TODO: The reason we pass in g_CoreParameter.errorString here is that it's persistent - + // it gets written to from the loader thread that gets spawned. + if (!CPU_Init(loadedFile, type, &g_CoreParameter.errorString)) { + CPU_Shutdown(false); + coreState = CORE_BOOT_ERROR; + g_CoreParameter.fileToStart.clear(); + *error_string = g_CoreParameter.errorString; + if (error_string->empty()) { + *error_string = "Failed initializing CPU/Memory"; } + g_bootState = BootState::Failed; + return false; + } - if (PSP_CoreParameter().startBreak) { - coreState = CORE_STEPPING_CPU; - System_Notify(SystemNotification::DEBUG_MODE_CHANGE); - } else { - coreState = CORE_RUNNING_CPU; - } + if (PSP_CoreParameter().startBreak) { + coreState = CORE_STEPPING_CPU; + System_Notify(SystemNotification::DEBUG_MODE_CHANGE); + } else { + coreState = CORE_RUNNING_CPU; + } + + g_bootState = BootState::Complete; - g_bootState = BootState::Complete; - }); return true; } @@ -600,10 +594,6 @@ BootState PSP_InitUpdate(std::string *error_string) { _dbg_assert_(g_bootState == BootState::Complete || g_bootState == BootState::Failed); - // Since we load on a background thread, wait for startup to complete. - _dbg_assert_(g_loadingThread.joinable()); - g_loadingThread.join(); - if (g_bootState == BootState::Failed) { // Failed! (Note: PSP_Shutdown was already called on the loader thread). Core_NotifyLifecycle(CoreLifecycle::START_COMPLETE); diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index d1fe05183d3d..464354ab48a7 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1485,7 +1485,6 @@ bool retro_load_game(const struct retro_game_info *game) ERROR_LOG(Log::Boot, "%s", error_string.c_str()); return false; } - struct retro_core_option_display option_display; // Show/hide 'MSAA' and 'Texture Shader' options, Vulkan only From 6ee33db400a3224f6d63dd272d0f2768bdc197a6 Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 06:08:38 +0200 Subject: [PATCH 03/70] Executing tasks sequentially (part1) --- Common/Thread/ThreadManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index aea8b7558e14..c467e3ed187e 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -238,6 +238,11 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) { } void ThreadManager::EnqueueTask(Task *task) { + // Serialization: run task directly, without invoking a thread + task->Run(); + task->Release(); + return; + if (task->Type() == TaskType::DEDICATED_THREAD) { std::thread th([=](Task *task) { SetCurrentThreadName("DedicatedThreadTask"); From 630400ca35c90a4a60532473cb93dc992ebb927e Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 06:14:21 +0200 Subject: [PATCH 04/70] Serialized thread manager --- Common/Thread/ThreadManager.cpp | 249 +------------------------------- 1 file changed, 7 insertions(+), 242 deletions(-) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index c467e3ed187e..b67ff783c005 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -53,6 +53,8 @@ ThreadManager::ThreadManager() : global_(new GlobalThreadContext()) { global_->compute_queue_size = 0; global_->io_queue_size = 0; global_->roundRobin = 0; + numComputeThreads_ = 1; + numThreads_ = 1; } ThreadManager::~ThreadManager() { @@ -60,181 +62,13 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Teardown() { - for (TaskThreadContext *&threadCtx : global_->threads_) { - std::unique_lock lock(threadCtx->mutex); - threadCtx->cancelled = true; - threadCtx->cond.notify_one(); - } - - // Purge any cancellable tasks while the threads shut down. - if (global_->compute_queue_size > 0 || global_->io_queue_size > 0) { - auto drainQueue = [&](std::deque queue[TASK_PRIORITY_COUNT], std::atomic &size) { - for (size_t i = 0; i < TASK_PRIORITY_COUNT; ++i) { - for (auto it = queue[i].begin(); it != queue[i].end(); ++it) { - if (TeardownTask(*it, false)) { - queue[i].erase(it); - size--; - return false; - } - } - } - return true; - }; - - std::unique_lock lock(global_->mutex); - while (!drainQueue(global_->compute_queue, global_->compute_queue_size)) - continue; - while (!drainQueue(global_->io_queue, global_->io_queue_size)) - continue; - } - - for (TaskThreadContext *&threadCtx : global_->threads_) { - threadCtx->thread.join(); - // TODO: Is it better to just delete these? - for (size_t i = 0; i < TASK_PRIORITY_COUNT; ++i) { - for (Task *task : threadCtx->private_queue[i]) { - TeardownTask(task, true); - } - } - delete threadCtx; - } - global_->threads_.clear(); - - if (global_->compute_queue_size > 0 || global_->io_queue_size > 0) { - WARN_LOG(Log::System, "ThreadManager::Teardown() with tasks still enqueued"); - } } bool ThreadManager::TeardownTask(Task *task, bool enqueue) { - if (!task) - return true; - - if (task->Cancellable()) { - task->Cancel(); - task->Release(); - return true; - } - - if (enqueue) { - size_t queueIndex = (size_t)task->Priority(); - if (task->Type() == TaskType::CPU_COMPUTE) { - global_->compute_queue[queueIndex].push_back(task); - global_->compute_queue_size++; - } else if (task->Type() == TaskType::IO_BLOCKING) { - global_->io_queue[queueIndex].push_back(task); - global_->io_queue_size++; - } else { - _assert_(false); - } - } - return false; -} - -static void WorkerThreadFunc(GlobalThreadContext *global, TaskThreadContext *thread) { - if (thread->type == TaskType::CPU_COMPUTE) { - snprintf(thread->name, sizeof(thread->name), "PoolW %d", thread->index); - } else { - _assert_(thread->type == TaskType::IO_BLOCKING); - snprintf(thread->name, sizeof(thread->name), "PoolW IO %d", thread->index); - } - SetCurrentThreadName(thread->name); - - // Should we do this on all threads? - if (thread->type == TaskType::IO_BLOCKING) { - AttachThreadToJNI(); - } - - const bool isCompute = thread->type == TaskType::CPU_COMPUTE; - const auto global_queue_size = [isCompute, &global]() -> int { - return isCompute ? global->compute_queue_size.load() : global->io_queue_size.load(); - }; - - while (!thread->cancelled) { - Task *task = nullptr; - - // Check the global queue first, then check the private queue and wait if there's nothing to do. - if (global_queue_size() > 0) { - // Grab one from the global queue if there is any. - std::unique_lock lock(global->mutex); - auto queue = isCompute ? global->compute_queue : global->io_queue; - auto &queue_size = isCompute ? global->compute_queue_size : global->io_queue_size; - - for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { - if (!queue[p].empty()) { - task = queue[p].front(); - queue[p].pop_front(); - queue_size--; - - // We are processing one now, so mark that. - thread->queue_size++; - break; - } else if (thread->queue_size != 0) { - // Check the thread, as we prefer a HIGH thread task to a global NORMAL task. - std::unique_lock lock(thread->mutex); - if (!thread->private_queue[p].empty()) { - task = thread->private_queue[p].front(); - thread->private_queue[p].pop_front(); - break; - } - } - } - } - - if (!task) { - // We didn't have any global, do we have anything on the thread? - std::unique_lock lock(thread->mutex); - for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { - if (thread->private_queue[p].empty()) - continue; - - task = thread->private_queue[p].front(); - thread->private_queue[p].pop_front(); - break; - } - - // We must check both queue and single again, while locked. - bool wait = !thread->cancelled && !task && global_queue_size() == 0; - - if (wait) - thread->cond.wait(lock); - } - // The task itself takes care of notifying anyone waiting on it. Not the - // responsibility of the ThreadManager (although it could be!). - if (task) { - task->Run(); - task->Release(); - // Reduce the queue size once complete. - thread->queue_size--; - // _dbg_assert_(thread->queue_size == thread->private_queue[0].size() + thread->private_queue[1].size() + thread->private_queue[2].size()); - } - } - - // In case it got attached to JNI, detach it. Don't think this has any side effects if called redundantly. - if (thread->type == TaskType::IO_BLOCKING) { - DetachThreadFromJNI(); - } + return true; } void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) { - if (IsInitialized()) { - Teardown(); - } - - numComputeThreads_ = std::min(numRealCores * numLogicalCoresPerCpu, MAX_CORES_TO_USE); - // Double it for the IO blocking threads. - int numThreads = numComputeThreads_ + std::max(MIN_IO_BLOCKING_THREADS, numComputeThreads_); - numThreads_ = numThreads; - - INFO_LOG(Log::System, "ThreadManager::Init(compute threads: %d, all: %d)", numComputeThreads_, numThreads_); - - for (int i = 0; i < numThreads; i++) { - TaskThreadContext *thread = new TaskThreadContext(); - thread->cancelled.store(false); - thread->type = i < numComputeThreads_ ? TaskType::CPU_COMPUTE : TaskType::IO_BLOCKING; - thread->index = i; - thread->thread = std::thread(&WorkerThreadFunc, global_, thread); - global_->threads_.push_back(thread); - } } void ThreadManager::EnqueueTask(Task *task) { @@ -242,82 +76,13 @@ void ThreadManager::EnqueueTask(Task *task) { task->Run(); task->Release(); return; - - if (task->Type() == TaskType::DEDICATED_THREAD) { - std::thread th([=](Task *task) { - SetCurrentThreadName("DedicatedThreadTask"); - task->Run(); - task->Release(); - }, task); - th.detach(); - return; - } - - _assert_msg_(IsInitialized(), "ThreadManager not initialized"); - - size_t queueIndex = (size_t)task->Priority(); - int minThread; - int maxThread; - if (task->Type() == TaskType::CPU_COMPUTE) { - // only the threads reserved for heavy compute. - minThread = 0; - maxThread = numComputeThreads_; - } else { - // Only IO blocking threads (to avoid starving compute threads.) - minThread = numComputeThreads_; - maxThread = numThreads_; - } - - // Find a thread with no outstanding work. - _assert_(maxThread <= (int)global_->threads_.size()); - for (int threadNum = minThread; threadNum < maxThread; threadNum++) { - TaskThreadContext *thread = global_->threads_[threadNum]; - if (thread->queue_size.load() == 0) { - std::unique_lock lock(thread->mutex); - thread->private_queue[queueIndex].push_back(task); - thread->queue_size++; - thread->cond.notify_one(); - // Found it - done. - return; - } - } - - // Still not scheduled? Put it on the global queue and notify a thread chosen by round-robin. - // Not particularly scientific, but hopefully we should not run into this too much. - { - std::unique_lock lock(global_->mutex); - if (task->Type() == TaskType::CPU_COMPUTE) { - global_->compute_queue[queueIndex].push_back(task); - global_->compute_queue_size++; - } else if (task->Type() == TaskType::IO_BLOCKING) { - global_->io_queue[queueIndex].push_back(task); - global_->io_queue_size++; - } else { - _assert_(false); - } - } - - int chosenIndex = global_->roundRobin++; - chosenIndex = minThread + (chosenIndex % (maxThread - minThread)); - TaskThreadContext *&chosenThread = global_->threads_[chosenIndex]; - - // Lock the thread to ensure it gets the message. - std::unique_lock lock(chosenThread->mutex); - chosenThread->cond.notify_one(); } void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) { - _assert_msg_(task->Type() != TaskType::DEDICATED_THREAD, "Dedicated thread tasks can't be put on specific threads"); - - _assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized"); - TaskThreadContext *thread = global_->threads_[threadNum]; - size_t queueIndex = (size_t)task->Priority(); - - thread->queue_size++; - - std::unique_lock lock(thread->mutex); - thread->private_queue[queueIndex].push_back(task); - thread->cond.notify_one(); + // Serialization: run task directly, without invoking a thread + task->Run(); + task->Release(); + return; } int ThreadManager::GetNumLooperThreads() const { From 8a570bbca67cd46131aad0cc6c1af6ccea52757f Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 10:32:39 +0200 Subject: [PATCH 05/70] Adding missing files --- build/git-version.cpp | 6 ++++++ build/miniupnpcstrings.h | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 build/git-version.cpp create mode 100644 build/miniupnpcstrings.h diff --git a/build/git-version.cpp b/build/git-version.cpp new file mode 100644 index 000000000000..e9022d697abb --- /dev/null +++ b/build/git-version.cpp @@ -0,0 +1,6 @@ +// This is a generated file. + +const char *PPSSPP_GIT_VERSION = "unknown"; + +// If you don't want this file to update/recompile, change to 1. +#define PPSSPP_GIT_VERSION_NO_UPDATE 0 diff --git a/build/miniupnpcstrings.h b/build/miniupnpcstrings.h new file mode 100644 index 000000000000..943ca20e5471 --- /dev/null +++ b/build/miniupnpcstrings.h @@ -0,0 +1,19 @@ +#ifndef MINIUPNPCSTRINGS_H_INCLUDED +#define MINIUPNPCSTRINGS_H_INCLUDED + +#define OS_STRING "Linux" +#define MINIUPNPC_VERSION_STRING "" + +#if 0 +/* according to "UPnP Device Architecture 1.0" */ +#define UPNP_VERSION_MAJOR 1 +#define UPNP_VERSION_MINOR 0 +#define UPNP_VERSION_STRING "UPnP/1.0" +#else +/* according to "UPnP Device Architecture 1.1" */ +#define UPNP_VERSION_MAJOR 1 +#define UPNP_VERSION_MINOR 1 +#define UPNP_VERSION_STRING "UPnP/1.1" +#endif + +#endif From ab602e4e46106e2ce4c9ecbad7fdb85ccf6c8aab Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 10:48:27 +0200 Subject: [PATCH 06/70] Removing threading --- Core/SaveState.cpp | 30 +------ libretro/LibretroGraphicsContext.cpp | 17 +--- libretro/libretro.cpp | 126 +-------------------------- 3 files changed, 3 insertions(+), 170 deletions(-) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index f553a598133a..5dc42c5c3744 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -17,8 +17,6 @@ #include #include -#include -#include #include "Common/Data/Text/I18n.h" #include "Common/Thread/ThreadUtil.h" @@ -114,22 +112,12 @@ double g_lastSaveTime = -1.0; } ~StateRingbuffer() { - if (compressThread_.joinable()) { - compressThread_.join(); - } } CChunkFileReader::Error Save() { rewindLastTime_ = time_now_d(); - // Make sure we're not processing a previous save. That'll cause a hitch though, but at least won't - // crash due to contention over buffer_. - if (compressThread_.joinable()) - compressThread_.join(); - - std::lock_guard guard(lock_); - int n = next_++ % size_; if ((next_ % size_) == first_) ++first_; @@ -159,8 +147,6 @@ double g_lastSaveTime = -1.0; CChunkFileReader::Error Restore(std::string *errorString) { - std::lock_guard guard(lock_); - // No valid states left. if (Empty()) return CChunkFileReader::ERROR_BAD_FILE; @@ -178,19 +164,11 @@ double g_lastSaveTime = -1.0; void ScheduleCompress(std::vector *result, const std::vector *state, const std::vector *base) { - if (compressThread_.joinable()) - compressThread_.join(); - compressThread_ = std::thread([=]{ - SetCurrentThreadName("SaveStateCompress"); - - // Should do no I/O, so no JNI thread context needed. - Compress(*result, *state, *base); - }); + Compress(*result, *state, *base); } void Compress(std::vector &result, const std::vector &state, const std::vector &base) { - std::lock_guard guard(lock_); // Bail if we were cleared before locking. if (first_ == 0 && next_ == 0) return; @@ -245,11 +223,7 @@ double g_lastSaveTime = -1.0; void Clear() { - if (compressThread_.joinable()) - compressThread_.join(); - // This lock is mainly for shutdown. - std::lock_guard guard(lock_); first_ = 0; next_ = 0; for (auto &b : bases_) { @@ -309,8 +283,6 @@ double g_lastSaveTime = -1.0; std::vector states_; StateBuffer bases_[2]; std::vector baseMapping_; - std::mutex lock_; - std::thread compressThread_; std::vector buffer_; int base_ = -1; diff --git a/libretro/LibretroGraphicsContext.cpp b/libretro/LibretroGraphicsContext.cpp index a220353d55e1..e2010de348af 100644 --- a/libretro/LibretroGraphicsContext.cpp +++ b/libretro/LibretroGraphicsContext.cpp @@ -42,10 +42,6 @@ LibretroHWRenderContext::LibretroHWRenderContext(retro_hw_context_type context_t void LibretroHWRenderContext::ContextReset() { INFO_LOG(Log::G3D, "Context reset"); - if (gpu && Libretro::useEmuThread) { - Libretro::EmuThreadPause(); - } - if (gpu) { gpu->DeviceLost(); } @@ -62,27 +58,16 @@ void LibretroHWRenderContext::ContextReset() { gpu->DeviceRestore(draw_); } - if (gpu && Libretro::useEmuThread) { - Libretro::EmuThreadStart(); - } } void LibretroHWRenderContext::ContextDestroy() { INFO_LOG(Log::G3D, "Context destroy"); - if (Libretro::useEmuThread) { - Libretro::EmuThreadStop(); - } - if (gpu) { gpu->DeviceLost(); } - if (!hw_render_.cache_context && Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED) { - DestroyDrawContext(); - } - - if (!hw_render_.cache_context && !Libretro::useEmuThread) { + if (!hw_render_.cache_context) { Shutdown(); } } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 464354ab48a7..2605354c5abf 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1,7 +1,6 @@ #include "ppsspp_config.h" #include #include -#include #include #include #include @@ -1318,10 +1317,6 @@ unsigned retro_api_version(void) { return RETRO_API_VERSION; } namespace Libretro { - bool useEmuThread = false; - std::atomic emuThreadState(EmuThreadState::DISABLED); - - static std::thread emuThread; static void EmuFrame() { ctx->SetRenderTarget(); @@ -1342,77 +1337,6 @@ namespace Libretro ctx->GetDrawContext()->Present(Draw::PresentMode::FIFO, 1); } } - - static void EmuThreadFunc() - { - SetCurrentThreadName("EmuThread"); - - for (;;) - { - switch ((EmuThreadState)emuThreadState) - { - case EmuThreadState::START_REQUESTED: - emuThreadState = EmuThreadState::RUNNING; - [[fallthrough]]; - case EmuThreadState::RUNNING: - EmuFrame(); - break; - case EmuThreadState::PAUSE_REQUESTED: - emuThreadState = EmuThreadState::PAUSED; - [[fallthrough]]; - case EmuThreadState::PAUSED: - sleep_ms(1, "libretro-paused"); - break; - default: - case EmuThreadState::QUIT_REQUESTED: - emuThreadState = EmuThreadState::STOPPED; - ctx->StopThread(); - return; - } - } - } - - void EmuThreadStart() - { - bool wasPaused = emuThreadState == EmuThreadState::PAUSED; - emuThreadState = EmuThreadState::START_REQUESTED; - - if (!wasPaused) - { - ctx->ThreadStart(); - emuThread = std::thread(&EmuThreadFunc); - } - } - - void EmuThreadStop() - { - if (emuThreadState != EmuThreadState::RUNNING) - return; - - emuThreadState = EmuThreadState::QUIT_REQUESTED; - - // Need to keep eating frames to allow the EmuThread to exit correctly. - while (ctx->ThreadFrame()) - ; - - emuThread.join(); - emuThread = std::thread(); - ctx->ThreadEnd(); - } - - void EmuThreadPause() - { - if (emuThreadState != EmuThreadState::RUNNING) - return; - - emuThreadState = EmuThreadState::PAUSE_REQUESTED; - - ctx->ThreadFrame(); // Eat 1 frame - - while (emuThreadState != EmuThreadState::PAUSED) - sleep_ms(1, "libretro-pause-poll"); - } - } // namespace Libretro static void retro_check_backend(void) @@ -1453,8 +1377,6 @@ bool retro_load_game(const struct retro_game_info *game) Core_SetGraphicsContext(ctx); SetGPUBackend((GPUBackend)g_Config.iGPUBackend); - useEmuThread = ctx->GetGPUCore() == GPUCORE_GLES; - // default to interpreter to allow startup in platforms w/o JIT capability g_Config.iCpuCore = (int)CPUCore::INTERPRETER; @@ -1509,9 +1431,6 @@ bool retro_load_game(const struct retro_game_info *game) void retro_unload_game(void) { - if (Libretro::useEmuThread) - Libretro::EmuThreadStop(); - PSP_Shutdown(true); g_VFS.Clear(); @@ -1665,27 +1584,7 @@ void retro_run(void) retro_input(); - if (useEmuThread) - { - if ( emuThreadState == EmuThreadState::PAUSED || - emuThreadState == EmuThreadState::PAUSE_REQUESTED) - { - VsyncSwapIntervalDetect(); - ctx->SwapBuffers(); - return; - } - - if (emuThreadState != EmuThreadState::RUNNING) - EmuThreadStart(); - - if (!ctx->ThreadFrame()) - { - VsyncSwapIntervalDetect(); - return; - } - } - else - EmuFrame(); + EmuFrame(); VsyncSwapIntervalDetect(); ctx->SwapBuffers(); @@ -1710,9 +1609,6 @@ size_t retro_serialize_size(void) return 134217728; // 128MB ought to be enough for anybody. SaveState::SaveStart state; - // TODO: Libretro API extension to use the savestate queue - if (useEmuThread) - EmuThreadPause(); return (CChunkFileReader::MeasurePtr(state) + 0x800000) & ~0x7FFFFF; // We don't unpause intentionally @@ -1723,21 +1619,11 @@ bool retro_serialize(void *data, size_t size) if (!gpu) // The HW renderer isn't ready on first pass. return false; - // TODO: Libretro API extension to use the savestate queue - if (useEmuThread) - EmuThreadPause(); // Does nothing if already paused - size_t measuredSize; SaveState::SaveStart state; auto err = CChunkFileReader::MeasureAndSavePtr(state, (u8 **)&data, &measuredSize); bool retVal = err == CChunkFileReader::ERROR_NONE; - if (useEmuThread) - { - EmuThreadStart(); - sleep_ms(4, "libretro-serialize"); - } - return retVal; } @@ -1746,21 +1632,11 @@ bool retro_unserialize(const void *data, size_t size) if (!gpu) // The HW renderer isn't ready on first pass. return false; - // TODO: Libretro API extension to use the savestate queue - if (useEmuThread) - EmuThreadPause(); // Does nothing if already paused - std::string errorString; SaveState::SaveStart state; bool retVal = CChunkFileReader::LoadPtr((u8 *)data, state, &errorString) == CChunkFileReader::ERROR_NONE; - if (useEmuThread) - { - EmuThreadStart(); - sleep_ms(4, "libretro-unserialize"); - } - return retVal; } From f3a8a1a1242ea4869d5eb05058f8e4c3ee7d278e Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 15:00:29 +0200 Subject: [PATCH 07/70] Finishing dethread --- Core/HLE/sceIo.cpp | 8 ++++---- Core/HLE/sceKernelMemory.cpp | 2 +- Core/HLE/sceSas.cpp | 10 +++++----- Core/Util/PortManager.cpp | 20 ++++++++++---------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index a8c754e9ada0..7ff400fc5917 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -687,10 +687,10 @@ void __IoInit() { memset(fds, 0, sizeof(fds)); - ioManagerThreadEnabled = true; - ioManager.SetThreadEnabled(true); - Core_ListenLifecycle(&__IoWakeManager); - ioManagerThread = new std::thread(&__IoManagerThread); + ioManagerThreadEnabled = false; + // ioManager.SetThreadEnabled(true); + // Core_ListenLifecycle(&__IoWakeManager); + // ioManagerThread = new std::thread(&__IoManagerThread); __KernelRegisterWaitTypeFuncs(WAITTYPE_ASYNCIO, __IoAsyncBeginCallback, __IoAsyncEndCallback); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index fc8a6b9b3dc2..8f2ed18201d1 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -306,7 +306,7 @@ void __KernelFplEndCallback(SceUID threadID, SceUID prevCallbackId); void __KernelMemoryInit() { - MemBlockInfoInit(); + //MemBlockInfoInit(); kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false); volatileMemory.Init(PSP_GetVolatileMemoryStart(), PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart(), false); diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 94a4205a8a67..cd8dc2e63a5d 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -164,12 +164,12 @@ void __SasInit() { sasMixEvent = CoreTiming::RegisterEvent("SasMix", sasMixFinish); - if (g_Config.bSeparateSASThread) { - sasThreadState = SasThreadState::READY; - sasThread = new std::thread(__SasThread); - } else { + // if (g_Config.bSeparateSASThread) { + // sasThreadState = SasThreadState::READY; + // sasThread = new std::thread(__SasThread); + // } else { sasThreadState = SasThreadState::DISABLED; - } + // } } void __SasDoState(PointerWrap &p) { diff --git a/Core/Util/PortManager.cpp b/Core/Util/PortManager.cpp index a552a89d2cde..50c96987528f 100644 --- a/Core/Util/PortManager.cpp +++ b/Core/Util/PortManager.cpp @@ -525,19 +525,19 @@ int upnpService(const unsigned int timeout) } void __UPnPInit(const unsigned int timeout) { - if (!upnpServiceRunning) { - upnpServiceRunning = true; - upnpServiceThread = std::thread(upnpService, timeout); - } + // if (!upnpServiceRunning) { + // upnpServiceRunning = true; + // upnpServiceThread = std::thread(upnpService, timeout); + // } } void __UPnPShutdown() { - if (upnpServiceRunning) { - upnpServiceRunning = false; - if (upnpServiceThread.joinable()) { - upnpServiceThread.join(); - } - } + // if (upnpServiceRunning) { + // upnpServiceRunning = false; + // if (upnpServiceThread.joinable()) { + // upnpServiceThread.join(); + // } + // } } void UPnP_Add(const char* protocol, unsigned short port, unsigned short intport) { From 2d096dd63ef916cf658f5769c8287e733048d21e Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 15:06:21 +0200 Subject: [PATCH 08/70] Removed unnecessary deinit --- Core/HLE/sceKernelMemory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 8f2ed18201d1..2b4ab7ec6aac 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -382,7 +382,7 @@ void __KernelMemoryShutdown() #endif kernelMemory.Shutdown(); tlsplThreadEndChecks.clear(); - MemBlockInfoShutdown(); + // MemBlockInfoShutdown(); } BlockAllocator *BlockAllocatorFromID(int id) { From 58186399d6627936a331bac37141231a5a63cf0f Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 16:08:05 +0200 Subject: [PATCH 09/70] Reading cd rom image from callbacks --- Core/FileLoaders/LocalFileLoader.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 3abd59300360..70f250341a0a 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -42,7 +42,14 @@ #if !defined(_WIN32) && !defined(HAVE_LIBRETRO_VFS) +extern std::string _cdImageFilePath; +extern uint32_t cd_get_size(void); +extern size_t readSegmentFromCD(void *buf_, const uint64_t address, const size_t size); + void LocalFileLoader::DetectSizeFd() { + + if (_cdImageFilePath == filename_.c_str()) { filesize_ = cd_get_size(); return; } + #if PPSSPP_PLATFORM(ANDROID) || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64) off64_t off = lseek64(fd_, 0, SEEK_END); filesize_ = off; @@ -58,6 +65,11 @@ void LocalFileLoader::DetectSizeFd() { LocalFileLoader::LocalFileLoader(const Path &filename) : filesize_(0), filename_(filename) { + if (_cdImageFilePath == filename_.c_str()) + { + filesize_ = cd_get_size(); + } + if (filename.empty()) { ERROR_LOG(Log::FileSystem, "LocalFileLoader can't load empty filenames"); return; @@ -123,6 +135,8 @@ LocalFileLoader::LocalFileLoader(const Path &filename) } LocalFileLoader::~LocalFileLoader() { + if (_cdImageFilePath == filename_.c_str()) return; + #if defined(HAVE_LIBRETRO_VFS) filestream_close(handle_); #elif !defined(_WIN32) @@ -137,6 +151,8 @@ LocalFileLoader::~LocalFileLoader() { } bool LocalFileLoader::Exists() { + if (_cdImageFilePath == filename_.c_str()) return true; + // If we opened it for reading, it must exist. Done. #if defined(HAVE_LIBRETRO_VFS) return handle_ != 0; @@ -158,6 +174,8 @@ bool LocalFileLoader::Exists() { } bool LocalFileLoader::IsDirectory() { + if (_cdImageFilePath == filename_.c_str()) return false; + File::FileInfo info; if (File::GetFileInfo(filename_, &info)) { return info.exists && info.isDirectory; @@ -170,6 +188,9 @@ s64 LocalFileLoader::FileSize() { } size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags) { + + if (_cdImageFilePath == filename_.c_str()) return readSegmentFromCD(data, absolutePos, bytes * count); + if (bytes == 0) return 0; From a2402a96668e84238b5da6784c1827bedfd036cf Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 18:20:52 +0200 Subject: [PATCH 10/70] Removing GL and vulkan dep --- Common/GPU/ShaderTranslation.cpp | 26 +++--- Core/Config.cpp | 59 ------------- Core/Dialog/PSPSaveDialog.cpp | 2 + Core/FileLoaders/CachingFileLoader.cpp | 2 + Core/FileLoaders/RamCachingFileLoader.cpp | 2 + Core/HLE/sceNetAdhoc.cpp | 1 + Core/HLE/sceNetAdhocMatching.cpp | 2 + Core/MIPS/IR/IRNativeCommon.cpp | 2 + Core/Reporting.cpp | 2 + Core/Util/GameManager.cpp | 3 + Core/Util/RecentFiles.cpp | 1 + Core/WebServer.cpp | 2 + GPU/Common/DepthBufferCommon.cpp | 16 ++-- GPU/Common/FragmentShaderGenerator.cpp | 50 ++--------- GPU/Common/GeometryShaderGenerator.cpp | 5 -- GPU/Common/PostShader.cpp | 8 -- GPU/Common/SoftwareTransformCommon.cpp | 2 +- GPU/Common/VertexShaderGenerator.cpp | 15 ---- GPU/GPU.cpp | 14 --- libretro/LibretroGLContext.cpp | 24 +++--- libretro/LibretroGraphicsContext.cpp | 100 ++++++++++------------ 21 files changed, 103 insertions(+), 235 deletions(-) diff --git a/Common/GPU/ShaderTranslation.cpp b/Common/GPU/ShaderTranslation.cpp index ad8c1ee76b5f..f609e03e7b74 100644 --- a/Common/GPU/ShaderTranslation.cpp +++ b/Common/GPU/ShaderTranslation.cpp @@ -337,19 +337,19 @@ bool TranslateShader(std::string *dest, ShaderLanguage destLang, const ShaderLan } case GLSL_3xx: { - spirv_cross::CompilerGLSL glsl(std::move(spirv)); - // The SPIR-V is now parsed, and we can perform reflection on it. - spirv_cross::ShaderResources resources = glsl.get_shader_resources(); - // Set some options. - spirv_cross::CompilerGLSL::Options options; - options.es = desc.gles; - options.version = gl_extensions.GLSLVersion(); - // macOS OpenGL 4.1 implementation does not support GL_ARB_shading_language_420pack. - // Prevent explicit binding location emission enabled in SPIRV-Cross by default. - options.enable_420pack_extension = gl_extensions.ARB_shading_language_420pack; - glsl.set_common_options(options); - // Compile to GLSL, ready to give to GL driver. - *dest = glsl.compile(); + // spirv_cross::CompilerGLSL glsl(std::move(spirv)); + // // The SPIR-V is now parsed, and we can perform reflection on it. + // spirv_cross::ShaderResources resources = glsl.get_shader_resources(); + // // Set some options. + // spirv_cross::CompilerGLSL::Options options; + // options.es = desc.gles; + // options.version = gl_extensions.GLSLVersion(); + // // macOS OpenGL 4.1 implementation does not support GL_ARB_shading_language_420pack. + // // Prevent explicit binding location emission enabled in SPIRV-Cross by default. + // options.enable_420pack_extension = gl_extensions.ARB_shading_language_420pack; + // glsl.set_common_options(options); + // // Compile to GLSL, ready to give to GL driver. + // *dest = glsl.compile(); return true; } default: diff --git a/Core/Config.cpp b/Core/Config.cpp index 45760dd5e243..39eb9a3b5a32 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -515,73 +515,14 @@ int Config::NextValidBackend() { if (failed.count((GPUBackend)iGPUBackend)) { ERROR_LOG(Log::Loader, "Graphics backend failed for %d, trying another", iGPUBackend); -#if !PPSSPP_PLATFORM(UWP) - if (!failed.count(GPUBackend::VULKAN) && VulkanMayBeAvailable()) { - return (int)GPUBackend::VULKAN; - } -#endif -#if PPSSPP_PLATFORM(WINDOWS) - if (!failed.count(GPUBackend::DIRECT3D11) && IsWin7OrHigher()) { - return (int)GPUBackend::DIRECT3D11; - } -#endif -#if PPSSPP_API(ANY_GL) - if (!failed.count(GPUBackend::OPENGL)) { - return (int)GPUBackend::OPENGL; - } -#endif -#if PPSSPP_API(D3D9) - if (!failed.count(GPUBackend::DIRECT3D9)) { - return (int)GPUBackend::DIRECT3D9; - } -#endif - - // They've all failed. Let them try the default - or on Android, OpenGL. - sFailedGPUBackends += ",ALL"; - ERROR_LOG(Log::Loader, "All graphics backends failed"); -#if PPSSPP_PLATFORM(ANDROID) - return (int)GPUBackend::OPENGL; -#else return DefaultGPUBackend(); -#endif } return iGPUBackend; } bool Config::IsBackendEnabled(GPUBackend backend) { - std::vector split; - - SplitString(sDisabledGPUBackends, ',', split); - for (const auto &str : split) { - if (str.empty()) - continue; - auto match = GPUBackendFromString(str); - if (match == backend) - return false; - } - -#if PPSSPP_PLATFORM(UWP) - if (backend != GPUBackend::DIRECT3D11) - return false; -#elif PPSSPP_PLATFORM(SWITCH) - if (backend != GPUBackend::OPENGL) - return false; -#elif PPSSPP_PLATFORM(WINDOWS) - if (backend == GPUBackend::DIRECT3D11 && !IsVistaOrHigher()) return false; -#else - if (backend == GPUBackend::DIRECT3D11 || backend == GPUBackend::DIRECT3D9) - return false; -#endif - -#if !PPSSPP_API(ANY_GL) - if (backend == GPUBackend::OPENGL) - return false; -#endif - if (backend == GPUBackend::VULKAN && !VulkanMayBeAvailable()) - return false; - return true; } template diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 6d11ef93bec4..755c8ed0bc0e 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -1227,6 +1227,8 @@ void PSPSaveDialog::StartIOThread() { } ioThreadStatus = SAVEIO_PENDING; + + fprintf(stderr, "Unexpected thread creation found in PSPSaveDialog.cpp\n"); std::abort(); ioThread = new std::thread(&DoExecuteIOAction, this); } diff --git a/Core/FileLoaders/CachingFileLoader.cpp b/Core/FileLoaders/CachingFileLoader.cpp index 5a419502e672..12abd47ec722 100644 --- a/Core/FileLoaders/CachingFileLoader.cpp +++ b/Core/FileLoaders/CachingFileLoader.cpp @@ -266,6 +266,8 @@ void CachingFileLoader::StartReadAhead(s64 pos) { aheadThreadRunning_ = true; if (aheadThread_.joinable()) aheadThread_.join(); + + fprintf(stderr, "Unexpected thread creation found in CachingFileLoader.cpp\n"); std::abort(); aheadThread_ = std::thread([this, pos] { SetCurrentThreadName("FileLoaderReadAhead"); diff --git a/Core/FileLoaders/RamCachingFileLoader.cpp b/Core/FileLoaders/RamCachingFileLoader.cpp index 8e4808c771eb..c6e69d5f2ba5 100644 --- a/Core/FileLoaders/RamCachingFileLoader.cpp +++ b/Core/FileLoaders/RamCachingFileLoader.cpp @@ -224,6 +224,8 @@ void RamCachingFileLoader::StartReadAhead(s64 pos) { aheadCancel_ = false; if (aheadThread_.joinable()) aheadThread_.join(); + + fprintf(stderr, "Unexpected thread creation found in RamCachingFileLoader.cpp\n"); std::abort(); aheadThread_ = std::thread([this] { SetCurrentThreadName("FileLoaderReadAhead"); diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index a187591bf2f2..59f464b6a659 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -1243,6 +1243,7 @@ void __NetAdhocInit() { // Create built-in AdhocServer Thread adhocServerRunning = false; if (g_Config.bEnableWlan && g_Config.bEnableAdhocServer) { + fprintf(stderr, "Unexpected thread creation found in sceNetAdhoc.cpp\n"); std::abort(); adhocServerThread = std::thread(proAdhocServerThread, SERVER_PORT); } } diff --git a/Core/HLE/sceNetAdhocMatching.cpp b/Core/HLE/sceNetAdhocMatching.cpp index 9351b8d76176..a5d28ffee88e 100644 --- a/Core/HLE/sceNetAdhocMatching.cpp +++ b/Core/HLE/sceNetAdhocMatching.cpp @@ -1890,6 +1890,8 @@ int NetAdhocMatching_Start(int matchingId, int evthPri, int evthPartitionId, int //item->matchingThread->Start(matchingId, 0); } + fprintf(stderr, "Unexpected thread creation found in sceNetAdhocMatching.cpp\n"); std::abort(); + //Create the threads if (!item->eventRunning) { item->eventRunning = true; diff --git a/Core/MIPS/IR/IRNativeCommon.cpp b/Core/MIPS/IR/IRNativeCommon.cpp index 229bd8810644..7132551bd878 100644 --- a/Core/MIPS/IR/IRNativeCommon.cpp +++ b/Core/MIPS/IR/IRNativeCommon.cpp @@ -494,6 +494,8 @@ void IRNativeJit::Init(IRNativeBackend &backend) { if (enableDebugProfiler && hooks_.profilerPC) { debugProfilerThreadStatus = true; + + fprintf(stderr, "Unexpected thread creation found in IRNativeCommon.cpp\n"); std::abort(); debugProfilerThread = std::thread([&] { // Spin, spin spin... maybe could at least hook into sleeps. while (debugProfilerThreadStatus) { diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index 8a0c5fee24cf..4721cc00896e 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -171,6 +171,8 @@ namespace Reporting crcFilename = gamePath; crcPending = true; crcCancel = false; + + fprintf(stderr, "Unexpected thread creation found in Reporting.cpp\n"); std::abort(); crcThread = std::thread(CalculateCRCThread); } diff --git a/Core/Util/GameManager.cpp b/Core/Util/GameManager.cpp index 11e633f635f3..3aa21e52fb7e 100644 --- a/Core/Util/GameManager.cpp +++ b/Core/Util/GameManager.cpp @@ -926,6 +926,7 @@ bool GameManager::InstallZipOnThread(ZipFileTask task) { return false; } + fprintf(stderr, "Unexpected thread creation found in GameManager.cpp\n"); std::abort(); installThread_ = std::thread(std::bind(&GameManager::InstallZipContents, this, task)); return true; } @@ -938,6 +939,8 @@ bool GameManager::UninstallGameOnThread(const std::string &name) { if (InstallInProgress() || installDonePending_ || curDownload_.get() != nullptr) { return false; } + + fprintf(stderr, "Unexpected thread creation found in GameManager.cpp\n"); std::abort(); installThread_ = std::thread(std::bind(&GameManager::UninstallGame, this, name)); return true; } diff --git a/Core/Util/RecentFiles.cpp b/Core/Util/RecentFiles.cpp index 8a9f0444512e..8e8ab4987389 100644 --- a/Core/Util/RecentFiles.cpp +++ b/Core/Util/RecentFiles.cpp @@ -31,6 +31,7 @@ void RecentFilesManager::EnsureThread() { return; } std::lock_guard guard(cmdLock_); + fprintf(stderr, "Unexpected thread creation found in RecentFiles.cpp\n"); std::abort(); thread_ = std::thread([this] { // NOTE: Can't create the thread in the constructor, because at that point, // JNI attachment doesn't yet work. diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index 1a36a45b9155..09d458a41307 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -460,6 +460,8 @@ bool StartWebServer(WebServerFlags flags) { case ServerStatus::STOPPED: serverStatus = ServerStatus::STARTING; serverFlags = (int)flags; + + fprintf(stderr, "Unexpected thread creation found in WebServer.cpp\n"); std::abort(); serverThread = std::thread(&ExecuteWebServer); return true; diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index f49a88d20d77..9810d3a82016 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -115,10 +115,11 @@ void main() { )"; static bool SupportsDepthTexturing() { - if (gl_extensions.IsGLES) { - return gl_extensions.OES_packed_depth_stencil && (gl_extensions.OES_depth_texture || gl_extensions.GLES3); - } - return gl_extensions.ARB_texture_float; + // if (gl_extensions.IsGLES) { + // return gl_extensions.OES_packed_depth_stencil && (gl_extensions.OES_depth_texture || gl_extensions.GLES3); + // } + // return gl_extensions.ARB_texture_float; + return false; } Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag) { @@ -168,11 +169,6 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x ERROR_LOG_REPORT_ONCE(vfbfbozero, Log::sceGe, "ReadbackDepthbufferSync: bad fbo"); return false; } - // Old desktop GL can download depth, but not upload. - if (gl_extensions.IsGLES && !SupportsDepthTexturing()) { - return false; - } - // Pixel size always 4 here because we always request float or RGBA. const u32 bufSize = destW * destH * 4; if (!convBuf_ || convBufSize_ < bufSize) { @@ -184,7 +180,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x float scaleX = (float)destW / w; float scaleY = (float)destH / h; - bool useColorPath = gl_extensions.IsGLES || scaleX != 1.0f || scaleY != 1.0f; + bool useColorPath = scaleX != 1.0f || scaleY != 1.0f; bool format16Bit = false; if (useColorPath) { diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 757cb4d291ab..0b475f1e6fac 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -58,33 +58,12 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu bool highpTexcoord = false; bool enableFragmentTestCache = gstate_c.Use(GPU_USE_FRAGMENT_TEST_CACHE); - if (compat.gles) { - // PowerVR needs highp to do the fog in MHU correctly. - // Others don't, and some can't handle highp in the fragment shader. - highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false; - highpTexcoord = highpFog; - } - bool texture3D = id.Bit(FS_BIT_3D_TEXTURE); bool arrayTexture = id.Bit(FS_BIT_SAMPLE_ARRAY_TEXTURE); ReplaceAlphaType stencilToAlpha = static_cast(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2)); std::vector extensions; - if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE && gl_extensions.EXT_blend_func_extended) { - extensions.push_back("#extension GL_EXT_blend_func_extended : require"); - } - if (gl_extensions.EXT_gpu_shader4) { - extensions.push_back("#extension GL_EXT_gpu_shader4 : enable"); - } - if (compat.framebufferFetchExtension) { - extensions.push_back(compat.framebufferFetchExtension); - } - if (gl_extensions.OES_texture_3D && texture3D) { - extensions.push_back("#extension GL_OES_texture_3D: enable"); - } - } ShaderWriterFlags flags = ShaderWriterFlags::NONE; if (useStereo) { @@ -361,9 +340,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, "};\n"); } } else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - if ((shaderDepalMode != ShaderDepalMode::OFF || colorWriteMask) && gl_extensions.IsGLES) { - WRITE(p, "precision highp int;\n"); - } if (doTexture) { if (texture3D) { @@ -461,9 +437,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (enableAlphaTest && !alphaTestAgainstZero) { if (compat.bitwiseOps) { WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n"); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { - WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n"); - } else { + } else { WRITE(p, "float roundAndScaleTo255f(in float x) { return floor(x * 255.0 + 0.5); }\n"); } } @@ -471,8 +445,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (compat.bitwiseOps) { WRITE(p, "uint roundAndScaleTo8x4(in vec3 x) { uvec3 u = uvec3(floor(x * 255.92)); return u.r | (u.g << 0x8u) | (u.b << 0x10u); }\n"); WRITE(p, "uint packFloatsTo8x4(in vec3 x) { uvec3 u = uvec3(x); return u.r | (u.g << 0x8u) | (u.b << 0x10u); }\n"); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { - WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n"); } else { WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n"); } @@ -531,11 +503,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu p.C("}\n"); } - // PowerVR needs a custom modulo function. For some reason, this has far higher precision than the builtin one. - if ((gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) && needShaderTexClamp) { - WRITE(p, "float mymod(float a, float b) { return a - b * floor(a / b); }\n"); - } - if (compat.shaderLanguage == HLSL_D3D11) { WRITE(p, "PS_OUT main( PS_IN In ) {\n"); WRITE(p, " PS_OUT outfragment;\n"); @@ -609,7 +576,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu // TODO: Not sure the right way to do this for projection. // This path destroys resolution on older PowerVR no matter what I do if projection is needed, // so we disable it on SGX 540 and lesser, and live with the consequences. - bool terriblePrecision = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_TERRIBLE) != 0; + bool terriblePrecision = false; bool clampDisabled = doTextureProjection && terriblePrecision; // Also with terrible precision we can't do wrapping without destroying the image. See #9189 if (terriblePrecision && (!id.Bit(FS_BIT_CLAMP_S) || !id.Bit(FS_BIT_CLAMP_T))) { @@ -626,7 +593,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu vcoord = "(v_texcoord.y / v_texcoord.z)"; } - std::string modulo = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? "mymod" : "mod"; + std::string modulo = "mod"; if (id.Bit(FS_BIT_CLAMP_S)) { ucoord = "clamp(" + ucoord + ", u_texclamp.z, u_texclamp.x - u_texclamp.z)"; @@ -954,12 +921,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu if (alphaTestFuncs[alphaTestFunc][0] != '#') { if (compat.bitwiseOps) { WRITE(p, " if ((roundAndScaleTo255i(v.a) & int(u_alphacolormask >> 0x18u)) %s int(u_alphacolorref >> 0x18u)) %s\n", alphaTestFuncs[alphaTestFunc], discardStatement); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { - // Work around bad PVR driver problem where equality check + discard just doesn't work. - if (alphaTestFunc != GE_COMP_NOTEQUAL) { - WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) %s\n", alphaTestFuncs[alphaTestFunc], discardStatement); - } - } else { + } else { WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) %s\n", alphaTestFuncs[alphaTestFunc], discardStatement); } } else { @@ -1021,9 +983,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " uint v_masked = v_uint & u_alphacolormask;\n"); WRITE(p, " uint colorTestRef = (u_alphacolorref & u_alphacolormask) & 0xFFFFFFu;\n"); WRITE(p, " if (v_masked %s colorTestRef) %s\n", test, discardStatement); - } else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) { - WRITE(p, " if (roundTo255thv(v.rgb) %s u_alphacolorref.rgb) %s\n", test, discardStatement); - } else { + } else { WRITE(p, " if (roundAndScaleTo255v(v.rgb) %s u_alphacolorref.rgb) %s\n", test, discardStatement); } } else { diff --git a/GPU/Common/GeometryShaderGenerator.cpp b/GPU/Common/GeometryShaderGenerator.cpp index d09775cf7636..9d7c0032bb92 100644 --- a/GPU/Common/GeometryShaderGenerator.cpp +++ b/GPU/Common/GeometryShaderGenerator.cpp @@ -40,11 +40,6 @@ bool GenerateGeometryShader(const GShaderID &id, char *buffer, const ShaderLanguageDesc &compat, const Draw::Bugs bugs, std::string *errorString) { std::vector extensions; - if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - if (gl_extensions.EXT_gpu_shader4) { - extensions.push_back("#extension GL_EXT_gpu_shader4 : enable"); - } - } bool vertexRangeCulling = !id.Bit(GS_BIT_CURVE); bool clipClampedDepth = gstate_c.Use(GPU_USE_DEPTH_CLAMP); diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index 9ea606078ba8..c783d1a8cc5d 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -176,14 +176,6 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct section.Get(StringFromFormat("SettingStep%d", i + 1).c_str(), &setting.step, 0.01f); } - // Let's ignore shaders we can't support. TODO: Not a very good check - if (gl_extensions.IsGLES && !gl_extensions.GLES3) { - bool requiresIntegerSupport; - section.Get("RequiresIntSupport", &requiresIntegerSupport, false); - if (requiresIntegerSupport) - continue; - } - if (info.visible) { appendShader(info); } else { diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index dc6e8139436f..629e18799652 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -389,7 +389,7 @@ void SoftwareTransform::Transform(int prim, u32 vertType, const DecVtxFormat &de result->safeHeight = scissorY2; } } - if (params_.allowClear && reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_IMGTEC) { + if (params_.allowClear && reallyAClear) { // If alpha is not allowed to be separate, it must match for both depth/stencil and color. Vulkan requires this. bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask(); bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask(); diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 55d62b7acc76..b46973f24cad 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -133,21 +133,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag std::vector extensions; extensions.reserve(6); - if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) { - if (gl_extensions.EXT_gpu_shader4) { - extensions.push_back("#extension GL_EXT_gpu_shader4 : enable"); - } - bool useClamp = gstate_c.Use(GPU_USE_DEPTH_CLAMP) && !id.Bit(VS_BIT_IS_THROUGH); - if (gl_extensions.EXT_clip_cull_distance && (id.Bit(VS_BIT_VERTEX_RANGE_CULLING) || useClamp)) { - extensions.push_back("#extension GL_EXT_clip_cull_distance : enable"); - } - if (gl_extensions.APPLE_clip_distance && (id.Bit(VS_BIT_VERTEX_RANGE_CULLING) || useClamp)) { - extensions.push_back("#extension GL_APPLE_clip_distance : enable"); - } - if (gl_extensions.ARB_cull_distance && id.Bit(VS_BIT_VERTEX_RANGE_CULLING)) { - extensions.push_back("#extension GL_ARB_cull_distance : enable"); - } - } bool useSimpleStereo = id.Bit(VS_BIT_SIMPLE_STEREO); diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index 7dfc759ebe4f..bbf4795b4000 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -25,20 +25,8 @@ #include "GPU/GPU.h" #include "GPU/GPUCommon.h" -#if PPSSPP_API(ANY_GL) -#include "GPU/GLES/GPU_GLES.h" -#endif -#include "GPU/Vulkan/GPU_Vulkan.h" #include "GPU/Software/SoftGpu.h" -#if PPSSPP_API(D3D9) -#include "GPU/Directx9/GPU_DX9.h" -#endif - -#if PPSSPP_API(D3D11) -#include "GPU/D3D11/GPU_D3D11.h" -#endif - GPUStatistics gpuStats; GPUCommon *gpu; GPUDebugInterface *gpuDebug; @@ -74,7 +62,6 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { case GPUCORE_GLES: // Disable GLES on ARM Windows (but leave it enabled on other ARM platforms). #if PPSSPP_API(ANY_GL) - SetGPU(new GPU_GLES(ctx, draw)); break; #else return false; @@ -102,7 +89,6 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { ERROR_LOG(Log::G3D, "Unable to init Vulkan GPU backend, no context"); break; } - SetGPU(new GPU_Vulkan(ctx, draw)); break; #endif default: diff --git a/libretro/LibretroGLContext.cpp b/libretro/LibretroGLContext.cpp index 45a33eb69be8..e156a752a152 100644 --- a/libretro/LibretroGLContext.cpp +++ b/libretro/LibretroGLContext.cpp @@ -17,18 +17,18 @@ bool LibretroGLContext::Init() { void LibretroGLContext::CreateDrawContext() { -#ifndef USING_GLES2 - // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. - // glewExperimental allows us to force GLEW to search for the pointers anyway. - if (gl_extensions.IsCoreContext) - glewExperimental = true; - if (GLEW_OK != glewInit()) { - printf("Failed to initialize glew!\n"); - } - // Unfortunately, glew will generate an invalid enum error, ignore. - if (gl_extensions.IsCoreContext) - glGetError(); -#endif +// #ifndef USING_GLES2 +// // Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc. +// // glewExperimental allows us to force GLEW to search for the pointers anyway. +// if (gl_extensions.IsCoreContext) +// glewExperimental = true; +// if (GLEW_OK != glewInit()) { +// printf("Failed to initialize glew!\n"); +// } +// // Unfortunately, glew will generate an invalid enum error, ignore. +// if (gl_extensions.IsCoreContext) +// glGetError(); +// #endif CheckGLExtensions(); draw_ = Draw::T3DCreateGLContext(false); diff --git a/libretro/LibretroGraphicsContext.cpp b/libretro/LibretroGraphicsContext.cpp index e2010de348af..1c7dbc0659b8 100644 --- a/libretro/LibretroGraphicsContext.cpp +++ b/libretro/LibretroGraphicsContext.cpp @@ -1,11 +1,5 @@ #include "libretro/LibretroGraphicsContext.h" -#include "libretro/LibretroGLContext.h" -#include "libretro/LibretroGLCoreContext.h" -#include "libretro/LibretroVulkanContext.h" -#ifdef _WIN32 -#include "libretro/LibretroD3D11Context.h" -#endif #include "Common/Log.h" #include "Core/Config.h" @@ -86,53 +80,53 @@ LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() { if (Libretro::backend != RETRO_HW_CONTEXT_DUMMY) preferred = Libretro::backend; -#ifndef USING_GLES2 - if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) { - ctx = new LibretroGLCoreContext(); - - if (ctx->Init()) { - return ctx; - } - delete ctx; - } -#endif - - if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL || preferred == RETRO_HW_CONTEXT_OPENGLES3) { - ctx = new LibretroGLContext(); - - if (ctx->Init()) { - return ctx; - } - delete ctx; - } - -#ifndef HAVE_LIBNX - if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_VULKAN) { - ctx = new LibretroVulkanContext(); - - if (ctx->Init()) { - return ctx; - } - delete ctx; - } -#endif - -#ifdef _WIN32 - if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_DIRECT3D) { - ctx = new LibretroD3D11Context(); - - if (ctx->Init()) { - return ctx; - } - delete ctx; - - ctx = new LibretroD3D9Context(); - if (ctx->Init()) { - return ctx; - } - delete ctx; - } -#endif +// #ifndef USING_GLES2 +// if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL_CORE) { +// ctx = new LibretroGLCoreContext(); + +// if (ctx->Init()) { +// return ctx; +// } +// delete ctx; +// } +// #endif + +// if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL || preferred == RETRO_HW_CONTEXT_OPENGLES3) { +// ctx = new LibretroGLContext(); + +// if (ctx->Init()) { +// return ctx; +// } +// delete ctx; +// } + +// #ifndef HAVE_LIBNX +// if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_VULKAN) { +// ctx = new LibretroVulkanContext(); + +// if (ctx->Init()) { +// return ctx; +// } +// delete ctx; +// } +// #endif + +// #ifdef _WIN32 +// if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_DIRECT3D) { +// ctx = new LibretroD3D11Context(); + +// if (ctx->Init()) { +// return ctx; +// } +// delete ctx; + +// ctx = new LibretroD3D9Context(); +// if (ctx->Init()) { +// return ctx; +// } +// delete ctx; +// } +// #endif ctx = new LibretroSoftwareContext(); ctx->Init(); From c01f97868b2af08e229b56c7a439983f4eead0d0 Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 18:23:19 +0200 Subject: [PATCH 11/70] Grabbing file that produced annoying warning --- ext/loslib.c | 424 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 ext/loslib.c diff --git a/ext/loslib.c b/ext/loslib.c new file mode 100644 index 000000000000..26faf50c7af1 --- /dev/null +++ b/ext/loslib.c @@ -0,0 +1,424 @@ +/* +** $Id: loslib.c $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + +#define loslib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** {================================================================== +** List of valid conversion specifiers for the 'strftime' function; +** options are grouped by length; group of length 2 start with '||'. +** =================================================================== +*/ +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ + +#if defined(LUA_USE_WINDOWS) +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ +#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" +#else /* C99 specification */ +#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ +#endif + +#endif /* } */ +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for time-related stuff +** =================================================================== +*/ + +/* +** type to represent time_t in Lua +*/ +#if !defined(LUA_NUMTIME) /* { */ + +#define l_timet lua_Integer +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) +#define l_gettime(L,arg) luaL_checkinteger(L, arg) + +#else /* }{ */ + +#define l_timet lua_Number +#define l_pushtime(L,t) lua_pushnumber(L,(lua_Number)(t)) +#define l_gettime(L,arg) luaL_checknumber(L, arg) + +#endif /* } */ + + +#if !defined(l_gmtime) /* { */ +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) +#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for 'tmpnam': +** By default, Lua uses tmpnam except when POSIX is available, where +** it uses mkstemp. +** =================================================================== +*/ +#if !defined(lua_tmpnam) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define LUA_TMPNAMBUFSIZE 32 + +#if !defined(LUA_TMPNAMTEMPLATE) +#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" +#endif + +#define lua_tmpnam(b,e) { \ + strcpy(b, LUA_TMPNAMTEMPLATE); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else /* }{ */ + +/* ISO C definitions */ +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif /* } */ + +#endif /* } */ +/* }================================================================== */ + + +#if !defined(l_system) +#if defined(LUA_USE_IOS) +/* Despite claiming to be ISO C, iOS does not implement 'system'. */ +#define l_system(cmd) ((cmd) == NULL ? 0 : -1) +#else +#define l_system(cmd) system(cmd) /* default definition */ +#endif +#endif + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat; + errno = 0; + stat = l_system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + errno = 0; + return luaL_fileresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + errno = 0; + return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); +} + + +static int os_tmpname (lua_State *L) { + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +/* +** About the overflow check: an overflow cannot occur when time +** is represented by a lua_Integer, because either lua_Integer is +** large enough to represent all int fields or it is not large enough +** to represent a time that cause a field to overflow. However, if +** times are represented as doubles and lua_Integer is int, then the +** time 0x1.e1853b0d184f6p+55 would cause an overflow when adding 1900 +** to compute the year. +*/ +static void setfield (lua_State *L, const char *key, int value, int delta) { + #if (defined(LUA_NUMTIME) && LUA_MAXINTEGER <= INT_MAX) + if (l_unlikely(value > LUA_MAXINTEGER - delta)) + luaL_error(L, "field '%s' is out-of-bound", key); + #endif + lua_pushinteger(L, (lua_Integer)value + delta); + lua_setfield(L, -2, key); +} + + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + + +/* +** Set all fields from structure 'tm' in the table on top of the stack +*/ +static void setallfields (lua_State *L, struct tm *stm) { + setfield(L, "year", stm->tm_year, 1900); + setfield(L, "month", stm->tm_mon, 1); + setfield(L, "day", stm->tm_mday, 0); + setfield(L, "hour", stm->tm_hour, 0); + setfield(L, "min", stm->tm_min, 0); + setfield(L, "sec", stm->tm_sec, 0); + setfield(L, "yday", stm->tm_yday, 1); + setfield(L, "wday", stm->tm_wday, 1); + setboolfield(L, "isdst", stm->tm_isdst); +} + + +static int getboolfield (lua_State *L, const char *key) { + int res; + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); /* get field and its type */ + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not an integer? */ + if (l_unlikely(t != LUA_TNIL)) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (l_unlikely(d < 0)) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); + res = d; + } + else { + if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) + return luaL_error(L, "field '%s' is out-of-bound", key); + res -= delta; + } + lua_pop(L, 1); + return (int)res; +} + + +static const char *checkoption (lua_State *L, const char *conv, + ptrdiff_t convlen, char *buff) { + const char *option = LUA_STRFTIMEOPTIONS; + int oplen = 1; /* length of options being checked */ + for (; *option != '\0' && oplen <= convlen; option += oplen) { + if (*option == '|') /* next block? */ + oplen++; /* will check options with next length (+1) */ + else if (memcmp(conv, option, oplen) == 0) { /* match? */ + memcpy(buff, conv, oplen); /* copy valid option to buffer */ + buff[oplen] = '\0'; + return conv + oplen; /* return next item */ + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +static time_t l_checktime (lua_State *L, int arg) { + l_timet t = l_gettime(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} + + +/* maximum size for an individual 'strftime' item */ +#define SIZETIMEFMT 250 + + +static int os_date (lua_State *L) { + size_t slen; + const char *s = luaL_optlstring(L, 1, "%c", &slen); + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); + const char *se = s + slen; /* 's' end */ + struct tm tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip '!' */ + } + else + stm = l_localtime(&t, &tmr); + if (stm == NULL) /* invalid date? */ + return luaL_error(L, + "date result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setallfields(L, stm); + } + else { + char cc[4]; /* buffer for individual conversion specifiers */ + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (s < se) { + if (*s != '%') /* not a conversion specifier? */ + luaL_addchar(&b, *s++); + else { + size_t reslen; + char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); + s++; /* skip '%' */ + s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_year = getfield(L, "year", -1, 1900); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + setallfields(L, &ts); /* update fields with normalized values */ + } + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + return luaL_error(L, + "time result cannot be represented in this installation"); + l_pushtime(L, t); + return 1; +} + + +static int os_difftime (lua_State *L) { + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; +} + + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); + return 1; +} + From f88e80fbefa6372f12d43be564245253d7f15ff4 Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 19:39:23 +0200 Subject: [PATCH 12/70] Removing camera stuff --- Core/Config.cpp | 1 - Core/HW/Camera.cpp | 251 --------------------------------------------- Core/HW/Camera.h | 2 +- 3 files changed, 1 insertion(+), 253 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 39eb9a3b5a32..62899e092698 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -46,7 +46,6 @@ #include "Common/System/System.h" #include "Common/StringUtils.h" #include "Common/Thread/ThreadUtil.h" -#include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/VR/PPSSPPVR.h" #include "Common/System/OSD.h" #include "Core/Config.h" diff --git a/Core/HW/Camera.cpp b/Core/HW/Camera.cpp index 7c542284c615..d6a76387a0e7 100644 --- a/Core/HW/Camera.cpp +++ b/Core/HW/Camera.cpp @@ -204,269 +204,18 @@ int __qt_stopCapture() { std::vector __v4l_getDeviceList() { std::vector deviceList; -#ifdef USE_FFMPEG - for (int i = 0; i < 64; i++) { - char path[256]; - snprintf(path, sizeof(path), "/dev/video%d", i); - if (access(path, F_OK) < 0) { - break; - } - int fd = -1; - if((fd = open(path, O_RDONLY)) < 0) { - ERROR_LOG(Log::HLE, "Cannot open '%s'; errno=%d(%s)", path, errno, strerror(errno)); - continue; - } - struct v4l2_capability video_cap; - if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) < 0) { - ERROR_LOG(Log::HLE, "VIDIOC_QUERYCAP"); - goto cont; - } else { - char device[256]; - snprintf(device, sizeof(device), "%d:%s", i, video_cap.card); - deviceList.push_back(device); - } -cont: - close(fd); - fd = -1; - } -#endif //USE_FFMPEG return deviceList; } void *v4l_loop(void *data) { -#ifdef USE_FFMPEG - SetCurrentThreadName("v4l_loop"); - while (v4l_fd >= 0) { - struct v4l2_buffer buf; - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - - if (ioctl(v4l_fd, VIDIOC_DQBUF, &buf) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_DQBUF; errno=%d(%s)", errno, strerror(errno)); - switch (errno) { - case EAGAIN: - continue; - default: - return nullptr; - } - } - - unsigned char *jpegData = nullptr; - int jpegLen = 0; - - if (v4l_format == V4L2_PIX_FMT_YUYV) { - convert_frame(v4l_hw_width, v4l_hw_height, (unsigned char*)v4l_buffers[buf.index].start, AV_PIX_FMT_YUYV422, - v4l_ideal_width, v4l_ideal_height, &jpegData, &jpegLen); - } else if (v4l_format == V4L2_PIX_FMT_JPEG - || v4l_format == V4L2_PIX_FMT_MJPEG) { - // decompress jpeg - int width, height, req_comps; - unsigned char *rgbData = jpgd::decompress_jpeg_image_from_memory( - (unsigned char*)v4l_buffers[buf.index].start, buf.bytesused, &width, &height, &req_comps, 3); - - convert_frame(v4l_hw_width, v4l_hw_height, (unsigned char*)rgbData, AV_PIX_FMT_RGB24, - v4l_ideal_width, v4l_ideal_height, &jpegData, &jpegLen); - free(rgbData); - } - - if (jpegData) { - Camera::pushCameraImage(jpegLen, jpegData); - free(jpegData); - jpegData = nullptr; - } - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_QBUF"); - return nullptr; - } - } return nullptr; -#endif //USE_FFMPEG } int __v4l_startCapture(int ideal_width, int ideal_height) { -#ifdef USE_FFMPEG - if (v4l_fd >= 0) { - __v4l_stopCapture(); - } - v4l_ideal_width = ideal_width; - v4l_ideal_height = ideal_height; - - int dev_index = 0; - char dev_name[64]; - sscanf(g_Config.sCameraDevice.c_str(), "%d:", &dev_index); - snprintf(dev_name, sizeof(dev_name), "/dev/video%d", dev_index); - - if ((v4l_fd = open(dev_name, O_RDWR)) == -1) { - ERROR_LOG(Log::HLE, "Cannot open '%s'; errno=%d(%s)", dev_name, errno, strerror(errno)); - return -1; - } - - struct v4l2_capability cap; - memset(&cap, 0, sizeof(cap)); - if (ioctl(v4l_fd, VIDIOC_QUERYCAP, &cap) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_QUERYCAP"); - return -1; - } - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { - ERROR_LOG(Log::HLE, "V4L2_CAP_VIDEO_CAPTURE"); - return -1; - } - if (!(cap.capabilities & V4L2_CAP_STREAMING)) { - ERROR_LOG(Log::HLE, "V4L2_CAP_STREAMING"); - return -1; - } - - struct v4l2_format fmt; - memset(&fmt, 0, sizeof(fmt)); - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmt.fmt.pix.pixelformat = 0; - - // select a pixel format - struct v4l2_fmtdesc desc; - memset(&desc, 0, sizeof(desc)); - desc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - while (ioctl(v4l_fd, VIDIOC_ENUM_FMT, &desc) == 0) { - desc.index++; - INFO_LOG(Log::HLE, "V4L2: pixel format supported: %s", desc.description); - if (fmt.fmt.pix.pixelformat != 0) { - continue; - } else if (desc.pixelformat == V4L2_PIX_FMT_YUYV - || desc.pixelformat == V4L2_PIX_FMT_JPEG - || desc.pixelformat == V4L2_PIX_FMT_MJPEG) { - INFO_LOG(Log::HLE, "V4L2: %s selected", desc.description); - fmt.fmt.pix.pixelformat = desc.pixelformat; - v4l_format = desc.pixelformat; - } - } - if (fmt.fmt.pix.pixelformat == 0) { - ERROR_LOG(Log::HLE, "V4L2: No supported format found"); - return -1; - } - - // select a frame size - fmt.fmt.pix.width = 0; - fmt.fmt.pix.height = 0; - struct v4l2_frmsizeenum frmsize; - memset(&frmsize, 0, sizeof(frmsize)); - frmsize.pixel_format = fmt.fmt.pix.pixelformat; - while (ioctl(v4l_fd, VIDIOC_ENUM_FRAMESIZES, &frmsize) == 0) { - frmsize.index++; - if (frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - INFO_LOG(Log::HLE, "V4L2: frame size supported: %dx%d", frmsize.discrete.width, frmsize.discrete.height); - bool matchesIdeal = frmsize.discrete.width >= ideal_width && frmsize.discrete.height >= ideal_height; - bool zeroPix = fmt.fmt.pix.width == 0 && fmt.fmt.pix.height == 0; - bool pixLarger = frmsize.discrete.width < fmt.fmt.pix.width && frmsize.discrete.height < fmt.fmt.pix.height; - if (matchesIdeal && (zeroPix || pixLarger)) { - fmt.fmt.pix.width = frmsize.discrete.width; - fmt.fmt.pix.height = frmsize.discrete.height; - } - } - } - - if (fmt.fmt.pix.width == 0 && fmt.fmt.pix.height == 0) { - fmt.fmt.pix.width = ideal_width; - fmt.fmt.pix.height = ideal_height; - } - INFO_LOG(Log::HLE, "V4L2: asking for %dx%d", fmt.fmt.pix.width, fmt.fmt.pix.height); - if (ioctl(v4l_fd, VIDIOC_S_FMT, &fmt) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_S_FMT"); - return -1; - } - v4l_hw_width = fmt.fmt.pix.width; - v4l_hw_height = fmt.fmt.pix.height; - INFO_LOG(Log::HLE, "V4L2: will receive %dx%d", v4l_hw_width, v4l_hw_height); - v4l_height_fixed_aspect = v4l_hw_width * ideal_height / ideal_width; - INFO_LOG(Log::HLE, "V4L2: will use %dx%d", v4l_hw_width, v4l_height_fixed_aspect); - - struct v4l2_requestbuffers req; - memset(&req, 0, sizeof(req)); - req.count = 1; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if (ioctl(v4l_fd, VIDIOC_REQBUFS, &req) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_REQBUFS"); - return -1; - } - v4l_buffer_count = req.count; - INFO_LOG(Log::HLE, "V4L2: buffer count: %d", v4l_buffer_count); - v4l_buffers = (v4l_buf_t*) calloc(v4l_buffer_count, sizeof(v4l_buf_t)); - - for (int buf_id = 0; buf_id < v4l_buffer_count; buf_id++) { - struct v4l2_buffer buf; - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = buf_id; - if (ioctl(v4l_fd, VIDIOC_QUERYBUF, &buf) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_QUERYBUF"); - return -1; - } - - v4l_buffers[buf_id].length = buf.length; - v4l_buffers[buf_id].start = mmap(NULL, - buf.length, - PROT_READ | PROT_WRITE, - MAP_SHARED, - v4l_fd, buf.m.offset); - if (v4l_buffers[buf_id].start == MAP_FAILED) { - ERROR_LOG(Log::HLE, "MAP_FAILED"); - return -1; - } - - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = buf_id; - if (ioctl(v4l_fd, VIDIOC_QBUF, &buf) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_QBUF"); - return -1; - } - } - - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(v4l_fd, VIDIOC_STREAMON, &type) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_STREAMON"); - return -1; - } - - pthread_create(&v4l_thread, NULL, v4l_loop, NULL); -#endif //USE_FFMPEG return 0; } int __v4l_stopCapture() { - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (v4l_fd < 0) { - goto exit; - } - - if (ioctl(v4l_fd, VIDIOC_STREAMOFF, &type) == -1) { - ERROR_LOG(Log::HLE, "VIDIOC_STREAMOFF"); - goto exit; - } - - for (int buf_id = 0; buf_id < v4l_buffer_count; buf_id++) { - if (munmap(v4l_buffers[buf_id].start, v4l_buffers[buf_id].length) == -1) { - ERROR_LOG(Log::HLE, "munmap"); - goto exit; - } - } - - if (close(v4l_fd) == -1) { - ERROR_LOG(Log::HLE, "close"); - goto exit; - } - - v4l_fd = -1; - //pthread_join(v4l_thread, NULL); - -exit: - v4l_fd = -1; return 0; } diff --git a/Core/HW/Camera.h b/Core/HW/Camera.h index 24f294b5ca68..453f3436b7b5 100644 --- a/Core/HW/Camera.h +++ b/Core/HW/Camera.h @@ -53,7 +53,7 @@ void __cameraDummyImage(int width, int height, unsigned char** outData, int* out #elif PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID) #include -#include +// #include #include #include From d427de8cdf3552c68573c82c93ebcdc7358c1dad Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 20:05:45 +0200 Subject: [PATCH 13/70] Waterbox compatible --- Common/File/FileUtil.cpp | 63 ------------------------------------ Common/Thread/ThreadUtil.cpp | 52 ----------------------------- libretro/libretro.cpp | 40 +++++++++++------------ 3 files changed, 20 insertions(+), 135 deletions(-) diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 28cbf5c64f94..72a72fe9979e 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -562,70 +562,7 @@ bool Delete(const Path &filename) { // Returns true if successful, or path already exists. bool CreateDir(const Path &path) { - if (SIMULATE_SLOW_IO) { - sleep_ms(100, "slow-io-sim"); - INFO_LOG(Log::System, "CreateDir %s", path.c_str()); - } - switch (path.Type()) { - case PathType::NATIVE: - break; // OK - case PathType::CONTENT_URI: - { - // NOTE: The Android storage API will simply create a renamed directory (append a number) if it already exists. - // We want to avoid that, so let's just return true if the directory already is there. - if (File::Exists(path)) { - return true; - } - - // Convert it to a "CreateDirIn" call, if possible, since that's - // what we can do with the storage API. - AndroidContentURI uri(path.ToString()); - std::string newDirName = uri.GetLastPart(); - if (uri.NavigateUp()) { - INFO_LOG(Log::Common, "Calling Android_CreateDirectory(%s, %s)", uri.ToString().c_str(), newDirName.c_str()); - return Android_CreateDirectory(uri.ToString(), newDirName) == StorageError::SUCCESS; - } else { - // Bad path - can't create this directory. - WARN_LOG(Log::Common, "CreateDir failed: '%s'", path.c_str()); - return false; - } - break; - } - default: - return false; - } - - DEBUG_LOG(Log::Common, "CreateDir('%s')", path.c_str()); -#ifdef _WIN32 -#if PPSSPP_PLATFORM(UWP) - if (CreateDirectoryFromAppW(path.ToWString().c_str(), NULL)) - return true; -#else - if (::CreateDirectory(path.ToWString().c_str(), NULL)) - return true; -#endif - - DWORD error = GetLastError(); - if (error == ERROR_ALREADY_EXISTS) { - DEBUG_LOG(Log::Common, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); - return true; - } - ERROR_LOG(Log::Common, "CreateDir: CreateDirectory failed on %s: %08x %s", path.c_str(), (uint32_t)error, GetStringErrorMsg(error).c_str()); return false; -#else - if (mkdir(path.ToString().c_str(), 0755) == 0) { - return true; - } - - int err = errno; - if (err == EEXIST) { - DEBUG_LOG(Log::Common, "CreateDir: mkdir failed on %s: already exists", path.c_str()); - return true; - } - - ERROR_LOG(Log::Common, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); - return false; -#endif } // Creates the full path of fullPath returns true on success diff --git a/Common/Thread/ThreadUtil.cpp b/Common/Thread/ThreadUtil.cpp index 3e7a809e8b49..bfa7e07ac44d 100644 --- a/Common/Thread/ThreadUtil.cpp +++ b/Common/Thread/ThreadUtil.cpp @@ -124,35 +124,6 @@ const char *GetCurrentThreadName() { } void SetCurrentThreadName(const char *threadName) { -#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) - InitializeSetThreadDescription(); - if (g_pSetThreadDescription) { - // Use the modern API - wchar_t buffer[256]; - ConvertUTF8ToWString(buffer, ARRAY_SIZE(buffer), threadName); - g_pSetThreadDescription(GetCurrentThread(), buffer); - } else { - // Use the old exception hack. - SetCurrentThreadNameThroughException(threadName); - } -#elif PPSSPP_PLATFORM(WINDOWS) - wchar_t buffer[256]; - ConvertUTF8ToWString(buffer, ARRAY_SIZE(buffer), threadName); - SetThreadDescription(GetCurrentThread(), buffer); -#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) - pthread_setname_np(pthread_self(), threadName); -#elif defined(__APPLE__) - pthread_setname_np(threadName); -#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) - pthread_set_name_np(pthread_self(), threadName); -#elif defined(__NetBSD__) - pthread_setname_np(pthread_self(), "%s", (void*)threadName); -#endif - - // Set the locally known threadname using a thread local variable. -#ifdef TLS_SUPPORTED - curThreadName = threadName; -#endif } #if PPSSPP_PLATFORM(WINDOWS) @@ -216,27 +187,4 @@ void AssertCurrentThreadName(const char *threadName) { } int GetCurrentThreadIdForDebug() { -#if __LIBRETRO__ - // Not sure why gettid() would not be available, but it isn't. - // The return value of this function is only used in unit tests anyway... - return 1; -#elif PPSSPP_PLATFORM(WINDOWS) - return (int)GetCurrentThreadId(); -#elif PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - uint64_t tid = 0; - pthread_threadid_np(NULL, &tid); - return (int)tid; -#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) - // See issue 14545 - return (int)syscall(__NR_gettid); - // return (int)gettid(); -#elif defined(__DragonFly__) || defined(__FreeBSD__) - return pthread_getthreadid_np(); -#elif defined(__NetBSD__) - return _lwp_self(); -#elif defined(__OpenBSD__) - return getthrid(); -#else - return 1; -#endif } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 2605354c5abf..89efb1472740 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -526,27 +526,27 @@ static void check_variables(CoreParameter &coreParam) g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED; } -#ifndef __EMSCRIPTEN__ - var.key = "ppsspp_cpu_core"; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) - { - if (!strcmp(var.value, "JIT")) - g_Config.iCpuCore = (int)CPUCore::JIT; - else if (!strcmp(var.value, "IR JIT")) - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; - else if (!strcmp(var.value, "Interpreter")) - g_Config.iCpuCore = (int)CPUCore::INTERPRETER; - } - - if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { - // Just gonna force it to the IR interpreter on startup. - // We don't hide the option, but we make sure it's off on bootup. In case someone wants - // to experiment in future iOS versions or something... - g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; - } -#else +// #ifndef __EMSCRIPTEN__ +// var.key = "ppsspp_cpu_core"; +// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) +// { +// if (!strcmp(var.value, "JIT")) +// g_Config.iCpuCore = (int)CPUCore::JIT; +// else if (!strcmp(var.value, "IR JIT")) +// g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; +// else if (!strcmp(var.value, "Interpreter")) +// g_Config.iCpuCore = (int)CPUCore::INTERPRETER; +// } + +// if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { +// // Just gonna force it to the IR interpreter on startup. +// // We don't hide the option, but we make sure it's off on bootup. In case someone wants +// // to experiment in future iOS versions or something... +// g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; +// } +// #else g_Config.iCpuCore = (int)CPUCore::INTERPRETER; -#endif +// #endif var.key = "ppsspp_fast_memory"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) From 2dbe99688abcbb1471d69f5d45ed87af4ca68d3e Mon Sep 17 00:00:00 2001 From: SergioMartin86 Date: Mon, 7 Apr 2025 20:07:21 +0200 Subject: [PATCH 14/70] Waterbox compatible --- libretro/libretro.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 89efb1472740..2605354c5abf 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -526,27 +526,27 @@ static void check_variables(CoreParameter &coreParam) g_Config.iLanguage = PSP_SYSTEMPARAM_LANGUAGE_CHINESE_SIMPLIFIED; } -// #ifndef __EMSCRIPTEN__ -// var.key = "ppsspp_cpu_core"; -// if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) -// { -// if (!strcmp(var.value, "JIT")) -// g_Config.iCpuCore = (int)CPUCore::JIT; -// else if (!strcmp(var.value, "IR JIT")) -// g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; -// else if (!strcmp(var.value, "Interpreter")) -// g_Config.iCpuCore = (int)CPUCore::INTERPRETER; -// } - -// if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { -// // Just gonna force it to the IR interpreter on startup. -// // We don't hide the option, but we make sure it's off on bootup. In case someone wants -// // to experiment in future iOS versions or something... -// g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; -// } -// #else +#ifndef __EMSCRIPTEN__ + var.key = "ppsspp_cpu_core"; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "JIT")) + g_Config.iCpuCore = (int)CPUCore::JIT; + else if (!strcmp(var.value, "IR JIT")) + g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + else if (!strcmp(var.value, "Interpreter")) + g_Config.iCpuCore = (int)CPUCore::INTERPRETER; + } + + if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { + // Just gonna force it to the IR interpreter on startup. + // We don't hide the option, but we make sure it's off on bootup. In case someone wants + // to experiment in future iOS versions or something... + g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; + } +#else g_Config.iCpuCore = (int)CPUCore::INTERPRETER; -// #endif +#endif var.key = "ppsspp_fast_memory"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) From 9f48dd984aed2e583488610e2753d168247411d2 Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Mon, 7 Apr 2025 21:23:48 +0200 Subject: [PATCH 15/70] Progress --- Common/Crypto/{md5.cpp => _md5.cpp} | 0 Common/Crypto/{sha1.cpp => _sha1.cpp} | 0 Common/Data/Collections/CyclicBuffer.h | 2 +- Common/System/{Display.cpp => _Display.cpp} | 0 Common/Thread/ThreadUtil.cpp | 1 + Common/VR/VRFramebuffer.cpp | 2 + Core/FileLoaders/LocalFileLoader.cpp | 6 +- .../{FileSystem.cpp => _FileSystem.cpp} | 0 Core/MIPS/{MIPS.cpp => _MIPS.cpp} | 0 .../{Breakpoints.cpp => _Breakpoints.cpp} | 0 GPU/GPU.cpp | 14 +- ext/_SymbolTable.cpp | 225 ++++++++++++ ext/_alloc.c | 319 ++++++++++++++++++ ext/{xxhash.c => _xxhash.c} | 0 ext/rcheevos | 2 +- pspautotests | 2 +- 16 files changed, 554 insertions(+), 19 deletions(-) rename Common/Crypto/{md5.cpp => _md5.cpp} (100%) rename Common/Crypto/{sha1.cpp => _sha1.cpp} (100%) rename Common/System/{Display.cpp => _Display.cpp} (100%) rename Core/FileSystems/{FileSystem.cpp => _FileSystem.cpp} (100%) rename Core/MIPS/{MIPS.cpp => _MIPS.cpp} (100%) rename GPU/Debugger/{Breakpoints.cpp => _Breakpoints.cpp} (100%) create mode 100644 ext/_SymbolTable.cpp create mode 100644 ext/_alloc.c rename ext/{xxhash.c => _xxhash.c} (100%) diff --git a/Common/Crypto/md5.cpp b/Common/Crypto/_md5.cpp similarity index 100% rename from Common/Crypto/md5.cpp rename to Common/Crypto/_md5.cpp diff --git a/Common/Crypto/sha1.cpp b/Common/Crypto/_sha1.cpp similarity index 100% rename from Common/Crypto/sha1.cpp rename to Common/Crypto/_sha1.cpp diff --git a/Common/Data/Collections/CyclicBuffer.h b/Common/Data/Collections/CyclicBuffer.h index 7eaa042198ee..a02ee2ebb394 100644 --- a/Common/Data/Collections/CyclicBuffer.h +++ b/Common/Data/Collections/CyclicBuffer.h @@ -18,7 +18,7 @@ #pragma once #include - +#include #include "Common/CommonTypes.h" diff --git a/Common/System/Display.cpp b/Common/System/_Display.cpp similarity index 100% rename from Common/System/Display.cpp rename to Common/System/_Display.cpp diff --git a/Common/Thread/ThreadUtil.cpp b/Common/Thread/ThreadUtil.cpp index bfa7e07ac44d..1b853a6cb23c 100644 --- a/Common/Thread/ThreadUtil.cpp +++ b/Common/Thread/ThreadUtil.cpp @@ -187,4 +187,5 @@ void AssertCurrentThreadName(const char *threadName) { } int GetCurrentThreadIdForDebug() { + return 0; } diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 21e5d3ed0ed4..4990fa501d92 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -1,5 +1,7 @@ #include "VRFramebuffer.h" +#undef XR_USE_GRAPHICS_API_OPENGL +#undef XR_USE_GRAPHICS_API_OPENGL_ES #if XR_USE_GRAPHICS_API_OPENGL || XR_USE_GRAPHICS_API_OPENGL_ES #include "Common/GPU/OpenGL/GLCommon.h" diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 70f250341a0a..6d47bd43fd90 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -40,11 +40,11 @@ #include #endif -#if !defined(_WIN32) && !defined(HAVE_LIBRETRO_VFS) - extern std::string _cdImageFilePath; extern uint32_t cd_get_size(void); -extern size_t readSegmentFromCD(void *buf_, const uint64_t address, const size_t size); +extern size_t readSegmentFromCD(void* buf_, const uint64_t address, const size_t size); + +#if !defined(_WIN32) && !defined(HAVE_LIBRETRO_VFS) void LocalFileLoader::DetectSizeFd() { diff --git a/Core/FileSystems/FileSystem.cpp b/Core/FileSystems/_FileSystem.cpp similarity index 100% rename from Core/FileSystems/FileSystem.cpp rename to Core/FileSystems/_FileSystem.cpp diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/_MIPS.cpp similarity index 100% rename from Core/MIPS/MIPS.cpp rename to Core/MIPS/_MIPS.cpp diff --git a/GPU/Debugger/Breakpoints.cpp b/GPU/Debugger/_Breakpoints.cpp similarity index 100% rename from GPU/Debugger/Breakpoints.cpp rename to GPU/Debugger/_Breakpoints.cpp diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index bbf4795b4000..6d19f7620faf 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -48,7 +48,7 @@ bool GPU_IsStarted() { } bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { - const auto &gpuCore = PSP_CoreParameter().gpuCore; + const auto& gpuCore = GPUCore::GPUCORE_SOFTWARE; _assert_(draw || gpuCore == GPUCORE_SOFTWARE); #if PPSSPP_PLATFORM(UWP) if (gpuCore == GPUCORE_SOFTWARE) { @@ -70,17 +70,6 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { SetGPU(new SoftGPU(ctx, draw)); break; case GPUCORE_DIRECTX9: -#if PPSSPP_API(D3D9) - SetGPU(new GPU_DX9(ctx, draw)); - break; -#else - return false; -#endif - case GPUCORE_DIRECTX11: -#if PPSSPP_API(D3D11) - SetGPU(new GPU_D3D11(ctx, draw)); - break; -#else return false; #endif #if !PPSSPP_PLATFORM(SWITCH) @@ -99,7 +88,6 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw) { SetGPU(nullptr); return gpu != nullptr; -#endif } #ifdef USE_CRT_DBG #define new DBG_NEW diff --git a/ext/_SymbolTable.cpp b/ext/_SymbolTable.cpp new file mode 100644 index 000000000000..b7f682f709c8 --- /dev/null +++ b/ext/_SymbolTable.cpp @@ -0,0 +1,225 @@ +#include "Core/SymbolTable.h" + +#include "Core/Assembler.h" +#include "Core/Common.h" +#include "Util/FileClasses.h" +#include "Util/Util.h" + +#include + +const char validSymbolCharacters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; + +bool operator<(SymbolKey const& lhs, SymbolKey const& rhs) +{ + if (lhs.file != rhs.file) + return lhs.file < rhs.file; + if (lhs.section != rhs.section) + return lhs.section < rhs.section; + return lhs.name.compare(rhs.name) < 0; +} + + +Label::Label(const Identifier &name) : + name(name), + originalName(name) +{ +} + + +SymbolTable::SymbolTable() +{ + uniqueCount = 0; +} + +SymbolTable::~SymbolTable() +{ + clear(); +} + +void SymbolTable::clear() +{ + symbols.clear(); + labels.clear(); + equationsCount = 0; + uniqueCount = 0; +} + +void SymbolTable::setFileSectionValues(const Identifier& symbol, int& file, int& section) +{ + if (symbol.string()[0] == '@') + { + if (symbol.string()[1] != '@') + { + // static label, @. the section doesn't matter + section = -1; + } else { + // local label, @@. the file doesn't matter + file = -1; + } + } else { + // global label. neither file nor section matters + file = section = -1; + } +} + +std::shared_ptr