From f81250660a9a1ccf51f75318d4aad8fd56821cc2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Jan 2021 11:49:25 -0800 Subject: [PATCH 001/261] Umd: Delay common wait drive stat funcs. These are sometimes used in loading or loops, and take time. This should reduce spin looping. --- Core/HLE/sceUmd.cpp | 53 ++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 51c44b72ae..4d4aba33ce 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -378,22 +378,18 @@ static void __UmdWaitStat(u32 timeout) * @return < 0 on error * */ -static int sceUmdWaitDriveStat(u32 stat) -{ +static int sceUmdWaitDriveStat(u32 stat) { if (stat == 0) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStat(stat = %08x): bad status", stat); - return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } - if (!__KernelIsDispatchEnabled()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStat(stat = %08x): dispatch disabled", stat); - return SCE_KERNEL_ERROR_CAN_NOT_WAIT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_CAN_NOT_WAIT, "dispatch disabled"); } if (__IsInInterrupt()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStat(stat = %08x): inside interrupt", stat); - return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ILLEGAL_CONTEXT, "inside interrupt"); } + hleEatCycles(520); if ((stat & __KernelUmdGetState()) == 0) { DEBUG_LOG(SCEIO, "sceUmdWaitDriveStat(stat = %08x): waiting", stat); umdWaitingThreads.push_back(__KernelGetCurThread()); @@ -401,26 +397,21 @@ static int sceUmdWaitDriveStat(u32 stat) return 0; } - DEBUG_LOG(SCEIO, "0=sceUmdWaitDriveStat(stat = %08x)", stat); - return 0; + return hleLogSuccessI(SCEIO, 0); } -static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) -{ +static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { if (stat == 0) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): bad status", stat, timeout); - return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } - if (!__KernelIsDispatchEnabled()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): dispatch disabled", stat, timeout); - return SCE_KERNEL_ERROR_CAN_NOT_WAIT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_CAN_NOT_WAIT, "dispatch disabled"); } if (__IsInInterrupt()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): inside interrupt", stat, timeout); - return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ILLEGAL_CONTEXT, "inside interrupt"); } + hleEatCycles(520); if ((stat & __KernelUmdGetState()) == 0) { DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d): waiting", stat, timeout); __UmdWaitStat(timeout); @@ -431,34 +422,29 @@ static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) hleReSchedule("umd stat checked"); } - DEBUG_LOG(SCEIO, "0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout); - return 0; + return hleLogSuccessI(SCEIO, 0); } -static int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) -{ +static int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { if (!UMDInserted) { WARN_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): UMD is taking out for switch UMD", stat, timeout); return PSP_UMD_NOT_PRESENT; } if (stat == 0) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): bad status", stat, timeout); - return SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } - if (!__KernelIsDispatchEnabled()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): dispatch disabled", stat, timeout); - return SCE_KERNEL_ERROR_CAN_NOT_WAIT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_CAN_NOT_WAIT, "dispatch disabled"); } if (__IsInInterrupt()) { - DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): inside interrupt", stat, timeout); - return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT; + return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ILLEGAL_CONTEXT, "inside interrupt"); } + hleEatCycles(520); hleCheckCurrentCallbacks(); if ((stat & __KernelUmdGetState()) == 0) { - DEBUG_LOG(SCEIO, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): waiting", stat, timeout); + DEBUG_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): waiting", stat, timeout); if (timeout == 0) { timeout = 8000; } @@ -470,8 +456,7 @@ static int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) hleReSchedule("umd stat waited"); } - DEBUG_LOG(SCEIO, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); - return 0; + return hleLogSuccessI(SCEIO, 0); } static u32 sceUmdCancelWaitDriveStat() From 871a0f94922cb35aea62e85bb13ba37fa339a6cd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Jan 2021 12:11:42 -0800 Subject: [PATCH 002/261] Umd: Wake waiting threads on eject/insert. --- Core/HLE/sceUmd.cpp | 71 +++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 4d4aba33ce..3b9d743e42 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -42,7 +42,7 @@ const u64 MICRO_DELAY_ACTIVATE = 4000; -static u8 umdActivated = 1; +static bool umdActivated = true; static u32 umdStatus = 0; static u32 umdErrorStat = 0; static int driveCBId = 0; @@ -71,7 +71,7 @@ void __UmdInit() umdStatTimeoutEvent = CoreTiming::RegisterEvent("UmdTimeout", __UmdStatTimeout); umdStatChangeEvent = CoreTiming::RegisterEvent("UmdChange", __UmdStatChange); umdInsertChangeEvent = CoreTiming::RegisterEvent("UmdInsertChange", __UmdInsertChange); - umdActivated = 1; + umdActivated = true; umdStatus = 0; umdErrorStat = 0; driveCBId = 0; @@ -87,7 +87,9 @@ void __UmdDoState(PointerWrap &p) if (!s) return; + u8 activatedByte = umdActivated ? 1 : 0; Do(p, umdActivated); + umdActivated = activatedByte != 0; Do(p, umdStatus); Do(p, umdErrorStat); Do(p, driveCBId); @@ -112,8 +114,11 @@ void __UmdDoState(PointerWrap &p) UMDInserted = true; } -static u8 __KernelUmdGetState() -{ +static u8 __KernelUmdGetState() { + if (!UMDInserted) { + return PSP_UMD_NOT_PRESENT; + } + // Most games seem to expect the disc to be ready early on, active or not. // It seems like the PSP sets this state when the disc is "ready". u8 state = PSP_UMD_PRESENT | PSP_UMD_READY; @@ -123,16 +128,7 @@ static u8 __KernelUmdGetState() return state; } -void __UmdInsertChange(u64 userdata, int cyclesLate) -{ - UMDInserted = true; -} - -void __UmdStatChange(u64 userdata, int cyclesLate) -{ - // TODO: Why not a bool anyway? - umdActivated = userdata & 0xFF; - +static void UmdWakeThreads() { // Wake anyone waiting on this. for (size_t i = 0; i < umdWaitingThreads.size(); ++i) { const SceUID threadID = umdWaitingThreads[i]; @@ -140,19 +136,32 @@ void __UmdStatChange(u64 userdata, int cyclesLate) u32 error; u32 stat = __KernelGetWaitValue(threadID, error); bool keep = false; - if (HLEKernel::VerifyWait(threadID, WAITTYPE_UMD, 1)) { - if ((stat & __KernelUmdGetState()) != 0) - __KernelResumeThreadFromWait(threadID, 0); + if (!HLEKernel::VerifyWait(threadID, WAITTYPE_UMD, 1)) { // Only if they are still waiting do we keep them in the list. - else - keep = true; + keep = (stat & __KernelUmdGetState()) == 0; + if (!keep) { + __KernelResumeThreadFromWait(threadID, 0); + } } - if (!keep) + if (!keep) { umdWaitingThreads.erase(umdWaitingThreads.begin() + i--); + } } } +static void __UmdStatChange(u64 userdata, int cyclesLate) { + umdActivated = userdata != 0; + + UmdWakeThreads(); +} + +static void __UmdInsertChange(u64 userdata, int cyclesLate) { + UMDInserted = true; + + UmdWakeThreads(); +} + static void __KernelUmdActivate() { u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE; @@ -268,20 +277,16 @@ static u32 sceUmdGetDiscInfo(u32 infoAddr) return PSP_ERROR_UMD_INVALID_PARAM; } -static int sceUmdActivate(u32 mode, const char *name) -{ +static int sceUmdActivate(u32 mode, const char *name) { if (mode < 1 || mode > 2) - return PSP_ERROR_UMD_INVALID_PARAM; + return hleLogWarning(SCEIO, PSP_ERROR_UMD_INVALID_PARAM); __KernelUmdActivate(); - if (mode == 1) { - DEBUG_LOG(SCEIO, "0=sceUmdActivate(%d, %s)", mode, name); - } else { - ERROR_LOG(SCEIO, "UNTESTED 0=sceUmdActivate(%d, %s)", mode, name); + if (mode != 1) { + return hleLogError(SCEIO, 0, "UNTESTED"); } - - return 0; + return hleLogSuccessI(SCEIO, 0); } static int sceUmdDeactivate(u32 mode, const char *name) @@ -426,11 +431,6 @@ static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { } static int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - if (!UMDInserted) { - WARN_LOG(SCEIO, "sceUmdWaitDriveStatCB(stat = %08x, timeout = %d): UMD is taking out for switch UMD", stat, timeout); - return PSP_UMD_NOT_PRESENT; - } - if (stat == 0) { return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } @@ -487,6 +487,9 @@ void __UmdReplace(std::string filepath) { } UMDInserted = false; + // Wake any threads waiting for the disc to be removed. + UmdWakeThreads(); + CoreTiming::ScheduleEvent(usToCycles(200*1000), umdInsertChangeEvent, 0); // Wait sceUmdCheckMedium call // TODO Is this always correct if UMD was not activated? u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED; From cfb52bf69edabe3e0624a62f2dbe4d9715bc9969 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Jan 2021 12:20:52 -0800 Subject: [PATCH 003/261] Umd: Disallow waiting on status that can't occur. Per tests, CHANGED is not waitable. --- Core/HLE/sceUmd.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 3b9d743e42..1b666ddb21 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -40,7 +40,9 @@ #include "Core/FileSystems/ISOFileSystem.h" #include "Core/FileSystems/VirtualDiscFileSystem.h" -const u64 MICRO_DELAY_ACTIVATE = 4000; +static constexpr u64 MICRO_DELAY_ACTIVATE = 4000; +// Does not include PSP_UMD_CHANGED. +static constexpr uint32_t UMD_STAT_ALLOW_WAIT = PSP_UMD_NOT_PRESENT | PSP_UMD_PRESENT | PSP_UMD_NOT_READY | PSP_UMD_READY | PSP_UMD_READABLE; static bool umdActivated = true; static u32 umdStatus = 0; @@ -60,11 +62,11 @@ struct PspUmdInfo { u32_le type; }; -void __UmdStatTimeout(u64 userdata, int cyclesLate); -void __UmdStatChange(u64 userdata, int cyclesLate); -void __UmdInsertChange(u64 userdata, int cyclesLate); -void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId); -void __UmdEndCallback(SceUID threadID, SceUID prevCallbackId); +static void __UmdStatTimeout(u64 userdata, int cyclesLate); +static void __UmdStatChange(u64 userdata, int cyclesLate); +static void __UmdInsertChange(u64 userdata, int cyclesLate); +static void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId); +static void __UmdEndCallback(SceUID threadID, SceUID prevCallbackId); void __UmdInit() { @@ -187,7 +189,7 @@ static void __KernelUmdDeactivate() __UmdStatChange(0, 0); } -void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId) +static void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId) { SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; @@ -213,7 +215,7 @@ void __UmdBeginCallback(SceUID threadID, SceUID prevCallbackId) WARN_LOG_REPORT(SCEIO, "sceUmdWaitDriveStatCB: beginning callback with bad wait id?"); } -void __UmdEndCallback(SceUID threadID, SceUID prevCallbackId) +static void __UmdEndCallback(SceUID threadID, SceUID prevCallbackId) { SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; @@ -352,7 +354,7 @@ static u32 sceUmdGetDriveStat() return retVal; } -void __UmdStatTimeout(u64 userdata, int cyclesLate) +static void __UmdStatTimeout(u64 userdata, int cyclesLate) { SceUID threadID = (SceUID)userdata; @@ -384,7 +386,7 @@ static void __UmdWaitStat(u32 timeout) * */ static int sceUmdWaitDriveStat(u32 stat) { - if (stat == 0) { + if ((stat & UMD_STAT_ALLOW_WAIT) == 0) { return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } if (!__KernelIsDispatchEnabled()) { @@ -406,7 +408,7 @@ static int sceUmdWaitDriveStat(u32 stat) { } static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { - if (stat == 0) { + if ((stat & UMD_STAT_ALLOW_WAIT) == 0) { return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } if (!__KernelIsDispatchEnabled()) { @@ -431,7 +433,7 @@ static int sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { } static int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - if (stat == 0) { + if ((stat & UMD_STAT_ALLOW_WAIT) == 0) { return hleLogDebug(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad status"); } if (!__KernelIsDispatchEnabled()) { From 55caac3e0901426053b32b2b506149c9b171a5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 19 Feb 2021 09:52:14 +0100 Subject: [PATCH 004/261] Only consider the actual PPGe texture in kernel ram reliable. It seems some Chinese patches like to allocate kernel space for textures. (On that note, we should probably allocate our texture elsewhere... in case it takes up too much space). --- Core/Util/PPGeDraw.cpp | 4 ++++ Core/Util/PPGeDraw.h | 3 +++ GPU/Common/TextureCacheCommon.cpp | 3 ++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 1beff411b8..e85590fa3d 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -197,6 +197,10 @@ static void EndVertexDataAndDraw(int prim) { WriteCmd(GE_CMD_PRIM, (prim << 16) | vertexCount); } +bool PPGeIsFontTextureAddress(u32 addr) { + return addr == atlasPtr; +} + static u32 __PPGeDoAlloc(u32 &size, bool fromTop, const char *name) { u32 ptr = kernelMemory.Alloc(size, fromTop, name); // Didn't get it. diff --git a/Core/Util/PPGeDraw.h b/Core/Util/PPGeDraw.h index 564f1e27ec..6e5fca6080 100644 --- a/Core/Util/PPGeDraw.h +++ b/Core/Util/PPGeDraw.h @@ -108,6 +108,9 @@ void PPGeScissorReset(); void PPGeNotifyFrame(); +// Could have returned the address directly I guess, but nothing out side of PPGe should actually use it so.. +bool PPGeIsFontTextureAddress(u32 addr); + class PPGeImage { public: PPGeImage(const std::string &pspFilename); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 91f54c06ff..2327f6dcab 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -33,6 +33,7 @@ #include "GPU/GPUCommon.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" +#include "Core/Util/PPGeDraw.h" #if defined(_M_SSE) #include @@ -505,7 +506,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { WARN_LOG_REPORT_ONCE(clutUseRender, G3D, "Using texture with rendered CLUT: texfmt=%d, clutfmt=%d", gstate.getTextureFormat(), gstate.getClutPaletteFormat()); } - if (Memory::IsKernelAndNotVolatileAddress(texaddr)) { + if (PPGeIsFontTextureAddress(texaddr)) { // It's the builtin font texture. entry->status = TexCacheEntry::STATUS_RELIABLE; } else if (g_Config.bTextureBackoffCache) { From d8b1271f29d36c367b196a235a9a5e65bd092f61 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Feb 2021 08:19:06 -0800 Subject: [PATCH 005/261] GPU: Dirty texparams when cropping a self-copy. If we used UV to limit the blit, we may need to do the blit again next time, so re-examine texture params. --- GPU/Common/FramebufferManagerCommon.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index f30a05bee5..12248f91ef 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -914,6 +914,9 @@ void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer x += gstate_c.curTextureXOffset; y += gstate_c.curTextureYOffset; } + + // We'll have to reapply these next time since we cropped to UV. + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } if (x < src->drawnWidth && y < src->drawnHeight && w > 0 && h > 0) { From f7ace3b8ee33e97e156f3b07f416301e885472c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 2 Mar 2021 21:50:51 +0100 Subject: [PATCH 006/261] Update version to 1.11.3 --- README.md | 3 +++ android/AndroidManifest.xml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5fcd0b4935..0a43ff4ffd 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ If you want to download regularly updated builds for Android, Windows x86 and x6 For game compatibility, see [community compatibility feedback](https://report.ppsspp.org/games). +What's new in 1.11.3 +==================== +* Fix for graphics glitches in the on-screen keyboard What's new in 1.11.2 ==================== diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index cc8739cf29..ab50419b96 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="111030000" + android:versionName="1.11.3.0"> From 5802529daa3779c38f0b5315290911ed93fc8c6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 20 Mar 2021 11:18:54 +0100 Subject: [PATCH 007/261] UTF-8 PPGe: Remove overlong encodings. Work around a weird issue in Ratchet & Clank. See issue #14297 --- Common/Data/Encoding/Utf8.cpp | 15 +++++++++++++++ Common/Data/Encoding/Utf8.h | 7 ++++++- Core/Util/PPGeDraw.cpp | 16 ++++++++++++++-- unittest/UnitTest.cpp | 1 + 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Common/Data/Encoding/Utf8.cpp b/Common/Data/Encoding/Utf8.cpp index f3c2b1e223..0a2a7355cc 100644 --- a/Common/Data/Encoding/Utf8.cpp +++ b/Common/Data/Encoding/Utf8.cpp @@ -483,6 +483,21 @@ std::string ConvertUCS2ToUTF8(const std::u16string &wstr) { return s; } +std::string SanitizeUTF8(const std::string &utf8string) { + UTF8 utf(utf8string.c_str()); + std::string s; + // Worst case. + s.resize(utf8string.size() * 4); + + size_t pos = 0; + while (!utf.end_or_overlong_end()) { + int c = utf.next(); + pos += UTF8::encode(&s[pos], c); + } + s.resize(pos); + return s; +} + static size_t ConvertUTF8ToUCS2Internal(char16_t *dest, size_t destSize, const std::string &source) { const char16_t *const orig = dest; const char16_t *const destEnd = dest + destSize; diff --git a/Common/Data/Encoding/Utf8.h b/Common/Data/Encoding/Utf8.h index b954ef5371..f36cb3e75a 100644 --- a/Common/Data/Encoding/Utf8.h +++ b/Common/Data/Encoding/Utf8.h @@ -31,10 +31,11 @@ public: UTF8(const char *c) : c_(c), index_(0) {} UTF8(const char *c, int index) : c_(c), index_(index) {} bool end() const { return c_[index_] == 0; } + bool end_or_overlong_end() const { return peek() == 0; } uint32_t next() { return u8_nextchar(c_, &index_); } - uint32_t peek() { + uint32_t peek() const { int tempIndex = index_; return u8_nextchar(c_, &tempIndex); } @@ -76,6 +77,10 @@ int UTF8StringNonASCIICount(const char *utf8string); bool UTF8StringHasNonASCII(const char *utf8string); +// Removes overlong encodings and similar. +std::string SanitizeUTF8(const std::string &utf8string); + + // UTF8 to Win32 UTF-16 // Should be used when calling Win32 api calls #ifdef _WIN32 diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 9674f69469..bc529efe3b 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -955,12 +955,24 @@ static void PPGeDecimateTextImages(int age) { } void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { - if (!text || !strlen(text)) { + if (!text) { + return; + } + // Seen in Ratchet & Clank - Secret Agent. To match the output of the real thing, we have to remove + // both the overlong encoding and "ENTR", whatever that is. If we just let SanitizeUTF8 remove + // the overlong null, the rest of the string is missing in the bottom left corner (save size, etc). + // It doesn't seem to be using sceCcc. + // Note how the double "" is required in the middle of the string to end the \x80 constant (otherwise it takes E). + // TODO: Potentially if the string is only ended by a C080, ReplaceAll might overshoot :( + std::string str = ReplaceAll(text, "\xC0\x80""ENTR", ""); + // Then SanitizeUTF8 is needed to get rid of various other overlong encodings. + str = SanitizeUTF8(str); + if (str.empty()) { return; } if (HasTextDrawer()) { - PPGeTextDrawerImage im = PPGeGetTextImage(text, style, 480.0f - x, false); + PPGeTextDrawerImage im = PPGeGetTextImage(str.c_str(), style, 480.0f - x, false); if (im.ptr) { PPGeDrawTextImage(im, x, y, style); return; diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 2733287e55..65447c27f0 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -44,6 +44,7 @@ #include "ext/disarm.h" #include "Common/Math/math_util.h" #include "Common/Data/Text/Parsers.h" +#include "Common/Data/Encoding/Utf8.h" #include "Common/ArmEmitter.h" #include "Common/BitScan.h" From a42d3834f288c07d20c9192bf818023627993334 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Mar 2021 17:06:21 -0700 Subject: [PATCH 008/261] Build: Remove "fake" vertex decoder jit. We don't really need this. Just replace it with a stub that always fails to generate a vertex decoder. --- CMakeLists.txt | 2 - GPU/Common/VertexDecoderCommon.h | 28 +-- GPU/Common/VertexDecoderFake.cpp | 266 ---------------------------- UWP/GPU_UWP/GPU_UWP.vcxproj | 1 - UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 1 - 5 files changed, 18 insertions(+), 280 deletions(-) delete mode 100644 GPU/Common/VertexDecoderFake.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 598107a6b7..ce5a6a9c2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -423,7 +423,6 @@ source_group(MIPS FILES ${CommonMIPS}) if(NOT (X86 OR ARM OR MIPS)) set(CommonFake Common/FakeCPUDetect.cpp - Common/FakeEmitter.h ) source_group(Fake FILES ${CommonFake}) endif() @@ -1251,7 +1250,6 @@ list(APPEND CoreExtra list(APPEND CoreExtra Core/MIPS/MIPS/MipsJit.cpp Core/MIPS/MIPS/MipsJit.h - GPU/Common/VertexDecoderFake.cpp ) if(NOT MOBILE_DEVICE) diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 9377b36119..2911e8e6fe 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -35,8 +35,6 @@ #include "Common/Arm64Emitter.h" #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #include "Common/x64Emitter.h" -#elif PPSSPP_ARCH(MIPS) -#include "Common/MipsEmitter.h" #else #include "Common/FakeEmitter.h" #endif @@ -601,18 +599,17 @@ public: // // that's it! - #if PPSSPP_ARCH(ARM) -class VertexDecoderJitCache : public ArmGen::ARMXCodeBlock { +#define VERTEXDECODER_JIT_BACKEND ArmGen::ARMXCodeBlock #elif PPSSPP_ARCH(ARM64) -class VertexDecoderJitCache : public Arm64Gen::ARM64CodeBlock { +#define VERTEXDECODER_JIT_BACKEND Arm64Gen::ARM64CodeBlock #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) -class VertexDecoderJitCache : public Gen::XCodeBlock { -#elif PPSSPP_ARCH(MIPS) -class VertexDecoderJitCache : public MIPSGen::MIPSCodeBlock { -#else -class VertexDecoderJitCache : public FakeGen::FakeXCodeBlock { +#define VERTEXDECODER_JIT_BACKEND Gen::XCodeBlock #endif + + +#ifdef VERTEXDECODER_JIT_BACKEND +class VertexDecoderJitCache : public VERTEXDECODER_JIT_BACKEND { public: VertexDecoderJitCache(); @@ -705,3 +702,14 @@ private: Arm64Gen::ARM64FloatEmitter fp; #endif }; +#else +class VertexDecoderJitCache : public FakeGen::FakeXCodeBlock { +public: + VertexDecoderJitCache(); + + JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize) { + return nullptr; + } + void Clear(); +}; +#endif diff --git a/GPU/Common/VertexDecoderFake.cpp b/GPU/Common/VertexDecoderFake.cpp deleted file mode 100644 index 709d0647e8..0000000000 --- a/GPU/Common/VertexDecoderFake.cpp +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2013- PPSSPP Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#include "ppsspp_config.h" -#include "Common/CPUDetect.h" -#if !PPSSPP_ARCH(MIPS) -#include "Common/FakeEmitter.h" -#endif -#include "Core/Config.h" -#include "Core/Reporting.h" -#include "GPU/GPUState.h" -#include "GPU/Common/VertexDecoderCommon.h" - -static const float by128 = 1.0f / 128.0f; -static const float by16384 = 1.0f / 16384.0f; -static const float by32768 = 1.0f / 32768.0f; - -#if PPSSPP_ARCH(MIPS) -using namespace MIPSGen; -#else -using namespace FakeGen; -#endif - -static const JitLookup jitLookup[] = { - {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, - {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, - {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, - - {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, - {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, - {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, - - {&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat}, - {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, - {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, - - {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, - {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, - {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, - - {&VertexDecoder::Step_TcU16ThroughToFloat, &VertexDecoderJitCache::Jit_TcU16ThroughToFloat}, - {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, - - {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, - {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, - {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, - - {&VertexDecoder::Step_NormalS8Skin, &VertexDecoderJitCache::Jit_NormalS8Skin}, - {&VertexDecoder::Step_NormalS16Skin, &VertexDecoderJitCache::Jit_NormalS16Skin}, - {&VertexDecoder::Step_NormalFloatSkin, &VertexDecoderJitCache::Jit_NormalFloatSkin}, - - {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, - {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, - {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, - {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, - - {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, - {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, - {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloat}, - - {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, - {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, - {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, - - {&VertexDecoder::Step_PosS8Skin, &VertexDecoderJitCache::Jit_PosS8Skin}, - {&VertexDecoder::Step_PosS16Skin, &VertexDecoderJitCache::Jit_PosS16Skin}, - {&VertexDecoder::Step_PosFloatSkin, &VertexDecoderJitCache::Jit_PosFloatSkin}, - - {&VertexDecoder::Step_NormalS8Morph, &VertexDecoderJitCache::Jit_NormalS8Morph}, - {&VertexDecoder::Step_NormalS16Morph, &VertexDecoderJitCache::Jit_NormalS16Morph}, - {&VertexDecoder::Step_NormalFloatMorph, &VertexDecoderJitCache::Jit_NormalFloatMorph}, - - {&VertexDecoder::Step_PosS8Morph, &VertexDecoderJitCache::Jit_PosS8Morph}, - {&VertexDecoder::Step_PosS16Morph, &VertexDecoderJitCache::Jit_PosS16Morph}, - {&VertexDecoder::Step_PosFloatMorph, &VertexDecoderJitCache::Jit_PosFloatMorph}, - - {&VertexDecoder::Step_Color8888Morph, &VertexDecoderJitCache::Jit_Color8888Morph}, - {&VertexDecoder::Step_Color4444Morph, &VertexDecoderJitCache::Jit_Color4444Morph}, - {&VertexDecoder::Step_Color565Morph, &VertexDecoderJitCache::Jit_Color565Morph}, - {&VertexDecoder::Step_Color5551Morph, &VertexDecoderJitCache::Jit_Color5551Morph}, -}; - -JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) { - dec_ = &dec; - //const u8 *start = AlignCode16(); - - bool prescaleStep = false; - bool skinning = false; - - return nullptr; -} - -void VertexDecoderJitCache::Jit_WeightsU8() { -} - -void VertexDecoderJitCache::Jit_WeightsU16() { -} - -void VertexDecoderJitCache::Jit_WeightsFloat() { -} - -void VertexDecoderJitCache::Jit_ApplyWeights() { -} - -void VertexDecoderJitCache::Jit_WeightsU8Skin() { -} - -void VertexDecoderJitCache::Jit_WeightsU16Skin() { -} - -void VertexDecoderJitCache::Jit_WeightsFloatSkin() { -} - -void VertexDecoderJitCache::Jit_TcU8ToFloat() { -} - -void VertexDecoderJitCache::Jit_TcU16ToFloat() { -} - -void VertexDecoderJitCache::Jit_TcFloat() { -} - -void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() { -} - -void VertexDecoderJitCache::Jit_TcFloatThrough() { -} - -void VertexDecoderJitCache::Jit_TcU8Prescale() { -} - -void VertexDecoderJitCache::Jit_TcU16Prescale() { -} - -void VertexDecoderJitCache::Jit_TcFloatPrescale() { -} - -void VertexDecoderJitCache::Jit_Color8888() { -} - -void VertexDecoderJitCache::Jit_Color4444() { -} - -void VertexDecoderJitCache::Jit_Color565() { -} - -void VertexDecoderJitCache::Jit_Color5551() { -} - -void VertexDecoderJitCache::Jit_Color8888Morph() { -} - -void VertexDecoderJitCache::Jit_Color4444Morph() { -} - -void VertexDecoderJitCache::Jit_Color565Morph() { -} - -void VertexDecoderJitCache::Jit_Color5551Morph() { -} - -void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) { -} - -void VertexDecoderJitCache::Jit_NormalS8() { -} - -void VertexDecoderJitCache::Jit_NormalS16() { -} - -void VertexDecoderJitCache::Jit_NormalFloat() { -} - -void VertexDecoderJitCache::Jit_PosS8Through() { -} - -void VertexDecoderJitCache::Jit_PosS16Through() { -} - -void VertexDecoderJitCache::Jit_PosS8() { -} - -void VertexDecoderJitCache::Jit_PosS16() { -} - -// Just copy 12 bytes. -void VertexDecoderJitCache::Jit_PosFloat() { -} - -void VertexDecoderJitCache::Jit_NormalS8Skin() { -} - -void VertexDecoderJitCache::Jit_NormalS16Skin() { -} - -void VertexDecoderJitCache::Jit_NormalFloatSkin() { -} - -void VertexDecoderJitCache::Jit_WriteMatrixMul(int outOff, bool pos) { -} - -void VertexDecoderJitCache::Jit_PosS8Skin() { -} - -void VertexDecoderJitCache::Jit_PosS16Skin() { -} - -void VertexDecoderJitCache::Jit_PosFloatSkin() { -} - -void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { -} - -void VertexDecoderJitCache::Jit_AnyS16ToFloat(int srcoff) { -} - -void VertexDecoderJitCache::Jit_AnyS8Morph(int srcoff, int dstoff) { -} - -void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) { -} - -void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { -} - -void VertexDecoderJitCache::Jit_PosS8Morph() { - Jit_AnyS8Morph(dec_->posoff, dec_->decFmt.posoff); -} - -void VertexDecoderJitCache::Jit_PosS16Morph() { - Jit_AnyS16Morph(dec_->posoff, dec_->decFmt.posoff); -} - -void VertexDecoderJitCache::Jit_PosFloatMorph() { - Jit_AnyFloatMorph(dec_->posoff, dec_->decFmt.posoff); -} - -void VertexDecoderJitCache::Jit_NormalS8Morph() { - Jit_AnyS8Morph(dec_->nrmoff, dec_->decFmt.nrmoff); -} - -void VertexDecoderJitCache::Jit_NormalS16Morph() { - Jit_AnyS16Morph(dec_->nrmoff, dec_->decFmt.nrmoff); -} - -void VertexDecoderJitCache::Jit_NormalFloatMorph() { - Jit_AnyFloatMorph(dec_->nrmoff, dec_->decFmt.nrmoff); -} - -bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { - return false; -} diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 61dfb4406d..45368643e6 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -460,7 +460,6 @@ - diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 0c5f3538bb..3f1d5431cf 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -23,7 +23,6 @@ - From ff98d81e33a2f08b1b9e280ec0cadcf17ca53a8f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 20 Mar 2021 17:25:50 -0700 Subject: [PATCH 009/261] Build: Simplify by always including FakeCPUDetect. --- CMakeLists.txt | 9 +-------- Common/Common.vcxproj | 20 ++++++++++++++++++++ Common/Common.vcxproj.filters | 2 ++ Common/FakeCPUDetect.cpp | 11 +++++++++++ UWP/CommonUWP/CommonUWP.vcxproj | 1 + UWP/CommonUWP/CommonUWP.vcxproj.filters | 1 + android/jni/Android.mk | 8 ++++---- libretro/Makefile.common | 7 ++++--- 8 files changed, 44 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce5a6a9c2d..640d323b45 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -420,13 +420,6 @@ set(CommonMIPS ) source_group(MIPS FILES ${CommonMIPS}) -if(NOT (X86 OR ARM OR MIPS)) - set(CommonFake - Common/FakeCPUDetect.cpp - ) - source_group(Fake FILES ${CommonFake}) -endif() - if(WIN32) set(CommonD3D Common/GPU/D3D9/D3D9ShaderCompiler.cpp @@ -446,7 +439,6 @@ add_library(Common STATIC ${CommonARM} ${CommonARM64} ${CommonMIPS} - ${CommonFake} ${CommonD3D} Common/Serialize/Serializer.cpp Common/Serialize/Serializer.h @@ -643,6 +635,7 @@ add_library(Common STATIC Common/ConsoleListener.h Common/DbgNew.h Common/FakeEmitter.h + Common/FakeCPUDetect.cpp Common/ExceptionHandlerSetup.cpp Common/ExceptionHandlerSetup.h Common/Log.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index d66d2ebac2..69e6ff977b 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -795,6 +795,26 @@ + + true + true + true + true + true + true + true + true + + + true + true + true + true + true + true + true + true + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 3a7dbc7980..c83818b6bd 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -392,6 +392,8 @@ + + diff --git a/Common/FakeCPUDetect.cpp b/Common/FakeCPUDetect.cpp index e110f0cdc0..9b1469c21c 100644 --- a/Common/FakeCPUDetect.cpp +++ b/Common/FakeCPUDetect.cpp @@ -15,6 +15,16 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ +#include "ppsspp_config.h" +#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) +#define REAL_CPUDETECT_AVAIL 1 +#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) +#define REAL_CPUDETECT_AVAIL 1 +#elif PPSSPP_ARCH(MIPS) || PPSSPP_ARCH(MIPS64) +#define REAL_CPUDETECT_AVAIL 1 +#endif + +#ifndef REAL_CPUDETECT_AVAIL #include #include #include @@ -48,3 +58,4 @@ std::string CPUInfo::Summarize() sum = StringFromFormat("%s, %i core", cpu_string, num_cores); return sum; } +#endif diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index eec0403a85..e1ba07540c 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -573,6 +573,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index c0fb4df3ec..95b4f0d0bd 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -96,6 +96,7 @@ + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 7475abcf13..04a223215c 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -16,7 +16,6 @@ ARCH_FILES := \ $(SRC)/Common/ABI.cpp \ $(SRC)/Common/x64Emitter.cpp \ $(SRC)/Common/x64Analyzer.cpp \ - $(SRC)/Common/CPUDetect.cpp \ $(SRC)/Common/Math/fast/fast_matrix_sse.c \ $(SRC)/Common/Thunk.cpp \ $(SRC)/Core/MIPS/x86/CompALU.cpp \ @@ -39,7 +38,6 @@ ARCH_FILES := \ $(SRC)/Common/ABI.cpp \ $(SRC)/Common/x64Emitter.cpp \ $(SRC)/Common/x64Analyzer.cpp \ - $(SRC)/Common/CPUDetect.cpp \ $(SRC)/Common/Math/fast/fast_matrix_sse.c \ $(SRC)/Common/Thunk.cpp \ $(SRC)/Core/MIPS/x86/CompALU.cpp \ @@ -62,7 +60,6 @@ ARCH_FILES := \ $(SRC)/GPU/Common/TextureDecoderNEON.cpp.neon \ $(SRC)/Core/Util/AudioFormatNEON.cpp.neon \ $(SRC)/Common/ArmEmitter.cpp \ - $(SRC)/Common/ArmCPUDetect.cpp \ $(SRC)/Common/ColorConvNEON.cpp.neon \ $(SRC)/Common/Math/fast/fast_matrix_neon.S.neon \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ @@ -90,7 +87,6 @@ ARCH_FILES := \ $(SRC)/GPU/Common/TextureDecoderNEON.cpp \ $(SRC)/Core/Util/AudioFormatNEON.cpp \ $(SRC)/Common/Arm64Emitter.cpp \ - $(SRC)/Common/ArmCPUDetect.cpp \ $(SRC)/Common/ColorConvNEON.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64CompALU.cpp \ $(SRC)/Core/MIPS/ARM64/Arm64CompBranch.cpp \ @@ -296,8 +292,11 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/UI/View.cpp \ $(SRC)/Common/UI/ViewGroup.cpp \ $(SRC)/Common/Serialize/Serializer.cpp \ + $(SRC)/Common/ArmCPUDetect.cpp \ $(SRC)/Common/ColorConv.cpp \ + $(SRC)/Common/CPUDetect.cpp \ $(SRC)/Common/ExceptionHandlerSetup.cpp \ + $(SRC)/Common/FakeCPUDetect.cpp \ $(SRC)/Common/Log.cpp \ $(SRC)/Common/LogManager.cpp \ $(SRC)/Common/MemArenaAndroid.cpp \ @@ -305,6 +304,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/MemArenaWin32.cpp \ $(SRC)/Common/MemArenaPosix.cpp \ $(SRC)/Common/MemoryUtil.cpp \ + $(SRC)/Common/MipsCPUDetect.cpp \ $(SRC)/Common/StringUtils.cpp \ $(SRC)/Common/SysError.cpp \ $(SRC)/Common/TimeUtil.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index bb185a17a1..9cf38c96a0 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -214,13 +214,17 @@ SOURCES_CXX += \ $(COMMONDIR)/UI/View.cpp \ $(COMMONDIR)/UI/ViewGroup.cpp \ $(COMMONDIR)/System/Display.cpp \ + $(COMMONDIR)/ArmCPUDetect.cpp \ + $(COMMONDIR)/CPUDetect.cpp \ $(COMMONDIR)/Buffer.cpp \ $(COMMONDIR)/ConsoleListener.cpp \ $(COMMONDIR)/ExceptionHandlerSetup.cpp \ + $(COMMONDIR)/FakeCPUDetect.cpp \ $(COMMONDIR)/Log.cpp \ $(COMMONDIR)/LogManager.cpp \ $(COMMONDIR)/OSVersion.cpp \ $(COMMONDIR)/MemoryUtil.cpp \ + $(COMMONDIR)/MipsCPUDetect.cpp \ $(COMMONDIR)/SysError.cpp \ $(COMMONDIR)/StringUtils.cpp \ $(COMMONDIR)/TimeUtil.cpp @@ -518,7 +522,6 @@ ifeq ($(WITH_DYNAREC),1) ifeq ($(TARGET_ARCH),arm) DYNAFLAGS += -D_ARCH_32 SOURCES_CXX += $(COMMONDIR)/ArmEmitter.cpp \ - $(COMMONDIR)/ArmCPUDetect.cpp \ $(COREDIR)/MIPS/ARM/ArmAsm.cpp \ $(COREDIR)/MIPS/ARM/ArmCompALU.cpp \ $(COREDIR)/MIPS/ARM/ArmCompBranch.cpp \ @@ -548,7 +551,6 @@ ifeq ($(WITH_DYNAREC),1) else ifeq ($(TARGET_ARCH),arm64) DYNAFLAGS += -D_ARCH_64 SOURCES_CXX += $(COMMONDIR)/Arm64Emitter.cpp \ - $(COMMONDIR)/ArmCPUDetect.cpp \ $(COREDIR)/MIPS/ARM64/Arm64Asm.cpp \ $(COREDIR)/MIPS/ARM64/Arm64CompALU.cpp \ $(COREDIR)/MIPS/ARM64/Arm64CompBranch.cpp \ @@ -597,7 +599,6 @@ endif $(COMMONDIR)/x64Analyzer.cpp \ $(COMMONDIR)/ABI.cpp \ $(COMMONDIR)/Thunk.cpp \ - $(COMMONDIR)/CPUDetect.cpp \ $(COREDIR)/MIPS/x86/CompReplace.cpp \ $(COREDIR)/MIPS/x86/CompBranch.cpp \ $(COREDIR)/MIPS/x86/Asm.cpp \ From 4ef36a79817b8bce87de740b9b73a9a3c9880a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 23 Mar 2021 23:41:16 +0100 Subject: [PATCH 010/261] Add a setting for choosing background animation. Off and Floating Symbols are the only choices so far. --- Core/Config.cpp | 2 + Core/Config.h | 6 +++ UI/GameSettingsScreen.cpp | 28 +++++++------- UI/MiscScreens.cpp | 81 ++++++++++++++++++++++++++------------- 4 files changed, 77 insertions(+), 40 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 16a75c3a41..f8a70ae981 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -494,6 +494,8 @@ static ConfigSetting generalSettings[] = { #endif ConfigSetting("InternalScreenRotation", &g_Config.iInternalScreenRotation, ROTATION_LOCKED_HORIZONTAL), + ConfigSetting("BackgroundAnimation", &g_Config.iBackgroundAnimation, 1, true, false), + #if defined(USING_WIN_UI) ConfigSetting("TopMost", &g_Config.bTopMost, false), ConfigSetting("WindowX", &g_Config.iWindowX, -1), // -1 tells us to center the window. diff --git a/Core/Config.h b/Core/Config.h index 061b90f241..9589ffe6e6 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -38,6 +38,11 @@ enum ChatPositions { CENTER_RIGHT = 7, }; +enum class BackgroundAnimation { + OFF = 0, + FLOATING_SYMBOLS = 1, +}; + namespace http { class Download; class Downloader; @@ -239,6 +244,7 @@ public: bool bShowIDOnGameIcon; float fGameGridScale; bool bShowOnScreenMessages; + int iBackgroundAnimation; // enum BackgroundAnimation // TODO: Maybe move to a separate theme system. uint32_t uItemStyleFg; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index fd0e821004..7ad03db35d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -860,9 +860,23 @@ void GameSettingsScreen::CreateViews() { systemSettingsScroll->Add(systemSettings); tabHolder->AddTab(ms->T("System"), systemSettingsScroll); - systemSettings->Add(new ItemHeader(sy->T("UI Language"))); // Should be renamed "UI"? + systemSettings->Add(new ItemHeader(sy->T("UI"))); systemSettings->Add(new Choice(dev->T("Language", "Language")))->OnClick.Handle(this, &GameSettingsScreen::OnLanguage); systemSettings->Add(new CheckBox(&g_Config.bUISound, sy->T("UI Sound"))); + const std::string bgPng = GetSysDirectory(DIRECTORY_SYSTEM) + "background.png"; + const std::string bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) + "background.jpg"; + if (File::Exists(bgPng) || File::Exists(bgJpg)) { + backgroundChoice_ = systemSettings->Add(new Choice(sy->T("Clear UI background"))); + } else if (System_GetPropertyBool(SYSPROP_HAS_IMAGE_BROWSER)) { + backgroundChoice_ = systemSettings->Add(new Choice(sy->T("Set UI background..."))); + } else { + backgroundChoice_ = nullptr; + } + if (backgroundChoice_ != nullptr) { + backgroundChoice_->OnClick.Handle(this, &GameSettingsScreen::OnChangeBackground); + } + static const char *backgroundAnimations[] = { "No animation", "Floating Symbols" }; + systemSettings->Add(new PopupMultiChoice(&g_Config.iBackgroundAnimation, sy->T("UI background animation"), backgroundAnimations, 0, ARRAY_SIZE(backgroundAnimations), sy->GetName(), screenManager())); systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team"))); enableReports_ = Reporting::IsEnabled(); @@ -906,18 +920,6 @@ void GameSettingsScreen::CreateViews() { } #endif systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP"))); - const std::string bgPng = GetSysDirectory(DIRECTORY_SYSTEM) + "background.png"; - const std::string bgJpg = GetSysDirectory(DIRECTORY_SYSTEM) + "background.jpg"; - if (File::Exists(bgPng) || File::Exists(bgJpg)) { - backgroundChoice_ = systemSettings->Add(new Choice(sy->T("Clear UI background"))); - } else if (System_GetPropertyBool(SYSPROP_HAS_IMAGE_BROWSER)) { - backgroundChoice_ = systemSettings->Add(new Choice(sy->T("Set UI background..."))); - } else { - backgroundChoice_ = nullptr; - } - if (backgroundChoice_ != nullptr) { - backgroundChoice_->OnClick.Handle(this, &GameSettingsScreen::OnChangeBackground); - } systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings); systemSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups"))); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 19bcc038ab..1e8271b9dd 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -73,7 +73,47 @@ static const uint32_t colors[4] = { static std::unique_ptr bgTexture; -static bool backgroundInited; +class Animation { +public: + virtual ~Animation() {} + virtual void Draw(UIContext &dc, double t, float alpha) = 0; +}; + +class FloatingSymbolsAnimation : public Animation { +public: + ~FloatingSymbolsAnimation() override {} + void Draw(UIContext &dc, double t, float alpha) override { + float xres = dc.GetBounds().w; + float yres = dc.GetBounds().h; + if (xbase[0] == 0.0f || last_xres != xres || last_yres != yres) { + GMRng rng; + for (int i = 0; i < 100; i++) { + xbase[i] = rng.F() * xres; + ybase[i] = rng.F() * yres; + } + last_xres = xres; + last_yres = yres; + } + + for (int i = 0; i < 100; i++) { + float x = xbase[i] + dc.GetBounds().x; + float y = ybase[i] + dc.GetBounds().y + 40 * cosf(i * 7.2f + t * 1.3f); + float angle = (float)sin(i + t); + int n = i & 3; + ui_draw2d.DrawImageRotated(symbols[n], x, y, 1.0f, angle, colorAlpha(colors[n], alpha * 0.1f)); + } + } +private: + float xbase[100] = { 0 }; + float ybase[100] = { 0 }; + float last_xres = 0; + float last_yres = 0; +}; + +// TODO: Add more styles. Remember to add to the enum in Config.cpp and the selector in GameSettings too. + +static BackgroundAnimation g_CurBackgroundAnimation = BackgroundAnimation::OFF; +static std::unique_ptr g_Animation; void UIBackgroundInit(UIContext &dc) { const std::string bgPng = GetSysDirectory(DIRECTORY_SYSTEM) + "background.png"; @@ -86,32 +126,22 @@ void UIBackgroundInit(UIContext &dc) { void UIBackgroundShutdown() { bgTexture.reset(nullptr); - backgroundInited = false; + g_Animation.reset(nullptr); } void DrawBackground(UIContext &dc, float alpha) { - if (!backgroundInited) { - UIBackgroundInit(dc); - backgroundInited = true; - } + if (g_CurBackgroundAnimation != (BackgroundAnimation)g_Config.iBackgroundAnimation) { + g_CurBackgroundAnimation = (BackgroundAnimation)g_Config.iBackgroundAnimation; - static float xbase[100] = {0}; - static float ybase[100] = {0}; - float xres = dc.GetBounds().w; - float yres = dc.GetBounds().h; - static int last_xres = 0; - static int last_yres = 0; - - if (xbase[0] == 0.0f || last_xres != xres || last_yres != yres) { - GMRng rng; - for (int i = 0; i < 100; i++) { - xbase[i] = rng.F() * xres; - ybase[i] = rng.F() * yres; + switch (g_CurBackgroundAnimation) { + case BackgroundAnimation::FLOATING_SYMBOLS: + g_Animation.reset(new FloatingSymbolsAnimation()); + break; + default: + g_Animation.reset(nullptr); } - last_xres = xres; - last_yres = yres; } - + uint32_t bgColor = whiteAlpha(alpha); if (bgTexture != nullptr) { @@ -135,12 +165,9 @@ void DrawBackground(UIContext &dc, float alpha) { #else double t = time_now_d(); #endif - for (int i = 0; i < 100; i++) { - float x = xbase[i] + dc.GetBounds().x; - float y = ybase[i] + dc.GetBounds().y + 40 * cosf(i * 7.2f + t * 1.3f); - float angle = (float)sin(i + t); - int n = i & 3; - ui_draw2d.DrawImageRotated(symbols[n], x, y, 1.0f, angle, colorAlpha(colors[n], alpha * 0.1f)); + + if (g_Animation) { + g_Animation->Draw(dc, t, alpha); } } From 566943d8ed5306f0a81001521b22a1e21ec23f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 24 Mar 2021 09:27:50 +0100 Subject: [PATCH 011/261] Update lang submodule --- assets/lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang b/assets/lang index ddb1246ec2..37fe9848b4 160000 --- a/assets/lang +++ b/assets/lang @@ -1 +1 @@ -Subproject commit ddb1246ec2ad2548711f4b966a801e80b7fbe73f +Subproject commit 37fe9848b4d2bf7879a3fd382796e5e1d1193ac4 From de7f485b9e67b45bc457b57895085240a3362a4d Mon Sep 17 00:00:00 2001 From: Autechre Date: Fri, 26 Mar 2021 16:05:53 +0100 Subject: [PATCH 012/261] Update .gitlab-ci.yml --- .gitlab-ci.yml | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 981f938ebc..23120d5c37 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,10 @@ -# libretro CI +# DESCRIPTION: GitLab CI/CD for libRetro (NOT FOR GitLab-proper) + +############################################################################## +################################# BOILERPLATE ################################ +############################################################################## + +# Core definitions variables: GIT_SUBMODULE_STRATEGY: normal @@ -15,61 +21,88 @@ variables: variables: MAKEFILE_PATH: libretro +# Inclusion templates, required for the build to work include: - - project: 'libretro-infrastructure/ci-templates' - file: '/android-cmake.yml' - - project: 'libretro-infrastructure/ci-templates' - file: '/linux-cmake.yml' + ################################## DESKTOPS ################################ + # Windows 64bit - project: 'libretro-infrastructure/ci-templates' file: '/windows-x64-msvc19-msys2.yml' + + # Windows 32bit - project: 'libretro-infrastructure/ci-templates' file: '/windows-i686-msvc19-msys2.yml' + # Linux + - project: 'libretro-infrastructure/ci-templates' + file: '/linux-cmake.yml' + + ################################## CELLULAR ################################ + # Android + - project: 'libretro-infrastructure/ci-templates' + file: '/android-cmake.yml' + + ################################## CONSOLES ################################ + + #################################### MISC ################################## + +# Stages for building stages: - build-prepare - build-shared -# Desktop +############################################################################## +#################################### STAGES ################################## +############################################################################## +# +################################### DESKTOPS ################################# +# Linux 64-bit libretro-build-linux-x64: extends: - .libretro-linux-cmake-x86_64 - .core-defs - .linux-defs +# Linux 32-bit libretro-build-linux-i686: extends: - .libretro-linux-cmake-x86 - .core-defs - .linux-defs +# Windows 64-bit libretro-build-windows-x64: extends: - .libretro-windows-x64-msvc19-msys2-make-default - .core-defs - .windows-defs +# Windows 32-bit libretro-build-windows-i686: extends: - .libretro-windows-i686-msvc19-msys2-make-default - .core-defs - .windows-defs -# Android +################################### CELLULAR ################################# +# Android ARMv7a libretro-build-android-armeabi-v7a: extends: - .libretro-android-cmake-armeabi-v7a - .core-defs +# Android ARMv8a libretro-build-android-arm64-v8a: extends: - .libretro-android-cmake-arm64-v8a - .core-defs +# Android 64-bit x86 libretro-build-android-x86_64: extends: - .libretro-android-cmake-x86_64 - .core-defs +# Android 32-bit x86 libretro-build-android-x86: extends: - .libretro-android-cmake-x86 From 35e743c68574a216a9729e23ee8372664962a2c9 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 26 Mar 2021 18:06:36 +0100 Subject: [PATCH 013/261] (Libretro/Gitlab) Add osx x64 target --- .gitlab-ci.yml | 47 ++++++++++++--------- libretro/Makefile | 89 ++++++++++++++++++++++++++++++---------- libretro/Makefile.common | 8 +--- 3 files changed, 96 insertions(+), 48 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23120d5c37..1c45ad7084 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,11 +13,11 @@ variables: CORENAME: ppsspp CORE_ARGS: -DLIBRETRO=ON -.linux-defs: +.cmake-defs: variables: EXTRA_PATH: lib -.windows-defs: +.make-defs: variables: MAKEFILE_PATH: libretro @@ -40,9 +40,9 @@ include: # Android - project: 'libretro-infrastructure/ci-templates' file: '/android-cmake.yml' - - ################################## CONSOLES ################################ + ################################## CONSOLES ################################ + #################################### MISC ################################## # Stages for building @@ -55,33 +55,40 @@ stages: ############################################################################## # ################################### DESKTOPS ################################# -# Linux 64-bit -libretro-build-linux-x64: - extends: - - .libretro-linux-cmake-x86_64 - - .core-defs - - .linux-defs - -# Linux 32-bit -libretro-build-linux-i686: - extends: - - .libretro-linux-cmake-x86 - - .core-defs - - .linux-defs - # Windows 64-bit libretro-build-windows-x64: extends: - .libretro-windows-x64-msvc19-msys2-make-default - .core-defs - - .windows-defs + - .make-defs # Windows 32-bit libretro-build-windows-i686: extends: - .libretro-windows-i686-msvc19-msys2-make-default - .core-defs - - .windows-defs + - .make-defs + +# Linux 64-bit +libretro-build-linux-x64: + extends: + - .libretro-linux-cmake-x86_64 + - .core-defs + - .cmake-defs + +# Linux 32-bit +libretro-build-linux-i686: + extends: + - .libretro-linux-cmake-x86 + - .core-defs + - .cmake-defs + +# MacOS 64-bit +libretro-build-osx-x64: + extends: + - .libretro-osx-x64-make-default + - .core-defs + - .make-defs ################################### CELLULAR ################################# # Android ARMv7a diff --git a/libretro/Makefile b/libretro/Makefile index 6cd3173449..5645e8c408 100644 --- a/libretro/Makefile +++ b/libretro/Makefile @@ -6,6 +6,8 @@ INCFLAGS := -I. COREFLAGS := CPUFLAGS := +PLATOFRM_EXT := + UNAME=$(shell uname -a) # Cross compile ? @@ -70,7 +72,7 @@ ifneq (,$(findstring unix,$(platform))) else GL_LIB := -lGL endif - PLATFORM_EXT := unix + PLATFORM_EXT = unix LDFLAGS += -lrt -ldl # Raspberry Pi @@ -82,7 +84,7 @@ else ifneq (,$(findstring rpi,$(platform))) GL_LIB := -lGLESv2 INCFLAGS += -I/opt/vc/include CPUFLAGS += -DARMv5_ONLY - PLATFORM_EXT := unix + PLATFORM_EXT = unix TARGET_ARCH = arm LDFLAGS += -lrt -ldl @@ -106,7 +108,7 @@ else ifneq (,$(findstring arm64,$(platform))) endif CPUFLAGS += -D__arm64__ -DARM64_ASM -D__NEON_OPT LDFLAGS += -lrt -ldl - PLATFORM_EXT := unix + PLATFORM_EXT = unix # i.MX6 else ifneq (,$(findstring imx6,$(platform))) @@ -116,7 +118,7 @@ else ifneq (,$(findstring imx6,$(platform))) GLES = 1 GL_LIB := -lGLESv2 CPUFLAGS += - PLATFORM_EXT := unix + PLATFORM_EXT = unix TARGET_ARCH = arm HAVE_NEON=1 FFMPEGINCFLAGS += -I$(FFMPEGDIR)/linux/$(TARGET_ARCH)/include @@ -127,21 +129,32 @@ else ifneq (,$(findstring imx6,$(platform))) # OS X else ifneq (,$(findstring osx,$(platform))) TARGET := $(TARGET_NAME)_libretro.dylib + MINVERSION := LDFLAGS += -dynamiclib OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9 )) && echo "YES"` ifeq ($(OSX_LT_MAVERICKS),"YES") - LDFLAGS += -mmacosx-version-min=10.5 + MINVERSION += -mmacosx-version-min=10.5 endif - LDFLAGS += -stdlib=libc++ + LDFLAGS += $(MINVERSION) + LDFLAGS += -stdlib=libc++ fpic = -fPIC - FFMPEGINCFLAGS += -I$(FFMPEGDIR)/macosx/$(TARGET_ARCH)/include - FFMPEGLIBDIR := $(FFMPEGDIR)/macosx/$(TARGET_ARCH)/lib + FFMPEGINCFLAGS += -I$(FFMPEGDIR)/macosx/universal/include + FFMPEGLIBDIR := $(FFMPEGDIR)/macosx/universal/lib FFMPEGLDFLAGS += -liconv -L$(FFMPEGLIBDIR) -lavformat -lavcodec -lavutil -lswresample -lswscale PLATCFLAGS += -D__MACOSX__ GL_LIB := -framework OpenGL - PLATFORM_EXT := darwin + PLATFORM_EXT = darwin + + ifeq ($(CROSS_COMPILE),1) + TARGET_RULE = -target $(LIBRETRO_APPLE_PLATFORM) -isysroot $(LIBRETRO_APPLE_ISYSROOT) + PLATCFLAGS += $(TARGET_RULE) + LDFLAGS += $(TARGET_RULE) + endif + + PLATCFLAGS += $(ARCHFLAGS) + LDFLAGS += $(ARCHFLAGS) # iOS else ifneq (,$(findstring ios,$(platform))) @@ -150,6 +163,7 @@ else ifneq (,$(findstring ios,$(platform))) fpic = -fPIC GLES = 1 GL_LIB := -framework OpenGLES + MINVERSION := HAVE_NEON = 1 FFMPEGINCFLAGS += -I$(FFMPEGDIR)/ios/universal/include @@ -160,18 +174,49 @@ else ifneq (,$(findstring ios,$(platform))) IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path) endif +ifeq ($(platform),ios-arm64) + CC = clang -arch arm64 -isysroot $(IOSSDK) + CXX = clang++ -arch arm64 -isysroot $(IOSSDK) +else CC = clang -arch armv7 -isysroot $(IOSSDK) CXX = clang++ -arch armv7 -isysroot $(IOSSDK) +endif OSXVER = `sw_vers -productVersion | cut -c 4` - ifneq ($(OSXVER),9) - CC += -miphoneos-version-min=5.0 - AS += -miphoneos-version-min=5.0 - CXX += -miphoneos-version-min=5.0 - PLATCFLAGS += -miphoneos-version-min=5.0 - endif + ifneq ($(OSXVER),9) + MINVERSION = -miphoneos-version-min=5.0 + else + MINVERSION = -miphoneos-version-min=8.0 + endif + PLATCFLAGS += $(MINVERSION) PLATCFLAGS += -DHAVE_POSIX_MEMALIGN CPUFLAGS += -DARMv5_ONLY -DARM - PLATFORM_EXT := unix + PLATFORM_EXT = darwin + TARGET_ARCH = arm + +else ifeq ($(platform), tvos-arm64) + TARGET := $(TARGET_NAME)_libretro_tvos.dylib + LDFLAGS += -dynamiclib -marm + fpic = -fPIC + GLES = 1 + GL_LIB := -framework OpenGLES + MINVERSION := + HAVE_NEON = 1 + + FFMPEGINCFLAGS += -I$(FFMPEGDIR)/ios/universal/include + FFMPEGLIBDIR := $(FFMPEGDIR)/ios/universal/lib + FFMPEGLDFLAGS += -L$(FFMPEGLIBDIR) -lavformat -lavcodec -lavutil -lswresample -lswscale + + ifeq ($(IOSSDK),) + IOSSDK := $(shell xcodebuild -version -sdk appletvos Path) + endif + + CC = clang -arch arm64 -isysroot $(IOSSDK) + CXX = clang++ -arch arm64 -isysroot $(IOSSDK) + OSXVER = `sw_vers -productVersion | cut -c 4` + PLATCFLAGS += $(MINVERSION) + PLATCFLAGS += -DHAVE_POSIX_MEMALIGN + CPUFLAGS += -DARMv5_ONLY -DARM + PLATFORM_EXT = darwin TARGET_ARCH = arm # Android @@ -196,7 +241,7 @@ else ifneq (,$(findstring android,$(platform))) FFMPEGLIBDIR := $(FFMPEGDIR)/android/armv7/lib FFMPEGLDFLAGS += -L$(FFMPEGLIBDIR) -lavformat -lavcodec -lavutil -lswresample -lswscale - PLATFORM_EXT := android + PLATFORM_EXT = android # QNX else ifeq ($(platform), qnx) @@ -216,7 +261,7 @@ else ifeq ($(platform), qnx) CPUFLAGS += -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp -D__arm__ -DARM_ASM -D__NEON_OPT CFLAGS += -D__QNX__ - PLATFORM_EXT := unix + PLATFORM_EXT = unix # ARM else ifneq (,$(findstring armv,$(platform))) @@ -264,7 +309,7 @@ else ifeq ($(platform), emscripten) -Daudio_convert_s16_to_float_C=mupen_audio_convert_s16_to_float_C -Daudio_convert_float_to_s16_C=mupen_audio_convert_float_to_s16_C \ -Daudio_convert_init_simd=mupen_audio_convert_init_simd -Drglgen_resolve_symbols_custom=mupen_rglgen_resolve_symbols_custom \ -Drglgen_resolve_symbols=mupen_rglgen_resolve_symbols - PLATFORM_EXT := unix + PLATFORM_EXT = unix # Windows MSVC 2017 all architectures else ifneq (,$(findstring windows_msvc2017,$(platform))) @@ -370,7 +415,7 @@ else ifneq (,$(findstring windows_msvc2017,$(platform))) TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 LDFLAGS += -DLL - PLATFORM_EXT := win32 + PLATFORM_EXT = win32 FFMPEGINCFLAGS += -I$(FFMPEGDIR)/Windows/$(TARGET_ARCH)/include FFMPEGLIBDIR := $(FFMPEGDIR)/Windows/$(TARGET_ARCH)/lib FFMPEGLDFLAGS += -LIBPATH:$(FFMPEGLIBDIR) @@ -481,7 +526,7 @@ else ifneq (,$(findstring windows_msvc2019,$(platform))) TARGET := $(TARGET_NAME)_libretro.dll PSS_STYLE :=2 LDFLAGS += -DLL - PLATFORM_EXT := win32 + PLATFORM_EXT = win32 FFMPEGINCFLAGS += -I$(FFMPEGDIR)/Windows/$(TARGET_ARCH)/include FFMPEGLIBDIR := $(FFMPEGDIR)/Windows/$(TARGET_ARCH)/lib FFMPEGLDFLAGS += -LIBPATH:$(FFMPEGLIBDIR) @@ -495,7 +540,7 @@ else ifneq (,$(findstring win,$(platform))) CXXFLAGS += -fpermissive -Wno-multichar -D_UNICODE -DUNICODE LDFLAGS += -shared -Wl,--no-undefined -static-libgcc -static-libstdc++ -Wl,--version-script=link.T -lwinmm -lgdi32 -lwsock32 -lws2_32 -ld3d9 -ld3dx9 GL_LIB := -lopengl32 - PLATFORM_EXT := win32 + PLATFORM_EXT = win32 FFMPEGINCFLAGS += -I$(FFMPEGDIR)/Windows/$(TARGET_ARCH)/include FFMPEGLDFLAGS += -lavformat -lavcodec -lavutil -lswresample -lswscale INCFLAGS += -include $(CORE_DIR)/Windows/mingw_defines.h diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 9cf38c96a0..29490b7369 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -340,6 +340,7 @@ SOURCES_CXX += $(COMMONDIR)/MemArenaAndroid.cpp \ $(EXTDIR)/glslang/glslang/OSDependent/Unix/ossource.cpp \ $(COMMONDIR)/Render/Text/draw_text_android.cpp else +COREFLAGS += -DVK_USE_PLATFORM_XLIB_KHR SOURCES_CXX += $(COMMONDIR)/MemArenaPosix.cpp \ $(EXTDIR)/glslang/glslang/OSDependent/Unix/ossource.cpp endif @@ -585,7 +586,7 @@ ifeq ($(WITH_DYNAREC),1) CPUFLAGS += -D_M_IX86_FP else CPUFLAGS += -msse -msse2 -endif + endif ifeq ($(TARGET_ARCH),x86_64) CPUFLAGS += -D_M_X64 -D_ARCH_64 else @@ -655,11 +656,6 @@ SOURCES_CXX += \ $(LIBRETRODIR)/LibretroVulkanContext.cpp \ $(LIBRETRODIR)/libretro_vulkan.cpp -ifneq ($(PLATFORM_EXT), darwin) - ifeq ($(PLATFORM_EXT), unix) - COREFLAGS += -DVK_USE_PLATFORM_XLIB_KHR - endif -endif ifeq ($(PLATFORM_EXT), win32) SOURCES_CXX += \ From 995d005f6f3e745005981659b8599edff9bd5ed6 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 26 Mar 2021 18:18:38 +0100 Subject: [PATCH 014/261] Add missing rule in .gitlab-ci.yml --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1c45ad7084..f94d19d932 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,6 +35,10 @@ include: # Linux - project: 'libretro-infrastructure/ci-templates' file: '/linux-cmake.yml' + + # MacOS 64-bit + - project: 'libretro-infrastructure/ci-templates' + file: '/osx-x64.yml' ################################## CELLULAR ################################ # Android From 7d085966f164d6af757db4d71de4c06d9ea5f663 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 13:45:01 -0700 Subject: [PATCH 015/261] PPGe: Apply overlong handling to wrapped text too. --- Core/Util/PPGeDraw.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index bc529efe3b..4ed8713b4f 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -954,10 +954,7 @@ static void PPGeDecimateTextImages(int age) { } } -void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { - if (!text) { - return; - } +static std::string PPGeSanitizeText(const std::string &text) { // Seen in Ratchet & Clank - Secret Agent. To match the output of the real thing, we have to remove // both the overlong encoding and "ENTR", whatever that is. If we just let SanitizeUTF8 remove // the overlong null, the rest of the string is missing in the bottom left corner (save size, etc). @@ -966,7 +963,14 @@ void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { // TODO: Potentially if the string is only ended by a C080, ReplaceAll might overshoot :( std::string str = ReplaceAll(text, "\xC0\x80""ENTR", ""); // Then SanitizeUTF8 is needed to get rid of various other overlong encodings. - str = SanitizeUTF8(str); + return SanitizeUTF8(str); +} + +void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { + if (!text) { + return; + } + std::string str = PPGeSanitizeText(text); if (str.empty()) { return; } @@ -1013,7 +1017,7 @@ static std::string CropLinesToCount(const std::string &s, int numLines) { } void PPGeDrawTextWrapped(const char *text, float x, float y, float wrapWidth, float wrapHeight, const PPGeStyle &style) { - std::string s = text; + std::string s = PPGeSanitizeText(text); if (wrapHeight != 0.0f) { s = StripTrailingWhite(s); } From 5ef8762c32fae4462205d225b59a4e3c67539953 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 14:16:17 -0700 Subject: [PATCH 016/261] PPGe: Interpret invalid UTF-8 sequences better. This matches PSP firmware behavior per tests. --- Common/Data/Encoding/Utf8.cpp | 31 +++++++++++++++++++++++++++++-- Common/Data/Encoding/Utf8.h | 11 ++++++++++- Core/Util/PPGeDraw.cpp | 2 +- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Common/Data/Encoding/Utf8.cpp b/Common/Data/Encoding/Utf8.cpp index 0a2a7355cc..d3ddbdbc21 100644 --- a/Common/Data/Encoding/Utf8.cpp +++ b/Common/Data/Encoding/Utf8.cpp @@ -234,6 +234,32 @@ uint32_t u8_nextchar(const char *s, int *i) return ch; } +uint32_t u8_nextchar_unsafe(const char *s, int *i) { + uint32_t ch = (unsigned char)s[(*i)++]; + int sz = 1; + + if (ch >= 0xF0) { + sz++; + ch &= ~0x10; + } + if (ch >= 0xE0) { + sz++; + ch &= ~0x20; + } + if (ch >= 0xC0) { + sz++; + ch &= ~0xC0; + } + + // Just assume the bytes must be there. This is the logic used on the PSP. + for (int j = 1; j < sz; ++j) { + ch <<= 6; + ch += ((unsigned char)s[(*i)++]) & 0x3F; + } + + return ch; +} + void u8_inc(const char *s, int *i) { (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) || @@ -489,9 +515,10 @@ std::string SanitizeUTF8(const std::string &utf8string) { // Worst case. s.resize(utf8string.size() * 4); + // This stops at invalid start bytes. size_t pos = 0; - while (!utf.end_or_overlong_end()) { - int c = utf.next(); + while (!utf.end() && !utf.invalid()) { + int c = utf.next_unsafe(); pos += UTF8::encode(&s[pos], c); } s.resize(pos); diff --git a/Common/Data/Encoding/Utf8.h b/Common/Data/Encoding/Utf8.h index f36cb3e75a..29d09f67e9 100644 --- a/Common/Data/Encoding/Utf8.h +++ b/Common/Data/Encoding/Utf8.h @@ -20,6 +20,7 @@ #include uint32_t u8_nextchar(const char *s, int *i); +uint32_t u8_nextchar_unsafe(const char *s, int *i); int u8_wc_toutf8(char *dest, uint32_t ch); int u8_strlen(const char *s); void u8_inc(const char *s, int *i); @@ -31,10 +32,18 @@ public: UTF8(const char *c) : c_(c), index_(0) {} UTF8(const char *c, int index) : c_(c), index_(index) {} bool end() const { return c_[index_] == 0; } - bool end_or_overlong_end() const { return peek() == 0; } + // Returns true if the next character is outside BMP and Planes 1 - 16. + bool invalid() const { + unsigned char c = (unsigned char)c_[index_]; + return (c >= 0x80 && c <= 0xC1) || c >= 0xF5; + } uint32_t next() { return u8_nextchar(c_, &index_); } + // Allow invalid continuation bytes. + uint32_t next_unsafe() { + return u8_nextchar_unsafe(c_, &index_); + } uint32_t peek() const { int tempIndex = index_; return u8_nextchar(c_, &tempIndex); diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 4ed8713b4f..da3726ec23 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -960,7 +960,7 @@ static std::string PPGeSanitizeText(const std::string &text) { // the overlong null, the rest of the string is missing in the bottom left corner (save size, etc). // It doesn't seem to be using sceCcc. // Note how the double "" is required in the middle of the string to end the \x80 constant (otherwise it takes E). - // TODO: Potentially if the string is only ended by a C080, ReplaceAll might overshoot :( + // This behavior doesn't replicate within other games, so it may be a game bug workaround. std::string str = ReplaceAll(text, "\xC0\x80""ENTR", ""); // Then SanitizeUTF8 is needed to get rid of various other overlong encodings. return SanitizeUTF8(str); From bab9581901dbf915cd2fda0b22c5ff604b781df5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 19:42:29 -0700 Subject: [PATCH 017/261] Core: Unbreak ValidSize limits. Broken in bdd2029. --- Core/MemMap.h | 8 ++++---- unittest/UnitTest.cpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/MemMap.h b/Core/MemMap.h index 465802fb32..b9afe2ea35 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -313,13 +313,13 @@ inline bool IsValidAddress(const u32 address) { inline u32 ValidSize(const u32 address, const u32 requested_size) { u32 max_size; if ((address & 0x3E000000) == 0x08000000) { - max_size = 0x08000000 + g_MemorySize - (address & 0x3E000000); + max_size = 0x08000000 + g_MemorySize - (address & 0x3FFFFFFF); } else if ((address & 0x3F800000) == 0x04000000) { - max_size = 0x04800000 - (address & 0x3F800000); + max_size = 0x04800000 - (address & 0x3FFFFFFF); } else if ((address & 0xBFFF0000) == 0x00010000) { - max_size = 0x00014000 - (address & 0xBFFF0000); + max_size = 0x00014000 - (address & 0xBFFFFFFF); } else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { - max_size = 0x08000000 + g_MemorySize - (address & 0x3F000000); + max_size = 0x08000000 + g_MemorySize - (address & 0x3FFFFFFF); } else { max_size = 0; } diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 65447c27f0..1e0310991b 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -567,6 +567,8 @@ static bool TestMemMap() { EXPECT_EQ_HEX(Memory::ValidSize(base, 0x40000001), range.size); EXPECT_EQ_HEX(Memory::ValidSize(base, 0x20000001), range.size); EXPECT_EQ_HEX(Memory::ValidSize(base, 0x10000001), range.size); + + EXPECT_EQ_HEX(Memory::ValidSize(base + range.size - 0x10, 0x20000001), 0x10); } } @@ -607,6 +609,7 @@ TestItem availableTests[] = { TEST_ITEM(ParseLBN), TEST_ITEM(QuickTexHash), TEST_ITEM(CLZ), + TEST_ITEM(MemMap), TEST_ITEM(ShaderGenerators), }; From 1d413c247048911fc96bdd196aa9001e5417c53e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 19:43:26 -0700 Subject: [PATCH 018/261] Core: Limit scan for functions to end of valid RAM. Otherwise we can scan ahead and cause a memory exception. --- Core/MIPS/MIPSAnalyst.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 6e88bbf63f..71d1d7c831 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -983,7 +983,8 @@ skip: // We assume the furthest jumpback is within the func. u32 furthestJumpbackAddr = INVALIDTARGET; - for (u32 ahead = fromAddr; ahead < fromAddr + MAX_AHEAD_SCAN; ahead += 4) { + const u32 scanEnd = fromAddr + Memory::ValidSize(fromAddr, MAX_AHEAD_SCAN); + for (u32 ahead = fromAddr; ahead < scanEnd; ahead += 4) { MIPSOpcode aheadOp = Memory::Read_Instruction(ahead, true); u32 target = GetBranchTargetNoRA(ahead, aheadOp); if (target == INVALIDTARGET && ((aheadOp & 0xFC000000) == 0x08000000)) { From f8306891c5aba6aa1a7a8a6236bd97b4eb73a36a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 19:44:17 -0700 Subject: [PATCH 019/261] Windows: Avoid segfault if memory except on boot. --- Core/System.cpp | 3 ++- Windows/Debugger/Debugger_MemoryDlg.cpp | 5 ++--- Windows/EmuThread.cpp | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Core/System.cpp b/Core/System.cpp index 96d6ae5f8a..f46eaa915d 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -122,7 +122,8 @@ void UpdateUIState(GlobalUIState newState) { // Never leave the EXIT state. if (globalUIState != newState && globalUIState != UISTATE_EXIT) { globalUIState = newState; - host->UpdateDisassembly(); + if (host) + host->UpdateDisassembly(); const char *state = nullptr; switch (globalUIState) { case UISTATE_EXIT: state = "exit"; break; diff --git a/Windows/Debugger/Debugger_MemoryDlg.cpp b/Windows/Debugger/Debugger_MemoryDlg.cpp index 6532c6a6f1..b11c53425f 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.cpp +++ b/Windows/Debugger/Debugger_MemoryDlg.cpp @@ -131,9 +131,8 @@ void CMemoryDlg::searchBoxRedraw(std::vector results) { } -void CMemoryDlg::NotifyMapLoaded() -{ - if (m_hDlg) +void CMemoryDlg::NotifyMapLoaded() { + if (m_hDlg && g_symbolMap) g_symbolMap->FillSymbolListBox(symListHdl, ST_DATA); Update(); } diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index a0a8a359fa..0e373989c4 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -263,6 +263,9 @@ void MainThreadFunc() { if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(g_graphicsContext); + if (coreState == CORE_BOOT_ERROR) { + break; + } } } Core_Stop(); From d0303e2430353f398168b87def5b1c5004ed5719 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 28 Mar 2021 23:53:38 -0700 Subject: [PATCH 020/261] Savedata: Always write the file list to the SFO. Matches tests on hardware using MAKEDATA, see also #8854. --- Core/Dialog/SavedataParam.cpp | 51 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 137d272e20..c67a33e7a7 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -417,8 +417,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD u8* cryptedData = 0; int cryptedSize = 0; - u8 cryptedHash[0x10]; - memset(cryptedHash,0,0x10); + u8 cryptedHash[0x10]{}; // Encrypt save. // TODO: Is this the correct difference between MAKEDATA and MAKEDATASECURE? if (param->dataBuf.IsValid() && g_Config.bEncryptSave && secureMode) @@ -467,35 +466,35 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD sfoFile.SetValue("CATEGORY","MS",4); sfoFile.SetValue("SAVEDATA_DIRECTORY", GetSaveDir(param, saveDirName), 64); + // Always write and update the file list. // For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding - if (secureMode) { - const int FILE_LIST_COUNT_MAX = 99; - const u32 FILE_LIST_TOTAL_SIZE = sizeof(SaveSFOFileListEntry) * FILE_LIST_COUNT_MAX; - u32 tmpDataSize = 0; - SaveSFOFileListEntry *tmpDataOrig = (SaveSFOFileListEntry *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize); - SaveSFOFileListEntry *updatedList = new SaveSFOFileListEntry[FILE_LIST_COUNT_MAX]; - if (tmpDataSize != 0) - memcpy(updatedList, tmpDataOrig, std::min(tmpDataSize, FILE_LIST_TOTAL_SIZE)); - if (tmpDataSize < FILE_LIST_TOTAL_SIZE) - memset(updatedList + tmpDataSize, 0, FILE_LIST_TOTAL_SIZE - tmpDataSize); - - if (param->dataBuf.IsValid()) { - const std::string saveFilename = GetFileName(param); - for (auto entry = updatedList; entry < updatedList + FILE_LIST_COUNT_MAX; ++entry) { - if (entry->filename[0] != '\0') { - if (strncmp(entry->filename, saveFilename.c_str(), sizeof(entry->filename)) != 0) - continue; - } - - snprintf(entry->filename, sizeof(entry->filename), "%s", saveFilename.c_str()); - memcpy(entry->hash, cryptedHash, 16); - break; + const int FILE_LIST_COUNT_MAX = 99; + const u32 FILE_LIST_TOTAL_SIZE = sizeof(SaveSFOFileListEntry) * FILE_LIST_COUNT_MAX; + u32 tmpDataSize = 0; + SaveSFOFileListEntry *tmpDataOrig = (SaveSFOFileListEntry *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize); + SaveSFOFileListEntry *updatedList = new SaveSFOFileListEntry[FILE_LIST_COUNT_MAX]; + if (tmpDataSize != 0) + memcpy(updatedList, tmpDataOrig, std::min(tmpDataSize, FILE_LIST_TOTAL_SIZE)); + if (tmpDataSize < FILE_LIST_TOTAL_SIZE) + memset(updatedList + tmpDataSize, 0, FILE_LIST_TOTAL_SIZE - tmpDataSize); + // Leave a hash there and unchanged if it was already there. + if (secureMode && param->dataBuf.IsValid()) { + const std::string saveFilename = GetFileName(param); + for (auto entry = updatedList; entry < updatedList + FILE_LIST_COUNT_MAX; ++entry) { + if (entry->filename[0] != '\0') { + if (strncmp(entry->filename, saveFilename.c_str(), sizeof(entry->filename)) != 0) + continue; } + + snprintf(entry->filename, sizeof(entry->filename), "%s", saveFilename.c_str()); + memcpy(entry->hash, cryptedHash, 16); + break; } - sfoFile.SetValue("SAVEDATA_FILE_LIST", (u8 *)updatedList, FILE_LIST_TOTAL_SIZE, (int)FILE_LIST_TOTAL_SIZE); - delete[] updatedList; } + sfoFile.SetValue("SAVEDATA_FILE_LIST", (u8 *)updatedList, FILE_LIST_TOTAL_SIZE, (int)FILE_LIST_TOTAL_SIZE); + delete[] updatedList; + // Init param with 0. This will be used to detect crypted save or not on loading u8 *tmpData = new u8[128]; memset(tmpData, 0, 128); From fe83f21df579b6e07af5bdf1c0bc12b80420c066 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 29 Mar 2021 00:21:26 -0700 Subject: [PATCH 021/261] PPGe: Remove ENTR hack, fix string concat. Sanitize first, then concatenate. This replicates the firmware behavior nicely. --- Core/Dialog/PSPSaveDialog.cpp | 4 +++- Core/Util/PPGeDraw.cpp | 10 +--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index a42d4389f5..34811f4fc6 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -26,6 +26,7 @@ #include #include "Common/Data/Text/I18n.h" +#include "Common/Data/Encoding/Utf8.h" #include "Common/Thread/ThreadUtil.h" #include "Common/File/FileUtil.h" @@ -541,7 +542,8 @@ void PSPSaveDialog::DisplaySaveDataInfo2(bool showNewData) { s64 sizeK = data_size / 1024; PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, 0.5f); - std::string saveinfoTxt = StringFromFormat("%.128s\n%s %s\n%lld KB", save_title, date_year, hour_time, sizeK); + std::string title = SanitizeUTF8(std::string(save_title, strnlen(save_title, 128))); + std::string saveinfoTxt = StringFromFormat("%s\n%s %s\n%lld KB", title.c_str(), date_year, hour_time, sizeK); PPGeDrawText(saveinfoTxt.c_str(), 8, 200, textStyle); } diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index da3726ec23..a65608775b 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -955,15 +955,7 @@ static void PPGeDecimateTextImages(int age) { } static std::string PPGeSanitizeText(const std::string &text) { - // Seen in Ratchet & Clank - Secret Agent. To match the output of the real thing, we have to remove - // both the overlong encoding and "ENTR", whatever that is. If we just let SanitizeUTF8 remove - // the overlong null, the rest of the string is missing in the bottom left corner (save size, etc). - // It doesn't seem to be using sceCcc. - // Note how the double "" is required in the middle of the string to end the \x80 constant (otherwise it takes E). - // This behavior doesn't replicate within other games, so it may be a game bug workaround. - std::string str = ReplaceAll(text, "\xC0\x80""ENTR", ""); - // Then SanitizeUTF8 is needed to get rid of various other overlong encodings. - return SanitizeUTF8(str); + return SanitizeUTF8(text); } void PPGeDrawText(const char *text, float x, float y, const PPGeStyle &style) { From 6babae0886e4a5b4ad6e96c770bdb43a63cd90cd Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Tue, 30 Mar 2021 08:06:08 +0700 Subject: [PATCH 022/261] Fix Window size issue #14317 --- Windows/MainWindow.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 170470094a..d01074b92b 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -484,7 +484,6 @@ namespace MainWindow BOOL Show(HINSTANCE hInstance) { hInst = hInstance; // Store instance handle in our global variable. RECT rc = DetermineWindowRectangle(); - SavePosition(); u32 style = WS_OVERLAPPEDWINDOW; From ee641c1ed1d8328efec90b7bdf7a2a52172fc393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 30 Mar 2021 09:29:14 +0200 Subject: [PATCH 023/261] yet another gradle update --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c8274d0b58..c9644d8802 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:4.1.2' + classpath 'com.android.tools.build:gradle:4.1.3' } } From e496c5e8cc03e327c586d12084e6554dcdbbc628 Mon Sep 17 00:00:00 2001 From: Stefano B <7770673-Linblow@users.noreply.gitlab.com> Date: Tue, 30 Mar 2021 23:15:49 +0200 Subject: [PATCH 024/261] Set ent_top/ent_size/stub_top/stub_size of SceModule --- Core/HLE/sceKernelModule.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index b6b270d916..b6d73cc023 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1431,8 +1431,14 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load u8 unknown2; }; + module->nm.ent_top = modinfo->libent; + module->nm.ent_size = modinfo->libentend - modinfo->libent; + module->nm.stub_top = modinfo->libstub; + module->nm.stub_size = modinfo->libstubend - modinfo->libstub; + const u32_le *entPos = (u32_le *)Memory::GetPointer(modinfo->libent); const u32_le *entEnd = (u32_le *)Memory::GetPointer(modinfo->libentend); + for (int m = 0; entPos < entEnd; ++m) { const PspLibEntEntry *ent = (const PspLibEntEntry *)entPos; entPos += ent->size; From 91bc56edd5c0314b3b6c46b51de99d5346e4f188 Mon Sep 17 00:00:00 2001 From: Tien Khoa Date: Thu, 1 Apr 2021 11:18:06 +0200 Subject: [PATCH 025/261] feat: reduceHash configuration --- Core/TextureReplacer.cpp | 79 ++++++++++++++++++++++++++++++++++++---- Core/TextureReplacer.h | 9 ++++- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 8969267b67..3f1134a9ad 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -77,10 +77,12 @@ bool TextureReplacer::LoadIni() { aliases_.clear(); hashranges_.clear(); filtering_.clear(); + reducehashranges_.clear(); allowVideo_ = false; ignoreAddress_ = false; reduceHash_ = false; + reduceHashGlobalValue = 0.5; // Prevents dumping the mipmaps. ignoreMipmap_ = false; @@ -192,6 +194,14 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { } } + if (ini.HasSection("reducehashranges")) { + auto reducehashranges = ini.GetOrCreateSection("reducehashranges")->ToMap(); + // Format: w,h = reducehashvalues + for (const auto& item : reducehashranges) { + ParseReduceHashRange(item.first, item.second); + } + } + return true; } @@ -247,6 +257,39 @@ void TextureReplacer::ParseFiltering(const std::string &key, const std::string & } } +void TextureReplacer::ParseReduceHashRange(const std::string& key, const std::string& value) { + std::vector keyParts; + SplitString(key, ',', keyParts); + std::vector valueParts; + SplitString(value, ',', valueParts); + + if (keyParts.size() != 2 || valueParts.size() != 1) { + ERROR_LOG(G3D, "Ignoring invalid reducehashrange %s = %s, expecting w,h = reducehashvalue", key.c_str(), value.c_str()); + return; + } + + u32 forW; + u32 forH; + if (!TryParse(keyParts[0], &forW) || !TryParse(keyParts[1], &forH)) { + ERROR_LOG(G3D, "Ignoring invalid reducehashrange %s = %s, key format is 512,512", key.c_str(), value.c_str()); + return; + } + + float rhashvalue; + if (!TryParse(valueParts[0], &rhashvalue)) { + ERROR_LOG(G3D, "Ignoring invalid reducehashrange %s = %s, value format is 0.5", key.c_str(), value.c_str()); + return; + } + + if (rhashvalue == 0) { + ERROR_LOG(G3D, "Ignoring invalid hashrange %s = %s, reducehashvalue can't be 0", key.c_str(), value.c_str()); + return; + } + + const u64 reducerangeKey = ((u64)forW << 16) | forH; + reducehashranges_[reducerangeKey] = rhashvalue; +} + u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV) { _dbg_assert_msg_(enabled_, "Replacement not enabled"); @@ -258,9 +301,10 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } const u8 *checkp = Memory::GetPointer(addr); - float reduceHashSize = 1.0; - if (reduceHash_) - reduceHashSize = 0.5; + if (reduceHash_) { + reduceHashSize = LookupReduceHashRange(w, h); + // default to reduceHashGlobalValue which default is 0.5 + } if (bufw <= w) { // We can assume the data is contiguous. These are the total used pixels. const u32 totalPixels = bufw * h + (w - bufw); @@ -344,7 +388,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, } for (int i = 0; i < MAX_MIP_LEVELS; ++i) { - const std::string hashfile = LookupHashFile(cachekey, hash, i); + const std::string hashfile = LookupHashFile(cachekey, hash, i, w, h); const std::string filename = basePath_ + hashfile; if (hashfile.empty() || !File::Exists(filename)) { // Out of valid mip levels. Bail out. @@ -428,7 +472,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl return; } - std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level); + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level, w, h); const std::string filename = basePath_ + hashfile; const std::string saveFilename = basePath_ + NEW_TEXTURE_DIR + hashfile; @@ -594,7 +638,7 @@ bool TextureReplacer::FindFiltering(u64 cachekey, u32 hash, TextureFiltering *fo return false; } -std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { +std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h) { ReplacementAliasKey key(cachekey, hash, level); auto alias = LookupWildcard(aliases_, key, cachekey, hash, ignoreAddress_); if (alias != aliases_.end()) { @@ -602,10 +646,10 @@ std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { return alias->second; } - return HashName(cachekey, hash, level) + ".png"; + return HashName(cachekey, hash, level, w, h) + ".png"; } -std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { +std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level, int w, int h) { char hashname[16 + 8 + 1 + 11 + 1] = {}; if (level > 0) { snprintf(hashname, sizeof(hashname), "%016llx%08x_%d", cachekey, hash, level); @@ -613,6 +657,13 @@ std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { snprintf(hashname, sizeof(hashname), "%016llx%08x", cachekey, hash); } + if ((reduceHash_) && (reduceHashSize != reduceHashGlobalValue)) + { + // if a reducehashrange is specified, add a prefix with their dimension to prevent overwriting dump with the global reducehash value ex : 128x256_hashname.png. + // Add only a prefix for value that are different to the reducehashglobalvalue + return std::to_string(w) + "x" + std::to_string(h) + "_" + hashname; + } + return hashname; } @@ -629,6 +680,18 @@ bool TextureReplacer::LookupHashRange(u32 addr, int &w, int &h) { return false; } +float TextureReplacer::LookupReduceHashRange(int& w, int& h) { + const u64 reducerangeKey = ((u64)w << 16) | h; + auto range = reducehashranges_.find(reducerangeKey); + if (range != reducehashranges_.end()) { + float rhv = range->second; + return rhv; + } + else { + return reduceHashGlobalValue; + } +} + void ReplacedTexture::Load(int level, void *out, int rowPitch) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 46d67037ed..8f159a3f7d 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -195,9 +195,11 @@ protected: bool LoadIniValues(IniFile &ini, bool isOverride = false); void ParseHashRange(const std::string &key, const std::string &value); void ParseFiltering(const std::string &key, const std::string &value); + void ParseReduceHashRange(const std::string& key, const std::string& value); //Banh-Canh Parse reduceHash settings bool LookupHashRange(u32 addr, int &w, int &h); - std::string LookupHashFile(u64 cachekey, u32 hash, int level); - std::string HashName(u64 cachekey, u32 hash, int level); + float LookupReduceHashRange(int& w, int& h); //Banh-Canh lookup ranges + std::string LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h); //Banh-Canh + std::string HashName(u64 cachekey, u32 hash, int level, int w, int h); // Banh-Canh void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); SimpleBuf saveBuf; @@ -205,12 +207,15 @@ protected: bool allowVideo_ = false; bool ignoreAddress_ = false; bool reduceHash_ = false; + float reduceHashSize = 1.0; //Banh-Canh default value + float reduceHashGlobalValue = 0.5; //Banh-Canh Global value for textures dump pngs of all sizes bool ignoreMipmap_ = false; std::string gameID_; std::string basePath_; ReplacedTextureHash hash_ = ReplacedTextureHash::QUICK; typedef std::pair WidthHeightPair; std::unordered_map hashranges_; + std::unordered_map reducehashranges_; //Banh-Canh std::unordered_map aliases_; std::unordered_map filtering_; From d27e073bf98350a2717647e11092c18e88e47390 Mon Sep 17 00:00:00 2001 From: Tien Khoa Date: Thu, 1 Apr 2021 13:29:47 +0200 Subject: [PATCH 026/261] fix: cleaned up my comment --- Core/TextureReplacer.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 8f159a3f7d..8b26f5b398 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -195,11 +195,11 @@ protected: bool LoadIniValues(IniFile &ini, bool isOverride = false); void ParseHashRange(const std::string &key, const std::string &value); void ParseFiltering(const std::string &key, const std::string &value); - void ParseReduceHashRange(const std::string& key, const std::string& value); //Banh-Canh Parse reduceHash settings + void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int &w, int &h); - float LookupReduceHashRange(int& w, int& h); //Banh-Canh lookup ranges - std::string LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h); //Banh-Canh - std::string HashName(u64 cachekey, u32 hash, int level, int w, int h); // Banh-Canh + float LookupReduceHashRange(int& w, int& h); + std::string LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h); + std::string HashName(u64 cachekey, u32 hash, int level, int w, int h); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); SimpleBuf saveBuf; @@ -207,15 +207,15 @@ protected: bool allowVideo_ = false; bool ignoreAddress_ = false; bool reduceHash_ = false; - float reduceHashSize = 1.0; //Banh-Canh default value - float reduceHashGlobalValue = 0.5; //Banh-Canh Global value for textures dump pngs of all sizes + float reduceHashSize = 1.0; // default value with reduceHash to false + float reduceHashGlobalValue = 0.5; // Global value for textures dump pngs of all sizes, 0.5 by default but can be set in textures.ini bool ignoreMipmap_ = false; std::string gameID_; std::string basePath_; ReplacedTextureHash hash_ = ReplacedTextureHash::QUICK; typedef std::pair WidthHeightPair; std::unordered_map hashranges_; - std::unordered_map reducehashranges_; //Banh-Canh + std::unordered_map reducehashranges_; std::unordered_map aliases_; std::unordered_map filtering_; From 14537e05a9dcac811a52318c49fae4e17628229d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 1 Apr 2021 21:29:16 -0700 Subject: [PATCH 027/261] UI: Fix savedata screen sorting. --- UI/SavedataScreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index 245897b8f5..b61fe465ae 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -352,6 +352,7 @@ SavedataBrowser::SavedataBrowser(std::string path, UI::LayoutParams *layoutParam } void SavedataBrowser::Update() { + LinearLayout::Update(); if (searchPending_) { searchPending_ = false; From e3228ca1b51682e39a46e8b8bc293bb74bd6dc00 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 2 Apr 2021 02:07:15 +0700 Subject: [PATCH 028/261] Use a function to check for loopback address --- Core/HLE/proAdhoc.cpp | 7 ++++++- Core/HLE/proAdhoc.h | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 98891072eb..3e041429a9 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1897,6 +1897,10 @@ bool isPrivateIP(uint32_t ip) { return false; } +bool isLoopbackIP(uint32_t ip) { + return ((uint8_t*)&ip)[0] == 0x7f; +} + void getLocalMac(SceNetEtherAddr * addr){ // Read MAC Address from config uint8_t mac[ETHER_ADDR_LEN] = {0}; @@ -2143,8 +2147,9 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ // If Server is at localhost Try to Bind socket to specific adapter before connecting to prevent 2nd instance being recognized as already existing 127.0.0.1 by AdhocServer // (may not works in WinXP/2003 for IPv4 due to "Weak End System" model) - if (((uint8_t*)&g_adhocServerIP.in.sin_addr.s_addr)[0] == 0x7f) { // (serverIp.S_un.S_un_b.s_b1 == 0x7f) + if (isLoopbackIP(g_adhocServerIP.in.sin_addr.s_addr)) { int on = 1; + // Not sure what is this SO_DONTROUTE supposed to fix, but i do remembered there were issue related to multiple-instances without SO_DONTROUTE, but forgot how to reproduce it :( setsockopt(metasocket, SOL_SOCKET, SO_DONTROUTE, (const char*)&on, sizeof(on)); setSockReuseAddrPort(metasocket); diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 4dae56e6c5..729018f63c 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -1279,6 +1279,11 @@ uint32_t getLocalIp(int sock); */ bool isPrivateIP(uint32_t ip); +/* + * Check if an IP (big-endian/network order) is Loopback IP + */ +bool isLoopbackIP(uint32_t ip); + /* * Get Number of bytes available in buffer to be Received * @param sock fd From e508885cc475bb38331b32f1bca23992a3e12af1 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 2 Apr 2021 05:07:25 +0700 Subject: [PATCH 029/261] Show the socket error code when failed to connect to adhoc server --- Core/HLE/proAdhoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 3e041429a9..4a1089fbc2 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -2199,7 +2199,7 @@ int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){ } if (IsSocketReady(metasocket, false, true) <= 0) { ERROR_LOG(SCENET, "Socket error (%i) when connecting to AdhocServer [%s/%s:%u]", errorcode, g_Config.proAdhocServer.c_str(), ip2str(g_adhocServerIP.in.sin_addr).c_str(), ntohs(g_adhocServerIP.in.sin_port)); - host->NotifyUserMessage(n->T("Failed to connect to Adhoc Server"), 1.0f, 0x0000ff); + host->NotifyUserMessage(std::string(n->T("Failed to connect to Adhoc Server")) + " (" + std::string(n->T("Error")) + ": " + std::to_string(errorcode) + ")", 1.0f, 0x0000ff); return iResult; } } From 7336ec6a81a9fb26358861dc0d675c864994d468 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 2 Apr 2021 12:14:54 +0700 Subject: [PATCH 030/261] Shows PSP error code as hex to be easier to find --- Core/HLE/sceNet.cpp | 4 ++-- Core/HLE/sceNetAdhoc.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 193a3e04c9..3d1f8e3fb8 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -141,7 +141,7 @@ static void __ApctlState(u64 userdata, int cyclesLate) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error); if (waitID == 0 || error != 0) { - WARN_LOG(SCENET, "sceNetApctl State WaitID(%i) on Thread(%i) already woken up? (error: %d)", uid, threadID, error); + WARN_LOG(SCENET, "sceNetApctl State WaitID(%i) on Thread(%i) already woken up? (error: %08x)", uid, threadID, error); return; } @@ -151,7 +151,7 @@ static void __ApctlState(u64 userdata, int cyclesLate) { } __KernelResumeThreadFromWait(threadID, result); - DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %d) Result (%08x) of sceNetApctl - Event: %d, State: %d", waitID, error, (int)result, event, netApctlState); + DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %08x) Result (%08x) of sceNetApctl - Event: %d, State: %d", waitID, error, (int)result, event, netApctlState); } // Used to change Apctl State after a delay and before executing callback mipscall (since we don't have beforeAction) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index c88a11dd60..0899f1f5ae 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -250,7 +250,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error); if (waitID == 0 || error != 0) { - WARN_LOG(SCENET, "sceNetAdhocctl Socket WaitID(%i) on Thread(%i) already woken up? (error: %d)", uid, threadID, error); + WARN_LOG(SCENET, "sceNetAdhocctl Socket WaitID(%i) on Thread(%i) already woken up? (error: %08x)", uid, threadID, error); return; } @@ -316,7 +316,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) { u32 waitVal = __KernelGetWaitValue(threadID, error); __KernelResumeThreadFromWait(threadID, result); - DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %d) Result (%08x) of sceNetAdhocctl - Opcode: %d, State: %d", waitID, error, (int)result, waitVal, adhocctlState); + DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %08x) Result (%08x) of sceNetAdhocctl - Opcode: %d, State: %d", waitID, error, (int)result, waitVal, adhocctlState); // We are done with this request adhocctlRequests.erase(uid); @@ -332,7 +332,7 @@ static void __AdhocctlState(u64 userdata, int cyclesLate) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error); if (waitID == 0 || error != 0) { - WARN_LOG(SCENET, "sceNetAdhocctl State WaitID(%i) on Thread(%i) already woken up? (error: %d)", uid, threadID, error); + WARN_LOG(SCENET, "sceNetAdhocctl State WaitID(%i) on Thread(%i) already woken up? (error: %08x)", uid, threadID, error); return; } @@ -348,7 +348,7 @@ static void __AdhocctlState(u64 userdata, int cyclesLate) { } __KernelResumeThreadFromWait(threadID, result); - DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %d) Result (%08x) of sceNetAdhocctl - Event: %d, State: %d", waitID, error, (int)result, event, adhocctlState); + DEBUG_LOG(SCENET, "Returning (WaitID: %d, error: %08x) Result (%08x) of sceNetAdhocctl - Event: %d, State: %d", waitID, error, (int)result, event, adhocctlState); } // Used to simulate blocking on metasocket when send OP code to AdhocServer @@ -815,7 +815,7 @@ static void __AdhocSocketNotify(u64 userdata, int cyclesLate) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_NET, error); if (waitID == 0 || error != 0) { - WARN_LOG(SCENET, "sceNetAdhoc Socket WaitID(%i) on Thread(%i) already woken up? (error: %d)", uid, threadID, error); + WARN_LOG(SCENET, "sceNetAdhoc Socket WaitID(%i) on Thread(%i) already woken up? (error: %08x)", uid, threadID, error); return; } @@ -901,7 +901,7 @@ static void __AdhocSocketNotify(u64 userdata, int cyclesLate) { } __KernelResumeThreadFromWait(threadID, result); - DEBUG_LOG(SCENET, "Returning (ThreadId: %d, WaitID: %d, error: %d) Result (%08x) of sceNetAdhoc[%d] - SocketID: %d", threadID, waitID, error, (int)result, req.type, req.id); + DEBUG_LOG(SCENET, "Returning (ThreadId: %d, WaitID: %d, error: %08x) Result (%08x) of sceNetAdhoc[%d] - SocketID: %d", threadID, waitID, error, (int)result, req.type, req.id); // We are done with this socket adhocSocketRequests.erase(userdata); From 206ab4345e70e3e3b380c12ef046c592a7e700d6 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 2 Apr 2021 12:17:10 +0700 Subject: [PATCH 031/261] Attempts to reconnect to Adhoc Server only when Creating/Joining/Connecting to a group or Scanning for groups, instead of on 2 seconds interval. --- Core/HLE/proAdhoc.cpp | 5 ++- Core/HLE/proAdhoc.h | 1 + Core/HLE/sceNetAdhoc.cpp | 88 ++++++++++++++-------------------------- 3 files changed, 36 insertions(+), 58 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 4a1089fbc2..2bd396ebf2 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -85,6 +85,7 @@ SceNetAdhocctlPeerInfo * friends = NULL; SceNetAdhocctlScanInfo * networks = NULL; SceNetAdhocctlScanInfo * newnetworks = NULL; u64 adhocctlStartTime = 0; +bool isAdhocctlNeedLogin = false; bool isAdhocctlBusy = false; int adhocctlState = ADHOCCTL_STATE_DISCONNECTED; int adhocctlCurrentMode = ADHOCCTL_MODE_NONE; @@ -1371,7 +1372,7 @@ int friendFinder(){ //_acquireNetworkLock(); // Reconnect when disconnected while Adhocctl is still inited - if (metasocket == (int)INVALID_SOCKET && netAdhocctlInited) { + if (metasocket == (int)INVALID_SOCKET && netAdhocctlInited && isAdhocctlNeedLogin) { if (g_Config.bEnableWlan) { if (initNetwork(&product_code) == 0) { networkInited = true; @@ -1389,6 +1390,8 @@ int friendFinder(){ } } } + // Prevent retrying to Login again unless it was on demand + isAdhocctlNeedLogin = false; if (networkInited) { // Ping Server diff --git a/Core/HLE/proAdhoc.h b/Core/HLE/proAdhoc.h index 729018f63c..6dce5865b1 100644 --- a/Core/HLE/proAdhoc.h +++ b/Core/HLE/proAdhoc.h @@ -927,6 +927,7 @@ extern bool friendFinderRunning; extern SceNetAdhocctlPeerInfo * friends; extern SceNetAdhocctlScanInfo * networks; extern u64 adhocctlStartTime; +extern bool isAdhocctlNeedLogin; extern bool isAdhocctlBusy; extern int adhocctlState; extern int adhocctlCurrentMode; diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 0899f1f5ae..68cb58cdf5 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -269,6 +269,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) { packet.base.opcode = req.opcode; packet.group = req.group; + // Don't send any packets not in these cases (by setting the len to 0) switch (req.opcode) { case OPCODE_CONNECT: @@ -287,7 +288,8 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) { if (len > 0) { ret = SOCKET_ERROR; sockerr = EAGAIN; - if (IsSocketReady(metasocket, false, true) > 0) { + // Don't send anything yet if connection to Adhoc Server is still in progress + if (!isAdhocctlNeedLogin && IsSocketReady(metasocket, false, true) > 0) { ret = send(metasocket, (const char*)&packet, len, MSG_NOSIGNAL); sockerr = errno; // Successfully Sent or Connection has been closed or Connection failure occurred @@ -300,6 +302,7 @@ static void __AdhocctlNotify(u64 userdata, int cyclesLate) { } } + // Retry until successfully sent. Login packet sent after successfully connected to Adhoc Server (indicated by networkInited), so we're not sending Login again here if ((req.opcode == OPCODE_LOGIN && !networkInited) || (ret == SOCKET_ERROR && (sockerr == EAGAIN || sockerr == EWOULDBLOCK))) { u64 now = (u64)(time_now_d() * 1000000.0); if (now - adhocctlStartTime <= static_cast(adhocDefaultTimeout) + 500) { @@ -1056,6 +1059,8 @@ void __NetAdhocDoState(PointerWrap &p) { netAdhocMatchingInited = cur_netAdhocMatchingInited; netAdhocctlInited = cur_netAdhocctlInited; netAdhocInited = cur_netAdhocInited; + + isAdhocctlNeedLogin = false; } } @@ -1142,6 +1147,7 @@ static u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { adhocctlEvents.clear(); netAdhocctlInited = true; //needed for cleanup during AdhocctlTerm even when it failed to connect to Adhoc Server (since it's being faked as success) + isAdhocctlNeedLogin = true; // Create fake PSP Thread for callback // TODO: Should use a separated threads for friendFinder, matchingEvent, and matchingInput and created on AdhocctlInit & AdhocMatchingStart instead of here @@ -1157,7 +1163,7 @@ static u32 sceNetAdhocctlInit(int stackSize, int prio, u32 productAddr) { friendFinderThread = std::thread(friendFinder); } - // Need to make sure to be connected to adhoc server before returning to prevent GTA VCS failed to create/join a group and unable to see any game room + // Need to make sure to be connected to Adhoc Server (indicated by networkInited) before returning to prevent GTA VCS failed to create/join a group and unable to see any game room int us = adhocDefaultDelay; if (g_Config.bEnableWlan && !networkInited) { AdhocctlRequest dummyreq = { OPCODE_LOGIN, {0} }; @@ -2092,6 +2098,7 @@ int sceNetAdhocctlScan() { // Only scan when in Disconnected state, otherwise AdhocServer will kick you out if (adhocctlState == ADHOCCTL_STATE_DISCONNECTED && !isAdhocctlBusy) { isAdhocctlBusy = true; + isAdhocctlNeedLogin = true; adhocctlState = ADHOCCTL_STATE_SCANNING; adhocctlCurrentMode = ADHOCCTL_MODE_NORMAL; @@ -2101,24 +2108,12 @@ int sceNetAdhocctlScan() { networks = NULL; peerlock.unlock(); - // Prepare Scan Request Packet - uint8_t opcode = OPCODE_SCAN; - - // Send Scan Request Packet, may failed with socket error 10054/10053 if someone else with the same IP already connected to AdHoc Server (the server might need to be modified to differentiate MAC instead of IP) - int iResult = send(metasocket, (char *)&opcode, 1, MSG_NOSIGNAL); - int error = errno; - - if (iResult == SOCKET_ERROR) { - if (error != EAGAIN && error != EWOULDBLOCK) { - ERROR_LOG(SCENET, "Socket error (%i) when sending", error); - adhocctlState = ADHOCCTL_STATE_DISCONNECTED; - //if (error == ECONNABORTED || error == ECONNRESET || error == ENOTCONN) return ERROR_NET_ADHOCCTL_NOT_INITIALIZED; // A case where it need to reconnect to AdhocServer - return hleLogError(SCENET, ERROR_NET_ADHOCCTL_BUSY, "busy"); - } - else if (friendFinderRunning) { - AdhocctlRequest req = { OPCODE_SCAN, {0} }; - return WaitBlockingAdhocctlSocket(req, us, "adhocctl scan"); - } + if (friendFinderRunning) { + AdhocctlRequest req = { OPCODE_SCAN, {0} }; + return WaitBlockingAdhocctlSocket(req, us, "adhocctl scan"); + } + else { + adhocctlState = ADHOCCTL_STATE_DISCONNECTED; } // Return Success and let friendFinder thread to notify the handler when scan completed @@ -2603,36 +2598,28 @@ int NetAdhocctl_Create(const char* groupName) { // Disconnected State if (adhocctlState == ADHOCCTL_STATE_DISCONNECTED && !isAdhocctlBusy) { isAdhocctlBusy = true; + isAdhocctlNeedLogin = true; // Set Network Name - if (groupNameStruct != NULL) parameter.group_name = *groupNameStruct; + if (groupNameStruct != NULL) + parameter.group_name = *groupNameStruct; // Reset Network Name - else memset(¶meter.group_name, 0, sizeof(parameter.group_name)); + else + memset(¶meter.group_name, 0, sizeof(parameter.group_name)); - // Prepare Connect Packet - SceNetAdhocctlConnectPacketC2S packet; + // Set HUD Connection Status + //setConnectionStatus(1); - // Clear Packet Memory - memset(&packet, 0, sizeof(packet)); - - // Set Packet Opcode - packet.base.opcode = OPCODE_CONNECT; - - // Set Target Group - if (groupNameStruct != NULL) packet.group = *groupNameStruct; - - // Acquire Network Lock - - // Send Packet - int iResult = send(metasocket, (const char*)&packet, sizeof(packet), MSG_NOSIGNAL); - int error = errno; - adhocctlStartTime = (u64)(time_now_d() * 1000000.0); - - if (iResult == SOCKET_ERROR && error != EAGAIN && error != EWOULDBLOCK) { - ERROR_LOG(SCENET, "Socket error (%i) when sending", error); - - //Faking success, to prevent Full Auto 2 from freezing while Initializing Network + // Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session + int us = adhocDefaultDelay; + if (friendFinderRunning) { + AdhocctlRequest req = { OPCODE_CONNECT, parameter.group_name }; + return WaitBlockingAdhocctlSocket(req, us, "adhocctl connect"); + } + //Faking success, to prevent Full Auto 2 from freezing while Initializing Network + else { + adhocctlStartTime = (u64)(time_now_d() * 1000000.0); if (adhocctlCurrentMode == ADHOCCTL_MODE_GAMEMODE) { adhocctlState = ADHOCCTL_STATE_GAMEMODE; notifyAdhocctlHandlers(ADHOCCTL_EVENT_GAME, 0); @@ -2645,19 +2632,6 @@ int NetAdhocctl_Create(const char* groupName) { } } - // Free Network Lock - - // Set HUD Connection Status - //setConnectionStatus(1); - - // Wait for Status to be connected to prevent Ford Street Racing from Failed to create game session - int us = adhocDefaultDelay; - if (adhocctlState != ADHOCCTL_STATE_CONNECTED && adhocctlState != ADHOCCTL_STATE_GAMEMODE && iResult == SOCKET_ERROR && friendFinderRunning) { - AdhocctlRequest req = { OPCODE_CONNECT, {0} }; - if (groupNameStruct != NULL) req.group = *groupNameStruct; - return WaitBlockingAdhocctlSocket(req, us, "adhocctl connect"); - } - hleEatMicro(us); // Return Success // FIXME: When tested using JPCSP + official prx files it seems sceNetAdhocctlCreate switching to a different thread for at least 100ms after returning success and before executing the next line. From 36ba5e0ef0fe87227e13fecc3da166e305bf2fd2 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 2 Apr 2021 12:48:40 +0700 Subject: [PATCH 032/261] Prevent flooding the logs with repeated attempts of Adding/Removing port mapping due to failure in the middle of UPnP initialization, as it needs to be reinitialized. --- Core/Util/PortManager.cpp | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/Core/Util/PortManager.cpp b/Core/Util/PortManager.cpp index 06e1968716..c01d2ab86e 100644 --- a/Core/Util/PortManager.cpp +++ b/Core/Util/PortManager.cpp @@ -181,8 +181,10 @@ bool PortManager::Initialize(const unsigned int timeout) { } ERROR_LOG(SCENET, "PortManager - upnpDiscover failed (error: %i) or No UPnP device detected", error); - auto n = GetI18NCategory("Networking"); - host->NotifyUserMessage(n->T("Unable to find UPnP device"), 2.0f, 0x0000ff); + if (g_Config.bEnableUPnP) { + auto n = GetI18NCategory("Networking"); + host->NotifyUserMessage(n->T("Unable to find UPnP device"), 2.0f, 0x0000ff); + } m_InitState = UPNP_INITSTATE_NONE; #endif // WITH_UPNP return false; @@ -197,13 +199,18 @@ bool PortManager::Add(const char* protocol, unsigned short port, unsigned short char port_str[16]; char intport_str[16]; int r; + auto n = GetI18NCategory("Networking"); if (intport == 0) intport = port; INFO_LOG(SCENET, "PortManager::Add(%s, %d, %d)", protocol, port, intport); if (urls == NULL || urls->controlURL == NULL || urls->controlURL[0] == '\0') { - if (g_Config.bEnableUPnP) WARN_LOG(SCENET, "PortManager::Add - the init was not done !"); + if (g_Config.bEnableUPnP) { + WARN_LOG(SCENET, "PortManager::Add - the init was not done !"); + host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + } + Terminate(); return false; } sprintf(port_str, "%d", port); @@ -229,8 +236,9 @@ bool PortManager::Add(const char* protocol, unsigned short port, unsigned short { ERROR_LOG(SCENET, "PortManager - AddPortMapping failed (error: %i)", r); if (r == UPNPCOMMAND_HTTP_ERROR) { - auto n = GetI18NCategory("Networking"); - host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + if (g_Config.bEnableUPnP) { + host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + } Terminate(); // Most of the time errors occurred because the router is no longer reachable (ie. changed networks) so we should invalidate the state to prevent further lags due to timeouts return false; } @@ -248,11 +256,16 @@ bool PortManager::Add(const char* protocol, unsigned short port, unsigned short bool PortManager::Remove(const char* protocol, unsigned short port) { #ifdef WITH_UPNP char port_str[16]; + auto n = GetI18NCategory("Networking"); INFO_LOG(SCENET, "PortManager::Remove(%s, %d)", protocol, port); if (urls == NULL || urls->controlURL == NULL || urls->controlURL[0] == '\0') { - if (g_Config.bEnableUPnP) WARN_LOG(SCENET, "PortManager::Remove - the init was not done !"); + if (g_Config.bEnableUPnP) { + WARN_LOG(SCENET, "PortManager::Remove - the init was not done !"); + host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + } + Terminate(); return false; } sprintf(port_str, "%d", port); @@ -261,8 +274,9 @@ bool PortManager::Remove(const char* protocol, unsigned short port) { { ERROR_LOG(SCENET, "PortManager - DeletePortMapping failed (error: %i)", r); if (r == UPNPCOMMAND_HTTP_ERROR) { - auto n = GetI18NCategory("Networking"); - host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + if (g_Config.bEnableUPnP) { + host->NotifyUserMessage(n->T("UPnP need to be reinitialized"), 2.0f, 0x0000ff); + } Terminate(); // Most of the time errors occurred because the router is no longer reachable (ie. changed networks) so we should invalidate the state to prevent further lags due to timeouts return false; } From 5dbf393e2066da6f8826ab7791b753b3b3496ae3 Mon Sep 17 00:00:00 2001 From: Banh-Canh Date: Sat, 3 Apr 2021 17:56:28 +0200 Subject: [PATCH 033/261] revert filename prefix for reducehashranges --- Core/TextureReplacer.cpp | 19 +++++++------------ Core/TextureReplacer.h | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 3f1134a9ad..32a54c37a2 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -388,7 +388,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, } for (int i = 0; i < MAX_MIP_LEVELS; ++i) { - const std::string hashfile = LookupHashFile(cachekey, hash, i, w, h); + const std::string hashfile = LookupHashFile(cachekey, hash, i); const std::string filename = basePath_ + hashfile; if (hashfile.empty() || !File::Exists(filename)) { // Out of valid mip levels. Bail out. @@ -472,7 +472,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl return; } - std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level, w, h); + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level); const std::string filename = basePath_ + hashfile; const std::string saveFilename = basePath_ + NEW_TEXTURE_DIR + hashfile; @@ -638,7 +638,7 @@ bool TextureReplacer::FindFiltering(u64 cachekey, u32 hash, TextureFiltering *fo return false; } -std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h) { +std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { ReplacementAliasKey key(cachekey, hash, level); auto alias = LookupWildcard(aliases_, key, cachekey, hash, ignoreAddress_); if (alias != aliases_.end()) { @@ -646,10 +646,10 @@ std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level, i return alias->second; } - return HashName(cachekey, hash, level, w, h) + ".png"; + return HashName(cachekey, hash, level) + ".png"; } -std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level, int w, int h) { +std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { char hashname[16 + 8 + 1 + 11 + 1] = {}; if (level > 0) { snprintf(hashname, sizeof(hashname), "%016llx%08x_%d", cachekey, hash, level); @@ -657,13 +657,6 @@ std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level, int w, snprintf(hashname, sizeof(hashname), "%016llx%08x", cachekey, hash); } - if ((reduceHash_) && (reduceHashSize != reduceHashGlobalValue)) - { - // if a reducehashrange is specified, add a prefix with their dimension to prevent overwriting dump with the global reducehash value ex : 128x256_hashname.png. - // Add only a prefix for value that are different to the reducehashglobalvalue - return std::to_string(w) + "x" + std::to_string(h) + "_" + hashname; - } - return hashname; } @@ -776,6 +769,8 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, std::string *genera fs << "[hashranges]\n"; fs << "\n"; fs << "[filtering]\n"; + fs << "\n"; + fs << "[reducehashranges]\n"; fs.close(); } return File::Exists(texturesDirectory + INI_FILENAME); diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 8b26f5b398..56b565356a 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -198,8 +198,8 @@ protected: void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int &w, int &h); float LookupReduceHashRange(int& w, int& h); - std::string LookupHashFile(u64 cachekey, u32 hash, int level, int w, int h); - std::string HashName(u64 cachekey, u32 hash, int level, int w, int h); + std::string LookupHashFile(u64 cachekey, u32 hash, int level); + std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); SimpleBuf saveBuf; From 7a8448614b9f9daa7069585bf0537b0cd713b090 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 4 Apr 2021 02:08:12 +0700 Subject: [PATCH 034/261] Fix crashing issue when leaving a multiplayer game room #14337 --- Core/HLE/sceNetAdhoc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 68cb58cdf5..510dd88965 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -7253,7 +7253,7 @@ int matchingInputThread(int matchingId) // TODO: The MatchingInput thread is usi // Iterate Message List int msg_count = 0; ThreadMessage* msg = context->input_stack; - for (; msg != NULL; msg = msg->next) + while (msg != NULL) { // Default Optional Data void* opt = NULL; From 428548515727e38dd8e57c4466efcd5d5fe84f3c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 16:03:21 -0700 Subject: [PATCH 035/261] Debugger: Add menu to jump to begin/end of alloc. Helpful when viewing memory. Should add a shortcut too... --- Windows/Debugger/CtrlMemView.cpp | 23 +++++++++++++++++++++++ Windows/ppsspp.rc | 3 +++ Windows/resource.h | 4 +++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 5b0e4400b8..8de34a1c81 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -533,6 +533,28 @@ void CtrlMemView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) } break; + case ID_MEMVIEW_EXTENTBEGIN: + { + std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, curAddress, 1); + uint32_t addr = curAddress; + for (MemBlockInfo info : memRangeInfo) { + addr = info.start; + } + gotoAddr(addr); + break; + } + + case ID_MEMVIEW_EXTENTEND: + { + std::vector memRangeInfo = FindMemInfoByFlag(highlightFlags_, curAddress, 1); + uint32_t addr = curAddress; + for (MemBlockInfo info : memRangeInfo) { + addr = info.start + info.size - 1; + } + gotoAddr(addr); + break; + } + case ID_MEMVIEW_COPYADDRESS: { char temp[24]; @@ -845,6 +867,7 @@ void CtrlMemView::toggleOffsetScale(CommonToggles toggle) void CtrlMemView::setHighlightType(MemBlockFlags flags) { if (highlightFlags_ != flags) { highlightFlags_ = flags; + updateStatusBarText(); redraw(); } } diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index bc7e30e064..cd0655dc24 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -679,6 +679,9 @@ BEGIN MENUITEM "Go to in Disasm", ID_MEMVIEW_GOTOINDISASM MENUITEM "Copy address", ID_MEMVIEW_COPYADDRESS MENUITEM SEPARATOR + MENUITEM "Go to Extent Begin", ID_MEMVIEW_EXTENTBEGIN + MENUITEM "Go to Extent End", ID_MEMVIEW_EXTENTEND + MENUITEM SEPARATOR MENUITEM "Copy Value (8 bit)", ID_MEMVIEW_COPYVALUE_8 MENUITEM "Copy Value (16 bit)", ID_MEMVIEW_COPYVALUE_16 MENUITEM "Copy Value (32 bit)", ID_MEMVIEW_COPYVALUE_32 diff --git a/Windows/resource.h b/Windows/resource.h index 96a4fcab50..1121a59da5 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -376,6 +376,8 @@ #define ID_FILE_DUMP_VIDEO_OUTPUT 40204 #define ID_EMULATION_CHAT 40205 #define IDC_MEMVIEW_STATUS 40206 +#define ID_MEMVIEW_EXTENTBEGIN 40207 +#define ID_MEMVIEW_EXTENTEND 40208 // Dummy option to let the buffered rendering hotkey cycle through all the options. #define ID_OPTIONS_BUFFEREDRENDERINGDUMMY 40500 @@ -388,7 +390,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 256 -#define _APS_NEXT_COMMAND_VALUE 40207 +#define _APS_NEXT_COMMAND_VALUE 40209 #define _APS_NEXT_CONTROL_VALUE 1202 #define _APS_NEXT_SYMED_VALUE 101 #endif From c88757b3e7cfd281f9147d3928f4b506ba5dc396 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 16:04:07 -0700 Subject: [PATCH 036/261] Debugger: Make memory tags longer. Need more space for better information. --- Core/Debugger/MemBlockInfo.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 5fa8c70517..c9d40de1da 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -46,7 +46,7 @@ private: uint64_t ticks = 0; uint32_t pc = 0; bool allocated = false; - char tag[32]{}; + char tag[128]{}; Slab *prev = nullptr; Slab *next = nullptr; @@ -77,7 +77,7 @@ struct PendingNotifyMem { uint32_t size; uint64_t ticks; uint32_t pc; - char tag[32]; + char tag[128]; }; static constexpr size_t MAX_PENDING_NOTIFIES = 512; @@ -199,7 +199,7 @@ void MemSlabMap::DoState(PointerWrap &p) { } void MemSlabMap::Slab::DoState(PointerWrap &p) { - auto s = p.Section("MemSlabMapSlab", 1, 2); + auto s = p.Section("MemSlabMapSlab", 1, 3); if (!s) return; @@ -208,8 +208,12 @@ void MemSlabMap::Slab::DoState(PointerWrap &p) { Do(p, ticks); Do(p, pc); Do(p, allocated); - if (s >= 2) { + if (s >= 3) { Do(p, tag); + } else if (s >= 2) { + char shortTag[32]; + Do(p, shortTag); + memcpy(tag, shortTag, sizeof(shortTag)); } else { std::string stringTag; Do(p, stringTag); From e36d09acc3061ba54f5663509bafce352b8ceaba Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 16:04:30 -0700 Subject: [PATCH 037/261] Debugger: Include filename in file IO memory tags. --- Core/HLE/sceIo.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 55ffcff2fe..16ee5c1891 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -26,6 +26,7 @@ #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" #include "Common/Serialize/SerializeSet.h" +#include "Common/StringUtils.h" #include "Core/Core.h" #include "Core/Config.h" #include "Core/ConfigValues.h" @@ -777,6 +778,14 @@ void __IoShutdown() { memStickFatCallbacks.clear(); } +static std::string IODetermineFilename(FileNode *f) { + uint64_t offset = pspFileSystem.GetSeekPos(f->handle); + if ((pspFileSystem.DevType(f->handle) & PSPDevType::BLOCK) != 0) { + return StringFromFormat("%s offset 0x%08llx", f->fullpath.c_str(), offset * 2048); + } + return StringFromFormat("%s offset 0x%08llx", f->fullpath.c_str(), offset); +} + u32 __IoGetFileHandleFromId(u32 id, u32 &outError) { FileNode *f = __IoGetFd(id, outError); @@ -1026,7 +1035,8 @@ static bool __IoRead(int &result, int id, u32 data_addr, int size, int &us) { result = SCE_KERNEL_ERROR_ILLEGAL_ADDR; return true; } else if (Memory::IsValidAddress(data_addr)) { - NotifyMemInfo(MemBlockFlags::WRITE, data_addr, size, "IoRead"); + const std::string tag = "IoRead/" + IODetermineFilename(f); + NotifyMemInfo(MemBlockFlags::WRITE, data_addr, size, tag.c_str(), tag.size()); u8 *data = (u8 *)Memory::GetPointer(data_addr); u32 validSize = Memory::ValidSize(data_addr, size); if (f->npdrm) { @@ -1162,7 +1172,8 @@ static bool __IoWrite(int &result, int id, u32 data_addr, int size, int &us) { return true; } - NotifyMemInfo(MemBlockFlags::READ, data_addr, size, "IoWrite"); + const std::string tag = "IoWrite/" + IODetermineFilename(f); + NotifyMemInfo(MemBlockFlags::READ, data_addr, size, tag.c_str(), tag.size()); bool useThread = __KernelIsDispatchEnabled() && ioManagerThreadEnabled && size > IO_THREAD_MIN_DATA_SIZE; if (useThread) { From aa89ed511177e4569115aa90f7fb73d78a33f3ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 16:56:31 -0700 Subject: [PATCH 038/261] Debugger: Include source tag in memcpys. --- Core/Debugger/MemBlockInfo.cpp | 8 ++++++++ Core/Debugger/MemBlockInfo.h | 2 ++ Core/HLE/ReplaceTables.cpp | 25 +++++++++++++++---------- Core/HLE/sceKernelInterrupt.cpp | 15 +++++++++------ GPU/GPUCommon.cpp | 5 +++-- 5 files changed, 37 insertions(+), 18 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index c9d40de1da..37734c232c 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -433,6 +433,14 @@ std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, return results; } +std::string GetMemWriteTagAt(uint32_t start, uint32_t size) { + std::vector memRangeInfo = FindMemInfoByFlag(MemBlockFlags::WRITE, start, size); + for (auto range : memRangeInfo) { + return range.tag; + } + return "none"; +} + void MemBlockInfoInit() { std::lock_guard guard(pendingMutex); pendingNotifies.reserve(MAX_PENDING_NOTIFIES); diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index e46bea8c87..4e38c8410d 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -63,6 +63,8 @@ inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, co std::vector FindMemInfo(uint32_t start, uint32_t size); std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size); +std::string GetMemWriteTagAt(uint32_t start, uint32_t size); + void MemBlockInfoInit(); void MemBlockInfoShutdown(); void MemBlockInfoDoState(PointerWrap &p); diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 992c893971..efde566c56 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -156,8 +156,9 @@ static int Replace_memcpy() { } RETURN(destPtr); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy"); + const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); return 10 + bytes / 4; // approximation } @@ -198,8 +199,9 @@ static int Replace_memcpy_jak() { currentMIPS->r[MIPS_REG_A3] = destPtr + bytes; RETURN(destPtr); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy"); + const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); return 5 + bytes * 8 + 2; // approximation. This is a slow memcpy - a byte copy loop.. } @@ -226,8 +228,9 @@ static int Replace_memcpy16() { } RETURN(destPtr); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemcpy16"); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemcpy16"); + const std::string tag = "ReplaceMemcpy16/" + GetMemWriteTagAt(srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); return 10 + bytes / 4; // approximation } @@ -264,8 +267,9 @@ static int Replace_memcpy_swizzled() { RETURN(0); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, "ReplaceMemcpySwizzle"); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, "ReplaceMemcpySwizzle"); + const std::string tag = "ReplaceMemcpySwizzle/" + GetMemWriteTagAt(srcPtr, pitch * h); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tag.c_str(), tag.size()); return 10 + (pitch * h) / 4; // approximation } @@ -292,8 +296,9 @@ static int Replace_memmove() { } RETURN(destPtr); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, "ReplaceMemmove"); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, "ReplaceMemmove"); + const std::string tag = "ReplaceMemmove/" + GetMemWriteTagAt(srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); return 10 + bytes / 4; // approximation } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index adaabd362f..161979a353 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -658,8 +658,9 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) } } - NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemcpy"); + const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); return dst; } @@ -690,8 +691,9 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) { if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { memcpy(Memory::GetPointer(dst), Memory::GetPointer(src), size); } - NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemcpy"); + const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); return dst; } @@ -790,8 +792,9 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) { memmove(Memory::GetPointer(dst), Memory::GetPointer(src), size); } - NotifyMemInfo(MemBlockFlags::READ, src, size, "KernelMemmove"); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, "KernelMemmove"); + const std::string tag = "KernelMemmove/" + GetMemWriteTagAt(src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); return 0; } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 4378047067..a6d48c123f 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2742,8 +2742,9 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { return true; } - NotifyMemInfo(MemBlockFlags::READ, src, size, "GPUMemcpy"); - NotifyMemInfo(MemBlockFlags::WRITE, dest, size, "GPUMemcpy"); + const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dest, size, tag.c_str(), tag.size()); InvalidateCache(dest, size, GPU_INVALIDATE_HINT); GPURecord::NotifyMemcpy(dest, src, size); return false; From ee749804fc44ff4049097d900a5a7b30f18f75ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:04:35 -0700 Subject: [PATCH 039/261] Debugger: Note GPU block transfer src as well. --- Core/Debugger/MemBlockInfo.cpp | 6 ++++++ GPU/GPUCommon.cpp | 7 +++++-- GPU/Software/SoftGpu.cpp | 7 +++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 37734c232c..96b18bfa52 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -438,6 +438,12 @@ std::string GetMemWriteTagAt(uint32_t start, uint32_t size) { for (auto range : memRangeInfo) { return range.tag; } + + // Fall back to alloc and texture, especially for VRAM. We prefer write above. + memRangeInfo = FindMemInfoByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size); + for (auto range : memRangeInfo) { + return range.tag; + } return "none"; } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a6d48c123f..3ca75338a3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2721,8 +2721,11 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); } - NotifyMemInfo(MemBlockFlags::READ, srcBasePtr + (srcY * srcStride + srcX) * bpp, height * srcStride * bpp, "GPUBlockTransfer"); - NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, "GPUBlockTransfer"); + const uint32_t src = srcBasePtr + (srcY * srcStride + srcX) * bpp; + const uint32_t srcSize = height * srcStride * bpp; + const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize); + NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, tag.c_str(), tag.size()); // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. cyclesExecuted += ((height * width * bpp) * 16) / 10; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index a04369a723..26ef1cbbb9 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -653,8 +653,11 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff) { memcpy(dst, src, width * bpp); } - NotifyMemInfo(MemBlockFlags::READ, srcBasePtr + (srcY * srcStride + srcX) * bpp, height * srcStride * bpp, "GPUBlockTransfer"); - NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, "GPUBlockTransfer"); + const uint32_t src = srcBasePtr + (srcY * srcStride + srcX) * bpp; + const uint32_t srcSize = height * srcStride * bpp; + const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize); + NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, tag.c_str(), tag.size()); // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. cyclesExecuted += ((height * width * bpp) * 16) / 10; From 8a9979b50e09c4535993972bc681a87516dcc424 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:11:34 -0700 Subject: [PATCH 040/261] Debugger: Include framebuffer in framebuf pack tag. --- GPU/Common/FramebufferManagerCommon.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 685a9f0934..349e244747 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2179,7 +2179,9 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int if (destPtr) { draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride, "PackFramebufferSync_"); - NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, "FramebufferPack"); + char tag[128]; + size_t len = snprintf(tag, sizeof(tag), "FramebufferPack/%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->format)); + NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, tag, len); } else { ERROR_LOG(G3D, "PackFramebufferSync_: Tried to readback to bad address %08x (stride = %d)", fb_address + dstByteOffset, vfb->fb_stride); } From e1e830c3b0b83ee7a4d81fc27e12f49a88531f6e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:27:38 -0700 Subject: [PATCH 041/261] Debugger: Include src tag in Memory::Memcpy. --- Core/MemMapHelpers.h | 63 +++++++++++++++++++++++++++++++++++++------- GPU/GPUCommon.cpp | 3 ++- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index f67ab9aa86..2b5bf1637d 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -30,31 +30,76 @@ extern MIPSState *currentMIPS; namespace Memory { -inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const char *tag = "Memcpy") { +inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const char *tag, size_t tagLen) { u8 *to = GetPointer(to_address); if (to) { memcpy(to, from_data, len); - size_t tagLen = strlen(tag); + if (!tag) { + tag = "Memcpy"; + tagLen = sizeof("Memcpy") - 1; + } NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); } // if not, GetPointer will log. } -inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const char *tag = "Memcpy") { +inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const char *tag, size_t tagLen) { const u8 *from = GetPointer(from_address); if (from) { memcpy(to_data, from, len); - size_t tagLen = strlen(tag); + if (!tag) { + tag = "Memcpy"; + tagLen = sizeof("Memcpy") - 1; + } NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); } // if not, GetPointer will log. } -inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const char *tag = "Memcpy") { - Memcpy(GetPointer(to_address), from_address, len); - size_t tagLen = strlen(tag); - NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); +inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const char *tag, size_t tagLen) { + u8 *to = GetPointer(to_address); + if (to) { + const u8 *from = GetPointer(from_address); + if (from) { + memcpy(to, from, len); + char tagData[128]; + if (!tag) { + const std::string srcTag = GetMemWriteTagAt(from_address, len); + tag = tagData; + tagLen = snprintf(tagData, sizeof(tagData), "Memcpy/%s", srcTag.c_str()); + } + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); + } + } + // if not, GetPointer will log. +} + +template +inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const char(&tag)[tagLen]) { + Memcpy(to_address, from_data, len, tag, tagLen); +} + +template +inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const char(&tag)[tagLen]) { + Memcpy(to_data, from_address, len, tag, tagLen); +} + +template +inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const char(&tag)[tagLen]) { + Memcpy(to_address, from_address, len, tag, tagLen); +} + +inline void Memcpy(const u32 to_address, const void *from_data, const u32 len) { + Memcpy(to_address, from_data, len, nullptr, 0); +} + +inline void Memcpy(void *to_data, const u32 from_address, const u32 len) { + Memcpy(to_data, from_address, len, nullptr, 0); +} + +inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len) { + Memcpy(to_address, from_address, len, nullptr, 0); } void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const char *tag = "Memset"); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 3ca75338a3..48310c36f3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2738,7 +2738,8 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { // We use a little hack for PerformMemoryDownload/PerformMemoryUpload using a VRAM mirror. // Since they're identical we don't need to copy. if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) { - Memory::Memcpy(dest, src, size); + const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size); + Memory::Memcpy(dest, src, size, tag.c_str(), tag.size()); } } InvalidateCache(dest, size, GPU_INVALIDATE_HINT); From 5264fd254aa41e62fec4c6e2950d0e102f2b13ea Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:28:09 -0700 Subject: [PATCH 042/261] Dmac: Invalidate source data before copy. Also add src tag information. --- Core/HLE/sceDmac.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 4defe951ca..2bd493f016 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -50,8 +50,9 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) { skip = gpu->PerformMemoryCopy(dst, src, size); } if (!skip) { - // TODO: InvalidateICache src before copy? - Memory::Memcpy(dst, Memory::GetPointer(src), size, "DmacMemcpy"); + currentMIPS->InvalidateICache(src, size); + const std::string tag = "DmacMemcpy/" + GetMemWriteTagAt(src, size); + Memory::Memcpy(dst, src, size, tag.c_str(), tag.size()); currentMIPS->InvalidateICache(dst, size); } From f5de7c23fe307a06ee7948658a8361c68f8e953e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:37:47 -0700 Subject: [PATCH 043/261] Debugger: Note writes from debugger. To avoid confusion. --- Core/MIPS/MIPSAsm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/MIPS/MIPSAsm.cpp b/Core/MIPS/MIPSAsm.cpp index 0e59e62da1..618b0c35b2 100644 --- a/Core/MIPS/MIPSAsm.cpp +++ b/Core/MIPS/MIPSAsm.cpp @@ -35,7 +35,7 @@ public: if (!Memory::IsValidAddress((u32)(address+length-1))) return false; - Memory::Memcpy((u32)address,data,(u32)length); + Memory::Memcpy((u32)address, data, (u32)length, "Debugger"); // In case this is a delay slot or combined instruction, clear cache above it too. if (MIPSComp::jit) From bef1988f3d2091a04a662d523a328127b2ef91be Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 17:59:06 -0700 Subject: [PATCH 044/261] Deflt: Cleanup and refactor to one common func. --- Core/HLE/sceDeflt.cpp | 149 ++++++++---------------------------------- 1 file changed, 29 insertions(+), 120 deletions(-) diff --git a/Core/HLE/sceDeflt.cpp b/Core/HLE/sceDeflt.cpp index 2f0b6ec469..2a7e0cc729 100644 --- a/Core/HLE/sceDeflt.cpp +++ b/Core/HLE/sceDeflt.cpp @@ -23,142 +23,51 @@ #include "Core/HLE/sceDeflt.h" #include "Core/MemMap.h" -// All the decompress functions are identical with only differing window bits. Possibly should be one function - -static int sceDeflateDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) { - DEBUG_LOG(HLE, "sceGzipDecompress(%08x, %x, %08x, %08x)", OutBuffer, OutBufferLength, InBuffer, Crc32Addr); - int err; - uLong crc; - z_stream stream; - u8 *outBufferPtr; - u32_le *crc32AddrPtr = nullptr; - +// All the decompress functions are identical with only differing window bits. +static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) { if (!Memory::IsValidAddress(OutBuffer) || !Memory::IsValidAddress(InBuffer)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x %08x", OutBuffer, InBuffer); - return 0; + return hleLogError(HLE, 0, "bad address"); } - if (Crc32Addr) { - if (!Memory::IsValidAddress(Crc32Addr)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x", Crc32Addr); - return 0; - } - crc32AddrPtr = (u32_le *)Memory::GetPointer(Crc32Addr); + + auto crc32Addr = PSPPointer::Create(Crc32Addr); + if (Crc32Addr && !crc32Addr.IsValid()) { + return hleLogError(HLE, 0, "bad crc32 address"); } - outBufferPtr = Memory::GetPointer(OutBuffer); + + z_stream stream{}; + u8 *outBufferPtr = Memory::GetPointer(OutBuffer); stream.next_in = (Bytef*)Memory::GetPointer(InBuffer); stream.avail_in = (uInt)OutBufferLength; stream.next_out = outBufferPtr; stream.avail_out = (uInt)OutBufferLength; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - err = inflateInit2(&stream, -MAX_WBITS); + + int err = inflateInit2(&stream, windowBits); if (err != Z_OK) { - ERROR_LOG(HLE, "sceZlibDecompress: inflateInit2 failed %08x", err); - return 0; + return hleLogError(HLE, 0, "inflateInit2 failed %08x", err); } err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - ERROR_LOG(HLE, "sceZlibDecompress: inflate failed %08x", err); - return 0; - } inflateEnd(&stream); - if (crc32AddrPtr) { - crc = crc32(0L, Z_NULL, 0); - *crc32AddrPtr = crc32(crc, outBufferPtr, stream.total_out); + + if (err != Z_STREAM_END) { + return hleLogError(HLE, 0, "inflate failed %08x", err); } - return stream.total_out; + if (crc32Addr.IsValid()) { + uLong crc = crc32(0L, Z_NULL, 0); + *crc32Addr = crc32(crc, outBufferPtr, stream.total_out); + } + return hleLogSuccessI(HLE, stream.total_out); } +static int sceDeflateDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) { + return CommonDecompress(-MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr); +} static int sceGzipDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) { - DEBUG_LOG(HLE, "sceGzipDecompress(%08x, %x, %08x, %08x)", OutBuffer, OutBufferLength, InBuffer, Crc32Addr); - int err; - uLong crc; - z_stream stream; - u8 *outBufferPtr; - u32_le *crc32AddrPtr = nullptr; - - if (!Memory::IsValidAddress(OutBuffer) || !Memory::IsValidAddress(InBuffer)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x %08x", OutBuffer, InBuffer); - return 0; - } - if (Crc32Addr) { - if (!Memory::IsValidAddress(Crc32Addr)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x", Crc32Addr); - return 0; - } - crc32AddrPtr = (u32_le *)Memory::GetPointer(Crc32Addr); - } - outBufferPtr = Memory::GetPointer(OutBuffer); - stream.next_in = (Bytef*)Memory::GetPointer(InBuffer); - stream.avail_in = (uInt)OutBufferLength; - stream.next_out = outBufferPtr; - stream.avail_out = (uInt)OutBufferLength; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - err = inflateInit2(&stream, 16+MAX_WBITS); - if (err != Z_OK) { - ERROR_LOG(HLE, "sceZlibDecompress: inflateInit2 failed %08x", err); - return 0; - } - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - ERROR_LOG(HLE, "sceZlibDecompress: inflate failed %08x", err); - return 0; - } - inflateEnd(&stream); - if (crc32AddrPtr) { - crc = crc32(0L, Z_NULL, 0); - *crc32AddrPtr = crc32(crc, outBufferPtr, stream.total_out); - } - return stream.total_out; + return CommonDecompress(16 + MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr); } static int sceZlibDecompress(u32 OutBuffer, int OutBufferLength, u32 InBuffer, u32 Crc32Addr) { - DEBUG_LOG(HLE, "sceZlibDecompress(%08x, %x, %08x, %08x)", OutBuffer, OutBufferLength, InBuffer, Crc32Addr); - int err; - uLong crc; - z_stream stream; - u8 *outBufferPtr; - u32_le *crc32AddrPtr = 0; - - if (!Memory::IsValidAddress(OutBuffer) || !Memory::IsValidAddress(InBuffer)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x %08x", OutBuffer, InBuffer); - return 0; - } - if (Crc32Addr) { - if (!Memory::IsValidAddress(Crc32Addr)) { - ERROR_LOG(HLE, "sceZlibDecompress: Bad address %08x", Crc32Addr); - return 0; - } - crc32AddrPtr = (u32_le *)Memory::GetPointer(Crc32Addr); - } - outBufferPtr = Memory::GetPointer(OutBuffer); - stream.next_in = (Bytef*)Memory::GetPointer(InBuffer); - stream.avail_in = (uInt)OutBufferLength; - stream.next_out = outBufferPtr; - stream.avail_out = (uInt)OutBufferLength; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - err = inflateInit2(&stream, MAX_WBITS); - if (err != Z_OK) { - ERROR_LOG(HLE, "sceZlibDecompress: inflateInit failed %08x", err); - return 0; - } - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - ERROR_LOG(HLE, "sceZlibDecompress: inflate failed %08x", err); - return 0; - } - inflateEnd(&stream); - if (crc32AddrPtr) { - crc = crc32(0L, Z_NULL, 0); - *crc32AddrPtr = crc32(crc, outBufferPtr, stream.total_out); - } - return stream.total_out; + return CommonDecompress(MAX_WBITS, OutBuffer, OutBufferLength, InBuffer, Crc32Addr); } const HLEFunction sceDeflt[] = { @@ -166,11 +75,11 @@ const HLEFunction sceDeflt[] = { {0X106A3552, nullptr, "sceGzipGetName", '?', "" }, {0X1B5B82BC, nullptr, "sceGzipIsValid", '?', "" }, {0X2EE39A64, nullptr, "sceZlibAdler32", '?', "" }, - {0X44054E03, &WrapI_UIUU, "sceDeflateDecompress", 'i', "xixx"}, + {0X44054E03, &WrapI_UIUU, "sceDeflateDecompress", 'i', "xixp"}, {0X6A548477, nullptr, "sceZlibGetCompressedData", '?', "" }, - {0X6DBCF897, &WrapI_UIUU, "sceGzipDecompress", 'i', "xixx"}, + {0X6DBCF897, &WrapI_UIUU, "sceGzipDecompress", 'i', "xixp"}, {0X8AA82C92, nullptr, "sceGzipGetInfo", '?', "" }, - {0XA9E4FB28, &WrapI_UIUU, "sceZlibDecompress", 'i', "xixx"}, + {0XA9E4FB28, &WrapI_UIUU, "sceZlibDecompress", 'i', "xixp"}, {0XAFE01FD3, nullptr, "sceZlibGetInfo", '?', "" }, {0XB767F9A0, nullptr, "sceGzipGetComment", '?', "" }, {0XE46EB986, nullptr, "sceZlibIsValid", '?', "" }, From ba71d9b555db138a9655d7daba9fe16b06a2bac7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 18:03:44 -0700 Subject: [PATCH 045/261] Deflt: Trigger memchecks / log source of writes. --- Core/HLE/sceDeflt.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/HLE/sceDeflt.cpp b/Core/HLE/sceDeflt.cpp index 2a7e0cc729..b2c29ea2f1 100644 --- a/Core/HLE/sceDeflt.cpp +++ b/Core/HLE/sceDeflt.cpp @@ -18,6 +18,7 @@ #include "zlib.h" #include "Common/CommonTypes.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceDeflt.h" @@ -55,6 +56,11 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength, uLong crc = crc32(0L, Z_NULL, 0); *crc32Addr = crc32(crc, outBufferPtr, stream.total_out); } + + const std::string tag = "sceDeflt/" + GetMemWriteTagAt(InBuffer, stream.total_in); + NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tag.c_str(), tag.size()); + return hleLogSuccessI(HLE, stream.total_out); } From d009203c249a14d40280e79c28cd44e8c5abeaa9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 18:08:17 -0700 Subject: [PATCH 046/261] Deflt: Correct available input length. The length of the output buffer can't have been always correct. --- Core/HLE/sceDeflt.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceDeflt.cpp b/Core/HLE/sceDeflt.cpp index b2c29ea2f1..fdf7b0d55c 100644 --- a/Core/HLE/sceDeflt.cpp +++ b/Core/HLE/sceDeflt.cpp @@ -38,7 +38,8 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength, z_stream stream{}; u8 *outBufferPtr = Memory::GetPointer(OutBuffer); stream.next_in = (Bytef*)Memory::GetPointer(InBuffer); - stream.avail_in = (uInt)OutBufferLength; + // We don't know the available length, just let it use as much as it wants. + stream.avail_in = (uInt)Memory::ValidSize(InBuffer, Memory::g_MemorySize); stream.next_out = outBufferPtr; stream.avail_out = (uInt)OutBufferLength; From 1b57739eb7251d93a97773efa6a6ff2dad2d66ce Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 18:28:22 -0700 Subject: [PATCH 047/261] Debugger: Memcheck and tag loading savedata to RAM. --- Core/Dialog/SavedataParam.cpp | 34 +++++++++++++++++++++++++--------- Core/Dialog/SavedataParam.h | 4 ++-- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 137d272e20..674db202a6 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -25,6 +25,7 @@ #include "Core/Host.h" #include "Core/Reporting.h" #include "Core/System.h" +#include "Core/Debugger/MemBlockInfo.h" #include "Core/Dialog/SavedataParam.h" #include "Core/Dialog/PSPSaveDialog.h" #include "Core/FileSystems/MetaFileSystem.h" @@ -645,7 +646,7 @@ int SavedataParam::LoadSaveData(SceUtilitySavedataParam *param, const std::strin } WARN_LOG_REPORT(SCEUTILITY, "Savedata version requested: %d", param->secureVersion); } - u8 *data_ = param->dataBuf; + std::string filename = GetFileName(param); std::string filePath = dirPath + "/" + filename; s64 readSize; @@ -664,21 +665,27 @@ int SavedataParam::LoadSaveData(SceUtilitySavedataParam *param, const std::strin int prevCryptMode = GetSaveCryptMode(param, saveDirName); bool isCrypted = prevCryptMode != 0 && secureMode; bool saveDone = false; + u32 loadedSize = 0; if (isCrypted) { if (DetermineCryptMode(param) > 1 && !HasKey(param)) return SCE_UTILITY_SAVEDATA_ERROR_LOAD_PARAM; u8 hash[16]; bool hasExpectedHash = GetExpectedHash(dirPath, filename, hash); - LoadCryptedSave(param, data_, saveData, saveSize, prevCryptMode, hasExpectedHash ? hash : nullptr, saveDone); + loadedSize = LoadCryptedSave(param, param->dataBuf, saveData, saveSize, prevCryptMode, hasExpectedHash ? hash : nullptr, saveDone); // TODO: Should return SCE_UTILITY_SAVEDATA_ERROR_LOAD_DATA_BROKEN here if !saveDone. } if (!saveDone) { - LoadNotCryptedSave(param, data_, saveData, saveSize); + loadedSize = LoadNotCryptedSave(param, param->dataBuf, saveData, saveSize); } param->dataSize = (SceSize)saveSize; delete[] saveData; + if (loadedSize != 0) { + std::string tag = "LoadSaveData/" + filePath; + NotifyMemInfo(MemBlockFlags::WRITE, param->dataBuf.ptr, loadedSize, tag.c_str(), tag.size()); + } + return 0; } @@ -697,7 +704,7 @@ int SavedataParam::DetermineCryptMode(const SceUtilitySavedataParam *param) cons return decryptMode; } -void SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, const u8 *saveData, int &saveSize, int prevCryptMode, const u8 *expectedHash, bool &saveDone) { +u32 SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, const u8 *saveData, int &saveSize, int prevCryptMode, const u8 *expectedHash, bool &saveDone) { int orig_size = saveSize; int align_len = align16(saveSize); u8 *data_base = new u8[align_len]; @@ -761,18 +768,27 @@ void SavedataParam::LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, co err = DecryptSave(decryptMode, data_base, &saveSize, &align_len, hasKey ? cryptKey : nullptr, nullptr); } + u32 sz = 0; if (err == 0) { - if (param->dataBuf.IsValid()) - memcpy(data, data_base, std::min((u32)saveSize, (u32)param->dataBufSize)); + if (param->dataBuf.IsValid()) { + sz = std::min((u32)saveSize, (u32)param->dataBufSize); + memcpy(data, data_base, sz); + } saveDone = true; } delete[] data_base; delete[] cryptKey; + + return sz; } -void SavedataParam::LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize) { - if (param->dataBuf.IsValid()) - memcpy(data, saveData, std::min((u32)saveSize, (u32)param->dataBufSize)); +u32 SavedataParam::LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize) { + if (param->dataBuf.IsValid()) { + u32 sz = std::min((u32)saveSize, (u32)param->dataBufSize); + memcpy(data, saveData, sz); + return sz; + } + return 0; } void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string& dirPath) { diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 3cf343914b..7011d45e37 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -364,8 +364,8 @@ private: PSPFileInfo GetSaveInfo(std::string saveDir); int LoadSaveData(SceUtilitySavedataParam *param, const std::string &saveDirName, const std::string& dirPath, bool secureMode); - void LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, const u8 *saveData, int &saveSize, int prevCryptMode, const u8 *expectedHash, bool &saveDone); - void LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize); + u32 LoadCryptedSave(SceUtilitySavedataParam *param, u8 *data, const u8 *saveData, int &saveSize, int prevCryptMode, const u8 *expectedHash, bool &saveDone); + u32 LoadNotCryptedSave(SceUtilitySavedataParam *param, u8 *data, u8 *saveData, int &saveSize); void LoadSFO(SceUtilitySavedataParam *param, const std::string& dirPath); void LoadFile(const std::string& dirPath, const std::string& filename, PspUtilitySavedataFileData *fileData); From 869ef9aca7a56bbadca687a3a8a9bfc2cfc41e35 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 18:45:24 -0700 Subject: [PATCH 048/261] Debugger: Tag savedata load and info. --- Core/Dialog/SavedataParam.cpp | 82 +++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 674db202a6..a22b9360e0 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -866,8 +866,11 @@ void SavedataParam::LoadFile(const std::string& dirPath, const std::string& file u8 *buf = fileData->buf; u32 size = Memory::ValidSize(fileData->buf.ptr, fileData->bufSize); s64 readSize = -1; - if (ReadPSPFile(filePath, &buf, size, &readSize)) + if (ReadPSPFile(filePath, &buf, size, &readSize)) { fileData->size = readSize; + const std::string tag = "SavedataLoad/" + filePath; + NotifyMemInfo(MemBlockFlags::WRITE, fileData->buf.ptr, fileData->size, tag.c_str(), tag.size()); + } } int SavedataParam::EncryptData(unsigned int mode, @@ -1083,6 +1086,7 @@ int SavedataParam::GetSizes(SceUtilitySavedataParam *param) const std::string spaceTxt = SavedataParam::GetSpaceText(freeBytes, false); memset(param->msFree->freeSpaceStr, 0, sizeof(param->msFree->freeSpaceStr)); strncpy(param->msFree->freeSpaceStr, spaceTxt.c_str(), sizeof(param->msFree->freeSpaceStr)); + NotifyMemInfo(MemBlockFlags::WRITE, param->msFree.ptr, sizeof(SceUtilitySavedataMsFreeInfo), "SavedataGetSizes"); } if (param->msData.IsValid()) { @@ -1120,6 +1124,7 @@ int SavedataParam::GetSizes(SceUtilitySavedataParam *param) strncpy(param->msData->info.usedSpace32Str, "", sizeof(param->msData->info.usedSpace32Str)); ret = SCE_UTILITY_SAVEDATA_ERROR_SIZES_NO_DATA; } + NotifyMemInfo(MemBlockFlags::WRITE, param->msData.ptr, sizeof(SceUtilitySavedataMsDataInfo), "SavedataGetSizes"); } if (param->utilityData.IsValid()) { @@ -1155,6 +1160,7 @@ int SavedataParam::GetSizes(SceUtilitySavedataParam *param) spaceTxt = SavedataParam::GetSpaceText(total_size, true); memset(param->utilityData->usedSpace32Str, 0, sizeof(param->utilityData->usedSpace32Str)); strncpy(param->utilityData->usedSpace32Str, spaceTxt.c_str(), sizeof(param->utilityData->usedSpace32Str)); + NotifyMemInfo(MemBlockFlags::WRITE, param->utilityData.ptr, sizeof(SceUtilitySavedataUsedDataInfo), "SavedataGetSizes"); } return ret; @@ -1174,47 +1180,47 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param) std::vector sfoFiles; std::vector allDir = pspFileSystem.GetDirListing(savePath); - if (param->idList.IsValid()) + std::string searchString = GetGameName(param)+GetSaveName(param); + for (size_t i = 0; i < allDir.size() && validDir.size() < maxFile; i++) { - std::string searchString = GetGameName(param)+GetSaveName(param); - for (size_t i = 0; i < allDir.size() && validDir.size() < maxFile; i++) + std::string dirName = allDir[i].name; + if(PSPMatch(dirName, searchString)) { - std::string dirName = allDir[i].name; - if(PSPMatch(dirName, searchString)) - { - validDir.push_back(allDir[i]); - } + validDir.push_back(allDir[i]); } + } - PSPFileInfo sfoFile; - for (size_t i = 0; i < validDir.size(); ++i) { - // GetFileName(param) == NUll here - // so use sfo files to set the date. - sfoFile = pspFileSystem.GetFileInfo(savePath + validDir[i].name + "/" + "PARAM.SFO"); - sfoFiles.push_back(sfoFile); - } + PSPFileInfo sfoFile; + for (size_t i = 0; i < validDir.size(); ++i) { + // GetFileName(param) == NUll here + // so use sfo files to set the date. + sfoFile = pspFileSystem.GetFileInfo(savePath + validDir[i].name + "/" + "PARAM.SFO"); + sfoFiles.push_back(sfoFile); + } - SceUtilitySavedataIdListEntry *entries = param->idList->entries; - for (u32 i = 0; i < (u32)validDir.size(); i++) - { - entries[i].st_mode = 0x11FF; - if (sfoFiles[i].exists) { - __IoCopyDate(entries[i].st_ctime, sfoFiles[i].ctime); - __IoCopyDate(entries[i].st_atime, sfoFiles[i].atime); - __IoCopyDate(entries[i].st_mtime, sfoFiles[i].mtime); - } else { - __IoCopyDate(entries[i].st_ctime, validDir[i].ctime); - __IoCopyDate(entries[i].st_atime, validDir[i].atime); - __IoCopyDate(entries[i].st_mtime, validDir[i].mtime); - } - // folder name without gamename (max 20 u8) - std::string outName = validDir[i].name.substr(GetGameName(param).size()); - memset(entries[i].name, 0, sizeof(entries[i].name)); - strncpy(entries[i].name, outName.c_str(), sizeof(entries[i].name)); + SceUtilitySavedataIdListEntry *entries = param->idList->entries; + for (u32 i = 0; i < (u32)validDir.size(); i++) + { + entries[i].st_mode = 0x11FF; + if (sfoFiles[i].exists) { + __IoCopyDate(entries[i].st_ctime, sfoFiles[i].ctime); + __IoCopyDate(entries[i].st_atime, sfoFiles[i].atime); + __IoCopyDate(entries[i].st_mtime, sfoFiles[i].mtime); + } else { + __IoCopyDate(entries[i].st_ctime, validDir[i].ctime); + __IoCopyDate(entries[i].st_atime, validDir[i].atime); + __IoCopyDate(entries[i].st_mtime, validDir[i].mtime); } + // folder name without gamename (max 20 u8) + std::string outName = validDir[i].name.substr(GetGameName(param).size()); + memset(entries[i].name, 0, sizeof(entries[i].name)); + strncpy(entries[i].name, outName.c_str(), sizeof(entries[i].name)); } // Save num of folder found param->idList->resultCount = (u32)validDir.size(); + + NotifyMemInfo(MemBlockFlags::WRITE, param->idList.ptr, sizeof(SceUtilitySavedataIdListInfo), "SavedataGetList"); + NotifyMemInfo(MemBlockFlags::WRITE, param->idList->entries.ptr, validDir.size() * sizeof(SceUtilitySavedataIdListEntry), "SavedataGetList"); } return true; } @@ -1323,6 +1329,14 @@ int SavedataParam::GetFilesList(SceUtilitySavedataParam *param) // Don't know what it is, but PSP always respond this param->bind = 1021; + NotifyMemInfo(MemBlockFlags::WRITE, fileList.ptr, sizeof(SceUtilitySavedataFileListInfo), "SavedataGetFilesList"); + if (fileList->resultNumSystemEntries != 0) + NotifyMemInfo(MemBlockFlags::WRITE, fileList->systemEntries.ptr, fileList->resultNumSystemEntries * sizeof(SceUtilitySavedataFileListEntry), "SavedataGetFilesList"); + if (fileList->resultNumSecureEntries != 0) + NotifyMemInfo(MemBlockFlags::WRITE, fileList->secureEntries.ptr, fileList->resultNumSecureEntries * sizeof(SceUtilitySavedataFileListEntry), "SavedataGetFilesList"); + if (fileList->resultNumNormalEntries != 0) + NotifyMemInfo(MemBlockFlags::WRITE, fileList->normalEntries.ptr, fileList->resultNumNormalEntries * sizeof(SceUtilitySavedataFileListEntry), "SavedataGetFilesList"); + return 0; } @@ -1389,6 +1403,8 @@ bool SavedataParam::GetSize(SceUtilitySavedataParam *param) truncate_cpy(param->sizeInfo->overwriteString, spaceTxt.c_str()); } } + + NotifyMemInfo(MemBlockFlags::WRITE, param->sizeInfo.ptr, sizeof(PspUtilitySavedataSizeInfo), "SavedataGetSize"); } return exists; From aa9b19be45f679fae6a008f5c0220cce9a1a58b4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 19:06:46 -0700 Subject: [PATCH 049/261] Debugger: Note atrac/sas reads from memory more. --- Core/HLE/sceAtrac.cpp | 31 +++++++++++++++++-------------- Core/HW/SasAudio.cpp | 10 +++++++++- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 55c896f345..105c332b1e 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -153,7 +153,7 @@ struct InputBuffer { struct Atrac; int __AtracSetContext(Atrac *atrac); -void _AtracGenerateContext(Atrac *atrac, SceAtracId *context); +void _AtracGenerateContext(Atrac *atrac); struct AtracLoopInfo { int cuePointID; @@ -1031,7 +1031,7 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { if (!atrac) return 0; int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset); - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, bufPtr, addbytes); + Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, bufPtr, addbytes, "AtracAddStreamData"); atrac->first_.size += bytesToAdd; if (atrac->first_.size >= atrac->first_.filesize) { atrac->first_.size = atrac->first_.filesize; @@ -1041,7 +1041,7 @@ u32 _AtracAddStreamData(int atracID, u32 bufPtr, u32 bytesToAdd) { atrac->first_.fileoffset += addbytes; if (atrac->context_.IsValid()) { // refresh context_ - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } return 0; } @@ -1142,7 +1142,7 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { atrac->first_.fileoffset = readOffset; int addbytes = std::min(bytesToAdd, atrac->first_.filesize - atrac->first_.fileoffset); if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr + atrac->first_.offset, addbytes); + Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr + atrac->first_.offset, addbytes, "AtracAddStreamData"); } atrac->first_.fileoffset += addbytes; } @@ -1152,7 +1152,7 @@ static u32 sceAtracAddStreamData(int atracID, u32 bytesToAdd) { if (atrac->bufferState_ == ATRAC_STATUS_HALFWAY_BUFFER) atrac->bufferState_ = ATRAC_STATUS_ALL_DATA_LOADED; if (atrac->context_.IsValid()) { - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } } @@ -1313,7 +1313,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 } if (atrac->context_.IsValid()) { // refresh context_ - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } } @@ -1729,7 +1729,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi // Okay, it's a valid number of bytes. Let's set them up. if (bytesWrittenFirstBuf != 0) { if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.size, atrac->first_.addr + atrac->first_.size, bytesWrittenFirstBuf); + Memory::Memcpy(atrac->dataBuf_ + atrac->first_.size, atrac->first_.addr + atrac->first_.size, bytesWrittenFirstBuf, "AtracResetPlayPosition"); } atrac->first_.fileoffset += bytesWrittenFirstBuf; atrac->first_.size += bytesWrittenFirstBuf; @@ -1752,7 +1752,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi if (bytesWrittenFirstBuf != 0) { if (!atrac->ignoreDataBuf_) { - Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr, bytesWrittenFirstBuf); + Memory::Memcpy(atrac->dataBuf_ + atrac->first_.fileoffset, atrac->first_.addr, bytesWrittenFirstBuf, "AtracResetPlayPosition"); } atrac->first_.fileoffset += bytesWrittenFirstBuf; } @@ -1769,7 +1769,7 @@ static u32 sceAtracResetPlayPosition(int atracID, int sample, int bytesWrittenFi } if (atrac->context_.IsValid()) { - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } return hleDelayResult(hleLogSuccessInfoI(ME, 0), "reset play pos", 3000); @@ -1924,7 +1924,7 @@ static int _AtracSetData(Atrac *atrac, u32 buffer, u32 readSize, u32 bufferSize, atrac->dataBuf_ = new u8[atrac->first_.filesize]; if (!atrac->ignoreDataBuf_) { u32 copybytes = std::min(bufferSize, atrac->first_.filesize); - Memory::Memcpy(atrac->dataBuf_, buffer, copybytes); + Memory::Memcpy(atrac->dataBuf_, buffer, copybytes, "AtracSetData"); } int ret = __AtracSetContext(atrac); if (ret < 0) { @@ -2083,7 +2083,7 @@ static u32 sceAtracSetLoopNum(int atracID, int loopNum) { atrac->loopEndSample_ = atrac->endSample_ + atrac->firstSampleOffset_ + atrac->FirstOffsetExtra(); } if (atrac->context_.IsValid()) { - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } } return 0; @@ -2291,7 +2291,8 @@ int _AtracGetIDByContext(u32 contextAddr) { return atracID; } -void _AtracGenerateContext(Atrac *atrac, SceAtracId *context) { +void _AtracGenerateContext(Atrac *atrac) { + SceAtracId *context = atrac->context_; context->info.buffer = atrac->first_.addr; context->info.bufferByte = atrac->bufferMaxSize_; context->info.secondBuffer = atrac->second_.addr; @@ -2321,6 +2322,8 @@ void _AtracGenerateContext(Atrac *atrac, SceAtracId *context) { u8 *buf = (u8 *)context; *(u32_le *)(buf + 0xfc) = atrac->atracID_; + + NotifyMemInfo(MemBlockFlags::WRITE, atrac->context_.ptr, sizeof(SceAtracId), "AtracContext"); } static u32 _sceAtracGetContextAddress(int atracID) { @@ -2341,7 +2344,7 @@ static u32 _sceAtracGetContextAddress(int atracID) { else WARN_LOG(ME, "%08x=_sceAtracGetContextAddress(%i)", atrac->context_.ptr, atracID); if (atrac->context_.IsValid()) - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); return atrac->context_.ptr; } @@ -2430,7 +2433,7 @@ static int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr) { int ret = __AtracSetContext(atrac); if (atrac->context_.IsValid()) { - _AtracGenerateContext(atrac, atrac->context_); + _AtracGenerateContext(atrac); } if (ret < 0) { diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index 52566ee0d7..e974f4de54 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -149,6 +149,8 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { } if (readp > origp) { + if (g_Config.bDebugMemInfoDetailed) + NotifyMemInfo(MemBlockFlags::READ, read_, readp - origp, "SasVagDecoder"); read_ += readp - origp; } } @@ -426,7 +428,7 @@ void SasVoice::ReadSamples(s16 *output, int numSamples) { pcmIndex = 0; break; } - Memory::Memcpy(out, pcmAddr + pcmIndex * sizeof(s16), size * sizeof(s16)); + Memory::Memcpy(out, pcmAddr + pcmIndex * sizeof(s16), size * sizeof(s16), "SasVoicePCM"); pcmIndex += size; needed -= size; out += size; @@ -580,6 +582,11 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) { if (outputMode == PSP_SAS_OUTPUTMODE_MIXED) { // Okay, apply effects processing to the Send buffer. WriteMixedOutput(outp, inp, leftVol, rightVol); + if (g_Config.bDebugMemInfoDetailed) { + if (inp) + NotifyMemInfo(MemBlockFlags::READ, inAddr, grainSize * sizeof(u16) * 2, "SasMix"); + NotifyMemInfo(MemBlockFlags::WRITE, outAddr, grainSize * sizeof(u16) * 2, "SasMix"); + } } else { s16 *outpL = outp + grainSize * 0; s16 *outpR = outp + grainSize * 1; @@ -592,6 +599,7 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) { *outpSendL++ = clamp_s16(sendBuffer[i + 0]); *outpSendR++ = clamp_s16(sendBuffer[i + 1]); } + NotifyMemInfo(MemBlockFlags::WRITE, outAddr, grainSize * sizeof(u16) * 4, "SasMix"); } memset(mixBuffer, 0, grainSize * sizeof(int) * 2); memset(sendBuffer, 0, grainSize * sizeof(int) * 2); From d3edb134b19c833f2a0b845462bd99978532a48d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 3 Apr 2021 19:19:20 -0700 Subject: [PATCH 050/261] Debugger: Maintain atrac data source info. Often this is the file it was read from. --- Core/HLE/sceAtrac.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 105c332b1e..bccf2ce748 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -520,6 +520,15 @@ struct Atrac { currentSample_ = sample; } + uint32_t CurBufferAddress(int adjust = 0) { + u32 off = FileOffsetBySample(currentSample_ + adjust); + if (off < first_.size && ignoreDataBuf_) { + return first_.addr + off; + } + // If it's in dataBug, it's not in PSP memory. + return 0; + } + bool FillPacket(int adjust = 0) { u32 off = FileOffsetBySample(currentSample_ + adjust); if (off < first_.size) { @@ -1208,6 +1217,8 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 AtracDecodeResult res = ATDECODE_FEEDME; while (atrac->FillPacket(-skipSamples)) { + uint32_t packetAddr = atrac->CurBufferAddress(-skipSamples); + int packetSize = atrac->packet_->size; res = atrac->DecodePacket(); if (res == ATDECODE_FAILED) { *SamplesNum = 0; @@ -1246,7 +1257,13 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int avret = swr_convert(atrac->swrCtx_, &out, numSamples, inbuf, numSamples); if (outbufPtr != 0) { u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); - NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); + if (packetAddr != 0 && g_Config.bDebugMemInfoDetailed) { + const std::string tag = "AtracDecode/" + GetMemWriteTagAt(packetAddr, packetSize); + NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size()); + NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size()); + } else { + NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); + } } if (avret < 0) { ERROR_LOG(ME, "swr_convert: Error while converting %d", avret); From 540a5e3a3bd0d2da2ea5dc2a7e9fa3d7d5971fe4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 07:29:12 -0700 Subject: [PATCH 051/261] UI: Log analog movement at a lower treshold. This should be high enough still to be outside the deadzone, and clearer. See #12062. --- UI/ControlMappingScreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 02ee1851c4..a0eb5693c4 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -531,7 +531,8 @@ bool AnalogTestScreen::axis(const AxisInput &axis) { if (IgnoreAxisForMapping(axis.axisId)) return false; - if (axis.value > AXIS_BIND_THRESHOLD || axis.value < -AXIS_BIND_THRESHOLD) { + const float AXIS_LOG_THRESHOLD = AXIS_BIND_THRESHOLD * 0.5f; + if (axis.value > AXIS_LOG_THRESHOLD || axis.value < -AXIS_LOG_THRESHOLD) { char buf[512]; snprintf(buf, sizeof(buf), "Axis: %d (value %1.3f) Device ID: %d", axis.axisId, axis.value, axis.deviceId); From c9428975fe259f83d999062337a3e1dffb351a35 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 08:16:26 -0700 Subject: [PATCH 052/261] Windows: Normalize left and right analog stick. --- Core/KeyMap.cpp | 31 ++++++++++ Core/KeyMap.h | 9 ++- Windows/DinputDevice.cpp | 121 ++++++++++++++++++++++----------------- 3 files changed, 108 insertions(+), 53 deletions(-) diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 13f298eaec..43e268c79a 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -849,6 +849,37 @@ bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) { return false; } +MappedAnalogAxes MappedAxesForDevice(int deviceId) { + MappedAnalogAxes result{}; + + // Find the axisId mapped for a specific virtual button. + auto findAxisId = [&](int btn) -> int { + for (const auto &key : g_controllerMap[btn]) { + if (key.deviceId == deviceId) { + int direction = 0; + return TranslateKeyCodeToAxis(key.keyCode, direction); + } + } + return -1; + }; + + // Find the axisId of a pair of opposing buttons. + auto findAxisIdPair = [&](int minBtn, int maxBtn) -> int { + int foundMin = findAxisId(minBtn); + int foundMax = findAxisId(maxBtn); + if (foundMin == foundMax) { + return foundMax; + } + return -1; + }; + + result.leftXAxisId = findAxisIdPair(VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX); + result.leftYAxisId = findAxisIdPair(VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX); + result.rightXAxisId = findAxisIdPair(VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX); + result.rightYAxisId = findAxisIdPair(VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX); + return result; +} + void RemoveButtonMapping(int btn) { for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) { if (iter->first == btn) { diff --git a/Core/KeyMap.h b/Core/KeyMap.h index a0afd74797..9953b0f87c 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -80,6 +80,13 @@ const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f; typedef std::map> KeyMapping; +struct MappedAnalogAxes { + int leftXAxisId; + int leftYAxisId; + int rightXAxisId; + int rightYAxisId; +}; + // KeyMap // A translation layer for key assignment. Provides // integration with Core's config state. @@ -129,7 +136,7 @@ namespace KeyMap { bool AxisToPspButton(int deviceId, int axisId, int direction, std::vector *pspKeys); bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction); - std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction); + MappedAnalogAxes MappedAxesForDevice(int deviceId); void LoadFromIni(IniFile &iniFile); void SaveToIni(IniFile &iniFile); diff --git a/Windows/DinputDevice.cpp b/Windows/DinputDevice.cpp index b87bc95537..4e605907ff 100644 --- a/Windows/DinputDevice.cpp +++ b/Windows/DinputDevice.cpp @@ -26,15 +26,11 @@ #include "Common/System/NativeApp.h" #include "Core/Config.h" #include "Core/HLE/sceCtrl.h" +#include "Core/KeyMap.h" #include "Core/Reporting.h" #include "Windows/DinputDevice.h" #pragma comment(lib,"dinput8.lib") -#ifdef min -#undef min -#undef max -#endif - //initialize static members of DinputDevice unsigned int DinputDevice::pInstances = 0; LPDIRECTINPUT8 DinputDevice::pDI = NULL; @@ -227,6 +223,69 @@ inline float LinearMaps(float val, float a0, float a1, float b0, float b1) { return b0 + (((val - a0) * (b1 - b0)) / (a1 - a0)); } +static void ApplyNormalization(LONG &jsx, LONG &jsy) { + // Circle to Square mapping, cribbed from XInputDevice + float sx = (float)jsx; + float sy = (float)jsy; + float scaleFactor = sqrtf((sx * sx + sy * sy) / std::max(sx * sx, sy * sy)); + jsx = (int)(sx * scaleFactor); + jsy = (int)(sy * scaleFactor); + + // Linear range mapping (used to invert deadzones) + float dz = g_Config.fDInputAnalogDeadzone; + int idzm = g_Config.iDInputAnalogInverseMode; + float idz = g_Config.fDInputAnalogInverseDeadzone; + float md = std::max(dz, idz); + float st = g_Config.fDInputAnalogSensitivity; + + float magnitude = sqrtf((float)(jsx * jsx + jsy * jsy)); + if (magnitude > dz * 10000.0f) { + if (idzm == 1) { + int xSign = Signs(jsx); + if (xSign != 0) { + jsx = LinearMaps(jsx, xSign * (int)(dz * 10000), xSign * 10000, xSign * (int)(md * 10000), xSign * (int)(st * 10000)); + } + } else if (idzm == 2) { + int ySign = Signs(jsy); + if (ySign != 0) { + jsy = LinearMaps(jsy, ySign * (int)(dz * 10000.0f), ySign * 10000, ySign * (int)(md * 10000.0f), ySign * (int)(st * 10000)); + } + } else if (idzm == 3) { + float xNorm = (float)jsx / magnitude; + float yNorm = (float)jsy / magnitude; + float mapMag = LinearMaps(magnitude, dz * 10000.0f, 10000.0f, md * 10000.0f, 10000.0f * st); + jsx = (short)(xNorm * mapMag); + jsy = (short)(yNorm * mapMag); + } + } else { + jsx = 0; + jsy = 0; + } + + jsx = (short)std::min(10000.0f, std::max((float)jsx, -10000.0f)); + jsy = (short)std::min(10000.0f, std::max((float)jsy, -10000.0f)); +} + +static LONG *ValueForAxisId(DIJOYSTATE2 &js, int axisId) { + switch (axisId) { + case JOYSTICK_AXIS_X: return &js.lX; + case JOYSTICK_AXIS_Y: return &js.lY; + case JOYSTICK_AXIS_Z: return &js.lZ; + case JOYSTICK_AXIS_RX: return &js.lRx; + case JOYSTICK_AXIS_RY: return &js.lRy; + case JOYSTICK_AXIS_RZ: return &js.lRz; + default: return nullptr; + } +} + +static void ApplyNormalization(DIJOYSTATE2 &js, int xAxisId, int yAxisId) { + LONG *nrmX = ValueForAxisId(js, xAxisId); + LONG *nrmY = ValueForAxisId(js, yAxisId); + if (nrmX != nullptr && nrmY != nullptr) { + ApplyNormalization(*nrmX, *nrmY); + } +} + int DinputDevice::UpdateState() { if (!pJoystick) return -1; @@ -246,53 +305,11 @@ int DinputDevice::UpdateState() { AxisInput axis; axis.deviceId = DEVICE_ID_PAD_0 + pDevNum; - // Circle to Square mapping, cribbed from XInputDevice - float sx = (float)js.lX; - float sy = (float)js.lY; - float scaleFactor = sqrtf((sx * sx + sy * sy) / std::max(sx * sx, sy * sy)); - js.lX = (int)(sx * scaleFactor); - js.lY = (int)(sy * scaleFactor); - - // Linear range mapping (used to invert deadzones) - float dz = g_Config.fDInputAnalogDeadzone; - int idzm = g_Config.iDInputAnalogInverseMode; - float idz = g_Config.fDInputAnalogInverseDeadzone; - float md = std::max(dz, idz); - float st = g_Config.fDInputAnalogSensitivity; - - float magnitude = sqrtf((float)(js.lX * js.lX + js.lY * js.lY)); - if (magnitude > dz * 10000.0f) { - if (idzm == 1) - { - int xSign = Signs(js.lX); - if (xSign != 0) { - js.lX = LinearMaps(js.lX, xSign * (int)(dz * 10000), xSign * 10000, xSign * (int)(md * 10000), xSign * (int)(st * 10000)); - } - } - else if (idzm == 2) - { - int ySign = Signs(js.lY); - if (ySign != 0) { - js.lY = LinearMaps(js.lY, ySign * (int)(dz * 10000.0f), ySign * 10000, ySign * (int)(md * 10000.0f), ySign * (int)(st * 10000)); - } - } - else if (idzm == 3) - { - float xNorm = (float)js.lX / magnitude; - float yNorm = (float)js.lY / magnitude; - float mapMag = LinearMaps(magnitude, dz * 10000.0f, 10000.0f, md * 10000.0f, 10000.0f * st); - js.lX = (short)(xNorm * mapMag); - js.lY = (short)(yNorm * mapMag); - } - } - else - { - js.lX = 0; - js.lY = 0; - } - - js.lX = (short)std::min(10000.0f, std::max((float)js.lX, -10000.0f)); - js.lY = (short)std::min(10000.0f, std::max((float)js.lY, -10000.0f)); + auto axesToSquare = KeyMap::MappedAxesForDevice(axis.deviceId); + ApplyNormalization(js, axesToSquare.leftXAxisId, axesToSquare.leftYAxisId); + // Prevent double normalization. + if (axesToSquare.leftXAxisId != axesToSquare.rightXAxisId && axesToSquare.leftXAxisId != axesToSquare.rightYAxisId) + ApplyNormalization(js, axesToSquare.rightXAxisId, axesToSquare.rightYAxisId); SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lX, last_lX_, JOYSTICK_AXIS_X); SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lY, last_lY_, JOYSTICK_AXIS_Y); From eca3a405b69f38b9757cacd87e12ed73f6643d87 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 08:39:49 -0700 Subject: [PATCH 053/261] UI: Flip Y analog direction based on config. --- Common/Input/InputState.cpp | 12 +++++++++++ Common/Input/InputState.h | 7 ++++++- Common/UI/Root.cpp | 23 +++++++++++++-------- Core/KeyMap.cpp | 41 ++++++++++++++++++++++++------------- Core/KeyMap.h | 13 ++++++++---- Windows/DinputDevice.cpp | 6 +++--- 6 files changed, 72 insertions(+), 30 deletions(-) diff --git a/Common/Input/InputState.cpp b/Common/Input/InputState.cpp index 90fc9b6a1a..66922ce77f 100644 --- a/Common/Input/InputState.cpp +++ b/Common/Input/InputState.cpp @@ -33,6 +33,7 @@ std::vector confirmKeys; std::vector cancelKeys; std::vector tabLeftKeys; std::vector tabRightKeys; +static std::unordered_map uiFlipAnalogY; static void AppendKeys(std::vector &keys, const std::vector &newKeys) { for (auto iter = newKeys.begin(); iter != newKeys.end(); ++iter) { @@ -61,3 +62,14 @@ void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector flipYByDeviceId) { + uiFlipAnalogY = flipYByDeviceId; +} + +int GetAnalogYDirection(int deviceId) { + auto configured = uiFlipAnalogY.find(deviceId); + if (configured != uiFlipAnalogY.end()) + return configured->second; + return 0; +} diff --git a/Common/Input/InputState.h b/Common/Input/InputState.h index 59a0a6e057..02377f3b24 100644 --- a/Common/Input/InputState.h +++ b/Common/Input/InputState.h @@ -4,8 +4,9 @@ // own mapping. Might later move the mapping system from PPSSPP to native. #include -#include #include +#include +#include #include "Common/Math/lin/vec3.h" #include "Common/Input/KeyCodes.h" @@ -162,3 +163,7 @@ void SetDPadKeys(const std::vector &leftKey, const std::vector & const std::vector &upKey, const std::vector &downKey); void SetConfirmCancelKeys(const std::vector &confirm, const std::vector &cancel); void SetTabLeftRightKeys(const std::vector &tabLeft, const std::vector &tabRight); + +// 0 means unknown (attempt autodetect), -1 means flip, 1 means original direction. +void SetAnalogFlipY(std::unordered_map flipYByDeviceId); +int GetAnalogYDirection(int deviceId); diff --git a/Common/UI/Root.cpp b/Common/UI/Root.cpp index fadbaeeb6d..ef60f64e12 100644 --- a/Common/UI/Root.cpp +++ b/Common/UI/Root.cpp @@ -4,11 +4,11 @@ #include "ppsspp_config.h" -#include "Common/UI/Root.h" -#include "Common/UI/ViewGroup.h" - +#include "Common/Input/InputState.h" #include "Common/Log.h" #include "Common/TimeUtil.h" +#include "Common/UI/Root.h" +#include "Common/UI/ViewGroup.h" namespace UI { @@ -346,14 +346,21 @@ bool AxisEvent(const AxisInput &axis, ViewGroup *root) { old.x = dir; } if (axis.axisId == JOYSTICK_AXIS_Y || axis.axisId == JOYSTICK_AXIS_HAT_Y) { - // We stupidly interpret the joystick Y axis backwards on Android and Linux instead of reversing - // it early (see keymaps...). Too late to fix without invalidating a lot of config files, so we - // reverse it here too. + int direction = GetAnalogYDirection(axis.deviceId); + if (direction == 0) { + // We stupidly interpret the joystick Y axis backwards on Android and Linux instead of reversing + // it early (see keymaps...). Too late to fix without invalidating a lot of config files, so we + // reverse it here too. #if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) - GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_UP, NKCODE_DPAD_DOWN); + GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_UP, NKCODE_DPAD_DOWN); #else - GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_DOWN, NKCODE_DPAD_UP); + GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_DOWN, NKCODE_DPAD_UP); #endif + } else if (direction == -1) { + GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_UP, NKCODE_DPAD_DOWN); + } else { + GenerateKeyFromAxis(old.y, dir, NKCODE_DPAD_DOWN, NKCODE_DPAD_UP); + } old.y = dir; } break; diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index 43e268c79a..ad3e95cac9 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -15,8 +15,9 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include #include +#include +#include #if defined(SDL) #include @@ -49,6 +50,7 @@ struct DefMappingStruct { KeyMapping g_controllerMap; int g_controllerMapGeneration = 0; std::set g_seenPads; +static std::set g_seenDeviceIds; bool g_swapped_keys = false; @@ -352,6 +354,13 @@ void UpdateNativeMenuKeys() { SetDPadKeys(upKeys, downKeys, leftKeys, rightKeys); SetConfirmCancelKeys(confirmKeys, cancelKeys); SetTabLeftRightKeys(tabLeft, tabRight); + + std::unordered_map flipYByDeviceId; + for (int deviceId : g_seenDeviceIds) { + auto analogs = MappedAxesForDevice(deviceId); + flipYByDeviceId[deviceId] = analogs.leftY.direction; + } + SetAnalogFlipY(flipYByDeviceId); } static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, size_t count, bool replace) { @@ -361,6 +370,7 @@ static void SetDefaultKeyMap(int deviceId, const DefMappingStruct *array, size_t else SetAxisMapping(array[i].pspKey, deviceId, array[i].key, array[i].direction, replace); } + g_seenDeviceIds.insert(deviceId); } void SetDefaultKeyMap(DefaultMaps dmap, bool replace) { @@ -853,30 +863,31 @@ MappedAnalogAxes MappedAxesForDevice(int deviceId) { MappedAnalogAxes result{}; // Find the axisId mapped for a specific virtual button. - auto findAxisId = [&](int btn) -> int { + auto findAxisId = [&](int btn) -> MappedAnalogAxis { + MappedAnalogAxis info{ -1 }; for (const auto &key : g_controllerMap[btn]) { if (key.deviceId == deviceId) { - int direction = 0; - return TranslateKeyCodeToAxis(key.keyCode, direction); + info.axisId = TranslateKeyCodeToAxis(key.keyCode, info.direction); + return info; } } - return -1; + return info; }; // Find the axisId of a pair of opposing buttons. - auto findAxisIdPair = [&](int minBtn, int maxBtn) -> int { - int foundMin = findAxisId(minBtn); - int foundMax = findAxisId(maxBtn); - if (foundMin == foundMax) { + auto findAxisIdPair = [&](int minBtn, int maxBtn) -> MappedAnalogAxis { + MappedAnalogAxis foundMin = findAxisId(minBtn); + MappedAnalogAxis foundMax = findAxisId(maxBtn); + if (foundMin.axisId == foundMax.axisId) { return foundMax; } - return -1; + return MappedAnalogAxis{ -1 }; }; - result.leftXAxisId = findAxisIdPair(VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX); - result.leftYAxisId = findAxisIdPair(VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX); - result.rightXAxisId = findAxisIdPair(VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX); - result.rightYAxisId = findAxisIdPair(VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX); + result.leftX = findAxisIdPair(VIRTKEY_AXIS_X_MIN, VIRTKEY_AXIS_X_MAX); + result.leftY = findAxisIdPair(VIRTKEY_AXIS_Y_MIN, VIRTKEY_AXIS_Y_MAX); + result.rightX = findAxisIdPair(VIRTKEY_AXIS_RIGHT_X_MIN, VIRTKEY_AXIS_RIGHT_X_MAX); + result.rightY = findAxisIdPair(VIRTKEY_AXIS_RIGHT_Y_MIN, VIRTKEY_AXIS_RIGHT_Y_MAX); return result; } @@ -905,6 +916,7 @@ void SetKeyMapping(int btn, KeyDef key, bool replace) { } g_controllerMapGeneration++; + g_seenDeviceIds.insert(key.deviceId); UpdateNativeMenuKeys(); } @@ -969,6 +981,7 @@ void LoadFromIni(IniFile &file) { int keyCode = atoi(parts[1].c_str()); SetKeyMapping(psp_button_names[i].key, KeyDef(deviceId, keyCode), false); + g_seenDeviceIds.insert(deviceId); } } diff --git a/Core/KeyMap.h b/Core/KeyMap.h index 9953b0f87c..f6918ec71b 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -80,11 +80,16 @@ const float AXIS_BIND_THRESHOLD_MOUSE = 0.01f; typedef std::map> KeyMapping; +struct MappedAnalogAxis { + int axisId; + int direction; +}; + struct MappedAnalogAxes { - int leftXAxisId; - int leftYAxisId; - int rightXAxisId; - int rightYAxisId; + MappedAnalogAxis leftX; + MappedAnalogAxis leftY; + MappedAnalogAxis rightX; + MappedAnalogAxis rightY; }; // KeyMap diff --git a/Windows/DinputDevice.cpp b/Windows/DinputDevice.cpp index 4e605907ff..cb80e23be9 100644 --- a/Windows/DinputDevice.cpp +++ b/Windows/DinputDevice.cpp @@ -306,10 +306,10 @@ int DinputDevice::UpdateState() { axis.deviceId = DEVICE_ID_PAD_0 + pDevNum; auto axesToSquare = KeyMap::MappedAxesForDevice(axis.deviceId); - ApplyNormalization(js, axesToSquare.leftXAxisId, axesToSquare.leftYAxisId); + ApplyNormalization(js, axesToSquare.leftX.axisId, axesToSquare.leftY.axisId); // Prevent double normalization. - if (axesToSquare.leftXAxisId != axesToSquare.rightXAxisId && axesToSquare.leftXAxisId != axesToSquare.rightYAxisId) - ApplyNormalization(js, axesToSquare.rightXAxisId, axesToSquare.rightYAxisId); + if (axesToSquare.leftX.axisId != axesToSquare.rightX.axisId && axesToSquare.leftX.axisId != axesToSquare.rightY.axisId) + ApplyNormalization(js, axesToSquare.rightX.axisId, axesToSquare.rightY.axisId); SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lX, last_lX_, JOYSTICK_AXIS_X); SendNativeAxis(DEVICE_ID_PAD_0 + pDevNum, js.lY, last_lY_, JOYSTICK_AXIS_Y); From e2a8c83b9f6d8ef10f54cf697dcd6da255c37428 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 10:48:42 -0700 Subject: [PATCH 054/261] UI: Add BG animation for recent games. Just a subdued slideshow in the background. --- Core/Config.h | 5 -- Core/ConfigValues.h | 6 ++ UI/GameSettingsScreen.cpp | 2 +- UI/MiscScreens.cpp | 126 ++++++++++++++++++++++++++++++++++---- 4 files changed, 122 insertions(+), 17 deletions(-) diff --git a/Core/Config.h b/Core/Config.h index 9589ffe6e6..a7fcd1c147 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -38,11 +38,6 @@ enum ChatPositions { CENTER_RIGHT = 7, }; -enum class BackgroundAnimation { - OFF = 0, - FLOATING_SYMBOLS = 1, -}; - namespace http { class Download; class Downloader; diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index 8936f63809..d55af77964 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -116,3 +116,9 @@ enum class UnthrottleMode { SKIP_DRAW = 1, SKIP_FLIP = 2, }; + +enum class BackgroundAnimation { + OFF = 0, + FLOATING_SYMBOLS = 1, + RECENT_GAMES = 2, +}; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 7ad03db35d..ba77244124 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -875,7 +875,7 @@ void GameSettingsScreen::CreateViews() { if (backgroundChoice_ != nullptr) { backgroundChoice_->OnClick.Handle(this, &GameSettingsScreen::OnChangeBackground); } - static const char *backgroundAnimations[] = { "No animation", "Floating Symbols" }; + static const char *backgroundAnimations[] = { "No animation", "Floating symbols", "Recent games" }; systemSettings->Add(new PopupMultiChoice(&g_Config.iBackgroundAnimation, sy->T("UI background animation"), backgroundAnimations, 0, ARRAY_SIZE(backgroundAnimations), sy->GetName(), screenManager())); systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team"))); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 1e8271b9dd..af1133b540 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -85,17 +85,11 @@ public: void Draw(UIContext &dc, double t, float alpha) override { float xres = dc.GetBounds().w; float yres = dc.GetBounds().h; - if (xbase[0] == 0.0f || last_xres != xres || last_yres != yres) { - GMRng rng; - for (int i = 0; i < 100; i++) { - xbase[i] = rng.F() * xres; - ybase[i] = rng.F() * yres; - } - last_xres = xres; - last_yres = yres; + if (last_xres != xres || last_yres != yres) { + Regenerate(xres, yres); } - for (int i = 0; i < 100; i++) { + for (int i = 0; i < COUNT; i++) { float x = xbase[i] + dc.GetBounds().x; float y = ybase[i] + dc.GetBounds().y + 40 * cosf(i * 7.2f + t * 1.3f); float angle = (float)sin(i + t); @@ -103,11 +97,118 @@ public: ui_draw2d.DrawImageRotated(symbols[n], x, y, 1.0f, angle, colorAlpha(colors[n], alpha * 0.1f)); } } + private: - float xbase[100] = { 0 }; - float ybase[100] = { 0 }; + static constexpr int COUNT = 100; + + float xbase[COUNT]{}; + float ybase[COUNT]{}; float last_xres = 0; float last_yres = 0; + + void Regenerate(int xres, int yres) { + GMRng rng; + for (int i = 0; i < COUNT; i++) { + xbase[i] = rng.F() * xres; + ybase[i] = rng.F() * yres; + } + + last_xres = xres; + last_yres = yres; + } +}; + +class RecentGamesAnimation : public FloatingSymbolsAnimation { +public: + ~RecentGamesAnimation() override {} + void Draw(UIContext &dc, double t, float alpha) override { + if (lastIndex_ == nextIndex_) { + CheckNext(dc, t); + } else if (t > nextT_) { + lastIndex_ = nextIndex_; + } + + if (!g_Config.recentIsos.empty()) { + std::shared_ptr lastInfo = GetInfo(dc, lastIndex_); + std::shared_ptr nextInfo = GetInfo(dc, nextIndex_); + dc.Flush(); + + float lastAmount = Clamp((float)(nextT_ - t) * 1.0f / TRANSITION, 0.0f, 1.0f); + DrawTex(dc, lastInfo, lastAmount * alpha * 0.2f); + + float nextAmount = lastAmount <= 0.0f ? 1.0f : 1.0f - lastAmount; + DrawTex(dc, nextInfo, nextAmount * alpha * 0.2f); + + dc.RebindTexture(); + } + + FloatingSymbolsAnimation::Draw(dc, t, alpha * 0.5f); + } + +private: + void CheckNext(UIContext &dc, double t) { + if (g_Config.recentIsos.empty()) { + return; + } + + for (int index = lastIndex_ + 1; index != lastIndex_; ++index) { + if (index < 0 || index >= (int)g_Config.recentIsos.size()) { + if (lastIndex_ == -1) + break; + index = 0; + } + + std::shared_ptr ginfo = GetInfo(dc, index); + if (ginfo && ginfo->pending) { + // Wait for it to load. It might be the next one. + break; + } + if (ginfo && (ginfo->pic1.texture || ginfo->pic0.texture)) { + nextIndex_ = index; + nextT_ = t + INTERVAL; + break; + } + + // Otherwise, keep going. This skips games with no BG. + } + } + + std::shared_ptr GetInfo(UIContext &dc, int index) { + if (index < 0) { + return nullptr; + } + return g_gameInfoCache->GetInfo(dc.GetDrawContext(), g_Config.recentIsos[index], GAMEINFO_WANTBG); + } + + Draw::Texture *GetTex(std::shared_ptr &ginfo) { + if (ginfo && ginfo->pic1.texture) { + return ginfo->pic1.texture->GetTexture(); + } + if (ginfo && ginfo->pic0.texture) { + return ginfo->pic0.texture->GetTexture(); + } + return nullptr; + } + + void DrawTex(UIContext &dc, std::shared_ptr &ginfo, float amount) { + if (!ginfo || amount <= 0.0f) + return; + Draw::Texture *tex = GetTex(ginfo); + if (!tex) + return; + + dc.GetDrawContext()->BindTexture(0, tex); + uint32_t color = whiteAlpha(amount) & 0xFFc0c0c0; + dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color); + dc.Flush(); + } + + static constexpr double INTERVAL = 8.0; + static constexpr float TRANSITION = 3.0f; + + int lastIndex_ = -1; + int nextIndex_ = -1; + double nextT_ = -INTERVAL; }; // TODO: Add more styles. Remember to add to the enum in Config.cpp and the selector in GameSettings too. @@ -137,6 +238,9 @@ void DrawBackground(UIContext &dc, float alpha) { case BackgroundAnimation::FLOATING_SYMBOLS: g_Animation.reset(new FloatingSymbolsAnimation()); break; + case BackgroundAnimation::RECENT_GAMES: + g_Animation.reset(new RecentGamesAnimation()); + break; default: g_Animation.reset(nullptr); } From f98bafb73df73e29b039cd3b62aa17f221912e90 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 10:57:40 -0700 Subject: [PATCH 055/261] UI: Centralize BG pic choosing a bit. It's in several places. --- UI/GameInfoCache.h | 8 ++++++++ UI/MainScreen.cpp | 8 ++------ UI/MiscScreens.cpp | 33 ++++++++------------------------- UI/TextureUtil.cpp | 8 +++----- 4 files changed, 21 insertions(+), 36 deletions(-) diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 8563d111f9..ce9a2bf7b7 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -100,6 +100,14 @@ public: std::string GetTitle(); void SetTitle(const std::string &newTitle); + GameInfoTex *GetBGPic() { + if (pic0.texture) + return &pic0; + if (pic1.texture) + return &pic1; + return nullptr; + } + // Hold this when reading or writing from the GameInfo. // Don't need to hold it when just passing around the pointer, // and obviously also not when creating it and holding the only pointer diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 8ab0288b8b..90be90c501 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1309,12 +1309,8 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, f return false; } - Draw::Texture *texture = nullptr; - if (ginfo->pic1.texture) { - texture = ginfo->pic1.texture->GetTexture(); - } else if (ginfo->pic0.texture) { - texture = ginfo->pic0.texture->GetTexture(); - } + auto pic = ginfo->GetBGPic(); + Draw::Texture *texture = pic ? pic->texture->GetTexture() : nullptr; uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0; if (texture) { diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index af1133b540..4667fb4273 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -180,24 +180,14 @@ private: return g_gameInfoCache->GetInfo(dc.GetDrawContext(), g_Config.recentIsos[index], GAMEINFO_WANTBG); } - Draw::Texture *GetTex(std::shared_ptr &ginfo) { - if (ginfo && ginfo->pic1.texture) { - return ginfo->pic1.texture->GetTexture(); - } - if (ginfo && ginfo->pic0.texture) { - return ginfo->pic0.texture->GetTexture(); - } - return nullptr; - } - void DrawTex(UIContext &dc, std::shared_ptr &ginfo, float amount) { if (!ginfo || amount <= 0.0f) return; - Draw::Texture *tex = GetTex(ginfo); - if (!tex) + GameInfoTex *pic = ginfo->GetBGPic(); + if (!pic) return; - dc.GetDrawContext()->BindTexture(0, tex); + dc.GetDrawContext()->BindTexture(0, pic->texture->GetTexture()); uint32_t color = whiteAlpha(amount) & 0xFFc0c0c0; dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color); dc.Flush(); @@ -281,19 +271,12 @@ void DrawGameBackground(UIContext &dc, const std::string &gamePath) { ginfo = g_gameInfoCache->GetInfo(dc.GetDrawContext(), gamePath, GAMEINFO_WANTBG); dc.Flush(); - bool hasPic = false; - double loadTime; - if (ginfo && ginfo->pic1.texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic1.texture->GetTexture()); - loadTime = ginfo->pic1.timeLoaded; - hasPic = true; - } else if (ginfo && ginfo->pic0.texture) { - dc.GetDrawContext()->BindTexture(0, ginfo->pic0.texture->GetTexture()); - loadTime = ginfo->pic0.timeLoaded; - hasPic = true; + GameInfoTex *pic = ginfo ? ginfo->GetBGPic() : nullptr; + if (pic) { + dc.GetDrawContext()->BindTexture(0, pic->texture->GetTexture()); } - if (hasPic) { - uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)) & 0xFFc0c0c0; + if (pic) { + uint32_t color = whiteAlpha(ease((time_now_d() - pic->timeLoaded) * 3)) & 0xFFc0c0c0; dc.Draw()->DrawTexRect(dc.GetBounds(), 0,0,1,1, color); dc.Flush(); dc.RebindTexture(); diff --git a/UI/TextureUtil.cpp b/UI/TextureUtil.cpp index 3d986e765a..9a5b377a90 100644 --- a/UI/TextureUtil.cpp +++ b/UI/TextureUtil.cpp @@ -236,11 +236,9 @@ void GameIconView::Draw(UIContext &dc) { // Fade icon with the backgrounds. double loadTime = info->icon.timeLoaded; - if (info->pic1.texture) { - loadTime = std::max(loadTime, info->pic1.timeLoaded); - } - if (info->pic0.texture) { - loadTime = std::max(loadTime, info->pic0.timeLoaded); + auto pic = info->GetBGPic(); + if (pic) { + loadTime = std::max(loadTime, pic->timeLoaded); } uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)); From 0aa8a4886c8f3875a575cb34239f1dc64ef6a241 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 10:57:40 -0700 Subject: [PATCH 056/261] UI: Don't include symbols in recent games anim. --- UI/MiscScreens.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 4667fb4273..c5e8a9f720 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -118,7 +118,7 @@ private: } }; -class RecentGamesAnimation : public FloatingSymbolsAnimation { +class RecentGamesAnimation : public Animation { public: ~RecentGamesAnimation() override {} void Draw(UIContext &dc, double t, float alpha) override { @@ -141,8 +141,6 @@ public: dc.RebindTexture(); } - - FloatingSymbolsAnimation::Draw(dc, t, alpha * 0.5f); } private: From cc40d294ac785b3b6cb5b7288bd02e1c76bb65b0 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 4 Apr 2021 08:02:04 +0700 Subject: [PATCH 057/261] Fix stuck issue when scanning AP for Recruit on MGS:PW --- Core/HLE/sceNet.cpp | 73 ++++++++++++++++++++++++++++++++++++++------- Core/HLE/sceNet.h | 24 ++++++++------- 2 files changed, 75 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 3d1f8e3fb8..bff75e9856 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -499,6 +499,12 @@ void __NetApctlCallbacks() break; case PSP_NET_APCTL_EVENT_SCAN_COMPLETE: + newState = PSP_NET_APCTL_STATE_DISCONNECTED; + if (error == 0) + apctlEvents.push_front({ newState, newState, PSP_NET_APCTL_EVENT_SCAN_STOP, 0 }); + break; + + case PSP_NET_APCTL_EVENT_SCAN_STOP: newState = PSP_NET_APCTL_STATE_DISCONNECTED; break; @@ -1178,8 +1184,9 @@ static int sceNetApctlScanUser() { static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x)", __FUNCTION__, sizeAddr, bufAddr); - const int userInfoSize = 8; - int entries = 1; + const int userInfoSize = 8; // 8 bytes per entry (next address + entry id) + // Faking 4 entries, games like MGS:PW Recruit will need to have a different AP for each entry + int entries = 4; if (!Memory::IsValidAddress(sizeAddr)) hleLogError(SCENET, -1, "apctl invalid arg"); @@ -1195,7 +1202,7 @@ static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { break; } - DEBUG_LOG(SCENET, "%s returning %d at %08x", __FUNCTION__, i, bufAddr + offset); + DEBUG_LOG(SCENET, "%s writing ID#%d to %08x", __FUNCTION__, i, bufAddr + offset); // Pointer to next Network structure in list Memory::Write_U32((i+1)*userInfoSize + bufAddr, bufAddr + offset); @@ -1219,17 +1226,48 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd if (!Memory::IsValidAddress(resultAddr)) hleLogError(SCENET, -1, "apctl invalid arg"); + // Generate an SSID name + char dummySSID[APCTL_SSID_MAXLEN] = "WifiAP0"; + dummySSID[6] += static_cast(entryId); + switch (infoId) { case PSP_NET_APCTL_DESC_IBSS: // IBSS, 6 bytes - Memory::WriteStruct(resultAddr, &netApctlInfo.bssid); + if (entryId == 0) + Memory::WriteStruct(resultAddr, &netApctlInfo.bssid); + else { + // Generate a BSSID/MAC address + char dummyMAC[ETHER_ADDR_LEN]; + memset(&dummyMAC, entryId, sizeof(dummyMAC)); + // Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo) + dummyMAC[0] &= 0xfc; + Memory::WriteStruct(resultAddr, &dummyMAC); + } break; case PSP_NET_APCTL_DESC_SSID_NAME: // Return 32 bytes - Memory::WriteStruct(resultAddr, &netApctlInfo.ssid); + if (entryId == 0) + Memory::WriteStruct(resultAddr, &netApctlInfo.ssid); + else { + Memory::WriteStruct(resultAddr, &dummySSID); + } break; case PSP_NET_APCTL_DESC_SSID_NAME_LENGTH: // Return one 32-bit value - Memory::WriteStruct(resultAddr, &netApctlInfo.ssidLength); + if (entryId == 0) + Memory::WriteStruct(resultAddr, &netApctlInfo.ssidLength); + else { + // Calculate the SSID length + Memory::Write_U32((u32)strlen(dummySSID), resultAddr); + } + break; + case PSP_NET_APCTL_DESC_CHANNEL: + // FIXME: Return one 1 byte value or may be 32-bit if it this is not channel? + if (entryId == 0) + Memory::WriteStruct(resultAddr, &netApctlInfo.channel); + else { + // Generate channel for testing purposes, not even sure whether this is channel or not + Memory::Write_U32(entryId, resultAddr); + } break; case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH: // Return 1 byte @@ -1247,16 +1285,29 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd } static int sceNetApctlScanSSID2() { - ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__); + ERROR_LOG(SCENET, "UNIMPL %s() at %08x", __FUNCTION__, currentMIPS->pc); return NetApctl_ScanUser(); } +/************** +* Arg1 = output buffer size being filled? (initially the same with Arg3 ?) +* Arg2 = output buffer? (linked list where the 1st 32-bit is the next address? followed by entry Id? ie. 8-bytes per entry?) +* Arg3 = max buffer size? (ie. 0x100 ?) +* Arg4 = input flag? or output number of entries being filled? (initially 0/1 ?) +***************/ static int sceNetApctlGetBSSDescIDList2(u32 Arg1, u32 Arg2, u32 Arg3, u32 Arg4) { - return hleLogError(SCENET, 0, "unimplemented"); + ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x, %08x, %08x) at %08x", __FUNCTION__, Arg1, Arg2, Arg3, Arg4, currentMIPS->pc); + return hleLogError(SCENET, sceNetApctlGetBSSDescIDListUser(Arg1, Arg2), "unimplemented"); } -static int sceNetApctlGetBSSDescEntry2(u32 Arg1, u32 Arg2, u32 Arg3, u32 Arg4) { - return hleLogError(SCENET, 0, "unimplemented"); +/************** +* Arg1 = a value returned from sceNetApctlGetBSSDescIDList2 ? entryId? +* Arg2 = input field type within the entry desc (ie. PSP_NET_APCTL_DESC_SSID_NAME ?) +* Arg3 = output buffer for retrieved entry data? (max size = 32 bytes? ie. APCTL_SSID_MAXLEN ? or similar to SceNetApctlInfoInternal union ?) +***************/ +static int sceNetApctlGetBSSDescEntry2(int entryId, int infoId, u32 resultAddr) { + ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x, %08x) at %08x", __FUNCTION__, entryId, infoId, resultAddr, currentMIPS->pc); + return hleLogError(SCENET, sceNetApctlGetBSSDescEntryUser(entryId, infoId, resultAddr), "unimplemented"); } static int sceNetResolverInit() @@ -1434,7 +1485,7 @@ const HLEFunction sceNetApctl[] = { {0XA3E77E13, &WrapI_V, "sceNetApctlScanSSID2", 'i', "" }, {0XE9B2E5E6, &WrapI_V, "sceNetApctlScanUser", 'i', "" }, {0XF25A5006, &WrapI_UUUU, "sceNetApctlGetBSSDescIDList2", 'i', "xxxx" }, - {0X2935C45B, &WrapI_UUUU, "sceNetApctlGetBSSDescEntry2", 'i', "xxxx" }, + {0X2935C45B, &WrapI_IIU, "sceNetApctlGetBSSDescEntry2", 'i', "iix" }, {0X04776994, &WrapI_IIU, "sceNetApctlGetBSSDescEntryUser", 'i', "iix" }, {0X6BDDCB8C, &WrapI_UU, "sceNetApctlGetBSSDescIDListUser", 'i', "xx" }, {0X7CFAB990, &WrapI_UU, "sceNetApctlAddInternalHandler", 'i', "xx" }, diff --git a/Core/HLE/sceNet.h b/Core/HLE/sceNet.h index a1ba8285c3..911b61e5eb 100644 --- a/Core/HLE/sceNet.h +++ b/Core/HLE/sceNet.h @@ -181,7 +181,8 @@ enum { PSP_NET_APCTL_EVENT_INFO = 7, PSP_NET_APCTL_EVENT_EAP_AUTH = 8, PSP_NET_APCTL_EVENT_KEY_EXCHANGE = 9, - PSP_NET_APCTL_EVENT_RECONNECT = 10 + PSP_NET_APCTL_EVENT_RECONNECT = 10, + PSP_NET_APCTL_EVENT_SCAN_STOP = 11 // FIXME: not sure what this is, MGS:PW seems to check this value within ApctlHandler during Recruit, related to sceNetApctlScanSSID2 ? }; #define PSP_NET_APCTL_INFO_PROFILE_NAME 0 @@ -204,17 +205,18 @@ enum { #define PSP_NET_APCTL_INFO_START_BROWSER 17 #define PSP_NET_APCTL_INFO_WIFISP 18 -#define PSP_NET_APCTL_INFO_SECURITY_TYPE_NONE 0 -#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WEP 1 -#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA 2 -#define PSP_NET_APCTL_INFO_SECURITY_TYPE_UNSUPPORTED 3 -#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA_AES 4 +#define PSP_NET_APCTL_INFO_SECURITY_TYPE_NONE 0 +#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WEP 1 +#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA 2 +#define PSP_NET_APCTL_INFO_SECURITY_TYPE_UNSUPPORTED 3 +#define PSP_NET_APCTL_INFO_SECURITY_TYPE_WPA_AES 4 -#define PSP_NET_APCTL_DESC_IBSS 0 -#define PSP_NET_APCTL_DESC_SSID_NAME 1 -#define PSP_NET_APCTL_DESC_SSID_NAME_LENGTH 2 -#define PSP_NET_APCTL_DESC_SIGNAL_STRENGTH 4 -#define PSP_NET_APCTL_DESC_SECURITY 5 +#define PSP_NET_APCTL_DESC_IBSS 0 +#define PSP_NET_APCTL_DESC_SSID_NAME 1 +#define PSP_NET_APCTL_DESC_SSID_NAME_LENGTH 2 +#define PSP_NET_APCTL_DESC_CHANNEL 3 // FIXME: not sure what this 3 is, may be Security Type based on the order of SceNetApctlInfoInternal ? +#define PSP_NET_APCTL_DESC_SIGNAL_STRENGTH 4 +#define PSP_NET_APCTL_DESC_SECURITY 5 #ifdef _MSC_VER #pragma pack(push,1) From 824fedbef67081614a94ae84d587b032d0da465f Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 4 Apr 2021 14:03:17 +0700 Subject: [PATCH 058/261] Randomize signal strength between 1%~99% since games like MGS:PW are using signal strength to determine the strength of the recruit --- Core/HLE/sceNet.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index bff75e9856..047e29745b 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -1271,7 +1271,12 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd break; case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH: // Return 1 byte - Memory::WriteStruct(resultAddr, &netApctlInfo.strength); + if (entryId == 0) + Memory::WriteStruct(resultAddr, &netApctlInfo.strength); + else { + // Randomize signal strength between 1%~99% since games like MGS:PW are using signal strength to determine the strength of the recruit + Memory::Write_U8(rand()*99 + 1, resultAddr); + } break; case PSP_NET_APCTL_DESC_SECURITY: // Return one 32-bit value From 9e64eed4321726af0dab961009b69a61058d72d7 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 4 Apr 2021 14:48:01 +0700 Subject: [PATCH 059/261] minor fix --- Core/HLE/sceNet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 047e29745b..b9b0115206 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -1265,8 +1265,8 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd if (entryId == 0) Memory::WriteStruct(resultAddr, &netApctlInfo.channel); else { - // Generate channel for testing purposes, not even sure whether this is channel or not - Memory::Write_U32(entryId, resultAddr); + // Generate channel for testing purposes, not even sure whether this is channel or not, MGS:PW seems to treat the data as u8 + Memory::Write_U8(entryId, resultAddr); } break; case PSP_NET_APCTL_DESC_SIGNAL_STRENGTH: From 89ca70a1417cbef24a1c8d0340f112088a1043c9 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 4 Apr 2021 18:32:48 +0700 Subject: [PATCH 060/261] Ooops wrong way to do random range --- Core/HLE/sceNet.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index b9b0115206..d8fee8e261 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -1237,7 +1237,7 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd else { // Generate a BSSID/MAC address char dummyMAC[ETHER_ADDR_LEN]; - memset(&dummyMAC, entryId, sizeof(dummyMAC)); + memset(dummyMAC, entryId, sizeof(dummyMAC)); // Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo) dummyMAC[0] &= 0xfc; Memory::WriteStruct(resultAddr, &dummyMAC); @@ -1261,7 +1261,7 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd } break; case PSP_NET_APCTL_DESC_CHANNEL: - // FIXME: Return one 1 byte value or may be 32-bit if it this is not channel? + // FIXME: Return one 1 byte value or may be 32-bit if this is not a channel? if (entryId == 0) Memory::WriteStruct(resultAddr, &netApctlInfo.channel); else { @@ -1275,7 +1275,7 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd Memory::WriteStruct(resultAddr, &netApctlInfo.strength); else { // Randomize signal strength between 1%~99% since games like MGS:PW are using signal strength to determine the strength of the recruit - Memory::Write_U8(rand()*99 + 1, resultAddr); + Memory::Write_U8((int)(((float)rand() / (float)RAND_MAX) * 99.0 + 1.0), resultAddr); } break; case PSP_NET_APCTL_DESC_SECURITY: From 951080991a6df63d4fbc5f0ed097aa871aff865c Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Mon, 5 Apr 2021 04:29:39 +0700 Subject: [PATCH 061/261] Forgot to return on invalid address, and moving reusable code out of HLE to prevent generating confusing logs --- Core/HLE/sceNet.cpp | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index d8fee8e261..ae7e8af541 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -1164,7 +1164,7 @@ static int sceNetApctlGetState(u32 pStateAddr) { return hleLogSuccessI(SCENET, 0); } - return hleLogError(SCENET, -1, "apctl invalid arg"); + return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ? } int NetApctl_ScanUser() { @@ -1181,14 +1181,12 @@ static int sceNetApctlScanUser() { return NetApctl_ScanUser(); } -static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { - WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x)", __FUNCTION__, sizeAddr, bufAddr); - +int NetApctl_GetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { const int userInfoSize = 8; // 8 bytes per entry (next address + entry id) // Faking 4 entries, games like MGS:PW Recruit will need to have a different AP for each entry int entries = 4; - if (!Memory::IsValidAddress(sizeAddr)) - hleLogError(SCENET, -1, "apctl invalid arg"); + if (!Memory::IsValidAddress(sizeAddr) || !Memory::IsValidAddress(bufAddr)) + return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ? int size = Memory::Read_U32(sizeAddr); // Return size required @@ -1205,7 +1203,7 @@ static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { DEBUG_LOG(SCENET, "%s writing ID#%d to %08x", __FUNCTION__, i, bufAddr + offset); // Pointer to next Network structure in list - Memory::Write_U32((i+1)*userInfoSize + bufAddr, bufAddr + offset); + Memory::Write_U32((i + 1) * userInfoSize + bufAddr, bufAddr + offset); offset += 4; // Entry ID @@ -1217,14 +1215,17 @@ static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { Memory::Write_U32(0, bufAddr + offset - userInfoSize); } - return hleLogWarning(SCENET, 0, "untested"); + return 0; } -static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAddr) { - WARN_LOG(SCENET, "UNTESTED %s(%i, %i, %08x)", __FUNCTION__, entryId, infoId, resultAddr); +static int sceNetApctlGetBSSDescIDListUser(u32 sizeAddr, u32 bufAddr) { + WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x)", __FUNCTION__, sizeAddr, bufAddr); + return NetApctl_GetBSSDescIDListUser(sizeAddr, bufAddr); +} +int NetApctl_GetBSSDescEntryUser(int entryId, int infoId, u32 resultAddr) { if (!Memory::IsValidAddress(resultAddr)) - hleLogError(SCENET, -1, "apctl invalid arg"); + return hleLogError(SCENET, -1, "apctl invalid arg"); // 0x8002013A or ERROR_NET_WLAN_INVALID_ARG ? // Generate an SSID name char dummySSID[APCTL_SSID_MAXLEN] = "WifiAP0"; @@ -1286,11 +1287,16 @@ static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAdd return hleLogError(SCENET, ERROR_NET_APCTL_INVALID_CODE, "unknown info id"); } - return hleLogWarning(SCENET, 0, "untested"); + return 0; +} + +static int sceNetApctlGetBSSDescEntryUser(int entryId, int infoId, u32 resultAddr) { + WARN_LOG(SCENET, "UNTESTED %s(%i, %i, %08x)", __FUNCTION__, entryId, infoId, resultAddr); + return NetApctl_GetBSSDescEntryUser(entryId, infoId, resultAddr); } static int sceNetApctlScanSSID2() { - ERROR_LOG(SCENET, "UNIMPL %s() at %08x", __FUNCTION__, currentMIPS->pc); + WARN_LOG(SCENET, "UNTESTED %s() at %08x", __FUNCTION__, currentMIPS->pc); return NetApctl_ScanUser(); } @@ -1298,11 +1304,11 @@ static int sceNetApctlScanSSID2() { * Arg1 = output buffer size being filled? (initially the same with Arg3 ?) * Arg2 = output buffer? (linked list where the 1st 32-bit is the next address? followed by entry Id? ie. 8-bytes per entry?) * Arg3 = max buffer size? (ie. 0x100 ?) -* Arg4 = input flag? or output number of entries being filled? (initially 0/1 ?) +* Arg4 = input flag? (initially 0/1 ?) ***************/ static int sceNetApctlGetBSSDescIDList2(u32 Arg1, u32 Arg2, u32 Arg3, u32 Arg4) { - ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x, %08x, %08x) at %08x", __FUNCTION__, Arg1, Arg2, Arg3, Arg4, currentMIPS->pc); - return hleLogError(SCENET, sceNetApctlGetBSSDescIDListUser(Arg1, Arg2), "unimplemented"); + WARN_LOG(SCENET, "UNTESTED %s(%08x, %08x, %08x, %08x) at %08x", __FUNCTION__, Arg1, Arg2, Arg3, Arg4, currentMIPS->pc); + return NetApctl_GetBSSDescIDListUser(Arg1, Arg2); } /************** @@ -1311,8 +1317,8 @@ static int sceNetApctlGetBSSDescIDList2(u32 Arg1, u32 Arg2, u32 Arg3, u32 Arg4) * Arg3 = output buffer for retrieved entry data? (max size = 32 bytes? ie. APCTL_SSID_MAXLEN ? or similar to SceNetApctlInfoInternal union ?) ***************/ static int sceNetApctlGetBSSDescEntry2(int entryId, int infoId, u32 resultAddr) { - ERROR_LOG(SCENET, "UNIMPL %s(%08x, %08x, %08x) at %08x", __FUNCTION__, entryId, infoId, resultAddr, currentMIPS->pc); - return hleLogError(SCENET, sceNetApctlGetBSSDescEntryUser(entryId, infoId, resultAddr), "unimplemented"); + WARN_LOG(SCENET, "UNTESTED %s(%i, %i, %08x) at %08x", __FUNCTION__, entryId, infoId, resultAddr, currentMIPS->pc); + return NetApctl_GetBSSDescEntryUser(entryId, infoId, resultAddr); } static int sceNetResolverInit() From 8bfd8e9e0fbc062d03c73bc143966218672bb8f3 Mon Sep 17 00:00:00 2001 From: yonggamer <24843208+yonggamer@users.noreply.github.com> Date: Mon, 5 Apr 2021 00:18:08 +0200 Subject: [PATCH 062/261] Update glslang_UWP.vcxproj --- UWP/glslang_UWP/glslang_UWP.vcxproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj b/UWP/glslang_UWP/glslang_UWP.vcxproj index a25f2b6a41..69bb015a2e 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj @@ -383,7 +383,6 @@ - @@ -508,4 +507,4 @@ - \ No newline at end of file + From 7a1398844a3118f330efb46377c6336dff347b03 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 20:23:51 -0700 Subject: [PATCH 063/261] Debugger: Add simple API to control tagging detail. In case a client requires it. --- CMakeLists.txt | 2 + Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 ++ Core/Debugger/MemBlockInfo.cpp | 16 +++- Core/Debugger/MemBlockInfo.h | 4 + Core/Debugger/WebSocket.cpp | 2 + .../WebSocket/MemoryInfoSubscriber.cpp | 73 +++++++++++++++++++ .../Debugger/WebSocket/MemoryInfoSubscriber.h | 22 ++++++ Core/HLE/sceAtrac.cpp | 2 +- Core/HW/SasAudio.cpp | 4 +- UWP/CoreUWP/CoreUWP.vcxproj | 2 + UWP/CoreUWP/CoreUWP.vcxproj.filters | 6 ++ android/jni/Android.mk | 1 + 13 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp create mode 100644 Core/Debugger/WebSocket/MemoryInfoSubscriber.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 640d323b45..0adcdf1aff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1501,6 +1501,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Debugger/WebSocket/InputSubscriber.h Core/Debugger/WebSocket/LogBroadcaster.cpp Core/Debugger/WebSocket/LogBroadcaster.h + Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp + Core/Debugger/WebSocket/MemoryInfoSubscriber.h Core/Debugger/WebSocket/MemorySubscriber.cpp Core/Debugger/WebSocket/MemorySubscriber.h Core/Debugger/WebSocket/SteppingBroadcaster.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 30c555b669..30498dc411 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -442,6 +442,7 @@ + @@ -988,6 +989,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index f66273cddd..3ae957593a 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -980,6 +980,9 @@ Debugger + + Debugger\WebSocket + @@ -1676,6 +1679,9 @@ Debugger + + Debugger\WebSocket + diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 96b18bfa52..9377599918 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -87,6 +87,7 @@ static MemSlabMap writeMap; static MemSlabMap textureMap; static std::vector pendingNotifies; static std::mutex pendingMutex; +static int detailedOverride; MemSlabMap::MemSlabMap() { Reset(); @@ -373,7 +374,7 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ bool needFlush = false; // When the setting is off, we skip smaller info to keep things fast. - if (g_Config.bDebugMemInfoDetailed || size >= 0x100) { + if (size >= 0x100 || MemBlockInfoDetailed()) { PendingNotifyMem info{ flags, start, size }; info.ticks = CoreTiming::GetTicks(); info.pc = pc; @@ -472,3 +473,16 @@ void MemBlockInfoDoState(PointerWrap &p) { writeMap.DoState(p); textureMap.DoState(p); } + +// Used by the debugger. +void MemBlockOverrideDetailed() { + detailedOverride++; +} + +void MemBlockReleaseDetailed() { + detailedOverride--; +} + +bool MemBlockInfoDetailed() { + return g_Config.bDebugMemInfoDetailed || detailedOverride != 0; +} diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index 4e38c8410d..aec9d03725 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -68,3 +68,7 @@ std::string GetMemWriteTagAt(uint32_t start, uint32_t size); void MemBlockInfoInit(); void MemBlockInfoShutdown(); void MemBlockInfoDoState(PointerWrap &p); + +void MemBlockOverrideDetailed(); +void MemBlockReleaseDetailed(); +bool MemBlockInfoDetailed(); diff --git a/Core/Debugger/WebSocket.cpp b/Core/Debugger/WebSocket.cpp index c609e08698..3bd69366d0 100644 --- a/Core/Debugger/WebSocket.cpp +++ b/Core/Debugger/WebSocket.cpp @@ -57,6 +57,7 @@ #include "Core/Debugger/WebSocket/GPURecordSubscriber.h" #include "Core/Debugger/WebSocket/HLESubscriber.h" #include "Core/Debugger/WebSocket/InputSubscriber.h" +#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h" #include "Core/Debugger/WebSocket/MemorySubscriber.h" #include "Core/Debugger/WebSocket/SteppingSubscriber.h" @@ -70,6 +71,7 @@ static const std::vector subscribers({ &WebSocketGPURecordInit, &WebSocketHLEInit, &WebSocketInputInit, + &WebSocketMemoryInfoInit, &WebSocketMemoryInit, &WebSocketSteppingInit, }); diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp new file mode 100644 index 0000000000..e81fa2d44d --- /dev/null +++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2021- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "Core/Debugger/MemBlockInfo.h" +#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h" +#include "Core/Debugger/WebSocket/WebSocketUtils.h" + +class WebSocketMemoryInfoState : public DebuggerSubscriber { +public: + WebSocketMemoryInfoState() { + } + ~WebSocketMemoryInfoState() override { + UpdateOverride(false); + } + + void Config(DebuggerRequest &req); + +protected: + void UpdateOverride(bool flag); + + bool detailOverride_ = false; +}; + +DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) { + auto p = new WebSocketMemoryInfoState(); + map["memory.info.config"] = std::bind(&WebSocketMemoryInfoState::Config, p, std::placeholders::_1); + + return p; +} + +void WebSocketMemoryInfoState::UpdateOverride(bool flag) { + if (detailOverride_ && !flag) + MemBlockReleaseDetailed(); + if (!detailOverride_ && flag) + MemBlockOverrideDetailed(); + detailOverride_ = flag; +} + +// Update memory info tracking config (memory.info.config) +// +// Parameters: +// - detailed: optional, boolean to force enable detailed tracking (perf impact.) +// +// Response (same event name): +// - detailed: boolean state of tracking before any changes. +// +// Note: Even if you set false, may stay enabled if set by user or another debug session. +void WebSocketMemoryInfoState::Config(DebuggerRequest &req) { + bool setDetailed = req.HasParam("detailed"); + bool detailed = false; + if (!req.ParamBool("detailed", &detailed, DebuggerParamType::OPTIONAL)) + return; + + JsonWriter &json = req.Respond(); + json.writeBool("detailed", MemBlockInfoDetailed()); + + if (setDetailed) + UpdateOverride(detailed); +} diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.h b/Core/Debugger/WebSocket/MemoryInfoSubscriber.h new file mode 100644 index 0000000000..a093c5b693 --- /dev/null +++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.h @@ -0,0 +1,22 @@ +// Copyright (c) 2021- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "Core/Debugger/WebSocket/WebSocketUtils.h" + +DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map); diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index bccf2ce748..9a34a8ab94 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1257,7 +1257,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 int avret = swr_convert(atrac->swrCtx_, &out, numSamples, inbuf, numSamples); if (outbufPtr != 0) { u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); - if (packetAddr != 0 && g_Config.bDebugMemInfoDetailed) { + if (packetAddr != 0 && MemBlockInfoDetailed()) { const std::string tag = "AtracDecode/" + GetMemWriteTagAt(packetAddr, packetSize); NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size()); diff --git a/Core/HW/SasAudio.cpp b/Core/HW/SasAudio.cpp index e974f4de54..31de118345 100644 --- a/Core/HW/SasAudio.cpp +++ b/Core/HW/SasAudio.cpp @@ -149,7 +149,7 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) { } if (readp > origp) { - if (g_Config.bDebugMemInfoDetailed) + if (MemBlockInfoDetailed()) NotifyMemInfo(MemBlockFlags::READ, read_, readp - origp, "SasVagDecoder"); read_ += readp - origp; } @@ -582,7 +582,7 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) { if (outputMode == PSP_SAS_OUTPUTMODE_MIXED) { // Okay, apply effects processing to the Send buffer. WriteMixedOutput(outp, inp, leftVol, rightVol); - if (g_Config.bDebugMemInfoDetailed) { + if (MemBlockInfoDetailed()) { if (inp) NotifyMemInfo(MemBlockFlags::READ, inAddr, grainSize * sizeof(u16) * 2, "SasMix"); NotifyMemInfo(MemBlockFlags::WRITE, outAddr, grainSize * sizeof(u16) * 2, "SasMix"); diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index c72b42d206..77d9054999 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -404,6 +404,7 @@ + @@ -637,6 +638,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index f324ec0208..1c49dfe521 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -697,6 +697,9 @@ Debugger\WebSocket + + Debugger\WebSocket + Debugger\WebSocket @@ -1512,6 +1515,9 @@ Debugger\WebSocket + + Debugger\WebSocket + Debugger\WebSocket diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 04a223215c..38aba84863 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -418,6 +418,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/Debugger/WebSocket/InputSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/LogBroadcaster.cpp \ $(SRC)/Core/Debugger/WebSocket/MemorySubscriber.cpp \ + $(SRC)/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/SteppingBroadcaster.cpp \ $(SRC)/Core/Debugger/WebSocket/SteppingSubscriber.cpp \ $(SRC)/Core/Debugger/WebSocket/WebSocketUtils.cpp \ From a0c1320aec5d162155355fbc2d29f5576858eacf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 20:24:16 -0700 Subject: [PATCH 064/261] Debugger: Return detail for breakpoints in macros. --- Core/Debugger/WebSocket/DisasmSubscriber.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Core/Debugger/WebSocket/DisasmSubscriber.cpp b/Core/Debugger/WebSocket/DisasmSubscriber.cpp index f8820cee48..5f4848ea8a 100644 --- a/Core/Debugger/WebSocket/DisasmSubscriber.cpp +++ b/Core/Debugger/WebSocket/DisasmSubscriber.cpp @@ -135,12 +135,20 @@ void WebSocketDisasmState::WriteDisasmLine(JsonWriter &json, const DisassemblyLi json.writeNull("dataSymbol"); } - bool enabled; + bool enabled = false; + int breakpointOffset = -1; + for (u32 i = 0; i < l.totalSize; i += 4) { + if (CBreakPoints::IsAddressBreakPoint(addr + i, &enabled)) + breakpointOffset = i; + if (breakpointOffset != -1 && enabled) + break; + } // TODO: Account for bp inside macro? - if (CBreakPoints::IsAddressBreakPoint(addr, &enabled)) { + if (breakpointOffset != -1) { json.pushDict("breakpoint"); json.writeBool("enabled", enabled); - auto cond = CBreakPoints::GetBreakPointCondition(addr); + json.writeUint("address", addr + breakpointOffset); + auto cond = CBreakPoints::GetBreakPointCondition(addr + breakpointOffset); if (cond) json.writeString("condition", cond->expressionString); else From 124774fecbe741032400f4a3e5f377fd2c786f06 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 21:27:30 -0700 Subject: [PATCH 065/261] Debugger: Provide memory mapping ranges. Most of these are entirely static, but introspection is good for APIs. --- .../WebSocket/MemoryInfoSubscriber.cpp | 69 +++++++++++++++++++ Core/MemMap.h | 20 +++--- 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp index e81fa2d44d..ee2f34cd75 100644 --- a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp +++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp @@ -18,6 +18,7 @@ #include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h" #include "Core/Debugger/WebSocket/WebSocketUtils.h" +#include "Core/MemMap.h" class WebSocketMemoryInfoState : public DebuggerSubscriber { public: @@ -27,6 +28,7 @@ public: UpdateOverride(false); } + void Mapping(DebuggerRequest &req); void Config(DebuggerRequest &req); protected: @@ -37,6 +39,7 @@ protected: DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) { auto p = new WebSocketMemoryInfoState(); + map["memory.mapping"] = std::bind(&WebSocketMemoryInfoState::Mapping, p, std::placeholders::_1); map["memory.info.config"] = std::bind(&WebSocketMemoryInfoState::Config, p, std::placeholders::_1); return p; @@ -50,6 +53,72 @@ void WebSocketMemoryInfoState::UpdateOverride(bool flag) { detailOverride_ = flag; } +// List memory map data (memory.mapping) +// +// No parameters. +// +// Response (same event name): +// - ranges: array of objects: +// - type: one of "ram", "vram", "sram". +// - subtype: "primary" or "mirror". +// - name: string, friendly name. +// - address: number, start address of range. +// - size: number, in bytes. +// +// Note: Even if you set false, may stay enabled if set by user or another debug session. +void WebSocketMemoryInfoState::Mapping(DebuggerRequest &req) { + struct MemRange { + const char *type; + const char *subtype; + const char *name; + const uint32_t address; + const uint32_t size; + }; + constexpr uint32_t kernelMemorySize = PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(); + constexpr uint32_t volatileMemorySize = PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart(); + static constexpr MemRange ranges[] = { + { "sram", "primary", "Scratchpad", PSP_GetScratchpadMemoryBase(), Memory::SCRATCHPAD_SIZE }, + { "vram", "primary", "VRAM", PSP_GetVidMemBase(), Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Swizzled)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 1, Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Mirror)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 2, Memory::VRAM_SIZE }, + { "vram", "mirror", "VRAM (Swizzled + Interleaved)", PSP_GetVidMemBase() + Memory::VRAM_SIZE * 3, Memory::VRAM_SIZE }, + { "ram", "primary", "Kernel Memory", 0x80000000 | PSP_GetKernelMemoryBase(), kernelMemorySize }, + { "ram", "primary", "Volatile Memory", PSP_GetVolatileMemoryStart(), volatileMemorySize }, + // Size is specially calculated. + { "ram", "primary", "User Memory", PSP_GetUserMemoryBase(), 0 }, + }; + + JsonWriter &json = req.Respond(); + json.pushArray("ranges"); + for (auto range : ranges) { + uint32_t size = range.size; + if (size == 0) { + size = Memory::g_MemorySize; + if (size == 0) { + size = Memory::RAM_NORMAL_SIZE; + } + size -= kernelMemorySize + volatileMemorySize; + } + json.pushDict(); + json.writeString("type", range.type); + json.writeString("subtype", range.subtype); + json.writeString("name", range.name); + json.writeUint("address", range.address); + json.writeUint("size", size); + json.pop(); + + // Also write the uncached range. + json.pushDict(); + json.writeString("type", range.type); + json.writeString("subtype", "mirror"); + json.writeString("name", std::string("Uncached ") + range.name); + json.writeUint("address", 0x40000000 | range.address); + json.writeUint("size", size); + json.pop(); + } + json.pop(); +} + // Update memory info tracking config (memory.info.config) // // Parameters: diff --git a/Core/MemMap.h b/Core/MemMap.h index b9afe2ea35..a70d1510e8 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -459,22 +459,22 @@ struct PSPPointer }; -inline u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} -inline u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} +constexpr u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;} +constexpr u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;} -inline u32 PSP_GetKernelMemoryBase() { return 0x08000000;} +constexpr u32 PSP_GetKernelMemoryBase() { return 0x08000000;} inline u32 PSP_GetUserMemoryEnd() { return PSP_GetKernelMemoryBase() + Memory::g_MemorySize;} -inline u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} +constexpr u32 PSP_GetKernelMemoryEnd() { return 0x08400000;} // "Volatile" RAM is between 0x08400000 and 0x08800000, can be requested by the // game through sceKernelVolatileMemTryLock. -inline u32 PSP_GetVolatileMemoryStart() { return 0x08400000; } -inline u32 PSP_GetVolatileMemoryEnd() { return 0x08800000; } +constexpr u32 PSP_GetVolatileMemoryStart() { return 0x08400000; } +constexpr u32 PSP_GetVolatileMemoryEnd() { return 0x08800000; } -inline u32 PSP_GetUserMemoryBase() { return 0x08800000;} -inline u32 PSP_GetDefaultLoadAddress() { return 0;} -inline u32 PSP_GetVidMemBase() { return 0x04000000;} -inline u32 PSP_GetVidMemEnd() { return 0x04800000;} +constexpr u32 PSP_GetUserMemoryBase() { return 0x08800000; } +constexpr u32 PSP_GetDefaultLoadAddress() { return 0; } +constexpr u32 PSP_GetVidMemBase() { return 0x04000000; } +constexpr u32 PSP_GetVidMemEnd() { return 0x04800000; } template inline bool operator==(const PSPPointer &lhs, const PSPPointer &rhs) { From 0081924fc48995ae25919ee51cd6348cf9d05a9e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 Apr 2021 21:39:16 -0700 Subject: [PATCH 066/261] UI: Oops, prioritize PIC1, not PIC0. Thought I'd pasted these in the right order... fixes #14350. --- UI/GameInfoCache.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index ce9a2bf7b7..db7423ba2c 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -101,10 +101,10 @@ public: void SetTitle(const std::string &newTitle); GameInfoTex *GetBGPic() { - if (pic0.texture) - return &pic0; if (pic1.texture) return &pic1; + if (pic0.texture) + return &pic0; return nullptr; } From 35c02c801218288cec8a39d7fbfd772a603442db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 5 Apr 2021 18:30:57 +0200 Subject: [PATCH 067/261] Disable spvremapper from glslang by default, we don't use it. May partially help #14351 --- ext/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 16b4adbd7e..440f3c362c 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -7,6 +7,7 @@ endif() set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "let's not build binaries we don't need" FORCE) set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON CACHE BOOL "let's not use exceptions" FORCE) +set(ENABLE_SPVREMAPPER OFF CACHE BOOL "we don't need spvremapper" FORCE) # This is really a workaround for an NDK 20 compiler issue (PPSSPP issue #12105), but shouldn't hurt. if(ANDROID) From a23c9e6a4172a33a86927a9a835bdfd298d88021 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 5 Apr 2021 20:55:52 -0700 Subject: [PATCH 068/261] GPU: Preconvert light vecs to Vec3f. This might align better for simd anyway, but should also prevent any memory over-reads. See #14353. --- Core/Dialog/SavedataParam.cpp | 2 +- GPU/Common/TransformCommon.cpp | 22 ++++++++-------------- GPU/Common/TransformCommon.h | 15 ++++++++++----- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index f91752cb36..3da8a05947 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -1219,7 +1219,7 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param) param->idList->resultCount = (u32)validDir.size(); NotifyMemInfo(MemBlockFlags::WRITE, param->idList.ptr, sizeof(SceUtilitySavedataIdListInfo), "SavedataGetList"); - NotifyMemInfo(MemBlockFlags::WRITE, param->idList->entries.ptr, validDir.size() * sizeof(SceUtilitySavedataIdListEntry), "SavedataGetList"); + NotifyMemInfo(MemBlockFlags::WRITE, param->idList->entries.ptr, (uint32_t)validDir.size() * sizeof(SceUtilitySavedataIdListEntry), "SavedataGetList"); } return true; } diff --git a/GPU/Common/TransformCommon.cpp b/GPU/Common/TransformCommon.cpp index 85031c8e0e..5d74f30dd3 100644 --- a/GPU/Common/TransformCommon.cpp +++ b/GPU/Common/TransformCommon.cpp @@ -51,15 +51,9 @@ Lighter::Lighter(int vertType) { lconv[l] = getFloat24(gstate.lconv[l]); int i = l * 3; if (gstate.isLightChanEnabled(l)) { - lpos[i] = getFloat24(gstate.lpos[i]); - lpos[i + 1] = getFloat24(gstate.lpos[i + 1]); - lpos[i + 2] = getFloat24(gstate.lpos[i + 2]); - ldir[i] = getFloat24(gstate.ldir[i]); - ldir[i + 1] = getFloat24(gstate.ldir[i + 1]); - ldir[i + 2] = getFloat24(gstate.ldir[i + 2]); - latt[i] = getFloat24(gstate.latt[i]); - latt[i + 1] = getFloat24(gstate.latt[i + 1]); - latt[i + 2] = getFloat24(gstate.latt[i + 2]); + lpos[l] = Vec3fFromGE(&gstate.lpos[i]); + ldir[l] = Vec3fFromGE(&gstate.ldir[i]); + latt[l] = Vec3fFromGE(&gstate.latt[i]); for (int t = 0; t < 3; t++) { u32 data = gstate.lcolor[l * 3 + t] & 0xFFFFFF; float r = (float)(data & 0xff) * (1.0f / 255.0f); @@ -108,9 +102,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ Vec3f lightDir(0, 0, 0); if (type == GE_LIGHTTYPE_DIRECTIONAL) - toLight = Vec3Packedf(&lpos[l * 3]); // lightdir is for spotlights + toLight = lpos[l]; // lightdir is for spotlights else - toLight = Vec3Packedf(&lpos[l * 3]) - pos; + toLight = lpos[l] - pos; bool doSpecular = gstate.isUsingSpecularLight(l); bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l); @@ -136,14 +130,14 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[ lightScale = 1.0f; break; case GE_LIGHTTYPE_POINT: - lightScale = clamp(1.0f / (latt[l * 3] + latt[l * 3 + 1] * distanceToLight + latt[l * 3 + 2] * distanceToLight*distanceToLight), 0.0f, 1.0f); + lightScale = clamp(1.0f / (latt[l].x + latt[l].y * distanceToLight + latt[l].z * distanceToLight*distanceToLight), 0.0f, 1.0f); break; case GE_LIGHTTYPE_SPOT: case GE_LIGHTTYPE_UNKNOWN: - lightDir = Vec3Packedf(&ldir[l * 3]); + lightDir = ldir[l]; angle = Dot(toLight.NormalizedOr001(cpu_info.bSSE4_1), lightDir.NormalizedOr001(cpu_info.bSSE4_1)); if (angle >= lcutoff[l]) - lightScale = clamp(1.0f / (latt[l * 3] + latt[l * 3 + 1] * distanceToLight + latt[l * 3 + 2] * distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, lconv[l]); + lightScale = clamp(1.0f / (latt[l].x + latt[l].y * distanceToLight + latt[l].z * distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, lconv[l]); break; default: // ILLEGAL diff --git a/GPU/Common/TransformCommon.h b/GPU/Common/TransformCommon.h index 0a97975d26..f33a33c4c3 100644 --- a/GPU/Common/TransformCommon.h +++ b/GPU/Common/TransformCommon.h @@ -69,6 +69,13 @@ public: void Light(float colorOut0[4], float colorOut1[4], const float colorIn[4], const Vec3f &pos, const Vec3f &normal); private: + inline Vec3f Vec3fFromGE(const u32 *values) const { + float x = getFloat24(values[0]); + float y = getFloat24(values[1]); + float z = getFloat24(values[2]); + return Vec3f(x, y, z); + } + Color4 globalAmbient; Color4 materialEmissive; Color4 materialAmbient; @@ -80,11 +87,9 @@ private: int materialUpdate_; // Converted light parameters -public: - float lpos[12]; // Used by shade UV mapping -private: - float ldir[12]; - float latt[12]; + Vec3f lpos[4]; // Used by shade UV mapping + Vec3f ldir[4]; + Vec3f latt[4]; float lcutoff[4]; float lconv[4]; float lcolor[3][4][3]; From 49a4edbab5ae2289b5cbebd34f8963d2f26ab488 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Apr 2021 07:04:25 -0700 Subject: [PATCH 069/261] UI: Show more detailed load error messages. --- Core/System.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/System.cpp b/Core/System.cpp index f46eaa915d..cf86c440eb 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -412,7 +412,10 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { PSP_SetLoading("Loading game..."); if (!CPU_Init()) { - *error_string = "Failed initializing CPU/Memory"; + *error_string = coreParameter.errorString; + if (error_string->empty()) { + *error_string = "Failed initializing CPU/Memory"; + } pspIsIniting = false; return false; } From 5904900d370663a7bcc755e6689494ff41975d0d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Apr 2021 07:03:48 -0700 Subject: [PATCH 070/261] Debugger: Add APIs to set/list/search mem tags. --- Core/Debugger/MemBlockInfo.cpp | 10 +- Core/Debugger/MemBlockInfo.h | 5 +- Core/Debugger/WebSocket/DisasmSubscriber.cpp | 21 +- .../WebSocket/MemoryInfoSubscriber.cpp | 252 ++++++++++++++++++ Core/Debugger/WebSocket/WebSocketUtils.cpp | 13 + Core/Debugger/WebSocket/WebSocketUtils.h | 2 + 6 files changed, 281 insertions(+), 22 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 9377599918..5750c6735f 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -395,10 +395,12 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ FlushPendingMemInfo(); } - if (flags & MemBlockFlags::WRITE) { - CBreakPoints::ExecMemCheck(start, true, size, pc, tagStr); - } else if (flags & MemBlockFlags::READ) { - CBreakPoints::ExecMemCheck(start, false, size, pc, tagStr); + if (!(flags & MemBlockFlags::SKIP_MEMCHECK)) { + if (flags & MemBlockFlags::WRITE) { + CBreakPoints::ExecMemCheck(start, true, size, pc, tagStr); + } else if (flags & MemBlockFlags::READ) { + CBreakPoints::ExecMemCheck(start, false, size, pc, tagStr); + } } } diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index aec9d03725..786e713ba0 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -34,6 +34,8 @@ enum class MemBlockFlags { READ = 0x0800, FREE = 0x1000, SUB_FREE = 0x2000, + + SKIP_MEMCHECK = 0x00010000, }; ENUM_CLASS_BITOPS(MemBlockFlags); @@ -47,7 +49,8 @@ struct MemBlockInfo { bool allocated; }; -void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *str, size_t strLength); +void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *tag, size_t tagLength); +void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const char *tag, size_t tagLength); // This lets us avoid calling strlen on string constants, instead the string length (including null, // so we have to subtract 1) is computed at compile time. diff --git a/Core/Debugger/WebSocket/DisasmSubscriber.cpp b/Core/Debugger/WebSocket/DisasmSubscriber.cpp index 5f4848ea8a..fdebe9a892 100644 --- a/Core/Debugger/WebSocket/DisasmSubscriber.cpp +++ b/Core/Debugger/WebSocket/DisasmSubscriber.cpp @@ -47,7 +47,6 @@ public: protected: void WriteDisasmLine(JsonWriter &json, const DisassemblyLineInfo &l); void WriteBranchGuide(JsonWriter &json, const BranchLine &l); - uint32_t RoundAddressUp(uint32_t addr); DisassemblyManager disasm_; }; @@ -248,18 +247,6 @@ void WebSocketDisasmState::WriteBranchGuide(JsonWriter &json, const BranchLine & json.pop(); } -uint32_t WebSocketDisasmState::RoundAddressUp(uint32_t addr) { - if (addr < PSP_GetScratchpadMemoryBase()) - return PSP_GetScratchpadMemoryBase(); - else if (addr >= PSP_GetScratchpadMemoryEnd() && addr < PSP_GetVidMemBase()) - return PSP_GetVidMemBase(); - else if (addr >= PSP_GetVidMemEnd() && addr < PSP_GetKernelMemoryBase()) - return PSP_GetKernelMemoryBase(); - else if (addr >= PSP_GetUserMemoryEnd()) - return PSP_GetScratchpadMemoryBase(); - return addr; -} - // Request the current PSP memory base address (memory.base) // // WARNING: Avoid this unless you have a good reason. Uses PPSSPP's address space. @@ -383,7 +370,7 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { // Parameters: // - thread: optional number indicating the thread id (may not affect search much.) // - address: starting address as a number. -// - end: optional end address as a number (otherwise uses start.) +// - end: optional end address as a number (otherwise uses start address.) // - match: string to search for. // - displaySymbols: optional, specify false to hide symbols in the searched parameters. // @@ -410,7 +397,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) { return; bool loopSearch = end <= start; - start = RoundAddressUp(start); + start = RoundMemAddressUp(start); if ((end <= start) != loopSearch) { // We must've passed end by rounding up. JsonWriter &json = req.Respond(); @@ -419,7 +406,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) { } // We do this after the check in case both were in unused memory. - end = RoundAddressUp(end); + end = RoundMemAddressUp(end); std::transform(match.begin(), match.end(), match.begin(), ::tolower); @@ -450,7 +437,7 @@ void WebSocketDisasmState::SearchDisasm(DebuggerRequest &req) { break; } - addr = RoundAddressUp(addr + line.totalSize); + addr = RoundMemAddressUp(addr + line.totalSize); } while (addr != end); JsonWriter &json = req.Respond(); diff --git a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp index ee2f34cd75..30eb8cdd02 100644 --- a/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp +++ b/Core/Debugger/WebSocket/MemoryInfoSubscriber.cpp @@ -15,6 +15,9 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include +#include "Core/MIPS/MIPS.h" +#include "Core/MIPS/MIPSDebugInterface.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h" #include "Core/Debugger/WebSocket/WebSocketUtils.h" @@ -30,6 +33,9 @@ public: void Mapping(DebuggerRequest &req); void Config(DebuggerRequest &req); + void Set(DebuggerRequest &req); + void List(DebuggerRequest &req); + void Search(DebuggerRequest &req); protected: void UpdateOverride(bool flag); @@ -41,6 +47,9 @@ DebuggerSubscriber *WebSocketMemoryInfoInit(DebuggerEventHandlerMap &map) { auto p = new WebSocketMemoryInfoState(); map["memory.mapping"] = std::bind(&WebSocketMemoryInfoState::Mapping, p, std::placeholders::_1); map["memory.info.config"] = std::bind(&WebSocketMemoryInfoState::Config, p, std::placeholders::_1); + map["memory.info.set"] = std::bind(&WebSocketMemoryInfoState::Set, p, std::placeholders::_1); + map["memory.info.list"] = std::bind(&WebSocketMemoryInfoState::List, p, std::placeholders::_1); + map["memory.info.search"] = std::bind(&WebSocketMemoryInfoState::Search, p, std::placeholders::_1); return p; } @@ -140,3 +149,246 @@ void WebSocketMemoryInfoState::Config(DebuggerRequest &req) { if (setDetailed) UpdateOverride(detailed); } + +static MemBlockFlags FlagFromType(const std::string &type) { + if (type == "write") + return MemBlockFlags::WRITE; + if (type == "texture") + return MemBlockFlags::TEXTURE; + if (type == "alloc") + return MemBlockFlags::ALLOC; + if (type == "suballoc") + return MemBlockFlags::SUB_ALLOC; + if (type == "free") + return MemBlockFlags::FREE; + if (type == "subfree") + return MemBlockFlags::SUB_FREE; + return MemBlockFlags::SKIP_MEMCHECK; +} + +static std::string TypeFromFlag(const MemBlockFlags &flag) { + if (flag & MemBlockFlags::WRITE) + return "write"; + else if (flag & MemBlockFlags::TEXTURE) + return "texture"; + else if (flag & MemBlockFlags::ALLOC) + return "alloc"; + else if (flag & MemBlockFlags::SUB_ALLOC) + return "suballoc"; + return "error"; +} + +// Update memory info tagging (memory.info.set) +// +// Parameters: +// - address: number representing start address of the range to modify. +// - size: number, bytes from start address. +// - type: string, one of: +// - "write" for last modification information. +// - "texture" for last texture usage information. +// - "alloc" for allocation information. +// - "suballoc" for allocations within an existing allocation. +// - "free" to mark a previous allocation and its suballocations freed (ignores tag.) +// - "subfree" to mark a previous suballocation freed (ignores tag.) +// - tag: string label to give the memory. Optional if type if free or subfree. +// - pc: optional, number indicating PC address for this tag. +// +// Response (same event name) with no extra data. +// +// Note: Only one tag per type is maintained for any given memory address. +// Small extent info may be ignored unless detailed tracking enabled (see memory.info.config.) +void WebSocketMemoryInfoState::Set(DebuggerRequest &req) { + if (!currentDebugMIPS->isAlive() || !Memory::IsActive()) + return req.Fail("CPU not started"); + + std::string type; + if (!req.ParamString("type", &type)) + return; + std::string tag; + if (type != "free" && type != "subfree") { + if (!req.ParamString("tag", &tag)) + return; + } + uint32_t addr; + if (!req.ParamU32("address", &addr)) + return; + uint32_t size; + if (!req.ParamU32("size", &size)) + return; + uint32_t pc = currentMIPS->pc; + if (!req.ParamU32("pc", &pc, false, DebuggerParamType::OPTIONAL)) + return; + + MemBlockFlags flags = MemBlockFlags::SKIP_MEMCHECK | FlagFromType(type); + if (flags == MemBlockFlags::SKIP_MEMCHECK) + return req.Fail("Invaid type - expecting write, texture, alloc, suballoc, free, or subfree"); + + if (!Memory::IsValidAddress(addr)) + return req.Fail("Invalid address"); + else if (!Memory::IsValidRange(addr, size)) + return req.Fail("Invalid size"); + + NotifyMemInfoPC(flags, addr, size, pc, tag.c_str(), tag.size()); + req.Respond(); +} + +// List memory info tags for address range (memory.info.list) +// +// Parameters: +// - address: number representing start address of the range. +// - size: number, bytes from start address. +// - type: optional string to limit information to one of: +// - "write" for last modification information. +// - "texture" for last texture usage information. +// - "alloc" for allocation information. +// - "suballoc" for allocations within an existing allocation. +// +// Response (same event name): +// - extents: array of objects: +// - type: one of the above type string values. +// - address: number (may be outside requested range if overlapping.) +// - size: number (may be outside requested range if overlapping.) +// - ticks: number indicating tick counter as of last tag. +// - pc: number address of last tag. +// - tag: string tag for this memory extent. +// - allocated: boolean, if this extent is marked as allocated (for alloc/suballoc types.) +void WebSocketMemoryInfoState::List(DebuggerRequest &req) { + if (!currentDebugMIPS->isAlive() || !Memory::IsActive()) + return req.Fail("CPU not started"); + + std::string type; + if (!req.ParamString("type", &type, DebuggerParamType::OPTIONAL)) + return; + uint32_t addr; + if (!req.ParamU32("address", &addr)) + return; + uint32_t size; + if (!req.ParamU32("size", &size)) + return; + + // Allow type to be omitted. + MemBlockFlags flags = MemBlockFlags::SKIP_MEMCHECK | FlagFromType(type); + if (flags == MemBlockFlags::SKIP_MEMCHECK && req.HasParam("type")) + return req.Fail("Invaid type - expecting write, texture, alloc, suballoc, free, or subfree"); + + if (!Memory::IsValidAddress(addr)) + return req.Fail("Invalid address"); + else if (!Memory::IsValidRange(addr, size)) + return req.Fail("Invalid size"); + + std::vector results; + if (flags == MemBlockFlags::SKIP_MEMCHECK) + results = FindMemInfo(addr, size); + else + results = FindMemInfoByFlag(flags, addr, size); + + JsonWriter &json = req.Respond(); + json.pushArray("extents"); + for (const auto &result : results) { + json.pushDict(); + json.writeString("type", TypeFromFlag(result.flags)); + json.writeUint("address", result.start); + json.writeUint("size", result.size); + json.writeFloat("ticks", result.ticks); + json.writeUint("pc", result.pc); + json.writeString("tag", result.tag); + json.writeBool("allocated", result.allocated); + json.pop(); + } + json.pop(); +} + +// Search memory info tags for a string (memory.info.search) +// +// Parameters: +// - address: optional number representing start address of the range. +// - end: optional end address as a number (otherwise uses start address.) +// - match: string to search for within tag. +// - type: optional string to limit information to one of: +// - "write" for last modification information. +// - "texture" for last texture usage information. +// - "alloc" for allocation information. +// - "suballoc" for allocations within an existing allocation. +// +// Response (same event name): +// - extent: null, or matching object containing: +// - type: one of the above type string values. +// - address: number (may be outside requested range if overlapping.) +// - size: number (may be outside requested range if overlapping.) +// - ticks: number indicating tick counter as of last tag. +// - pc: number address of last tag. +// - tag: string tag for this memory extent. +// - allocated: boolean, if this extent is marked as allocated (for alloc/suballoc types.) +// +// Note: may not be fast. +void WebSocketMemoryInfoState::Search(DebuggerRequest &req) { + if (!currentDebugMIPS->isAlive() || !Memory::IsActive()) + return req.Fail("CPU not started"); + + uint32_t start = 0; + if (!req.ParamU32("address", &start, false, DebuggerParamType::OPTIONAL)) + return; + uint32_t end = start; + if (!req.ParamU32("end", &end, false, DebuggerParamType::OPTIONAL)) + return; + std::string type; + if (!req.ParamString("type", &type, DebuggerParamType::OPTIONAL)) + return; + std::string match; + if (!req.ParamString("match", &match)) + return; + + // Allow type to be omitted. + MemBlockFlags flags = MemBlockFlags::SKIP_MEMCHECK | FlagFromType(type); + if (flags == MemBlockFlags::SKIP_MEMCHECK && req.HasParam("type")) + return req.Fail("Invaid type - expecting write, texture, alloc, suballoc, free, or subfree"); + + start = RoundMemAddressUp(start); + end = RoundMemAddressUp(end); + std::transform(match.begin(), match.end(), match.begin(), ::tolower); + + bool found = false; + MemBlockInfo foundResult; + + uint32_t addr = start; + constexpr uint32_t CHUNK_SIZE = 0x1000; + do { + uint32_t chunk_end = addr + CHUNK_SIZE; + if (addr < end && chunk_end >= end) { + chunk_end = end; + } + + std::vector results; + if (flags == MemBlockFlags::SKIP_MEMCHECK) + results = FindMemInfo(addr, chunk_end - addr); + else + results = FindMemInfoByFlag(flags, addr, chunk_end - addr); + + for (const auto &result : results) { + std::string lowercase = result.tag; + std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower); + + if (lowercase.find(match) != lowercase.npos) { + found = true; + foundResult = result; + break; + } + } + addr = RoundMemAddressUp(chunk_end); + } while (!found && addr != end); + + JsonWriter &json = req.Respond(); + if (found) { + json.pushDict("extent"); + json.writeString("type", TypeFromFlag(foundResult.flags)); + json.writeUint("address", foundResult.start); + json.writeUint("size", foundResult.size); + json.writeFloat("ticks", foundResult.ticks); + json.writeUint("pc", foundResult.pc); + json.writeString("tag", foundResult.tag); + json.writeBool("allocated", foundResult.allocated); + json.pop(); + } else { + json.writeNull("extent"); + } +} diff --git a/Core/Debugger/WebSocket/WebSocketUtils.cpp b/Core/Debugger/WebSocket/WebSocketUtils.cpp index a9120b5caa..cc49e33336 100644 --- a/Core/Debugger/WebSocket/WebSocketUtils.cpp +++ b/Core/Debugger/WebSocket/WebSocketUtils.cpp @@ -21,6 +21,7 @@ #include "Common/Data/Text/Parsers.h" #include "Common/StringUtils.h" #include "Core/Debugger/WebSocket/WebSocketUtils.h" +#include "Core/MemMap.h" inline void DebuggerJsonAddTicket(JsonWriter &writer, const JsonGet &data) { const JsonNode *value = data.get("ticket"); @@ -273,3 +274,15 @@ bool DebuggerRequest::ParamString(const char *name, std::string *out, DebuggerPa Fail(StringFromFormat("Invalid '%s' parameter type", name)); return false; } + +uint32_t RoundMemAddressUp(uint32_t addr) { + if (addr < PSP_GetScratchpadMemoryBase()) + return PSP_GetScratchpadMemoryBase(); + else if (addr >= PSP_GetScratchpadMemoryEnd() && addr < PSP_GetVidMemBase()) + return PSP_GetVidMemBase(); + else if (addr >= PSP_GetVidMemEnd() && addr < PSP_GetKernelMemoryBase()) + return PSP_GetKernelMemoryBase(); + else if (addr >= PSP_GetUserMemoryEnd()) + return PSP_GetScratchpadMemoryBase(); + return addr; +} diff --git a/Core/Debugger/WebSocket/WebSocketUtils.h b/Core/Debugger/WebSocket/WebSocketUtils.h index 5caa28adaf..38edc24a68 100644 --- a/Core/Debugger/WebSocket/WebSocketUtils.h +++ b/Core/Debugger/WebSocket/WebSocketUtils.h @@ -109,3 +109,5 @@ public: typedef std::function DebuggerEventHandler; typedef std::unordered_map DebuggerEventHandlerMap; + +uint32_t RoundMemAddressUp(uint32_t addr); From 7b5d8bc38f2e0fc63b9f514b0869846d259b947d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Apr 2021 21:59:40 -0700 Subject: [PATCH 071/261] Utility: Move dialog classes to heap. This makes it easier to properly reset them on game reset. --- Core/Dialog/PSPSaveDialog.cpp | 1 + Core/HLE/sceUtility.cpp | 128 +++++++++++++++++++--------------- 2 files changed, 72 insertions(+), 57 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 34811f4fc6..3b54cb8b55 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -62,6 +62,7 @@ PSPSaveDialog::PSPSaveDialog(UtilityDialogType type) : PSPDialog(type) { } PSPSaveDialog::~PSPSaveDialog() { + JoinIOThread(); } int PSPSaveDialog::Init(int paramAddr) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index e0aa43ec83..1814cbff5b 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -123,12 +123,12 @@ static const ModuleLoadInfo moduleLoadInfo[] = { // Only a single dialog is allowed at a time. static UtilityDialogType currentDialogType; bool currentDialogActive; -static PSPSaveDialog saveDialog(UtilityDialogType::SAVEDATA); -static PSPMsgDialog msgDialog(UtilityDialogType::MSG); -static PSPOskDialog oskDialog(UtilityDialogType::OSK); -static PSPNetconfDialog netDialog(UtilityDialogType::NET); -static PSPScreenshotDialog screenshotDialog(UtilityDialogType::SCREENSHOT); -static PSPGamedataInstallDialog gamedataInstallDialog(UtilityDialogType::GAMEDATAINSTALL); +static PSPSaveDialog *saveDialog; +static PSPMsgDialog *msgDialog; +static PSPOskDialog *oskDialog; +static PSPNetconfDialog *netDialog; +static PSPScreenshotDialog *screenshotDialog; +static PSPGamedataInstallDialog *gamedataInstallDialog; static int oldStatus = 100; //random value static std::map currentlyLoadedModules; @@ -159,15 +159,22 @@ static void DeactivateDialog() { static void UtilityVolatileUnlock(u64 userdata, int cyclesLate) { // There can only be one active, so just try each of them. - saveDialog.FinishVolatile(); - msgDialog.FinishVolatile(); - oskDialog.FinishVolatile(); - netDialog.FinishVolatile(); - screenshotDialog.FinishVolatile(); - gamedataInstallDialog.FinishVolatile(); + saveDialog->FinishVolatile(); + msgDialog->FinishVolatile(); + oskDialog->FinishVolatile(); + netDialog->FinishVolatile(); + screenshotDialog->FinishVolatile(); + gamedataInstallDialog->FinishVolatile(); } void __UtilityInit() { + saveDialog = new PSPSaveDialog(UtilityDialogType::SAVEDATA); + msgDialog = new PSPMsgDialog(UtilityDialogType::MSG); + oskDialog = new PSPOskDialog(UtilityDialogType::OSK); + netDialog = new PSPNetconfDialog(UtilityDialogType::NET); + screenshotDialog = new PSPScreenshotDialog(UtilityDialogType::SCREENSHOT); + gamedataInstallDialog = new PSPGamedataInstallDialog(UtilityDialogType::GAMEDATAINSTALL); + currentDialogType = UtilityDialogType::NONE; DeactivateDialog(); SavedataParam::Init(); @@ -183,12 +190,12 @@ void __UtilityDoState(PointerWrap &p) { Do(p, currentDialogType); Do(p, currentDialogActive); - saveDialog.DoState(p); - msgDialog.DoState(p); - oskDialog.DoState(p); - netDialog.DoState(p); - screenshotDialog.DoState(p); - gamedataInstallDialog.DoState(p); + saveDialog->DoState(p); + msgDialog->DoState(p); + oskDialog->DoState(p); + netDialog->DoState(p); + screenshotDialog->DoState(p); + gamedataInstallDialog->DoState(p); if (s >= 2) { Do(p, currentlyLoadedModules); @@ -225,17 +232,24 @@ void __UtilityDoState(PointerWrap &p) { } void __UtilityShutdown() { - saveDialog.Shutdown(true); - msgDialog.Shutdown(true); - oskDialog.Shutdown(true); - netDialog.Shutdown(true); - screenshotDialog.Shutdown(true); - gamedataInstallDialog.Shutdown(true); + saveDialog->Shutdown(true); + msgDialog->Shutdown(true); + oskDialog->Shutdown(true); + netDialog->Shutdown(true); + screenshotDialog->Shutdown(true); + gamedataInstallDialog->Shutdown(true); if (accessThread) { delete accessThread; accessThread = nullptr; } + + delete saveDialog; + delete msgDialog; + delete oskDialog; + delete netDialog; + delete screenshotDialog; + delete gamedataInstallDialog; } void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) { @@ -277,19 +291,19 @@ static int UtilityFinishDialog(int type) { case UtilityDialogType::NONE: break; case UtilityDialogType::SAVEDATA: - return hleLogSuccessI(SCEUTILITY, saveDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, saveDialog->FinishShutdown()); case UtilityDialogType::MSG: - return hleLogSuccessI(SCEUTILITY, msgDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, msgDialog->FinishShutdown()); case UtilityDialogType::OSK: - return hleLogSuccessI(SCEUTILITY, oskDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, oskDialog->FinishShutdown()); case UtilityDialogType::NET: - return hleLogSuccessI(SCEUTILITY, netDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, netDialog->FinishShutdown()); case UtilityDialogType::SCREENSHOT: - return hleLogSuccessI(SCEUTILITY, screenshotDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, screenshotDialog->FinishShutdown()); case UtilityDialogType::GAMESHARING: return hleLogError(SCEUTILITY, -1, "unimplemented"); case UtilityDialogType::GAMEDATAINSTALL: - return hleLogSuccessI(SCEUTILITY, gamedataInstallDialog.FinishShutdown()); + return hleLogSuccessI(SCEUTILITY, gamedataInstallDialog->FinishShutdown()); } return hleLogError(SCEUTILITY, 0, "invalid dialog type?"); } @@ -306,7 +320,7 @@ static int sceUtilitySavedataInitStart(u32 paramAddr) { oldStatus = 100; ActivateDialog(UtilityDialogType::SAVEDATA); - int ret = saveDialog.Init(paramAddr); + int ret = saveDialog->Init(paramAddr); DEBUG_LOG(SCEUTILITY,"%08x=sceUtilitySavedataInitStart(%08x)",ret,paramAddr); return ret; } @@ -316,7 +330,7 @@ static int sceUtilitySavedataShutdownStart() { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); DeactivateDialog(); - int ret = saveDialog.Shutdown(); + int ret = saveDialog->Shutdown(); hleEatCycles(30000); return hleLogSuccessX(SCEUTILITY, ret); } @@ -328,7 +342,7 @@ static int sceUtilitySavedataGetStatus() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int status = saveDialog.GetStatus(); + int status = saveDialog->GetStatus(); if (oldStatus != status) { oldStatus = status; DEBUG_LOG(SCEUTILITY, "%08x=sceUtilitySavedataGetStatus()", status); @@ -344,7 +358,7 @@ static int sceUtilitySavedataUpdate(int animSpeed) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int result = saveDialog.Update(animSpeed); + int result = saveDialog->Update(animSpeed); DEBUG_LOG(SCEUTILITY,"%08x=sceUtilitySavedataUpdate(%i)", result, animSpeed); if (result >= 0) return hleDelayResult(result, "savedata update", 300); @@ -442,7 +456,7 @@ static int sceUtilityMsgDialogInitStart(u32 paramAddr) { oldStatus = 100; ActivateDialog(UtilityDialogType::MSG); - int ret = msgDialog.Init(paramAddr); + int ret = msgDialog->Init(paramAddr); INFO_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogInitStart(%08x)", ret, paramAddr); return ret; } @@ -454,7 +468,7 @@ static int sceUtilityMsgDialogShutdownStart() { } DeactivateDialog(); - int ret = msgDialog.Shutdown(); + int ret = msgDialog->Shutdown(); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogShutdownStart()", ret); return ret; } @@ -465,7 +479,7 @@ static int sceUtilityMsgDialogUpdate(int animSpeed) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = msgDialog.Update(animSpeed); + int ret = msgDialog->Update(animSpeed); DEBUG_LOG(SCEUTILITY,"%08x=sceUtilityMsgDialogUpdate(%i)", ret, animSpeed); if (ret >= 0) return hleDelayResult(ret, "msgdialog update", 800); @@ -478,7 +492,7 @@ static int sceUtilityMsgDialogGetStatus() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int status = msgDialog.GetStatus(); + int status = msgDialog->GetStatus(); if (oldStatus != status) { oldStatus = status; DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogGetStatus()", status); @@ -493,7 +507,7 @@ static int sceUtilityMsgDialogAbort() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = msgDialog.Abort(); + int ret = msgDialog->Abort(); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogAbort()", ret); return ret; } @@ -508,7 +522,7 @@ static int sceUtilityOskInitStart(u32 oskPtr) { oldStatus = 100; ActivateDialog(UtilityDialogType::OSK); - int ret = oskDialog.Init(oskPtr); + int ret = oskDialog->Init(oskPtr); INFO_LOG(SCEUTILITY, "%08x=sceUtilityOskInitStart(%08x)", ret, oskPtr); return ret; } @@ -521,7 +535,7 @@ static int sceUtilityOskShutdownStart() { } DeactivateDialog(); - int ret = oskDialog.Shutdown(); + int ret = oskDialog->Shutdown(); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskShutdownStart()",ret); return ret; } @@ -532,7 +546,7 @@ static int sceUtilityOskUpdate(int animSpeed) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = oskDialog.Update(animSpeed); + int ret = oskDialog->Update(animSpeed); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskUpdate(%i)", ret, animSpeed); return ret; } @@ -543,7 +557,7 @@ static int sceUtilityOskGetStatus() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int status = oskDialog.GetStatus(); + int status = oskDialog->GetStatus(); if (oldStatus != status) { oldStatus = status; DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskGetStatus()", status); @@ -560,7 +574,7 @@ static int sceUtilityNetconfInitStart(u32 paramsAddr) { oldStatus = 100; ActivateDialog(UtilityDialogType::NET); - return hleLogSuccessInfoI(SCEUTILITY, netDialog.Init(paramsAddr)); + return hleLogSuccessInfoI(SCEUTILITY, netDialog->Init(paramsAddr)); } static int sceUtilityNetconfShutdownStart() { @@ -569,7 +583,7 @@ static int sceUtilityNetconfShutdownStart() { } DeactivateDialog(); - return hleLogSuccessI(SCEUTILITY, netDialog.Shutdown()); + return hleLogSuccessI(SCEUTILITY, netDialog->Shutdown()); } static int sceUtilityNetconfUpdate(int animSpeed) { @@ -577,7 +591,7 @@ static int sceUtilityNetconfUpdate(int animSpeed) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - return hleLogSuccessI(SCEUTILITY, netDialog.Update(animSpeed)); + return hleLogSuccessI(SCEUTILITY, netDialog->Update(animSpeed)); } static int sceUtilityNetconfGetStatus() { @@ -586,7 +600,7 @@ static int sceUtilityNetconfGetStatus() { return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int status = netDialog.GetStatus(); + int status = netDialog->GetStatus(); if (oldStatus != status) { oldStatus = status; return hleLogSuccessI(SCEUTILITY, status); @@ -614,7 +628,7 @@ static int sceUtilityScreenshotInitStart(u32 paramAddr) { oldStatus = 100; ActivateDialog(UtilityDialogType::SCREENSHOT); - u32 retval = screenshotDialog.Init(paramAddr); + u32 retval = screenshotDialog->Init(paramAddr); WARN_LOG_REPORT(SCEUTILITY, "%08x=sceUtilityScreenshotInitStart(%08x)", retval, paramAddr); return retval; } @@ -626,7 +640,7 @@ static int sceUtilityScreenshotShutdownStart() { } DeactivateDialog(); - int ret = screenshotDialog.Shutdown(); + int ret = screenshotDialog->Shutdown(); WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotShutdownStart()", ret); return ret; } @@ -637,7 +651,7 @@ static int sceUtilityScreenshotUpdate(u32 animSpeed) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = screenshotDialog.Update(animSpeed); + int ret = screenshotDialog->Update(animSpeed); WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotUpdate(%i)", ret, animSpeed); return ret; } @@ -648,7 +662,7 @@ static int sceUtilityScreenshotGetStatus() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int status = screenshotDialog.GetStatus(); + int status = screenshotDialog->GetStatus(); if (oldStatus != status) { oldStatus = status; WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotGetStatus()", status); @@ -663,7 +677,7 @@ static int sceUtilityScreenshotContStart(u32 paramAddr) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = screenshotDialog.ContStart(); + int ret = screenshotDialog->ContStart(); WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotContStart(%08x)", ret, paramAddr); return ret; } @@ -675,7 +689,7 @@ static int sceUtilityGamedataInstallInitStart(u32 paramsAddr) { } ActivateDialog(UtilityDialogType::GAMEDATAINSTALL); - int ret = gamedataInstallDialog.Init(paramsAddr); + int ret = gamedataInstallDialog->Init(paramsAddr); INFO_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallInitStart(%08x)",ret,paramsAddr); return ret; } @@ -688,7 +702,7 @@ static int sceUtilityGamedataInstallShutdownStart() { DeactivateDialog(); DEBUG_LOG(SCEUTILITY, "sceUtilityGamedataInstallShutdownStart()"); - return gamedataInstallDialog.Shutdown(); + return gamedataInstallDialog->Shutdown(); } static int sceUtilityGamedataInstallUpdate(int animSpeed) { @@ -697,7 +711,7 @@ static int sceUtilityGamedataInstallUpdate(int animSpeed) { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int ret = gamedataInstallDialog.Update(animSpeed); + int ret = gamedataInstallDialog->Update(animSpeed); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallUpdate(%i)", ret, animSpeed); return ret; } @@ -709,7 +723,7 @@ static int sceUtilityGamedataInstallGetStatus() { return SCE_ERROR_UTILITY_WRONG_TYPE; } - int status = gamedataInstallDialog.GetStatus(); + int status = gamedataInstallDialog->GetStatus(); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallGetStatus()", status); CleanupDialogThreads(); return status; @@ -722,7 +736,7 @@ static int sceUtilityGamedataInstallAbort() { } DeactivateDialog(); - int ret = gamedataInstallDialog.Abort(); + int ret = gamedataInstallDialog->Abort(); DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallDialogAbort",ret); return ret; } From 4200021a95c38fc8a621c1af336d078368a1ffc7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Apr 2021 22:18:28 -0700 Subject: [PATCH 072/261] Utility: Update logging to new syntax for dialogs. --- Core/HLE/sceUtility.cpp | 167 ++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 111 deletions(-) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 1814cbff5b..6f37c50ad4 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -313,16 +313,13 @@ static int sceUtilitySavedataInitStart(u32 paramAddr) { if (PSP_CoreParameter().compat.flags().YugiohSaveFix) { WARN_LOG(SCEUTILITY, "Yugioh Savedata Correction"); } else { - WARN_LOG(SCEUTILITY, "sceUtilitySavedataInitStart(%08x): wrong dialog type", paramAddr); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } } oldStatus = 100; ActivateDialog(UtilityDialogType::SAVEDATA); - int ret = saveDialog->Init(paramAddr); - DEBUG_LOG(SCEUTILITY,"%08x=sceUtilitySavedataInitStart(%08x)",ret,paramAddr); - return ret; + return hleLogSuccessX(SCEUTILITY, saveDialog->Init(paramAddr)); } static int sceUtilitySavedataShutdownStart() { @@ -337,29 +334,26 @@ static int sceUtilitySavedataShutdownStart() { static int sceUtilitySavedataGetStatus() { if (currentDialogType != UtilityDialogType::SAVEDATA) { - DEBUG_LOG(SCEUTILITY, "sceUtilitySavedataGetStatus(): wrong dialog type"); hleEatCycles(200); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } int status = saveDialog->GetStatus(); - if (oldStatus != status) { - oldStatus = status; - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilitySavedataGetStatus()", status); - } hleEatCycles(200); CleanupDialogThreads(); - return status; + if (oldStatus != status) { + oldStatus = status; + return hleLogSuccessI(SCEUTILITY, status); + } + return hleLogSuccessVerboseI(SCEUTILITY, status); } static int sceUtilitySavedataUpdate(int animSpeed) { if (currentDialogType != UtilityDialogType::SAVEDATA) { - WARN_LOG(SCEUTILITY, "sceUtilitySavedataUpdate(%i): wrong dialog type", animSpeed); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int result = saveDialog->Update(animSpeed); - DEBUG_LOG(SCEUTILITY,"%08x=sceUtilitySavedataUpdate(%i)", result, animSpeed); + int result = hleLogSuccessI(SCEUTILITY, saveDialog->Update(animSpeed)); if (result >= 0) return hleDelayResult(result, "savedata update", 300); return result; @@ -450,37 +444,29 @@ static u32 sceUtilityUnloadModule(u32 module) { static int sceUtilityMsgDialogInitStart(u32 paramAddr) { if (currentDialogActive && currentDialogType != UtilityDialogType::MSG) { - WARN_LOG(SCEUTILITY, "sceUtilityMsgDialogInitStart(%08x): wrong dialog type", paramAddr); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } oldStatus = 100; ActivateDialog(UtilityDialogType::MSG); - int ret = msgDialog->Init(paramAddr); - INFO_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogInitStart(%08x)", ret, paramAddr); - return ret; + return hleLogSuccessInfoX(SCEUTILITY, msgDialog->Init(paramAddr)); } static int sceUtilityMsgDialogShutdownStart() { if (currentDialogType != UtilityDialogType::MSG) { - WARN_LOG(SCEUTILITY, "sceUtilityMsgDialogShutdownStart(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } DeactivateDialog(); - int ret = msgDialog->Shutdown(); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogShutdownStart()", ret); - return ret; + return hleLogSuccessX(SCEUTILITY, msgDialog->Shutdown()); } static int sceUtilityMsgDialogUpdate(int animSpeed) { if (currentDialogType != UtilityDialogType::MSG) { - WARN_LOG(SCEUTILITY, "sceUtilityMsgDialogUpdate(%i): wrong dialog type", animSpeed); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = msgDialog->Update(animSpeed); - DEBUG_LOG(SCEUTILITY,"%08x=sceUtilityMsgDialogUpdate(%i)", ret, animSpeed); + int ret = hleLogSuccessX(SCEUTILITY, msgDialog->Update(animSpeed)); if (ret >= 0) return hleDelayResult(ret, "msgdialog update", 800); return ret; @@ -488,82 +474,67 @@ static int sceUtilityMsgDialogUpdate(int animSpeed) { static int sceUtilityMsgDialogGetStatus() { if (currentDialogType != UtilityDialogType::MSG) { - DEBUG_LOG(SCEUTILITY, "sceUtilityMsgDialogGetStatus(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } int status = msgDialog->GetStatus(); + CleanupDialogThreads(); if (oldStatus != status) { oldStatus = status; - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogGetStatus()", status); + return hleLogSuccessI(SCEUTILITY, status); } - CleanupDialogThreads(); - return status; + return hleLogSuccessVerboseI(SCEUTILITY, status); } static int sceUtilityMsgDialogAbort() { if (currentDialogType != UtilityDialogType::MSG) { - WARN_LOG(SCEUTILITY, "sceUtilityMsgDialogAbort(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = msgDialog->Abort(); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityMsgDialogAbort()", ret); - return ret; + return hleLogSuccessX(SCEUTILITY, msgDialog->Abort()); } // On screen keyboard static int sceUtilityOskInitStart(u32 oskPtr) { if (currentDialogActive && currentDialogType != UtilityDialogType::OSK) { - WARN_LOG(SCEUTILITY, "sceUtilityOskInitStart(%08x): wrong dialog type", oskPtr); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } oldStatus = 100; ActivateDialog(UtilityDialogType::OSK); - int ret = oskDialog->Init(oskPtr); - INFO_LOG(SCEUTILITY, "%08x=sceUtilityOskInitStart(%08x)", ret, oskPtr); - return ret; + return hleLogSuccessInfoX(SCEUTILITY, oskDialog->Init(oskPtr)); } static int sceUtilityOskShutdownStart() { - if (currentDialogType != UtilityDialogType::OSK) - { - WARN_LOG(SCEUTILITY, "sceUtilityOskShutdownStart(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + if (currentDialogType != UtilityDialogType::OSK) { + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } DeactivateDialog(); - int ret = oskDialog->Shutdown(); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskShutdownStart()",ret); - return ret; + return hleLogSuccessX(SCEUTILITY, oskDialog->Shutdown()); } static int sceUtilityOskUpdate(int animSpeed) { if (currentDialogType != UtilityDialogType::OSK) { - WARN_LOG(SCEUTILITY, "sceUtilityOskUpdate(%i): wrong dialog type", animSpeed); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = oskDialog->Update(animSpeed); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskUpdate(%i)", ret, animSpeed); - return ret; + return hleLogSuccessX(SCEUTILITY, oskDialog->Update(animSpeed)); } static int sceUtilityOskGetStatus() { if (currentDialogType != UtilityDialogType::OSK) { - DEBUG_LOG(SCEUTILITY, "sceUtilityOskGetStatus(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } int status = oskDialog->GetStatus(); + CleanupDialogThreads(); if (oldStatus != status) { oldStatus = status; - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityOskGetStatus()", status); + return hleLogSuccessI(SCEUTILITY, status); } - CleanupDialogThreads(); - return status; + return hleLogSuccessVerboseI(SCEUTILITY, status); } @@ -601,11 +572,11 @@ static int sceUtilityNetconfGetStatus() { } int status = netDialog->GetStatus(); + CleanupDialogThreads(); if (oldStatus != status) { oldStatus = status; return hleLogSuccessI(SCEUTILITY, status); } - CleanupDialogThreads(); return hleLogSuccessVerboseI(SCEUTILITY, status); } @@ -622,123 +593,97 @@ static int sceUtilityCheckNetParam(int id) //but it requires more investigation static int sceUtilityScreenshotInitStart(u32 paramAddr) { if (currentDialogActive && currentDialogType != UtilityDialogType::SCREENSHOT) { - WARN_LOG(SCEUTILITY, "sceUtilityScreenshotInitStart(%08x): wrong dialog type", paramAddr); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } oldStatus = 100; ActivateDialog(UtilityDialogType::SCREENSHOT); - u32 retval = screenshotDialog->Init(paramAddr); - WARN_LOG_REPORT(SCEUTILITY, "%08x=sceUtilityScreenshotInitStart(%08x)", retval, paramAddr); - return retval; + return hleReportWarning(SCEUTILITY, screenshotDialog->Init(paramAddr)); } static int sceUtilityScreenshotShutdownStart() { if (currentDialogType != UtilityDialogType::SCREENSHOT) { - WARN_LOG(SCEUTILITY, "sceUtilityScreenshotShutdownStart(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } DeactivateDialog(); - int ret = screenshotDialog->Shutdown(); - WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotShutdownStart()", ret); - return ret; + return hleLogWarning(SCEUTILITY, screenshotDialog->Shutdown()); } static int sceUtilityScreenshotUpdate(u32 animSpeed) { if (currentDialogType != UtilityDialogType::SCREENSHOT) { - WARN_LOG(SCEUTILITY, "sceUtilityScreenshotUpdate(%i): wrong dialog type", animSpeed); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = screenshotDialog->Update(animSpeed); - WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotUpdate(%i)", ret, animSpeed); - return ret; + return hleLogWarning(SCEUTILITY, screenshotDialog->Update(animSpeed)); } static int sceUtilityScreenshotGetStatus() { if (currentDialogType != UtilityDialogType::SCREENSHOT) { - DEBUG_LOG(SCEUTILITY, "sceUtilityScreenshotGetStatus(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } int status = screenshotDialog->GetStatus(); + CleanupDialogThreads(); if (oldStatus != status) { oldStatus = status; - WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotGetStatus()", status); + return hleLogWarning(SCEUTILITY, status); } - CleanupDialogThreads(); - return status; + return hleLogSuccessVerboseI(SCEUTILITY, status); } static int sceUtilityScreenshotContStart(u32 paramAddr) { if (currentDialogType != UtilityDialogType::SCREENSHOT) { - WARN_LOG(SCEUTILITY, "sceUtilityScreenshotContStart(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = screenshotDialog->ContStart(); - WARN_LOG(SCEUTILITY, "%08x=sceUtilityScreenshotContStart(%08x)", ret, paramAddr); - return ret; + return hleLogWarning(SCEUTILITY, screenshotDialog->ContStart()); } static int sceUtilityGamedataInstallInitStart(u32 paramsAddr) { if (currentDialogActive && currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { - WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallInitStart(%08x): wrong dialog type", paramsAddr); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } ActivateDialog(UtilityDialogType::GAMEDATAINSTALL); - int ret = gamedataInstallDialog->Init(paramsAddr); - INFO_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallInitStart(%08x)",ret,paramsAddr); - return ret; + return hleLogSuccessInfoX(SCEUTILITY, gamedataInstallDialog->Init(paramsAddr)); } static int sceUtilityGamedataInstallShutdownStart() { if (currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { - WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallShutdownStart(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } DeactivateDialog(); - DEBUG_LOG(SCEUTILITY, "sceUtilityGamedataInstallShutdownStart()"); - return gamedataInstallDialog->Shutdown(); + return hleLogSuccessX(SCEUTILITY, gamedataInstallDialog->Shutdown()); } static int sceUtilityGamedataInstallUpdate(int animSpeed) { if (currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { - WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallUpdate(%i): wrong dialog type", animSpeed); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - int ret = gamedataInstallDialog->Update(animSpeed); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallUpdate(%i)", ret, animSpeed); - return ret; + return hleLogSuccessX(SCEUTILITY, gamedataInstallDialog->Update(animSpeed)); } static int sceUtilityGamedataInstallGetStatus() { if (currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { // This is called incorrectly all the time by some games. So let's not bother warning. - // WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallGetStatus(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogDebug(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } int status = gamedataInstallDialog->GetStatus(); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallGetStatus()", status); CleanupDialogThreads(); - return status; + return hleLogSuccessI(SCEUTILITY, status); } static int sceUtilityGamedataInstallAbort() { if (currentDialogType != UtilityDialogType::GAMEDATAINSTALL) { - WARN_LOG(SCEUTILITY, "sceUtilityGamedataInstallAbort(): wrong dialog type"); - return SCE_ERROR_UTILITY_WRONG_TYPE; + return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } DeactivateDialog(); - int ret = gamedataInstallDialog->Abort(); - DEBUG_LOG(SCEUTILITY, "%08x=sceUtilityGamedataInstallDialogAbort",ret); - return ret; + return hleLogSuccessX(SCEUTILITY, gamedataInstallDialog->Abort()); } //TODO: should save to config file From 7da25563d30dae3b1c0ac083ed4afe85fa9e2359 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Apr 2021 22:23:17 -0700 Subject: [PATCH 073/261] Utility: Add a helper for the active dialog. --- Core/HLE/sceUtility.cpp | 53 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 6f37c50ad4..82873e4896 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -157,14 +157,32 @@ static void DeactivateDialog() { CleanupDialogThreads(); } +static PSPDialog *CurrentDialog(UtilityDialogType type) { + switch (type) { + case UtilityDialogType::NONE: + break; + case UtilityDialogType::SAVEDATA: + return saveDialog; + case UtilityDialogType::MSG: + return msgDialog; + case UtilityDialogType::OSK: + return oskDialog; + case UtilityDialogType::NET: + return netDialog; + case UtilityDialogType::SCREENSHOT: + return screenshotDialog; + case UtilityDialogType::GAMESHARING: + break; + case UtilityDialogType::GAMEDATAINSTALL: + return gamedataInstallDialog; + } + return nullptr; +} + static void UtilityVolatileUnlock(u64 userdata, int cyclesLate) { - // There can only be one active, so just try each of them. - saveDialog->FinishVolatile(); - msgDialog->FinishVolatile(); - oskDialog->FinishVolatile(); - netDialog->FinishVolatile(); - screenshotDialog->FinishVolatile(); - gamedataInstallDialog->FinishVolatile(); + PSPDialog *dialog = CurrentDialog(currentDialogType); + if (dialog) + dialog->FinishVolatile(); } void __UtilityInit() { @@ -287,24 +305,9 @@ static int UtilityWorkUs(int us) { } static int UtilityFinishDialog(int type) { - switch ((UtilityDialogType)type) { - case UtilityDialogType::NONE: - break; - case UtilityDialogType::SAVEDATA: - return hleLogSuccessI(SCEUTILITY, saveDialog->FinishShutdown()); - case UtilityDialogType::MSG: - return hleLogSuccessI(SCEUTILITY, msgDialog->FinishShutdown()); - case UtilityDialogType::OSK: - return hleLogSuccessI(SCEUTILITY, oskDialog->FinishShutdown()); - case UtilityDialogType::NET: - return hleLogSuccessI(SCEUTILITY, netDialog->FinishShutdown()); - case UtilityDialogType::SCREENSHOT: - return hleLogSuccessI(SCEUTILITY, screenshotDialog->FinishShutdown()); - case UtilityDialogType::GAMESHARING: - return hleLogError(SCEUTILITY, -1, "unimplemented"); - case UtilityDialogType::GAMEDATAINSTALL: - return hleLogSuccessI(SCEUTILITY, gamedataInstallDialog->FinishShutdown()); - } + PSPDialog *dialog = CurrentDialog((UtilityDialogType)type); + if (dialog) + return hleLogSuccessI(SCEUTILITY, dialog->FinishShutdown()); return hleLogError(SCEUTILITY, 0, "invalid dialog type?"); } From 429b4594d0daedee6c5a6edf13ef30e36edbe7eb Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 7 Apr 2021 18:07:48 -0700 Subject: [PATCH 074/261] Dialog: Use a thread to init dialogs too. --- Core/Dialog/PSPDialog.cpp | 20 +++++++++++++++++--- Core/Dialog/PSPDialog.h | 1 + Core/HLE/sceUtility.cpp | 36 ++++++++++++++++++++++++++++++++++++ Core/HLE/sceUtility.h | 1 + 4 files changed, 55 insertions(+), 3 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index f15ea6da63..e11837b65a 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -75,6 +75,7 @@ void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) { } } status = newStatus; + pendingStatus = newStatus; pendingStatusTicks = 0; } else { pendingStatus = newStatus; @@ -93,6 +94,13 @@ void PSPDialog::FinishVolatile() { } } +int PSPDialog::FinishInit() { + if (ReadStatus() != SCE_UTILITY_STATUS_INITIALIZE) + return -1; + ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0); + return 0; +} + int PSPDialog::FinishShutdown() { if (ReadStatus() != SCE_UTILITY_STATUS_SHUTDOWN) return -1; @@ -101,12 +109,18 @@ int PSPDialog::FinishShutdown() { } void PSPDialog::ChangeStatusInit(int delayUs) { - status = SCE_UTILITY_STATUS_INITIALIZE; - ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs); + ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0); + + auto params = GetCommonParam(); + if (params) + UtilityDialogInitialize(DialogType(), delayUs, params->accessThread); + else + ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs); } void PSPDialog::ChangeStatusShutdown(int delayUs) { - status = SCE_UTILITY_STATUS_SHUTDOWN; + ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0); + auto params = GetCommonParam(); if (params) UtilityDialogShutdown(DialogType(), delayUs, params->accessThread); diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index e340314d18..54c95e217b 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -86,6 +86,7 @@ public: void EndDraw(); void FinishVolatile(); + int FinishInit(); int FinishShutdown(); protected: diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 82873e4896..dc6a6ba683 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -270,6 +270,30 @@ void __UtilityShutdown() { delete gamedataInstallDialog; } +void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority) { + int partDelay = delayUs / 4; + const u32_le insts[] = { + // Make sure we don't discard/deadbeef 'em. + (u32_le)MIPS_MAKE_ORI(MIPS_REG_S0, MIPS_REG_A0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_ZERO, (int)type), + (u32_le)MIPS_MAKE_JR_RA(), + (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityInitDialog"), + }; + + CleanupDialogThreads(); + _assert_(accessThread == nullptr); + accessThread = new HLEHelperThread("ScePafJob", insts, (uint32_t)ARRAY_SIZE(insts), priority, 0x200); + accessThread->Start(partDelay, 0); +} + void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) { // Break it up so better-priority rescheduling happens. // The windows aren't this regular, but close. @@ -299,11 +323,22 @@ void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority) { static int UtilityWorkUs(int us) { // This blocks, but other better priority threads can get time. // Simulate this by allowing a reschedule. + if (us > 1000) { + hleEatMicro(us - 400); + return hleDelayResult(0, "utility work", 400); + } hleEatMicro(us); hleReSchedule("utility work"); return 0; } +static int UtilityInitDialog(int type) { + PSPDialog *dialog = CurrentDialog((UtilityDialogType)type); + if (dialog) + return hleLogSuccessI(SCEUTILITY, dialog->FinishInit()); + return hleLogError(SCEUTILITY, 0, "invalid dialog type?"); +} + static int UtilityFinishDialog(int type) { PSPDialog *dialog = CurrentDialog((UtilityDialogType)type); if (dialog) @@ -1046,6 +1081,7 @@ const HLEFunction sceUtility[] = // Fake functions for PPSSPP's use. {0xC0DE0001, &WrapI_I, "__UtilityFinishDialog", 'i', "i" }, {0xC0DE0002, &WrapI_I, "__UtilityWorkUs", 'i', "i" }, + {0xC0DE0003, &WrapI_I, "__UtilityInitDialog", 'i', "i" }, }; void Register_sceUtility() diff --git a/Core/HLE/sceUtility.h b/Core/HLE/sceUtility.h index 1cc4798a0a..510b22ea72 100644 --- a/Core/HLE/sceUtility.h +++ b/Core/HLE/sceUtility.h @@ -94,6 +94,7 @@ void __UtilityInit(); void __UtilityDoState(PointerWrap &p); void __UtilityShutdown(); +void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority); void UtilityDialogShutdown(UtilityDialogType type, int delayUs, int priority); void Register_sceUtility(); From 90f4098b3dbcbe5227625cd10ab3598359b53019 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 7 Apr 2021 18:12:50 -0700 Subject: [PATCH 075/261] Dialog: Lock volatile on thread. This means it doesn't matter if GetStatus is called. --- Core/Dialog/PSPDialog.cpp | 2 ++ Core/HLE/sceUtility.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index e11837b65a..09257da935 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -97,6 +97,8 @@ void PSPDialog::FinishVolatile() { int PSPDialog::FinishInit() { if (ReadStatus() != SCE_UTILITY_STATUS_INITIALIZE) return -1; + // The thread already locked. + volatileLocked_ = true; ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0); return 0; } diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index dc6a6ba683..15405bfe0d 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -283,6 +283,12 @@ void UtilityDialogInitialize(UtilityDialogType type, int delayUs, int priority) (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_S0, 0), (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityWorkUs"), + // Now actually lock the volatile memory. Maybe this should be earlier... + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_ZERO, 0), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A1, MIPS_REG_ZERO, 0), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A2, MIPS_REG_ZERO, 0), + (u32_le)MIPS_MAKE_SYSCALL("sceSuspendForUser", "sceKernelVolatileMemLock"), + (u32_le)MIPS_MAKE_ORI(MIPS_REG_A0, MIPS_REG_ZERO, (int)type), (u32_le)MIPS_MAKE_JR_RA(), (u32_le)MIPS_MAKE_SYSCALL("sceUtility", "__UtilityInitDialog"), From 4128b5c6e6975c326b1f731f3cb182748beba6b8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 7 Apr 2021 21:22:31 -0700 Subject: [PATCH 076/261] Dialog: Reset last status more consistently. This is only used to reduce log spam. --- Core/HLE/sceUtility.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 15405bfe0d..f25d2f4388 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -130,7 +130,7 @@ static PSPNetconfDialog *netDialog; static PSPScreenshotDialog *screenshotDialog; static PSPGamedataInstallDialog *gamedataInstallDialog; -static int oldStatus = 100; //random value +static int oldStatus = -1; static std::map currentlyLoadedModules; static int volatileUnlockEvent = -1; static HLEHelperThread *accessThread = nullptr; @@ -146,6 +146,8 @@ static void ActivateDialog(UtilityDialogType type) { if (!currentDialogActive) { currentDialogType = type; currentDialogActive = true; + // So that we log the next one. + oldStatus = -1; } CleanupDialogThreads(); } @@ -361,7 +363,6 @@ static int sceUtilitySavedataInitStart(u32 paramAddr) { } } - oldStatus = 100; ActivateDialog(UtilityDialogType::SAVEDATA); return hleLogSuccessX(SCEUTILITY, saveDialog->Init(paramAddr)); } @@ -491,7 +492,6 @@ static int sceUtilityMsgDialogInitStart(u32 paramAddr) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - oldStatus = 100; ActivateDialog(UtilityDialogType::MSG); return hleLogSuccessInfoX(SCEUTILITY, msgDialog->Init(paramAddr)); } @@ -545,7 +545,6 @@ static int sceUtilityOskInitStart(u32 oskPtr) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - oldStatus = 100; ActivateDialog(UtilityDialogType::OSK); return hleLogSuccessInfoX(SCEUTILITY, oskDialog->Init(oskPtr)); } @@ -587,7 +586,6 @@ static int sceUtilityNetconfInitStart(u32 paramsAddr) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - oldStatus = 100; ActivateDialog(UtilityDialogType::NET); return hleLogSuccessInfoI(SCEUTILITY, netDialog->Init(paramsAddr)); } @@ -640,7 +638,6 @@ static int sceUtilityScreenshotInitStart(u32 paramAddr) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } - oldStatus = 100; ActivateDialog(UtilityDialogType::SCREENSHOT); return hleReportWarning(SCEUTILITY, screenshotDialog->Init(paramAddr)); } From 60690109f03630a0722cc8b0bba6d99700592785 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 13:32:13 -0700 Subject: [PATCH 077/261] GLES: Handle GLSL 1.30/1.40 better. Was causing errors for people using older GL. --- Common/GPU/OpenGL/thin3d_gl.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 29e8283d53..0acb176dea 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -641,8 +641,12 @@ OpenGLContext::OpenGLContext() { } else if (gl_extensions.VersionGEThan(3, 0, 0)) { shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx; shaderLanguageDesc_.fragColor0 = "fragColor0"; + shaderLanguageDesc_.texture = "texture"; shaderLanguageDesc_.bitwiseOps = true; shaderLanguageDesc_.texelFetch = "texelFetch"; + shaderLanguageDesc_.varying_vs = "out"; + shaderLanguageDesc_.varying_fs = "in"; + shaderLanguageDesc_.attribute = "in"; } else { // This too... shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx; From 9a812f7f0baccb5b6c1d730e8b215e53a5578c2f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 13:41:41 -0700 Subject: [PATCH 078/261] Shaders: Set vert shaders to mediump by default. Seeing errors in logs about precision not agreeing. --- assets/shaders/4xhqglsl.vsh | 5 +++++ assets/shaders/5xBR.vsh | 6 ++++++ assets/shaders/aacolor.vsh | 5 +++++ assets/shaders/cartoon.vsh | 5 +++++ assets/shaders/fxaa.vsh | 5 +++++ assets/shaders/natural.vsh | 5 +++++ assets/shaders/naturalA.vsh | 25 +++++++++++++++---------- assets/shaders/upscale_spline36.vsh | 5 +++++ 8 files changed, 51 insertions(+), 10 deletions(-) diff --git a/assets/shaders/4xhqglsl.vsh b/assets/shaders/4xhqglsl.vsh index 128512e413..3ed7ccda8e 100644 --- a/assets/shaders/4xhqglsl.vsh +++ b/assets/shaders/4xhqglsl.vsh @@ -1,3 +1,8 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; uniform vec2 u_texelDelta; diff --git a/assets/shaders/5xBR.vsh b/assets/shaders/5xBR.vsh index b3649d47d0..01e85aab98 100644 --- a/assets/shaders/5xBR.vsh +++ b/assets/shaders/5xBR.vsh @@ -18,6 +18,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; varying vec2 v_texcoord0; diff --git a/assets/shaders/aacolor.vsh b/assets/shaders/aacolor.vsh index 85fecb4640..97199877e0 100644 --- a/assets/shaders/aacolor.vsh +++ b/assets/shaders/aacolor.vsh @@ -1,6 +1,11 @@ // by guest(r) - guest.r@gmail.com // license: GNU-GPL +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; uniform vec2 u_texelDelta; diff --git a/assets/shaders/cartoon.vsh b/assets/shaders/cartoon.vsh index 13a5b0ae3c..701ce8f74f 100644 --- a/assets/shaders/cartoon.vsh +++ b/assets/shaders/cartoon.vsh @@ -1,3 +1,8 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; uniform vec2 u_texelDelta; diff --git a/assets/shaders/fxaa.vsh b/assets/shaders/fxaa.vsh index 49295bb532..0c93df96f0 100644 --- a/assets/shaders/fxaa.vsh +++ b/assets/shaders/fxaa.vsh @@ -1,3 +1,8 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; varying vec2 v_texcoord0; diff --git a/assets/shaders/natural.vsh b/assets/shaders/natural.vsh index 34402d93de..cebb5f7c43 100644 --- a/assets/shaders/natural.vsh +++ b/assets/shaders/natural.vsh @@ -1,3 +1,8 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + uniform vec2 u_texelDelta; attribute vec4 a_position; diff --git a/assets/shaders/naturalA.vsh b/assets/shaders/naturalA.vsh index ebad6e2724..8e52bc055f 100644 --- a/assets/shaders/naturalA.vsh +++ b/assets/shaders/naturalA.vsh @@ -1,10 +1,15 @@ -attribute vec4 a_position; -attribute vec2 a_texcoord0; - -varying vec2 v_texcoord0; - -void main() -{ - gl_Position=a_position; - v_texcoord0=a_texcoord0; -} +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + +attribute vec4 a_position; +attribute vec2 a_texcoord0; + +varying vec2 v_texcoord0; + +void main() +{ + gl_Position=a_position; + v_texcoord0=a_texcoord0; +} diff --git a/assets/shaders/upscale_spline36.vsh b/assets/shaders/upscale_spline36.vsh index 4b47d816cb..77d2f36f15 100644 --- a/assets/shaders/upscale_spline36.vsh +++ b/assets/shaders/upscale_spline36.vsh @@ -1,3 +1,8 @@ +#ifdef GL_ES +precision mediump float; +precision mediump int; +#endif + attribute vec4 a_position; attribute vec2 a_texcoord0; From c18236b5fa4fc334d005c1cd94b7b789525ee303 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 14:01:33 -0700 Subject: [PATCH 079/261] GPU: Avoid switch on uint. Vivante seems to get confused. --- GPU/Common/FragmentShaderGenerator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 2d8c52b594..3fc0e16ffc 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -589,8 +589,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " uint depalOffset = ((u_depal_mask_shift_off_fmt >> 16) & 0xFFU) << 4;\n"); WRITE(p, " uint depalFmt = (u_depal_mask_shift_off_fmt >> 24) & 0x3U;\n"); WRITE(p, " uvec4 col; uint index0; uint index1; uint index2; uint index3;\n"); - WRITE(p, " switch (depalFmt) {\n"); // We might want to include fmt in the shader ID if this is a performance issue. - WRITE(p, " case 0U:\n"); // 565 + WRITE(p, " switch (int(depalFmt)) {\n"); // We might want to include fmt in the shader ID if this is a performance issue. + WRITE(p, " case 0:\n"); // 565 WRITE(p, " col = uvec4(t.rgb * vec3(31.99, 63.99, 31.99), 0);\n"); WRITE(p, " index0 = (col.b << 11) | (col.g << 5) | (col.r);\n"); WRITE(p, " if (bilinear) {\n"); @@ -602,7 +602,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " index3 = (col.b << 11) | (col.g << 5) | (col.r);\n"); WRITE(p, " }\n"); WRITE(p, " break;\n"); - WRITE(p, " case 1U:\n"); // 5551 + WRITE(p, " case 1:\n"); // 5551 WRITE(p, " col = uvec4(t.rgba * vec4(31.99, 31.99, 31.99, 1.0));\n"); WRITE(p, " index0 = (col.a << 15) | (col.b << 10) | (col.g << 5) | (col.r);\n"); WRITE(p, " if (bilinear) {\n"); @@ -614,7 +614,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " index3 = (col.a << 15) | (col.b << 10) | (col.g << 5) | (col.r);\n"); WRITE(p, " }\n"); WRITE(p, " break;\n"); - WRITE(p, " case 2U:\n"); // 4444 + WRITE(p, " case 2:\n"); // 4444 WRITE(p, " col = uvec4(t.rgba * 15.99);\n"); WRITE(p, " index0 = (col.a << 12) | (col.b << 8) | (col.g << 4) | (col.r);\n"); WRITE(p, " if (bilinear) {\n"); @@ -626,7 +626,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu WRITE(p, " index3 = (col.a << 12) | (col.b << 8) | (col.g << 4) | (col.r);\n"); WRITE(p, " }\n"); WRITE(p, " break;\n"); - WRITE(p, " case 3U:\n"); // 8888 + WRITE(p, " case 3:\n"); // 8888 WRITE(p, " col = uvec4(t.rgba * 255.99);\n"); WRITE(p, " index0 = (col.a << 24) | (col.b << 16) | (col.g << 8) | (col.r);\n"); WRITE(p, " if (bilinear) {\n"); From 1b4f0e25b7ab474d173c147d059f752e46c8aa01 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 15:11:44 -0700 Subject: [PATCH 080/261] Reporting: Log more data about sceIoChStat(). --- Core/HLE/sceIo.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 16ee5c1891..7706c08620 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -949,11 +949,15 @@ static u32 sceIoGetstat(const char *filename, u32 addr) { } static u32 sceIoChstat(const char *filename, u32 iostatptr, u32 changebits) { + auto iostat = PSPPointer::Create(iostatptr); + if (!iostat.IsValid()) + return hleReportError(SCEIO, SCE_KERNEL_ERROR_ERRNO_INVALID_ARGUMENT, "bad address"); + ERROR_LOG_REPORT(SCEIO, "UNIMPL sceIoChstat(%s, %08x, %08x)", filename, iostatptr, changebits); if (changebits & SCE_CST_MODE) - ERROR_LOG(SCEIO, "sceIoChstat: change mode requested"); + ERROR_LOG_REPORT(SCEIO, "sceIoChstat: change mode to %03o requested", iostat->st_mode); if (changebits & SCE_CST_ATTR) - ERROR_LOG(SCEIO, "sceIoChstat: change attr requested"); + ERROR_LOG_REPORT(SCEIO, "sceIoChstat: change attr to %04x requested", iostat->st_attr); if (changebits & SCE_CST_SIZE) ERROR_LOG(SCEIO, "sceIoChstat: change size requested"); if (changebits & SCE_CST_CT) @@ -961,7 +965,7 @@ static u32 sceIoChstat(const char *filename, u32 iostatptr, u32 changebits) { if (changebits & SCE_CST_AT) ERROR_LOG(SCEIO, "sceIoChstat: change access time requested"); if (changebits & SCE_CST_MT) - ERROR_LOG(SCEIO, "sceIoChstat: change modification time requested"); + ERROR_LOG_REPORT(SCEIO, "sceIoChstat: change modification time to %04d-%02d-%02d requested", iostat->st_m_time.year, iostat->st_m_time.month, iostat->st_m_time.day); if (changebits & SCE_CST_PRVT) ERROR_LOG(SCEIO, "sceIoChstat: change private data requested"); return 0; From 3c09b5c01013247bcad526e01480a2b59db3ee3f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 16:26:39 -0700 Subject: [PATCH 081/261] GLES: Always use fragColor0 on GL 3.0+. --- Common/GPU/OpenGL/GLQueueRunner.cpp | 2 +- GPU/Common/DepalettizeShaderCommon.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 487a335dd0..3f3dec4c4d 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -199,7 +199,7 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski // Dual source alpha glBindFragDataLocationIndexed(program->program, 0, 0, "fragColor0"); glBindFragDataLocationIndexed(program->program, 0, 1, "fragColor1"); - } else if (gl_extensions.VersionGEThan(3, 3, 0)) { + } else if (gl_extensions.VersionGEThan(3, 0, 0)) { glBindFragDataLocation(program->program, 0, "fragColor0"); } #elif !PPSSPP_PLATFORM(IOS) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index 11236f1f9a..11c598a7f0 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -292,7 +292,7 @@ void GenerateDepalShaderFloat(char *buffer, GEBufferFormat pixelFormat, ShaderLa WRITE(p, "precision mediump float;\n"); } else { WRITE(p, "#version %d\n", gl_extensions.GLSLVersion()); - if (gl_extensions.VersionGEThan(3, 3)) { + if (gl_extensions.VersionGEThan(3, 0, 0)) { WRITE(p, "#define gl_FragColor fragColor0\n"); WRITE(p, "out vec4 fragColor0;\n"); } From f88648c5a2962553f8168326d97ead0da1773647 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 17:10:35 -0700 Subject: [PATCH 082/261] Kernel: Define most reported missing kernel funcs. Kernel plugins and patches are still often not going to work, but might as well define these. --- Core/HLE/sceKernel.cpp | 26 ++++++++++++++++++++++++++ Core/HLE/sceKernelInterrupt.cpp | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 5907848036..d4b4619878 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -913,6 +913,32 @@ const HLEFunction ThreadManForKernel[] = {0x616403ba, &WrapI_I, "sceKernelTerminateThread", 'i', "i" ,HLE_KERNEL_SYSCALL }, {0x383f7bcc, &WrapI_I, "sceKernelTerminateDeleteThread", 'i', "i" ,HLE_KERNEL_SYSCALL }, {0x57cf62dd, &WrapU_U, "sceKernelGetThreadmanIdType", 'x', "x" ,HLE_KERNEL_SYSCALL }, + {0x94aa61ee, &WrapI_V, "sceKernelGetThreadCurrentPriority", 'i', "", HLE_KERNEL_SYSCALL }, + {0x293B45B8, &WrapI_V, "sceKernelGetThreadId", 'i', "", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT }, + {0x3B183E26, &WrapI_I, "sceKernelGetThreadExitStatus", 'i', "i", HLE_KERNEL_SYSCALL }, + {0x82BC5777, &WrapU64_V, "sceKernelGetSystemTimeWide", 'X', "", HLE_KERNEL_SYSCALL }, + {0xDB738F35, &WrapI_U, "sceKernelGetSystemTime", 'i', "x", HLE_KERNEL_SYSCALL }, + {0x369ED59D, &WrapU_V, "sceKernelGetSystemTimeLow", 'x', "", HLE_KERNEL_SYSCALL }, + {0x6652B8CA, &WrapI_UUU, "sceKernelSetAlarm", 'i', "xxx", HLE_KERNEL_SYSCALL }, + {0xB2C25152, &WrapI_UUU, "sceKernelSetSysClockAlarm", 'i', "xxx", HLE_KERNEL_SYSCALL }, + {0x7E65B999, &WrapI_I, "sceKernelCancelAlarm", 'i', "i", HLE_KERNEL_SYSCALL }, + {0xDAA3F564, &WrapI_IU, "sceKernelReferAlarmStatus", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x8125221D, &WrapI_CUU, "sceKernelCreateMbx", 'i', "sxx", HLE_KERNEL_SYSCALL }, + {0x86255ADA, &WrapI_I, "sceKernelDeleteMbx", 'i', "i", HLE_KERNEL_SYSCALL }, + {0xE9B3061E, &WrapI_IU, "sceKernelSendMbx", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x18260574, &WrapI_IUU, "sceKernelReceiveMbx", 'i', "ixx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, + {0xF3986382, &WrapI_IUU, "sceKernelReceiveMbxCB", 'i', "ixx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, + {0x0D81716A, &WrapI_IU, "sceKernelPollMbx", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x87D4DD36, &WrapI_IU, "sceKernelCancelReceiveMbx", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0xA8E8C846, &WrapI_IU, "sceKernelReferMbxStatus", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x56C039B5, &WrapI_CIUUU, "sceKernelCreateVpl", 'i', "sixxx", HLE_KERNEL_SYSCALL }, + {0x89B3D48C, &WrapI_I, "sceKernelDeleteVpl", 'i', "i", HLE_KERNEL_SYSCALL }, + {0xBED27435, &WrapI_IUUU, "sceKernelAllocateVpl", 'i', "ixxx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, + {0xEC0A693F, &WrapI_IUUU, "sceKernelAllocateVplCB", 'i', "ixxx", HLE_KERNEL_SYSCALL | HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED }, + {0xAF36D708, &WrapI_IUU, "sceKernelTryAllocateVpl", 'i', "ixx", HLE_KERNEL_SYSCALL }, + {0xB736E9FF, &WrapI_IU, "sceKernelFreeVpl", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x1D371B8A, &WrapI_IU, "sceKernelCancelVpl", 'i', "ix", HLE_KERNEL_SYSCALL }, + {0x39810265, &WrapI_IU, "sceKernelReferVplStatus", 'i', "ix", HLE_KERNEL_SYSCALL }, }; void Register_ThreadManForUser() diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 161979a353..88a3848be5 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -15,9 +15,10 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include +#include #include #include +#include #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" @@ -798,6 +799,31 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { return 0; } +static u32 sysclib_strncpy(u32 dest, u32 src, u32 size) { + if (!Memory::IsValidAddress(dest) || Memory::IsValidAddress(src)) { + return hleLogError(SCEKERNEL, 0, "invalid address"); + } + + // This is just regular strncpy, but being explicit to avoid warnings/safety fixes on missing null. + u32 i = 0; + u32 srcSize = Memory::ValidSize(src, size); + const u8 *srcp = Memory::GetPointer(src); + u8 *destp = Memory::GetPointer(dest); + for (i = 0; i < srcSize; ++i) { + u8 c = *srcp++; + if (c == 0) + break; + *destp++ = c; + } + + u32 destSize = Memory::ValidSize(dest, size); + for (; i < destSize; ++i) { + *destp++ = 0; + } + + return hleLogSuccessX(SCEKERNEL, dest); +} + const HLEFunction SysclibForKernel[] = { {0xAB7592FF, &WrapU_UUU, "memcpy", 'x', "xxx", HLE_KERNEL_SYSCALL }, @@ -809,8 +835,9 @@ const HLEFunction SysclibForKernel[] = {0x7661E728, &WrapI_UU, "sprintf", 'i', "xx", HLE_KERNEL_SYSCALL }, {0x10F3BB61, &WrapU_UII, "memset", 'x', "xii", HLE_KERNEL_SYSCALL }, {0x0D188658, &WrapI_UU, "strstr", 'i', "xx", HLE_KERNEL_SYSCALL }, - {0x7AB35214, &WrapI_UUU, "strncmp", 'i', "xxx", HLE_KERNEL_SYSCALL }, - {0xA48D2592, &WrapU_UUU, "memmove", 'x', "xxx", HLE_KERNEL_SYSCALL }, + {0x7AB35214, &WrapI_UUU, "strncmp", 'i', "xxx", HLE_KERNEL_SYSCALL }, + {0xA48D2592, &WrapU_UUU, "memmove", 'x', "xxx", HLE_KERNEL_SYSCALL }, + {0xB49A7697, &WrapU_UUU, "strncpy", 'x', "xxi", HLE_KERNEL_SYSCALL }, }; void Register_Kernel_Library() From eedd0b32ddf369d1f42770cbac858591b77951c7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 15:18:09 -0700 Subject: [PATCH 083/261] Module: Add a missing error return case. --- Core/HLE/sceKernelModule.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index b6d73cc023..59d23607ad 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1184,6 +1184,8 @@ static PSPModule *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 load *error_string = StringFromFormat("ELF/PRX truncated: %d > %d", (int)size, (int)elfSize); module->Cleanup(); kernelObjects.Destroy(module->GetUID()); + // TODO: Might be the wrong error code. + error = SCE_KERNEL_ERROR_FILEERR; return nullptr; } const auto maxElfSize = std::max(head->elf_size, head->psp_size); From ffd468c3ae3f6be7b47411cd64bc590b1bb57589 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 18:33:44 -0700 Subject: [PATCH 084/261] Reporting: Add more info to libstubend error. --- Core/HLE/sceKernelModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 59d23607ad..1501681784 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -986,7 +986,7 @@ static bool KernelImportModuleFuncs(PSPModule *module, u32 *firstImportStubAddr, return false; } if (!Memory::IsValidRange(module->libstub, module->libstubend - module->libstub)) { - ERROR_LOG_REPORT(LOADER, "Garbage libstub address or end"); + ERROR_LOG_REPORT(LOADER, "Garbage libstub address %08x or end %08x", module->libstub, module->libstubend); return false; } From ca1a936d5643076d26083e6301acdc233741f832 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 18:35:23 -0700 Subject: [PATCH 085/261] GPU: Stop using Off as terminator for postshaders. There's really no need to have a dummy entry at the end of the array. --- Core/Config.cpp | 15 ++++++--------- Core/CwCheat.cpp | 31 ++++++++++++++----------------- GPU/Common/PostShader.cpp | 7 ++++--- GPU/Common/PresentationCommon.cpp | 4 ++-- UI/GameSettingsScreen.cpp | 16 ++++++++++------ UI/MiscScreens.cpp | 9 +++++++-- Windows/MainWindowMenu.cpp | 16 ++++++++++++---- 7 files changed, 55 insertions(+), 43 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index f8a70ae981..af24885d82 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1263,10 +1263,9 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap(); vPostShaderNames.clear(); for (auto it : postShaderChain) { - vPostShaderNames.push_back(it.second); + if (it.second != "Off") + vPostShaderNames.push_back(it.second); } - if (vPostShaderNames.empty()) - vPostShaderNames.push_back("Off"); // This caps the exponent 4 (so 16x.) if (iAnisotropyLevel > 4) { @@ -1699,10 +1698,9 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap(); vPostShaderNames.clear(); for (auto it : postShaderChain) { - vPostShaderNames.push_back(it.second); + if (it.second != "Off") + vPostShaderNames.push_back(it.second); } - if (vPostShaderNames.empty()) - vPostShaderNames.push_back("Off"); IterateSettings(iniFile, [](Section *section, ConfigSetting *setting) { if (setting->perGame_) { @@ -1737,10 +1735,9 @@ void Config::unloadGameConfig() { auto postShaderChain = iniFile.GetOrCreateSection("PostShaderList")->ToMap(); vPostShaderNames.clear(); for (auto it : postShaderChain) { - vPostShaderNames.push_back(it.second); + if (it.second != "Off") + vPostShaderNames.push_back(it.second); } - if (vPostShaderNames.empty()) - vPostShaderNames.push_back("Off"); LoadStandardControllerIni(); } diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index c86ef008b4..6c9782027c 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -953,8 +953,7 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, auto shaderChain = GetFullPostShadersChain(g_Config.vPostShaderNames); if (op.PostShaderUniform.shader < shaderChain.size()) { std::string shaderName = shaderChain[op.PostShaderUniform.shader]->section; - if (shaderName != "Off") - g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = op.PostShaderUniform.value.f; + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = op.PostShaderUniform.value.f; } } break; @@ -969,21 +968,19 @@ void CWCheatEngine::ExecuteOp(const CheatOperation &op, const CheatCode &cheat, } value; value.u = Memory::Read_U32(op.addr); std::string shaderName = shaderChain[op.PostShaderUniform.shader]->section; - if (shaderName != "Off") { - switch (op.PostShaderUniform.format) { - case 0: - g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x000000FF; - break; - case 1: - g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x0000FFFF; - break; - case 2: - g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u; - break; - case 3: - g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.f; - break; - } + switch (op.PostShaderUniform.format) { + case 0: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x000000FF; + break; + case 1: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u & 0x0000FFFF; + break; + case 2: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.u; + break; + case 3: + g_Config.mPostShaderSetting[StringFromFormat("%sSettingValue%d", shaderName.c_str(), op.PostShaderUniform.uniform + 1)] = value.f; + break; } } } diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index e415aa9226..ecf4724b9e 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -126,6 +126,9 @@ void LoadPostShaderInfo(const std::vector &directories) { section.Get("SSAA", &info.SSAAFilterLevel, 0); section.Get("60fps", &info.requires60fps, false); + if (info.parent == "Off") + info.parent = ""; + for (size_t i = 0; i < ARRAY_SIZE(info.settings); ++i) { auto &setting = info.settings[i]; section.Get(StringFromFormat("SettingName%d", i + 1).c_str(), &setting.name, ""); @@ -198,7 +201,7 @@ std::vector GetPostShaderChain(const std::string &name) { while (shaderInfo) { backwards.push_back(shaderInfo); - if (!shaderInfo->parent.empty() && shaderInfo->parent != "Off") { + if (!shaderInfo->parent.empty()) { shaderInfo = GetPostShaderInfo(shaderInfo->parent); } else { shaderInfo = nullptr; @@ -219,8 +222,6 @@ std::vector GetPostShaderChain(const std::string &name) { std::vector GetFullPostShadersChain(const std::vector &names) { std::vector fullChain; for (auto shaderName : names) { - if (shaderName == "Off") - break; auto shaderChain = GetPostShaderChain(shaderName); fullChain.insert(fullChain.end(), shaderChain.begin(), shaderChain.end()); } diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 2122980b66..9c294a4f39 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -211,7 +211,7 @@ static std::string ReadShaderSrc(const std::string &filename) { // Note: called on resize and settings changes. bool PresentationCommon::UpdatePostShader() { std::vector shaderInfo; - if (!g_Config.vPostShaderNames.empty() && g_Config.vPostShaderNames[0] != "Off") { + if (!g_Config.vPostShaderNames.empty()) { ReloadAllPostShaderInfo(); shaderInfo = GetFullPostShadersChain(g_Config.vPostShaderNames); } @@ -735,7 +735,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) { // Check if postprocessing shader is doing upscaling as it requires native resolution std::vector shaderInfo; - if (!g_Config.vPostShaderNames.empty() && g_Config.vPostShaderNames[0] != "Off") { + if (!g_Config.vPostShaderNames.empty()) { ReloadAllPostShaderInfo(); shaderInfo = GetFullPostShadersChain(g_Config.vPostShaderNames); } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ba77244124..90d56fb763 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -18,6 +18,7 @@ #include "ppsspp_config.h" #include +#include #include "Common/Net/Resolve.h" #include "Common/GPU/OpenGL/GLFeatures.h" @@ -313,10 +314,10 @@ void GameSettingsScreen::CreateViews() { graphicsSettings->Add(new ItemHeader(gr->T("Postprocessing effect"))); - std::vector alreadyAddedShader; - for (int i = 0; i < g_Config.vPostShaderNames.size() && i < ARRAY_SIZE(shaderNames_); ++i) { + std::set alreadyAddedShader; + for (int i = 0; i < g_Config.vPostShaderNames.size() + 1 && i < ARRAY_SIZE(shaderNames_); ++i) { // Vector element pointer get invalidated on resize, cache name to have always a valid reference in the rendering thread - shaderNames_[i] = g_Config.vPostShaderNames[i]; + shaderNames_[i] = i == g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[i]; postProcChoice_ = graphicsSettings->Add(new ChoiceWithValueDisplay(&shaderNames_[i], StringFromFormat("%s #%d", gr->T("Postprocessing Shader"), i + 1), &PostShaderTranslateName)); postProcChoice_->OnClick.Add([=](EventParams &e) { auto gr = GetI18NCategory("Graphics"); @@ -331,11 +332,15 @@ void GameSettingsScreen::CreateViews() { return g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; }); + // No need for settings on the last one. + if (i == g_Config.vPostShaderNames.size()) + continue; + auto shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]); for (auto shaderInfo : shaderChain) { // Disable duplicated shader slider - bool duplicated = std::find(alreadyAddedShader.begin(), alreadyAddedShader.end(), shaderInfo->section) != alreadyAddedShader.end(); - alreadyAddedShader.push_back(shaderInfo->section); + bool duplicated = alreadyAddedShader.find(shaderInfo->section) != alreadyAddedShader.end(); + alreadyAddedShader.insert(shaderInfo->section); for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) { auto &setting = shaderInfo->settings[i]; if (!setting.name.empty()) { @@ -1525,7 +1530,6 @@ UI::EventReturn GameSettingsScreen::OnLanguageChange(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnPostProcShaderChange(UI::EventParams &e) { g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); - g_Config.vPostShaderNames.push_back("Off"); g_ShaderNameListChanged = true; NativeMessageReceived("gpu_resized", ""); return UI::EVENT_DONE; diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index c5e8a9f720..2ee6ba8463 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -430,10 +430,11 @@ PostProcScreen::PostProcScreen(const std::string &title, int id) : ListPopupScre shaders_ = GetAllPostShaderInfo(); std::vector items; int selected = -1; + const std::string selectedName = id_ >= g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[id_]; for (int i = 0; i < (int)shaders_.size(); i++) { if (!shaders_[i].visible) continue; - if (shaders_[i].section == g_Config.vPostShaderNames[id_]) + if (shaders_[i].section == selectedName) selected = i; items.push_back(ps->T(shaders_[i].section.c_str(), shaders_[i].name.c_str())); } @@ -443,7 +444,11 @@ PostProcScreen::PostProcScreen(const std::string &title, int id) : ListPopupScre void PostProcScreen::OnCompleted(DialogResult result) { if (result != DR_OK) return; - g_Config.vPostShaderNames[id_] = shaders_[listView_->GetSelected()].section; + const std::string &value = shaders_[listView_->GetSelected()].section; + if (id_ < g_Config.vPostShaderNames.size()) + g_Config.vPostShaderNames[id_] = value; + else + g_Config.vPostShaderNames.push_back(value); } TextureShaderScreen::TextureShaderScreen(const std::string &title) : ListPopupScreen(title) { diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 867ff4fe52..c4a31fb92b 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -156,8 +156,15 @@ namespace MainWindow { void UpdateDynamicMenuCheckmarks(HMENU menu) { int item = ID_SHADERS_BASE + 1; - for (size_t i = 0; i < availableShaders.size(); i++) - CheckMenuItem(menu, item++, ((g_Config.vPostShaderNames[0] == availableShaders[i] && (g_Config.vPostShaderNames[0] == "Off" || g_Config.vPostShaderNames[1] == "Off")) ? MF_CHECKED : MF_UNCHECKED)); + for (size_t i = 0; i < availableShaders.size(); i++) { + bool checked = false; + if (g_Config.vPostShaderNames.empty() && availableShaders[i] == "Off") + checked = true; + else if (g_Config.vPostShaderNames.size() == 1 && availableShaders[i] == g_Config.vPostShaderNames[0]) + checked = true; + + CheckMenuItem(menu, item++, checked ? MF_CHECKED : MF_UNCHECKED); + } } bool CreateShadersSubmenu(HMENU menu) { @@ -191,7 +198,9 @@ namespace MainWindow { continue; int checkedStatus = MF_UNCHECKED; availableShaders.push_back(i->section); - if (g_Config.vPostShaderNames[0] == i->section && (g_Config.vPostShaderNames[0] == "Off" || g_Config.vPostShaderNames[1] == "Off")) { + if (g_Config.vPostShaderNames.empty() && i->section == "Off") { + checkedStatus = MF_CHECKED; + } else if (g_Config.vPostShaderNames.size() == 1 && g_Config.vPostShaderNames[0] == i->section) { checkedStatus = MF_CHECKED; } @@ -1060,7 +1069,6 @@ namespace MainWindow { g_Config.vPostShaderNames.clear(); if (availableShaders[index] != "Off") g_Config.vPostShaderNames.push_back(availableShaders[index]); - g_Config.vPostShaderNames.push_back("Off"); g_ShaderNameListChanged = true; g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames)); NativeMessageReceived("gpu_resized", ""); From b5d21b4f9ba659c4dd4f26e340ebd8509c91da6b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 18:42:40 -0700 Subject: [PATCH 086/261] UI: Remove extern global for UI message. --- UI/GameSettingsScreen.cpp | 18 ++++++++++-------- UI/GameSettingsScreen.h | 1 + UI/NativeApp.cpp | 1 - Windows/MainWindowMenu.cpp | 4 ++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 90d56fb763..618f675ec5 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -79,8 +79,6 @@ #include "Windows/W32Util/ShellUtil.h" #endif -extern bool g_ShaderNameListChanged; - GameSettingsScreen::GameSettingsScreen(std::string gamePath, std::string gameID, bool editThenRestore) : UIDialogScreenWithGameBackground(gamePath), gameID_(gameID), enableReports_(false), editThenRestore_(editThenRestore) { lastVertical_ = UseVerticalLayout(); @@ -1260,11 +1258,6 @@ void GameSettingsScreen::update() { RecreateViews(); lastVertical_ = vertical; } - if (g_ShaderNameListChanged) { - g_ShaderNameListChanged = false; - g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames)); - RecreateViews(); - } } void GameSettingsScreen::onFinish(DialogResult result) { @@ -1292,6 +1285,14 @@ void GameSettingsScreen::onFinish(DialogResult result) { NativeMessageReceived("gpu_clearCache", ""); } +void GameSettingsScreen::sendMessage(const char *message, const char *value) { + UIDialogScreenWithGameBackground::sendMessage(message, value); + if (!strcmp(message, "postshader_updated")) { + g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames)); + RecreateViews(); + } +} + #if PPSSPP_PLATFORM(ANDROID) void GameSettingsScreen::CallbackMemstickFolder(bool yes) { auto sy = GetI18NCategory("System"); @@ -1530,8 +1531,9 @@ UI::EventReturn GameSettingsScreen::OnLanguageChange(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnPostProcShaderChange(UI::EventParams &e) { g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end()); - g_ShaderNameListChanged = true; + NativeMessageReceived("gpu_resized", ""); + NativeMessageReceived("postshader_updated", ""); return UI::EVENT_DONE; } diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 76fd384aed..ec7542f483 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -37,6 +37,7 @@ public: std::string tag() const override { return "settings"; } protected: + void sendMessage(const char *message, const char *value) override; void CreateViews() override; void CallbackRestoreDefaults(bool yes); void CallbackRenderingBackend(bool yes); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e36f59a016..1631461115 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -144,7 +144,6 @@ std::string config_filename; // Really need to clean this mess of globals up... but instead I add more :P bool g_TakeScreenshot; -bool g_ShaderNameListChanged = false; static bool isOuya; static bool resized = false; static bool restarting = false; diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index c4a31fb92b..689cd6366c 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -50,7 +50,6 @@ #include "Core/Core.h" extern bool g_TakeScreenshot; -extern bool g_ShaderNameListChanged; namespace MainWindow { extern HINSTANCE hInst; @@ -1069,9 +1068,10 @@ namespace MainWindow { g_Config.vPostShaderNames.clear(); if (availableShaders[index] != "Off") g_Config.vPostShaderNames.push_back(availableShaders[index]); - g_ShaderNameListChanged = true; g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames)); + NativeMessageReceived("gpu_resized", ""); + NativeMessageReceived("postshader_updated", ""); break; } From c06035aa315e6d4b8b3f99e4673d254b39c0bda8 Mon Sep 17 00:00:00 2001 From: Stuart Kenny Date: Sun, 11 Apr 2021 11:52:10 +0100 Subject: [PATCH 087/261] Enable save encryption to bring libreto in line with standalone configuration defaults. Fixes issue with saving in Toca Race Drive 2 and 3 --- libretro/libretro.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 9751924cb9..f15e1f413b 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -364,6 +364,7 @@ void retro_init(void) g_Config.iCwCheatRefreshRate = 60; g_Config.iMemStickSizeGB = 16; g_Config.bFuncReplacements = true; + g_Config.bEncryptSave = true; g_Config.iFirmwareVersion = PSP_DEFAULT_FIRMWARE; g_Config.iPSPModel = PSP_MODEL_SLIM; From d3e2aa6d28c64d528c2820aaa11776627c8badfe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 22:19:56 -0700 Subject: [PATCH 088/261] Build: Add libzstd to build. --- .gitmodules | 3 + CMakeLists.txt | 3 +- Common/Common.vcxproj | 16 +- Core/Core.vcxproj | 16 +- GPU/GPU.vcxproj | 16 +- UWP/CommonUWP/CommonUWP.vcxproj | 24 +- UWP/CoreUWP/CoreUWP.vcxproj | 24 +- UWP/GPU_UWP/GPU_UWP.vcxproj | 24 +- UWP/PPSSPP_UWP.sln | 26 ++ UWP/UWP.vcxproj | 3 + UWP/libzstd_UWP/libzstd_UWP.vcxproj | 317 +++++++++++++++ UWP/libzstd_UWP/libzstd_UWP.vcxproj.filters | 61 +++ UWP/libzstd_UWP/pch.cpp | 1 + UWP/libzstd_UWP/pch.h | 9 + UWP/libzstd_UWP/targetver.h | 8 + Windows/PPSSPP.sln | 37 ++ Windows/PPSSPP.vcxproj | 3 + android/jni/Android.mk | 45 ++- android/jni/Locals.mk | 1 + ext/CMakeLists.txt | 2 + ext/libzstd.vcxproj | 410 ++++++++++++++++++++ ext/zstd | 1 + headless/Headless.vcxproj | 5 +- libretro/Makefile.common | 1 + unittest/UnitTests.vcxproj | 3 + 25 files changed, 994 insertions(+), 65 deletions(-) create mode 100644 UWP/libzstd_UWP/libzstd_UWP.vcxproj create mode 100644 UWP/libzstd_UWP/libzstd_UWP.vcxproj.filters create mode 100644 UWP/libzstd_UWP/pch.cpp create mode 100644 UWP/libzstd_UWP/pch.h create mode 100644 UWP/libzstd_UWP/targetver.h create mode 100644 ext/libzstd.vcxproj create mode 160000 ext/zstd diff --git a/.gitmodules b/.gitmodules index 7513c5e5e3..773fbeb290 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,3 +31,6 @@ [submodule "ext/miniupnp"] path = ext/miniupnp url = https://github.com/hrydgard/miniupnp.git +[submodule "zstd"] + path = ext/zstd + url = https://github.com/facebook/zstd.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 640d323b45..d035963a72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1815,7 +1815,8 @@ if(ANDROID) endif() endif() -set(CoreExtraLibs ${CoreExtraLibs} armips) +set(CoreExtraLibs ${CoreExtraLibs} armips libzstd_static) +include_directories(ext/zstd/lib) # needed for VK_USE_PLATFORM_XCB_KHR only #if(VULKAN AND NOT WIN32) diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 69e6ff977b..8029db0faa 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -136,7 +136,7 @@ _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) Common/DbgNew.h MultiThreadedDebug - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib StreamingSIMDExtensions2 Precise true @@ -161,7 +161,7 @@ Common/DbgNew.h MultiThreadedDebug _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib NotSet Precise false @@ -187,7 +187,7 @@ Common/DbgNew.h MultiThreadedDebug _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib NotSet Precise false @@ -214,7 +214,7 @@ MultiThreadedDebug _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib NotSet Precise false @@ -246,7 +246,7 @@ false StreamingSIMDExtensions2 Precise - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib Speed true false @@ -275,7 +275,7 @@ USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib false NotSet Precise @@ -309,7 +309,7 @@ USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib false NotSet Precise @@ -343,7 +343,7 @@ USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;NDEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) - ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;.. + ../ext/glew;../ext/snappy;../ext/glslang;../ext/libpng17;../ext;../ext/zlib;..;../ext/zstd/lib false NotSet Precise diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 30c555b669..fa1c66a731 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -138,7 +138,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) StreamingSIMDExtensions2 Precise @@ -161,7 +161,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_M_X64=1;_DEBUG;_LIB;_UNICODE;UNICODE;MINIUPNP_STATICLIB;%(PreprocessorDefinitions) NotSet Precise @@ -185,7 +185,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_64=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) NotSet Precise @@ -209,7 +209,7 @@ Level3 - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;USE_FFMPEG;WITH_UPNP;WIN32;_ARCH_32=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) NotSet Precise @@ -237,7 +237,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib false StreamingSIMDExtensions2 Precise @@ -268,7 +268,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib;../ext/zstd/lib NotSet Precise false @@ -299,7 +299,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\aarch64\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib NotSet Precise false @@ -330,7 +330,7 @@ MaxSpeed true true - ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext + ..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\arm\include;../common;..;../ext/glew;../ext/snappy;../ext/libpng17;../ext/zlib;../ext;../ext/zstd/lib NotSet Precise false diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index ddaaa6e7ef..290a86c054 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -164,7 +164,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) StreamingSIMDExtensions2 Precise @@ -182,7 +182,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib NotSet Precise false @@ -202,7 +202,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib NotSet Precise false @@ -221,7 +221,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib NotSet Precise false @@ -244,7 +244,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib false StreamingSIMDExtensions2 Precise @@ -267,7 +267,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib false NotSet Precise @@ -292,7 +292,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib false NotSet Precise @@ -317,7 +317,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib false NotSet Precise diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index e1ba07540c..f1d57b3acc 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -203,7 +203,7 @@ false false pch.h - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) NotUsing @@ -217,7 +217,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) pch.h NotUsing @@ -232,7 +232,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) pch.h NotUsing @@ -248,7 +248,7 @@ false false pch.h - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) NotUsing @@ -263,7 +263,7 @@ false false pch.h - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) NotUsing @@ -277,7 +277,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) pch.h NotUsing @@ -292,7 +292,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) pch.h NotUsing @@ -307,7 +307,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) pch.h NotUsing @@ -322,7 +322,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) pch.h NotUsing @@ -338,7 +338,7 @@ false false pch.h - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) NotUsing @@ -352,7 +352,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) pch.h NotUsing @@ -367,7 +367,7 @@ false false - ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/native;../../ext/snappy;../../ext/glslang;../../ext/zlib;../../ext/libpng17;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) NOMINMAX;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) pch.h NotUsing diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index c72b42d206..11b9f7551d 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -204,7 +204,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -219,7 +219,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -234,7 +234,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -249,7 +249,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -264,7 +264,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -279,7 +279,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -294,7 +294,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -309,7 +309,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -324,7 +324,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -339,7 +339,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -354,7 +354,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -369,7 +369,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 45368643e6..60246c4892 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -204,7 +204,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -219,7 +219,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -234,7 +234,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -249,7 +249,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -264,7 +264,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -279,7 +279,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -294,7 +294,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -309,7 +309,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -324,7 +324,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -339,7 +339,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -354,7 +354,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -369,7 +369,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) diff --git a/UWP/PPSSPP_UWP.sln b/UWP/PPSSPP_UWP.sln index fc6a017b01..42c7eddb2e 100644 --- a/UWP/PPSSPP_UWP.sln +++ b/UWP/PPSSPP_UWP.sln @@ -28,6 +28,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPIRVCross_UWP", "SPIRVCros EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Armips_UWP", "Armips_UWP\Armips_UWP.vcxproj", "{75286959-E7A2-4CBE-8B95-BF05C9C540FF}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd_UWP", "libzstd_UWP\libzstd_UWP.vcxproj", "{75286959-E7A2-4CBE-8B95-BF05C9C540FE}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc_UWP", "miniupnpc_UWP\miniupnpc_UWP.vcxproj", "{D31FD4F0-53EB-477C-9DC7-149796F628E2}" EndProject Global @@ -322,6 +324,30 @@ Global {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|Win32.Build.0 = Release|Win32 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|x64.ActiveCfg = Release|x64 {75286959-E7A2-4CBE-8B95-BF05C9C540FF}.UWP Gold|x64.Build.0 = Release|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM.ActiveCfg = Debug|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM.Build.0 = Debug|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|ARM64.Build.0 = Debug|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|Win32.ActiveCfg = Debug|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|Win32.Build.0 = Debug|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|x64.ActiveCfg = Debug|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Debug|x64.Build.0 = Debug|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM.ActiveCfg = Release|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM.Build.0 = Release|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM64.ActiveCfg = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|Win32.Build.0 = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|x64.ActiveCfg = Release|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.Release|x64.Build.0 = Release|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM.ActiveCfg = Release|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM.Build.0 = Release|ARM + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM64.ActiveCfg = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|ARM64.Build.0 = Release|ARM64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|Win32.ActiveCfg = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|Win32.Build.0 = Release|Win32 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|x64.ActiveCfg = Release|x64 + {75286959-E7A2-4CBE-8B95-BF05C9C540FE}.UWP Gold|x64.Build.0 = Release|x64 {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM.ActiveCfg = Debug|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM.Build.0 = Debug|ARM {D31FD4F0-53EB-477C-9DC7-149796F628E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 117be5285c..ec1fbc6934 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -1728,6 +1728,9 @@ {2f911c05-b341-4291-8bf5-09edecbdd5f5} + + {75286959-e7a2-4cbe-8b95-bf05c9c540fe} + {2b2d16bd-1d37-46af-a3f8-552900951b26} diff --git a/UWP/libzstd_UWP/libzstd_UWP.vcxproj b/UWP/libzstd_UWP/libzstd_UWP.vcxproj new file mode 100644 index 0000000000..46cc2b2b25 --- /dev/null +++ b/UWP/libzstd_UWP/libzstd_UWP.vcxproj @@ -0,0 +1,317 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + {75286959-e7a2-4cbe-8b95-bf05c9c540fe} + StaticLibrary + libzstd_UWP + en-US + 14.0 + true + Windows Store + 10.0.17763.0 + 10.0.15063.0 + 10.0 + + + + StaticLibrary + true + + + StaticLibrary + true + + + StaticLibrary + true + + + StaticLibrary + true + + + StaticLibrary + false + true + + + StaticLibrary + false + true + + + StaticLibrary + false + true + + + StaticLibrary + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + false + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + NotUsing + false + false + + + Console + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + Create + Create + Create + Create + Create + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/UWP/libzstd_UWP/libzstd_UWP.vcxproj.filters b/UWP/libzstd_UWP/libzstd_UWP.vcxproj.filters new file mode 100644 index 0000000000..4b04ed6865 --- /dev/null +++ b/UWP/libzstd_UWP/libzstd_UWP.vcxproj.filters @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/UWP/libzstd_UWP/pch.cpp b/UWP/libzstd_UWP/pch.cpp new file mode 100644 index 0000000000..bcb5590be1 --- /dev/null +++ b/UWP/libzstd_UWP/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/UWP/libzstd_UWP/pch.h b/UWP/libzstd_UWP/pch.h new file mode 100644 index 0000000000..529bbb17fe --- /dev/null +++ b/UWP/libzstd_UWP/pch.h @@ -0,0 +1,9 @@ +#pragma once + +#include "targetver.h" + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include diff --git a/UWP/libzstd_UWP/targetver.h b/UWP/libzstd_UWP/targetver.h new file mode 100644 index 0000000000..a66ecb00f1 --- /dev/null +++ b/UWP/libzstd_UWP/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// Including SDKDDKVer.h defines the highest available Windows platform. + +// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and +// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. + +#include diff --git a/Windows/PPSSPP.sln b/Windows/PPSSPP.sln index 8859935282..d2b028722c 100644 --- a/Windows/PPSSPP.sln +++ b/Windows/PPSSPP.sln @@ -8,6 +8,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPPWindows", "PPSSPP.vcx {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {D8A71225-178B-424E-96C1-CC3BE2C1B047} {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} {533F1D30-D04D-47CC-AD71-20F658907E36} = {533F1D30-D04D-47CC-AD71-20F658907E36} + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} {457F45D2-556F-47BC-A31D-AFF0D15BEAED} = {457F45D2-556F-47BC-A31D-AFF0D15BEAED} @@ -16,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPPWindows", "PPSSPP.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\Common\Common.vcxproj", "{3FCDBAE2-5103-4350-9A8E-848CE9C73195}" ProjectSection(ProjectDependencies) = postProject + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} {F761046E-6C38-4428-A5F1-38391A37BB34} = {F761046E-6C38-4428-A5F1-38391A37BB34} EndProjectSection EndProject @@ -24,6 +26,7 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPU", "..\GPU\GPU.vcxproj", "{457F45D2-556F-47BC-A31D-AFF0D15BEAED}" ProjectSection(ProjectDependencies) = postProject {4328A62C-F1E9-47ED-B816-A1A81DAF4363} = {4328A62C-F1E9-47ED-B816-A1A81DAF4363} + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} {3FCDBAE2-5103-4350-9A8E-848CE9C73195} = {3FCDBAE2-5103-4350-9A8E-848CE9C73195} EndProjectSection EndProject @@ -78,6 +81,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZimTool", "..\ext\native\to EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc", "..\ext\miniupnpc.vcxproj", "{D8A71225-178B-424E-96C1-CC3BE2C1B047}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ext", "Ext", "{39FCACF8-10D9-4D8D-97AA-7507436AD932}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{999C12EA-A74F-4868-84F7-64C258043C49}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "..\ext\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM @@ -332,10 +341,38 @@ Global {D8A71225-178B-424E-96C1-CC3BE2C1B047}.Release|Win32.Build.0 = Release|Win32 {D8A71225-178B-424E-96C1-CC3BE2C1B047}.Release|x64.ActiveCfg = Release|x64 {D8A71225-178B-424E-96C1-CC3BE2C1B047}.Release|x64.Build.0 = Release|x64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.ActiveCfg = Debug|ARM + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM.Build.0 = Debug|ARM + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|ARM64.Build.0 = Debug|ARM64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.ActiveCfg = Debug|Win32 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|Win32.Build.0 = Debug|Win32 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.ActiveCfg = Debug|x64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Debug|x64.Build.0 = Debug|x64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.ActiveCfg = Release|ARM + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM.Build.0 = Release|ARM + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.ActiveCfg = Release|ARM64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|ARM64.Build.0 = Release|ARM64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.ActiveCfg = Release|Win32 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.Build.0 = Release|Win32 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64 + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {F761046E-6C38-4428-A5F1-38391A37BB34} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {3BAAE095-E0AB-4B0E-B5DF-CE39C8AE31DE} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {129E5E2B-39C1-4D84-96FE-DFD22DBB4A25} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {EDFA2E87-8AC1-4853-95D4-D7594FF81947} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {4328A62C-F1E9-47ED-B816-A1A81DAF4363} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {BEB0A821-3C7F-410F-A525-63AFBC69BF8F} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {FBE46262-7C2C-400C-92F9-F8A9E72594DD} = {999C12EA-A74F-4868-84F7-64C258043C49} + {B7DED405-40A2-48F8-9382-538F10D442F1} = {999C12EA-A74F-4868-84F7-64C258043C49} + {D8A71225-178B-424E-96C1-CC3BE2C1B047} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {39FCACF8-10D9-4D8D-97AA-7507436AD932} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2FD47774-A031-48F4-B645-A49A3140A29B} EndGlobalSection diff --git a/Windows/PPSSPP.vcxproj b/Windows/PPSSPP.vcxproj index bef161003e..e3b348add4 100644 --- a/Windows/PPSSPP.vcxproj +++ b/Windows/PPSSPP.vcxproj @@ -1686,6 +1686,9 @@ {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} + + {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} + {457f45d2-556f-47bc-a31d-aff0d15beaed} diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 04a223215c..41e2b01086 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -584,7 +584,46 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk -LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips + +LIBZSTD_FILES := \ + $(SRC)/ext/zstd/lib/common/debug.c \ + $(SRC)/ext/zstd/lib/common/entropy_common.c \ + $(SRC)/ext/zstd/lib/common/error_private.c \ + $(SRC)/ext/zstd/lib/common/fse_decompress.c \ + $(SRC)/ext/zstd/lib/common/pool.c \ + $(SRC)/ext/zstd/lib/common/threading.c \ + $(SRC)/ext/zstd/lib/common/xxhash.c \ + $(SRC)/ext/zstd/lib/common/zstd_common.c \ + $(SRC)/ext/zstd/lib/common/zstd_trace.c \ + $(SRC)/ext/zstd/lib/compress/fse_compress.c \ + $(SRC)/ext/zstd/lib/compress/hist.c \ + $(SRC)/ext/zstd/lib/compress/huf_compress.c \ + $(SRC)/ext/zstd/lib/compress/zstd_compress.c \ + $(SRC)/ext/zstd/lib/compress/zstd_compress_literals.c \ + $(SRC)/ext/zstd/lib/compress/zstd_compress_sequences.c \ + $(SRC)/ext/zstd/lib/compress/zstd_compress_superblock.c \ + $(SRC)/ext/zstd/lib/compress/zstd_double_fast.c \ + $(SRC)/ext/zstd/lib/compress/zstd_fast.c \ + $(SRC)/ext/zstd/lib/compress/zstd_lazy.c \ + $(SRC)/ext/zstd/lib/compress/zstd_ldm.c \ + $(SRC)/ext/zstd/lib/compress/zstd_opt.c \ + $(SRC)/ext/zstd/lib/compress/zstdmt_compress.c \ + $(SRC)/ext/zstd/lib/decompress/huf_decompress.c \ + $(SRC)/ext/zstd/lib/decompress/zstd_ddict.c \ + $(SRC)/ext/zstd/lib/decompress/zstd_decompress.c \ + $(SRC)/ext/zstd/lib/decompress/zstd_decompress_block.c \ + $(SRC)/ext/zstd/lib/dictBuilder/cover.c \ + $(SRC)/ext/zstd/lib/dictBuilder/divsufsort.c \ + $(SRC)/ext/zstd/lib/dictBuilder/fastcover.c \ + $(SRC)/ext/zstd/lib/dictBuilder/zdict.c + +LOCAL_MODULE := libzstd +LOCAL_SRC_FILES := $(LIBZSTD_FILES) +include $(BUILD_STATIC_LIBRARY) + +include $(CLEAR_VARS) +include $(LOCAL_PATH)/Locals.mk +LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips libzstd # These are the files just for ppsspp_jni LOCAL_MODULE := ppsspp_jni @@ -634,7 +673,7 @@ endif ifeq ($(HEADLESS),1) include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk - LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips + LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips libzstd # Android 5.0 requires PIE for executables. Only supported on 4.1+, but this is testing anyway. LOCAL_CFLAGS += -fPIE @@ -652,7 +691,7 @@ endif ifeq ($(UNITTEST),1) include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk - LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips + LOCAL_STATIC_LIBRARIES += ppsspp_core libarmips libzstd # Android 5.0 requires PIE for executables. Only supported on 4.1+, but this is testing anyway. LOCAL_CFLAGS += -fPIE diff --git a/android/jni/Locals.mk b/android/jni/Locals.mk index 44e8f57cf8..552d4f1f96 100644 --- a/android/jni/Locals.mk +++ b/android/jni/Locals.mk @@ -16,6 +16,7 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/$(NATIVE)/base \ $(LOCAL_PATH)/../../ext/libpng17 \ $(LOCAL_PATH)/../../ext/libzip \ + $(LOCAL_PATH)/../../ext/zstd/lib \ $(LOCAL_PATH)/$(NATIVE) \ $(LOCAL_PATH) diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 440f3c362c..3597ca190e 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -8,6 +8,7 @@ endif() set(ENABLE_GLSLANG_BINARIES OFF CACHE BOOL "let's not build binaries we don't need" FORCE) set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS ON CACHE BOOL "let's not use exceptions" FORCE) set(ENABLE_SPVREMAPPER OFF CACHE BOOL "we don't need spvremapper" FORCE) +set(ZSTD_BUILD_PROGRAMS OFF CACHE BOOL "we don't need zstd programs" FORCE) # This is really a workaround for an NDK 20 compiler issue (PPSSPP issue #12105), but shouldn't hurt. if(ANDROID) @@ -21,3 +22,4 @@ add_subdirectory(SPIRV-Cross-build) if(USE_DISCORD AND NOT IOS AND NOT LIBRETRO) add_subdirectory(discord-rpc-build) endif() +add_subdirectory(zstd/build/cmake EXCLUDE_FROM_ALL) diff --git a/ext/libzstd.vcxproj b/ext/libzstd.vcxproj new file mode 100644 index 0000000000..268bfde84a --- /dev/null +++ b/ext/libzstd.vcxproj @@ -0,0 +1,410 @@ + + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {8BFD8150-94D5-4BF9-8A50-7BD9929A0850} + Win32Proj + libzstd + libzstd_static + Unicode + StaticLibrary + $(SolutionDir)..\ext\zstd\bin\$(Platform)_$(Configuration)\ + $(SolutionDir)..\ext\zstd\bin\obj\$(RootNamespace)_$(Platform)_$(Configuration)\ + 10.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + $(DefaultPlatformToolset) + + + true + $(DefaultPlatformToolset) + + + true + $(DefaultPlatformToolset) + + + true + $(DefaultPlatformToolset) + + + false + true + $(DefaultPlatformToolset) + + + false + true + $(DefaultPlatformToolset) + + + false + true + $(DefaultPlatformToolset) + + + false + true + $(DefaultPlatformToolset) + + + + + + + + + + + + + + + + + + + true + $(IncludePath);$(SolutionDir)..\ext\zstd\lib;$(SolutionDir)..\ext\zstd\programs\legacy;$(SolutionDir)..\ext\zstd\lib\legacy;$(SolutionDir)..\ext\zstd\lib\common;$(SolutionDir)..\ext\zstd\lib\dictBuilder;$(UniversalCRT_IncludePath); + false + + + true + $(IncludePath);$(SolutionDir)..\ext\zstd\lib;$(SolutionDir)..\ext\zstd\programs\legacy;$(SolutionDir)..\ext\zstd\lib\legacy;$(SolutionDir)..\ext\zstd\lib\common;$(SolutionDir)..\ext\zstd\lib\dictBuilder;$(UniversalCRT_IncludePath); + false + + + false + $(IncludePath);$(SolutionDir)..\ext\zstd\lib;$(SolutionDir)..\ext\zstd\programs\legacy;$(SolutionDir)..\ext\zstd\lib\legacy;$(SolutionDir)..\ext\zstd\lib\common;$(SolutionDir)..\ext\zstd\lib\dictBuilder;$(UniversalCRT_IncludePath); + false + + + false + $(IncludePath);$(SolutionDir)..\ext\zstd\lib;$(SolutionDir)..\ext\zstd\programs\legacy;$(SolutionDir)..\ext\zstd\lib\legacy;$(SolutionDir)..\ext\zstd\lib\common;$(SolutionDir)..\ext\zstd\lib\dictBuilder;$(UniversalCRT_IncludePath); + false + + + + $(OutDir)$(TargetName).pdb + + + + + + + Level4 + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + true + ProgramDatabase + false + + + Windows + true + MachineX86 + + + + + + + Level4 + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + ProgramDatabase + false + + + Windows + true + + + + + + + Level4 + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + ProgramDatabase + false + + + Windows + true + + + + + + + Level4 + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + true + ProgramDatabase + false + + + Windows + true + + + + + Level4 + + + MaxSpeed + true + true + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + MultiThreaded + true + ProgramDatabase + AnySuitable + Speed + true + false + + + Windows + true + true + true + MachineX86 + + + + + Level4 + + + MaxSpeed + true + true + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + false + MultiThreaded + true + ProgramDatabase + false + true + AnySuitable + Speed + + + Windows + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + false + MultiThreaded + true + ProgramDatabase + false + true + AnySuitable + Speed + + + Windows + true + true + true + + + + + Level4 + + + MaxSpeed + true + true + ZSTD_MULTITHREAD=1;ZSTD_LEGACY_SUPPORT=5;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + false + MultiThreaded + true + ProgramDatabase + false + true + AnySuitable + Speed + + + Windows + true + true + true + + + + + + \ No newline at end of file diff --git a/ext/zstd b/ext/zstd new file mode 160000 index 0000000000..56421f34e4 --- /dev/null +++ b/ext/zstd @@ -0,0 +1 @@ +Subproject commit 56421f34e4ab5c17cbac0832bd12413e4f27ecf9 diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index c5cfc506c3..8bca7efb04 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -497,6 +497,9 @@ {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} + + {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} + {457f45d2-556f-47bc-a31d-aff0d15beaed} @@ -513,4 +516,4 @@ - + \ No newline at end of file diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 29490b7369..994ffe7985 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -23,6 +23,7 @@ INCFLAGS += \ $(FFMPEGINCFLAGS) \ -I$(EXTDIR)/cityhash \ -I$(EXTDIR)/armips \ + -I$(EXTDIR)/zstd/lib \ -I$(EXTDIR) \ -I$(NATIVEDIR) \ -I$(EXTDIR)/libpng17 \ diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj index 5a63519960..0b73c9224a 100644 --- a/unittest/UnitTests.vcxproj +++ b/unittest/UnitTests.vcxproj @@ -409,6 +409,9 @@ {3baae095-e0ab-4b0e-b5df-ce39c8ae31de} + + {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} + {f761046e-6c38-4428-a5f1-38391a37bb34} From 7a719dc245aee5c2b3e5033e50c7ba6bf3b9516c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 23:20:53 -0700 Subject: [PATCH 089/261] SaveState: Switch to zstd. Choose a level that is just slightly slower than snappy, but much smaller typically. --- Common/Serialize/Serializer.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Common/Serialize/Serializer.cpp b/Common/Serialize/Serializer.cpp index 4a6c9d94a9..099479949c 100644 --- a/Common/Serialize/Serializer.cpp +++ b/Common/Serialize/Serializer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" @@ -287,8 +288,15 @@ CChunkFileReader::Error CChunkFileReader::LoadFile(const std::string &filename, if (header.Compress) { u8 *uncomp_buffer = new u8[header.UncompressedSize]; size_t uncomp_size = header.UncompressedSize; - auto status = snappy_uncompress((const char *)buffer, sz, (char *)uncomp_buffer, &uncomp_size); - if (status != SNAPPY_OK) { + bool success = false; + if (header.Compress == 1) { + auto status = snappy_uncompress((const char *)buffer, sz, (char *)uncomp_buffer, &uncomp_size); + success = status == SNAPPY_OK; + } else { + auto status = ZSTD_decompress((char *)uncomp_buffer, uncomp_size, (const char *)buffer, sz); + success = !ZSTD_isError(status); + } + if (!success) { ERROR_LOG(SAVESTATE, "ChunkReader: Failed to decompress file"); delete [] uncomp_buffer; delete [] buffer; @@ -328,7 +336,7 @@ CChunkFileReader::Error CChunkFileReader::SaveFile(const std::string &filename, } // Make sure we can allocate a buffer to compress before compressing. - size_t write_len = snappy_max_compressed_length(sz); + size_t write_len = ZSTD_compressBound(sz); u8 *compressed_buffer = (u8 *)malloc(write_len); u8 *write_buffer = buffer; if (!compressed_buffer) { @@ -336,7 +344,8 @@ CChunkFileReader::Error CChunkFileReader::SaveFile(const std::string &filename, // We'll save uncompressed. Better than not saving... write_len = sz; } else { - snappy_compress((const char *)buffer, sz, (char *)compressed_buffer, &write_len); + // TODO: If free disk space is low, we could max this out to 22? + write_len = ZSTD_compress(compressed_buffer, write_len, buffer, sz, 1); free(buffer); write_buffer = compressed_buffer; @@ -344,7 +353,7 @@ CChunkFileReader::Error CChunkFileReader::SaveFile(const std::string &filename, // Create header SChunkHeader header{}; - header.Compress = compressed_buffer ? 1 : 0; + header.Compress = compressed_buffer ? 2 : 0; header.Revision = REVISION_CURRENT; header.ExpectedSize = (u32)write_len; header.UncompressedSize = (u32)sz; From a97030068cab2a37e3a52152db73682eeca53a12 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 10 Apr 2021 23:56:19 -0700 Subject: [PATCH 090/261] GE Debugger: Use zstd for save states. --- GPU/Debugger/Playback.cpp | 12 ++++++++---- GPU/Debugger/Record.cpp | 6 +++--- GPU/Debugger/RecordFormat.h | 3 ++- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/GPU/Debugger/Playback.cpp b/GPU/Debugger/Playback.cpp index 9009632b33..459fe52f23 100644 --- a/GPU/Debugger/Playback.cpp +++ b/GPU/Debugger/Playback.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "Common/Profiler/Profiler.h" #include "Common/Common.h" #include "Common/Log.h" @@ -637,7 +638,7 @@ bool DumpExecute::Run() { return true; } -static bool ReadCompressed(u32 fp, void *dest, size_t sz) { +static bool ReadCompressed(u32 fp, void *dest, size_t sz, uint32_t version) { u32 compressed_size = 0; if (pspFileSystem.ReadFile(fp, (u8 *)&compressed_size, sizeof(compressed_size)) != sizeof(compressed_size)) { return false; @@ -650,7 +651,10 @@ static bool ReadCompressed(u32 fp, void *dest, size_t sz) { } size_t real_size = sz; - snappy_uncompress((const char *)compressed, compressed_size, (char *)dest, &real_size); + if (version < 5) + snappy_uncompress((const char *)compressed, compressed_size, (char *)dest, &real_size); + else + real_size = ZSTD_decompress(dest, real_size, compressed, compressed_size); delete[] compressed; return real_size == sz; @@ -699,8 +703,8 @@ bool RunMountedReplay(const std::string &filename) { lastExecPushbuf.resize(bufsz); bool truncated = false; - truncated = truncated || !ReadCompressed(fp, lastExecCommands.data(), sizeof(Command) * sz); - truncated = truncated || !ReadCompressed(fp, lastExecPushbuf.data(), bufsz); + truncated = truncated || !ReadCompressed(fp, lastExecCommands.data(), sizeof(Command) * sz, header.version); + truncated = truncated || !ReadCompressed(fp, lastExecPushbuf.data(), bufsz, header.version); pspFileSystem.CloseFile(fp); diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 4fdc32b29f..eca8ec9a68 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "Common/Common.h" #include "Common/File/FileUtil.h" @@ -98,9 +98,9 @@ static void BeginRecording() { } static void WriteCompressed(FILE *fp, const void *p, size_t sz) { - size_t compressed_size = snappy_max_compressed_length(sz); + size_t compressed_size = ZSTD_compressBound(sz); u8 *compressed = new u8[compressed_size]; - snappy_compress((const char *)p, sz, (char *)compressed, &compressed_size); + compressed_size = ZSTD_compress(compressed, compressed_size, p, sz, 6); u32 write_size = (u32)compressed_size; fwrite(&write_size, sizeof(write_size), 1, fp); diff --git a/GPU/Debugger/RecordFormat.h b/GPU/Debugger/RecordFormat.h index f59e71aa7e..22395e1594 100644 --- a/GPU/Debugger/RecordFormat.h +++ b/GPU/Debugger/RecordFormat.h @@ -33,7 +33,8 @@ static const char *HEADER_MAGIC = "PPSSPPGE"; // Version 2: Uses snappy // Version 3: Adds FRAMEBUF0-FRAMEBUF9 // Version 4: Expanded header with game ID -static const int VERSION = 4; +// Version 5: Uses zstd +static const int VERSION = 5; static const int MIN_VERSION = 2; enum class CommandType : u8 { From a0887401a6e86373e08ad0c72d547e9a4fe42061 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Apr 2021 00:39:56 -0700 Subject: [PATCH 091/261] UI: Add zstd to ZIM compression handling. --- Common/Data/Format/ZIMLoad.cpp | 9 +++++++++ Common/Data/Format/ZIMLoad.h | 1 + Common/Data/Format/ZIMSave.cpp | 11 +++++++++++ ext/native/tools/atlastool.cpp | 6 +++--- ext/native/tools/atlastool/atlastool.vcxproj | 3 +++ ext/native/tools/zimtool/zimtool.vcxproj | 3 +++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/Common/Data/Format/ZIMLoad.cpp b/Common/Data/Format/ZIMLoad.cpp index 45f23e2857..edc1abfec2 100644 --- a/Common/Data/Format/ZIMLoad.cpp +++ b/Common/Data/Format/ZIMLoad.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "zlib.h" @@ -106,6 +107,14 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int // Shouldn't happen if return value was Z_OK. ERROR_LOG(IO, "Wrong size data in ZIM: %i vs %i", (int)outlen, (int)total_data_size); } + } else if (*flags & ZIM_ZSTD_COMPRESSED) { + size_t outlen = ZSTD_decompress(*image, total_data_size, zim + 16, datasize - 16); + if (outlen != (size_t)total_data_size) { + ERROR_LOG(IO, "ZIM zstd format decompression failed: %lld", (long long)outlen); + free(*image); + *image = 0; + return 0; + } } else { memcpy(*image, zim + 16, datasize - 16); if (datasize - 16 != (size_t)total_data_size) { diff --git a/Common/Data/Format/ZIMLoad.h b/Common/Data/Format/ZIMLoad.h index 18354bc6d6..85276b08dd 100644 --- a/Common/Data/Format/ZIMLoad.h +++ b/Common/Data/Format/ZIMLoad.h @@ -32,6 +32,7 @@ enum { ZIM_ETC1_MEDIUM = 1024, ZIM_ETC1_HIGH = 0, // default ZIM_ETC1_DITHER = 2048, + ZIM_ZSTD_COMPRESSED = 4096, }; // ZIM will only ever support up to 12 levels (4096x4096 max). diff --git a/Common/Data/Format/ZIMSave.cpp b/Common/Data/Format/ZIMSave.cpp index 4f5fb230c6..3d61ace397 100644 --- a/Common/Data/Format/ZIMSave.cpp +++ b/Common/Data/Format/ZIMSave.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "zlib.h" @@ -201,6 +202,16 @@ void SaveZIM(FILE *f, int width, int height, int pitch, int flags, const uint8_t ERROR_LOG(IO, "Zlib compression failed.\n"); } delete [] dest; + } else if (flags & ZIM_ZSTD_COMPRESSED) { + size_t dest_len = ZSTD_compressBound(data_size); + uint8_t *dest = new uint8_t[dest_len]; + dest_len = ZSTD_compress(dest, dest_len, data, data_size, 22); + if (!ZSTD_isError(dest_len)) { + fwrite(dest, 1, dest_len, f); + } else { + ERROR_LOG(IO, "Zlib compression failed.\n"); + } + delete [] dest; } else { fwrite(data, 1, data_size, f); } diff --git a/ext/native/tools/atlastool.cpp b/ext/native/tools/atlastool.cpp index c2a9e1be1d..d3bcf498c1 100644 --- a/ext/native/tools/atlastool.cpp +++ b/ext/native/tools/atlastool.cpp @@ -190,7 +190,7 @@ struct Image { memcpy(image_data + y * width() * 4, &dat[y][0], width() * 4); } FILE *f = fopen(zim_name, "wb"); - // SaveZIM takes ownership voer image_data, there's no leak. + // SaveZIM takes ownership over image_data, there's no leak. ::SaveZIM(f, width(), height(), width() * 4, zim_format | ZIM_DITHER, image_data); fclose(f); } @@ -962,10 +962,10 @@ int main(int argc, char **argv) { vector results = bucket.Resolve(image_width, dest); if (highcolor) { printf("Writing .ZIM %ix%i RGBA8888...\n", dest.width(), dest.height()); - dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888 | ZIM_ZLIB_COMPRESSED); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA8888 | ZIM_ZSTD_COMPRESSED); } else { printf("Writing .ZIM %ix%i RGBA4444...\n", dest.width(), dest.height()); - dest.SaveZIM(image_name.c_str(), ZIM_RGBA4444 | ZIM_ZLIB_COMPRESSED); + dest.SaveZIM(image_name.c_str(), ZIM_RGBA4444 | ZIM_ZSTD_COMPRESSED); } // Also save PNG for debugging. diff --git a/ext/native/tools/atlastool/atlastool.vcxproj b/ext/native/tools/atlastool/atlastool.vcxproj index dbbfbfefee..560b47bc34 100644 --- a/ext/native/tools/atlastool/atlastool.vcxproj +++ b/ext/native/tools/atlastool/atlastool.vcxproj @@ -14,6 +14,9 @@ {3fcdbae2-5103-4350-9a8e-848ce9c73195} + + {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} + {f761046e-6c38-4428-a5f1-38391a37bb34} diff --git a/ext/native/tools/zimtool/zimtool.vcxproj b/ext/native/tools/zimtool/zimtool.vcxproj index ee9eca5b90..d667a82ea8 100644 --- a/ext/native/tools/zimtool/zimtool.vcxproj +++ b/ext/native/tools/zimtool/zimtool.vcxproj @@ -14,6 +14,9 @@ {3fcdbae2-5103-4350-9a8e-848ce9c73195} + + {8bfd8150-94d5-4bf9-8a50-7bd9929a0850} + {f761046e-6c38-4428-a5f1-38391a37bb34} From 08eda131c4ee49a90c20c150f406520bb30b7e31 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Apr 2021 01:17:53 -0700 Subject: [PATCH 092/261] UI: Load/save compressed atlas metadata. --- Common/Render/TextureAtlas.cpp | 23 +++++++++---- ext/native/tools/atlastool.cpp | 36 +++++++++++++++++--- ext/native/tools/atlastool/atlastool.vcxproj | 2 +- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Common/Render/TextureAtlas.cpp b/Common/Render/TextureAtlas.cpp index 285f766892..c23cb33646 100644 --- a/Common/Render/TextureAtlas.cpp +++ b/Common/Render/TextureAtlas.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "Common/Render/TextureAtlas.h" @@ -22,10 +23,19 @@ public: } template - T *ReadMultipleAlloc(size_t count) { + T *ReadMultipleAlloc(size_t count, bool compressed) { T *t = new T[count]; - memcpy(t, data_ + offset_, sizeof(T) * count); - offset_ += sizeof(T) * count; + if (!compressed) { + memcpy(t, data_ + offset_, sizeof(T) * count); + offset_ += sizeof(T) * count; + } else { + uint32_t compressed_size = 0; + memcpy(&compressed_size, data_ + offset_, sizeof(uint32_t)); + offset_ += sizeof(uint32_t); + + ZSTD_decompress(t, sizeof(T) * count, data_ + offset_, compressed_size); + offset_ += compressed_size; + } return t; } @@ -45,7 +55,8 @@ bool Atlas::Load(const uint8_t *data, size_t data_size) { return false; } - images = reader.ReadMultipleAlloc(num_images); + images = reader.ReadMultipleAlloc(num_images, header.version >= 1); + fonts = new AtlasFont[num_fonts]; for (int i = 0; i < num_fonts; i++) { AtlasFontHeader font_header = reader.Read(); @@ -55,8 +66,8 @@ bool Atlas::Load(const uint8_t *data, size_t data_size) { fonts[i].distslope = font_header.distslope; fonts[i].numRanges = font_header.numRanges; fonts[i].numChars = font_header.numChars; - fonts[i].ranges = reader.ReadMultipleAlloc(font_header.numRanges); - fonts[i].charData = reader.ReadMultipleAlloc(font_header.numChars); + fonts[i].ranges = reader.ReadMultipleAlloc(font_header.numRanges, header.version >= 1); + fonts[i].charData = reader.ReadMultipleAlloc(font_header.numChars, header.version >= 1); memcpy(fonts[i].name, font_header.name, sizeof(font_header.name)); } return true; diff --git a/ext/native/tools/atlastool.cpp b/ext/native/tools/atlastool.cpp index d3bcf498c1..e745736640 100644 --- a/ext/native/tools/atlastool.cpp +++ b/ext/native/tools/atlastool.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "Common/Render/TextureAtlas.h" @@ -853,6 +854,30 @@ void GetLocales(const char *locales, std::vector &ranges) std::sort(ranges.begin(), ranges.end()); } +static bool WriteCompressed(const void *src, size_t sz, size_t num, FILE *fp) { + size_t src_size = sz * num; + size_t compressed_size = ZSTD_compressBound(src_size); + uint8_t *compressed = new uint8_t[compressed_size]; + compressed_size = ZSTD_compress(compressed, compressed_size, src, src_size, 22); + if (ZSTD_isError(compressed_size)) { + delete[] compressed; + return false; + } + + uint32_t write_size = (uint32_t)compressed_size; + if (fwrite(&write_size, sizeof(uint32_t), 1, fp) != 1) { + delete[] compressed; + return false; + } + if (fwrite(compressed, 1, compressed_size, fp) != compressed_size) { + delete[] compressed; + return false; + } + + delete[] compressed; + return true; +} + int main(int argc, char **argv) { // initProgram(&argc, const_cast(&argv)); // /usr/share/fonts/truetype/msttcorefonts/Arial_Black.ttf @@ -981,15 +1006,16 @@ int main(int argc, char **argv) { FILE *meta = fopen(meta_name.c_str(), "wb"); AtlasHeader header; header.magic = ATLAS_MAGIC; - header.version = 0; + header.version = 1; header.numFonts = (int)fonts.size(); header.numImages = (int)images.size(); fwrite(&header, 1, sizeof(header), meta); // For each image + AtlasImage *atalas_images = new AtlasImage[images.size()]; for (int i = 0; i < (int)images.size(); i++) { - AtlasImage atlas_image = images[i].ToAtlasImage((float)dest.width(), (float)dest.height(), results); - fwrite(&atlas_image, 1, sizeof(atlas_image), meta); + atalas_images[i] = images[i].ToAtlasImage((float)dest.width(), (float)dest.height(), results); } + WriteCompressed(atalas_images, sizeof(AtlasImage), images.size(), meta); // For each font for (int i = 0; i < (int)fonts.size(); i++) { auto &font = fonts[i]; @@ -997,9 +1023,9 @@ int main(int argc, char **argv) { AtlasFontHeader font_header = font.GetHeader(); fwrite(&font_header, 1, sizeof(font_header), meta); auto ranges = font.GetRanges(); - fwrite(ranges.data(), sizeof(AtlasCharRange), ranges.size(), meta); + WriteCompressed(ranges.data(), sizeof(AtlasCharRange), ranges.size(), meta); auto chars = font.GetChars((float)dest.width(), (float)dest.height(), results); - fwrite(chars.data(), sizeof(AtlasChar), chars.size(), meta); + WriteCompressed(chars.data(), sizeof(AtlasChar), chars.size(), meta); } fclose(meta); } diff --git a/ext/native/tools/atlastool/atlastool.vcxproj b/ext/native/tools/atlastool/atlastool.vcxproj index 560b47bc34..65b315ebdc 100644 --- a/ext/native/tools/atlastool/atlastool.vcxproj +++ b/ext/native/tools/atlastool/atlastool.vcxproj @@ -95,7 +95,7 @@ true _CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) true - ../../../../;../../ext;../../;../../../../ext;../prebuilt + ../../../../;../../ext;../../;../../../../ext;../prebuilt;../../../../ext/zstd/lib MultiThreaded false From 372deeaef1de57dd73913ee419095580a7135343 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 11 Apr 2021 00:49:28 -0700 Subject: [PATCH 093/261] UI: Compress zim files with zstd. Loads in nearly half the time. Compressed at level 22. --- android/assets/ppge_atlas.zim | Bin 870970 -> 666530 bytes android/assets/ui_atlas.zim | Bin 1684105 -> 1070639 bytes assets/ppge_atlas.zim | Bin 870970 -> 666530 bytes assets/ui_atlas.zim | Bin 1684105 -> 1070639 bytes assets/ui_atlas_lowmem.zim | Bin 94627 -> 0 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 assets/ui_atlas_lowmem.zim diff --git a/android/assets/ppge_atlas.zim b/android/assets/ppge_atlas.zim index 6c33fb087dea6550908838838e663763d8df5b5f..9ee0af22ababc2850c130042b01beae7d70f819a 100644 GIT binary patch literal 666530 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�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%0A!t$>o=k+ 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 z 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
    BwdXxd|luA2_|j9n*Enj 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

    _Ig;Mq6` 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 z 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