mirror of
https://github.com/par274/sharpemu.git
synced 2026-08-24 10:06:57 +08:00
[Codec/Native] Real H.264 decode for sceVideodec2, fix TLS loader missing the main module (#824)
* [Codec/Native] Real H.264 decode for sceVideodec2, fix TLS loader missing the main module sceVideodec2 was a capability-only stub: the game's video pipeline worked end-to-end but never produced a picture, so intro/cinematic videos stayed black even though playback "completed" without errors (confirmed on Ghost of Yotei's intro cinematic). - Videodec2Decoder: owns an FFmpeg H.264 session per decoder handle, running decode and presentation pacing on their own threads (never the guest thread) so a whole clip isn't decoded faster than it can be displayed. Converts to BGRA and submits straight to VulkanVideoPresenter, bypassing guest memory the same way the existing Bink2 path does. - Videodec2Exports: wires the real decoder into sceVideodec2CreateDecoder/Decode/Flush/Reset/DeleteDecoder, falling back to the original no-picture stub whenever FFmpeg is unavailable or a given decoder failed to open. - VulkanVideoPresenter: decoded frames were being dropped under a single "latest wins" slot the render loop didn't always poll in time before the next frame overwrote it. Queues pending video presentations the same way guest-image flips already are. - DirectExecutionBackend: the TLS load patcher's one-shot scan missed the main game module when the entry point resolves to a separate bootstrap allocation, and never re-scanned lazily-committed pages patched in afterward -- both left FS:[0] TLS loads unpatched, causing an early mutex-spin boot stall (reproduced on Demon's Souls: stuck at import #256). Now scans both the entry point's own allocation and the standard PS5/PS4 image base, and re-scans each newly committed executable range as it's touched. * [GUI] Add a toggle for SHARPEMU_FORCE_SUBMIT_ORPHAN_PREAMBLES This flag already existed as an AGC workaround (forces queued GPU command-buffer preambles through when their target queue never picks them up, unblocking titles stuck on a WAIT_REG_MEM that never signals) but was only reachable by setting the environment variable by hand. Expose it as a checkbox next to the other env toggles, in both the global Options panel and the per-game settings panel, so it can be turned on for a specific title without touching a shell. * [GUI] Add remaining language translations for the new env toggle The previous commit only added the new key to en.json/fr.json, relying on Localization's runtime fallback to English -- but LocalizationTests.EmbeddedLanguages_ContainEveryEnglishOptionsKey requires every Options.* key to exist in every embedded language file, which broke CI on all three build jobs. Fills in the remaining 13 languages.
This commit is contained in:
@@ -3145,8 +3145,33 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
||||
// Large Gen5 executables can keep valid code well past the first 32 MiB.
|
||||
// Astro Bot, for example, has an FS:[0] TLS load near +0x70A0000.
|
||||
const ulong MaxScanBytes = 134217728uL;
|
||||
ulong num = _entryPoint;
|
||||
ulong num2 = num + MaxScanBytes;
|
||||
|
||||
// _entryPoint can be a separate bootstrap allocation, not the main module —
|
||||
// always also scan the standard PS5/PS4 image base.
|
||||
const ulong Ps5MainImageBase = 0x0000000800000000UL;
|
||||
const ulong Ps4MainImageBase = 0x0000000000400000UL;
|
||||
ulong scanStart = _entryPoint;
|
||||
if (VirtualQuery((void*)_entryPoint, out var entryRegion, (nuint)sizeof(MEMORY_BASIC_INFORMATION64)) != 0 &&
|
||||
entryRegion.AllocationBase != 0 &&
|
||||
entryRegion.AllocationBase <= _entryPoint)
|
||||
{
|
||||
scanStart = entryRegion.AllocationBase;
|
||||
}
|
||||
|
||||
PatchTlsPatternsInRange(scanStart, scanStart + MaxScanBytes, announce: true);
|
||||
|
||||
// Scan both windows unconditionally; overlap is safe, patched bytes just stop matching.
|
||||
var mainImageBase = _entryPoint >= Ps5MainImageBase ? Ps5MainImageBase : Ps4MainImageBase;
|
||||
if (mainImageBase < scanStart)
|
||||
{
|
||||
PatchTlsPatternsInRange(mainImageBase, mainImageBase + MaxScanBytes, announce: false);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void PatchTlsPatternsInRange(ulong rangeStart, ulong rangeEnd, bool announce)
|
||||
{
|
||||
ulong num = rangeStart;
|
||||
ulong num2 = rangeEnd;
|
||||
int num3 = 0;
|
||||
int num4 = 0;
|
||||
int num9 = 0;
|
||||
@@ -3195,7 +3220,11 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
||||
}
|
||||
num = num6 > num ? num6 : num + 4096uL;
|
||||
}
|
||||
Console.Error.WriteLine($"[LOADER][INFO] Patched {num3} TLS loads, {num9} TLS stores, {num4} stack-canary accesses, {sse4aPatchCount} SSE4a EXTRQ blends");
|
||||
if (announce || num3 + num4 + num9 + sse4aPatchCount > 0)
|
||||
{
|
||||
Console.Error.WriteLine($"[LOADER][INFO] Patched {num3} TLS loads, {num9} TLS stores, {num4} stack-canary accesses, {sse4aPatchCount} SSE4a EXTRQ blends" +
|
||||
(announce ? string.Empty : $" (lazy-commit rescan 0x{rangeStart:X16}-0x{rangeEnd:X16})"));
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe bool TryPatchSse4aExtrqBlend(nint address, byte* source)
|
||||
|
||||
Reference in New Issue
Block a user