From b48d917e29f37b2ccb60d885061584be087000db Mon Sep 17 00:00:00 2001 From: Sam Kenny <968135+sammiq@users.noreply.github.com> Date: Mon, 11 May 2026 10:22:41 +1000 Subject: [PATCH] Fixes regressions and issues causing PSP emulated games to not run. (#4389) * Fixes PSP emulation with the following changes: 1. Reserved Memory cannot be mapped, this seems to be incorrect and the PSP emulation relies on reserving then mapping memory at startup. From other logs, this may affect PS2 emulation as well. 2. Temp directory output may have garbase and the API is not null terminating the output, resulting in failures when the file path is not valid. 3. Fix misaligned images when viewport is sized for PSP. This fixes garbage in movies on the PSP emulator, making the movies viewable, scaled correctly for the screen. 4. Some PSP moves render incorrectly without sceVideodec2GetAvcPictureInfo 5. Fix dirty hash size calculation and RGB4444 mapping to fix textures These changes combined allow Jean d'Arc, LocoRoco and Patapon to run decently. * fix formatting * null terminate the temp path rather than using memset * fix memory mapping in a more correct way * revert RGB4444 changes as it breaks other games color mapping --- src/core/libraries/app_content/app_content.cpp | 1 + src/core/libraries/videodec/videodec2.cpp | 8 ++++++++ src/core/libraries/videodec/videodec2.h | 5 ++++- src/core/libraries/videodec/videodec2_impl.cpp | 6 +++--- src/core/memory.cpp | 2 +- src/video_core/texture_cache/texture_cache.cpp | 6 +++++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/app_content/app_content.cpp b/src/core/libraries/app_content/app_content.cpp index bf2b72b07..c01c0d655 100644 --- a/src/core/libraries/app_content/app_content.cpp +++ b/src/core/libraries/app_content/app_content.cpp @@ -402,6 +402,7 @@ int PS4_SYSV_ABI sceAppContentTemporaryDataMount2(OrbisAppContentTemporaryDataOp } static constexpr std::string_view TmpMount = "/temp0"; TmpMount.copy(mountPoint->data, TmpMount.size()); + mountPoint->data[TmpMount.size()] = '\0'; LOG_INFO(Lib_AppContent, "sceAppContentTemporaryDataMount2: option = {}, mountPoint = {}", option, mountPoint->data); return ORBIS_OK; diff --git a/src/core/libraries/videodec/videodec2.cpp b/src/core/libraries/videodec/videodec2.cpp index 07055966f..c364f43cc 100644 --- a/src/core/libraries/videodec/videodec2.cpp +++ b/src/core/libraries/videodec/videodec2.cpp @@ -229,6 +229,12 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp return ORBIS_OK; } +s32 PS4_SYSV_ABI sceVideodec2GetAvcPictureInfo(const OrbisVideodec2OutputInfo* outputInfo, + void* p1stPictureInfoOut, void* p2ndPictureInfoOut) { + LOG_TRACE(Lib_Vdec2, "called"); + return sceVideodec2GetPictureInfo(outputInfo, p1stPictureInfoOut, p2ndPictureInfoOut); +} + void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("RnDibcGCPKw", "libSceVideodec2", 1, "libSceVideodec2", sceVideodec2QueryComputeMemoryInfo); @@ -246,6 +252,8 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("wJXikG6QFN8", "libSceVideodec2", 1, "libSceVideodec2", sceVideodec2Reset); LIB_FUNCTION("NtXRa3dRzU0", "libSceVideodec2", 1, "libSceVideodec2", sceVideodec2GetPictureInfo); + LIB_FUNCTION("kjrLbcyhEiw", "libSceVideodec2", 1, "libSceVideodec2", + sceVideodec2GetAvcPictureInfo); } } // namespace Libraries::Videodec2 diff --git a/src/core/libraries/videodec/videodec2.h b/src/core/libraries/videodec/videodec2.h index 0311e4d27..6b4aefab1 100644 --- a/src/core/libraries/videodec/videodec2.h +++ b/src/core/libraries/videodec/videodec2.h @@ -137,5 +137,8 @@ s32 PS4_SYSV_ABI sceVideodec2Reset(OrbisVideodec2Decoder decoder); s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outputInfo, void* p1stPictureInfo, void* p2ndPictureInfo); +s32 PS4_SYSV_ABI sceVideodec2GetAvcPictureInfo(const OrbisVideodec2OutputInfo* outputInfo, + void* p1stPictureInfoOut, void* p2ndPictureInfoOut); + void RegisterLib(Core::Loader::SymbolsResolver* sym); -} // namespace Libraries::Videodec2 \ No newline at end of file +} // namespace Libraries::Videodec2 diff --git a/src/core/libraries/videodec/videodec2_impl.cpp b/src/core/libraries/videodec/videodec2_impl.cpp index e1ef5d587..7fa237941 100644 --- a/src/core/libraries/videodec/videodec2_impl.cpp +++ b/src/core/libraries/videodec/videodec2_impl.cpp @@ -133,7 +133,7 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData, // Only set framePitchInBytes if the game uses the newer struct version. if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) { - outputInfo.framePitchInBytes = frame->linesize[0]; + outputInfo.framePitchInBytes = frame->width; } if (outputInfo.isValid) { @@ -201,7 +201,7 @@ s32 VdecDecoder::Flush(OrbisVideodec2FrameBuffer& frameBuffer, outputInfo.codecType = 1; // FIXME: Hardcoded to AVC outputInfo.frameWidth = frame->width; outputInfo.frameHeight = frame->height; - outputInfo.framePitch = frame->linesize[0]; + outputInfo.framePitch = frame->width; outputInfo.frameBufferSize = frameBuffer.frameBufferSize; outputInfo.frameBuffer = frameBuffer.frameBuffer; @@ -211,7 +211,7 @@ s32 VdecDecoder::Flush(OrbisVideodec2FrameBuffer& frameBuffer, // Only set framePitchInBytes if the game uses the newer struct version. if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) { - outputInfo.framePitchInBytes = frame->linesize[0]; + outputInfo.framePitchInBytes = frame->width; } // FIXME: Should we add picture info here too? diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 64b1bb750..0d5861fdb 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -720,7 +720,7 @@ s32 MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, u64 size, Memory prot &= ~MemoryProt::CpuExec; } - if (True(flags & MemoryMapFlags::Fixed) && False(flags & MemoryMapFlags::NoOverwrite)) { + if (True(flags & MemoryMapFlags::Fixed) && True(flags & MemoryMapFlags::NoOverwrite)) { ASSERT_MSG(IsValidMapping(virtual_addr, size), "Attempted to access invalid address {:#x}", virtual_addr); auto vma = FindVMA(virtual_addr)->second; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index ca63f60ed..b682196af 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -5,6 +5,7 @@ #include "common/assert.h" #include "common/debug.h" +#include "common/div_ceil.h" #include "common/scope_exit.h" #include "core/emulator_settings.h" #include "core/memory.h" @@ -731,7 +732,10 @@ void TextureCache::RefreshImage(Image& image) { const auto addr = std::bit_cast(image.info.guest_address); const u32 w = std::min(image.info.size.width, u32(8)); const u32 h = std::min(image.info.size.height, u32(8)); - const u32 size = w * h * image.info.num_bits >> (3 + image.info.props.is_block ? 4 : 0); + + const u32 s_w = image.info.props.is_block ? Common::DivCeil(w, 4u) : w; + const u32 s_h = image.info.props.is_block ? Common::DivCeil(h, 4u) : h; + const u32 size = s_w * s_h * (image.info.num_bits / 8); const u64 hash = XXH3_64bits(addr, size); if (image.hash == hash) { image.flags &= ~ImageFlagBits::MaybeCpuDirty;