When a fixed mapping spans multiple free runs and a later gap cannot be
backed, any earlier host allocations were leaked. Stage all allocations
during the walk and insert MemoryRegions only after every gap has been
backed successfully. On any failure, free all staged allocations.
Fixes#472🤖 Generated with Hermes Agent
Quake (PPSA01880, Kex Engine) crashes at startup because
sceVideoOutIsOutputSupported (NID Nv8c-Kb+DUM) is unimplemented.
The game calls it to check video output capabilities before
initializing rendering.
Add HLE export stub: returns 1 (supported) for SceVideoOutBusTypeMain,
0 otherwise. The emulator renders via Vulkan and supports any pixel
format or aspect ratio on the main bus.
NID verified via Ps5Nid.Compute SHA1 algorithm.
Export name confirmed in scripts/ps5_names.txt.
VReadlaneB32 (VOP3 0x360) had two bugs:
1. Decode: VOP3 decode always set destinations = Vector(word & 0xFF).
For VReadlaneB32, bits 0-7 are unused — the scalar destination is
in bits 8-14. Now decodes as Scalar((word >> 8) & 0x7F).
2. Emission: VReadlaneB32 was in the VMovB32 fall-through group,
just returning GetRawSource(instruction, 0) — reading the current
lane's value. By ISA, sdst = vsrc0[lane(src1)], which requires
reading a different lane's value. Now uses SPIR-V
GroupNonUniformBroadcast(scope=Subgroup, value=src0, lane=src1)
when subgroup operations are available, with a fallback to the
current-lane simplification when not.
3. Routing: TryEmitVectorAlu called TryGetVectorDestination first,
which checks for VectorRegister kind. With the scalar destination
fix, VReadlaneB32 now routes to a new TryEmitReadlane handler
before the vector destination check.
4. Subgroup capability: UsesSubgroupShuffle now includes VReadlaneB32
so GroupNonUniform capability is enabled when needed.
Verified: dotnet build 0 errors/0 warnings, 26/26 tests pass,
ShaderDump all programs behaved as expected.
PR #200 moved shader files from SharpEmu.Libs/Agc/ to new projects
SharpEmu.ShaderCompiler and SharpEmu.ShaderCompiler.Vulkan. This
re-ports the VOP3 decode fix from PR #226 to the new file paths.
Decode table (Gen5ShaderTranslator.cs):
- 0x360: VMadU32U16 -> VReadlaneB32 (per RDNA2 ISA)
- 0x361: VMulLoU32 -> VWritelaneB32 (0x361 was a duplicate of 0x169)
- 0x373: added VMadU32U16 at its correct opcode
Emission (Gen5SpirvTranslator.Alu.cs):
- VWritelaneB32: per-lane conditional write via IEqual+Select,
stores with guardWithExec:false (writelane bypasses exec mask)
- VReadlaneB32: kept as GetRawSource(instruction, 0) simplification
(correct emission with src1 lane select is a follow-up)
Verified: dotnet build 0 errors/0 warnings, 26/26 tests pass,
ShaderDump all programs behaved as expected.
- FileLogSink: thread-safe file writer with AutoFlush, FileShare.Read for
concurrent read access (tail -f), automatic parent directory creation,
full date-time timestamps, IDisposable for graceful shutdown
- CompositeLogSink: fan-out to multiple sinks with per-sink exception
isolation (one broken sink cannot silence the others), IDisposable
propagates to children
- SharpEmuLog: ResolveSinkFromEnvironment() reads SHARPEMU_LOG_FILE and
creates CompositeLogSink(console + file) when set; Sink setter now
disposes the previous IDisposable sink to prevent file handle leaks;
Shutdown() flushes and disposes the active sink
- Program.cs: Main wrapped in try/finally to guarantee SharpEmuLog.Shutdown()
runs on all exit paths (GUI, mitigated child, normal, exception)
Co-authored-by: Hermes Atlas <hermesatlas@example.com>
* [agc] Add shader type 4 (GS) and register defaults v13 support
Astro Bot (#11) crashes on boot due to two missing GPU features:
1. Shader type 4 (Geometry Shader) — SPI_SHADER_PGM_LO/HI register
offsets 0x8A/0x8B were missing. Added constants and switch cases
for shader type 4 in GetExpectedSpiShaderPgmLo/Hi. Also added
type 4 to IsEsGeometryShaderType (2 or 4 or 6).
2. Register defaults version 13 — was not recognized as supported.
Added RegisterDefaultsVersion13 constant and included it in
IsSupportedRegisterDefaultsVersion.
* [kernel] Add POSIX pthread_cond_timedwait export
SILENT HILL (#4) and Poppy Playtime (#3) crash on boot due to
missing POSIX pthread_cond_timedwait (NID 27bAgiJmOh0).
The Sony wrapper scePthreadCondTimedwait (NID BmMjYxmew1w) was
already implemented, but the raw POSIX symbol was not exported.
Added [SysAbiExport] for pthread_cond_timedwait delegating to
existing PthreadCondWaitCore with timed: true.
* [memory] Fix FlushInstructionCache null process handle
PhysicalVirtualMemory.cs called FlushInstructionCache with null as the
process handle in two places (SetProtection and TryWriteExclusive).
On Windows, a null handle does not reliably resolve to the current
process — the correct call is GetCurrentProcess() (pseudo-handle -1).
Also corrected the P/Invoke signature:
- Changed return type from void to bool with [return: MarshalAs(Bool)]
- Added SetLastError = true
- Added GetCurrentProcess() P/Invoke import
This matches the pattern already used in DirectExecutionBackend.cs
which correctly passes GetCurrentProcess() to all FlushInstructionCache
calls.
* [hle] Distinguish NOT_FOUND from NOT_IMPLEMENTED and log duplicate NIDs
Three diagnostic improvements to the HLE dispatch path:
1. ModuleManager.RegisterFromAssembly — duplicate NID registration was
silently skipped (dispatchTable first-wins, exportTable last-wins,
causing metadata divergence). Now logs a warning with the NID and
export name so conflicts are visible.
2. ModuleManager.TryDispatch — generation mismatch returned
ORBIS_GEN2_ERROR_NOT_FOUND, conflating 'function does not exist'
with 'function exists but not for this generation'. Now returns
ORBIS_GEN2_ERROR_NOT_IMPLEMENTED for generation mismatch, matching
the existing convention in CpuDispatcher. Also adds debug logging
for both NOT_FOUND and NOT_IMPLEMENTED paths.
3. DirectExecutionBackend.Imports.cs — the import dispatch else-branch
(the actual hot path that bypasses ModuleManager.TyDispatch via
cached export) had the same conflation. Split into:
- else if (export exists but generation mismatch) → NOT_IMPLEMENTED
- else (no export at all) → NOT_FOUND
This makes runtime diagnostics correctly distinguish missing exports
from generation-unsupported exports.
* [cpu] Check VirtualProtect return values in all stub creation paths
9 VirtualProtect calls in DirectExecutionBackend.cs had unchecked
return values. If VirtualProtect silently fails, memory protection
remains incorrect — stubs allocated with PAGE_EXECUTE_READWRITE (0x40)
never get downgraded to PAGE_EXECUTE_READ (0x20), or guest thread
entry stubs never get upgraded to writable. This causes access
violations on next execution or silent data corruption.
Fixed all 9 sites with proper error handling:
- 6 stub creation methods (return 0 on failure + log error)
- 2 guest thread entry methods (set reason + return Exception)
- 1 guest entry method (set LastError + return MEMORY_FAULT)
Stub creation sites fixed:
- CreateImportDispatchStub (line ~1683)
- EnsureTlsHandler (void, log + return)
- CreateUnresolvedReturnStub (return 0)
- CreateGuestReturnStub (return 0)
- CreateExceptionHandlerTrampoline (return 0)
- CreateTlsStoreHelperStub (return 0)
Guest thread entry sites fixed:
- StartGuestThreadNativeCall (return Exception)
- StartGuestContinuationNativeCall (return Exception)
- RunGuestEntryPoint (return MEMORY_FAULT)
* [kernel] Remove unused duplicate _nextFileDescriptor field
KernelExports.cs declared _nextFileDescriptor but never used it.
The actual field used for file descriptor allocation lives in
KernelMemoryCompatExports.cs (lines 1314, 1337). This was a dead
duplicate causing CS0414 warning.
Build is now 0 errors, 0 warnings.
---------
Co-authored-by: Hermes Atlas <hermesatlas@example.com>