* AGC: retain active label producer records
Ported from the archived silent-hill-minimal branch (274ccfdf).
RegisterLabelProducer bounded its history with RemoveRange(0, 1024) once it
reached 4096 entries, which evicts the oldest records regardless of whether
their label write has completed. Those records are not a diagnostic cache:
a suspended DCB resolves its wait_reg_mem by finding the producer that will
write the watched label. Dropping an active record hides an earlier
same-submission label write, so a legitimate in-stream fence suspends
forever and the graphics queue stops.
Compact only completed history, and let the list exceed the soft bound when
every record is still active — correctness over a diagnostic limit.
Two hardening changes over the ported version, because a suspended queue is
exactly when every record is active:
- compaction is a single order-preserving pass instead of repeated RemoveAt,
which would shift the tail per eviction (quadratic) while the label gate is
held;
- when a pass frees nothing the bound is raised to twice the current count, so
registration does not rescan the whole list on every subsequent add, and it
is reset once compaction can make progress again.
Tests: 664 pass, 0 fail (SharpEmu.Libs.Tests 598 -> 600).
* AGC: keep produced label values a suspended wait still needs
GpuWaitRegistry.RecordProduced dropped the entire produced-value table once it
reached 8192 entries:
if (_lastProduced.Count >= 8192) { _lastProduced.Clear(); }
Those entries are release state, not a cache. CollectDeadlockBroken is the only
way out for a DCB suspended on a WAIT_REG_MEM whose label the guest has since
recycled for other data: it replays the value a real producer already wrote to
that label. Clearing the table wholesale erases exactly the records live waiters
depend on, so every such waiter is stranded permanently — the suspended graphics
queue never resumes, and with it the render thread and the whole engine thread
graph park.
That is what Silent Hill (PPSA10112) hits. Its final unsatisfied waits watch
labels holding guest allocator metadata (each reads a pointer into its own
region rather than the expected 1), i.e. recycled memory, which is precisely
the case the deadlock breaker exists to handle — yet agc.deadlock_break fires 0
times across a run with 490 wait suspensions and 1068 successful release_mem
writes, because the producing values had already been cleared.
Prune only values no registered waiter is watching, and let the table exceed the
soft bound while they are all watched. Same reasoning as the label-producer
history in the preceding commit: correctness of synchronization state takes
precedence over a diagnostic bound.
Tests: 666 pass, 0 fail. The regression test fails against the previous
wholesale Clear() and passes with the prune, verified by reverting the fix.
* AGC: report release-label writes that never reach guest memory
Both release_mem handlers recorded the produced label value only on success:
if (wroteData && dataSelection is 1 or 2) GpuWaitRegistry.RecordProduced(...)
with no else. A failed write is not benign here. That packet is the producer a
suspended WAIT_REG_MEM is waiting for, so when it fails the label is neither
written nor recorded, CollectDeadlockBroken has no value to replay, and the
graphics queue stays suspended forever — the render thread and the engine
thread graph park behind it with nothing in the log to say why.
Measured on Silent Hill (PPSA10112): the fatal AccessViolation lands exactly
here, on the presenter thread, in ApplySubmittedReleaseMem's label write into a
protected guest page. The faulting variant kills the process; the
returns-false variant wedges the GPU silently. Only the first was ever visible.
Report the failure (rate-limited: first 16, then powers of two) instead of
dropping it. This does not fix the underlying write failure — it makes a
permanently suspended queue diagnosable rather than silent.
Tests: 666 pass, 0 fail.
SharpEmu
An experimental PlayStation 5 emulator for Windows, Linux and macOS.
Note
SharpEmu supports Windows x64, Linux x64, and macOS x64. Apple Silicon Macs can run the macOS x64 build through Rosetta 2, and Windows on ARM devices (e.g. Snapdragon) can run the Windows x64 build through Windows' built-in x64 emulation.
Warning
SharpEmu is an experimental PS5 emulator developed from scratch in C#. The current focus is on accuracy and infrastructure setup rather than game-specific compatibility.
Info
SharpEmu is an emulator project currently in its early stages of development.
This project is developed purely for research and educational purposes. There are no commercial goals associated with it. We enjoy learning about system architecture and reverse engineering.
SharpEmu focuses exclusively on the PlayStation 5.
Our goal is not to emulate PS4 games, as there is already an excellent emulator dedicated to that platform: ShadPS4.
Games Tested
| Demons Souls Remake | Dreaming Sarah |
|---|---|
![]() |
![]() |
| Void Terrarium | Dead Cells |
|---|---|
![]() |
![]() |
Status
The emulator can currently load the eboot.bin of real games, execute native CPU instructions, and partially handle kernel-related functionality. However, several critical components are still missing.
Current capabilities include:
- Loading
eboot.binand.elffiles - Executing native CPU instructions
- Reading basic game metadata (title, version, etc.)
- Loading system modules (
prx/sys_module) - Partial support for some kernel functions
FiberandAMPRexports- PlayGo scenarios
- Initial loading game files
- Shader/resource submits and AGC initial
- Video outputs in some games
Some games have reached like sceVideoOut and AGC stages.
SharpEmu supports Windows, Linux, and macOS hosts. Video output uses Vulkan on Windows and Linux, and MoltenVK on macOS. Platform support is still experimental, so compatibility and performance vary by game, operating system, and GPU driver.
Using
Download the release archive for your operating system, extract it, and launch
SharpEmu with the path to a legally obtained game's eboot.bin.
Windows PowerShell:
.\SharpEmu.exe "C:\path\to\game\eboot.bin" 2>&1 |
Tee-Object -FilePath "SharpEmu.log"
Linux and macOS:
chmod +x ./SharpEmu
./SharpEmu "/path/to/game/eboot.bin" 2>&1 |
tee SharpEmu.log
A Vulkan-capable GPU and current graphics driver are required. The macOS release includes the MoltenVK Vulkan implementation.
Important
This project does not support or condone piracy.
All games used during development and testing are dumped from consoles that we personally own.
Users are expected to use legally obtained copies of their games.
Build
- Install the .NET SDK version specified in
global.json. - Clone the repository:
git clone https://github.com/sharpemu/sharpemu.git - Open the solution file (
SharpEmu.slnx) in VSCode. - Build the project:
dotnet buildordotnet publish - Build artifacts will be located in the
artifactsdirectory.
Disclaimer
SharpEmu is an experimental emulator intended for research and educational purposes.
This project does not contain any copyrighted system firmware, game data, or proprietary PlayStation assets.
Special Thanks
The following projects were extremely helpful during development:
-
ShadPS4
Helped with understanding the basic architecture of the PlayStation 4. -
Kyty
One of the few PS5 emulator projects available and very useful for studying native code execution. -
Ryujinx
Provided valuable references for filesystem handling and low-level C# implementation patterns.
License
Support
Support SharpEmu via GitHub Sponsors or cryptocurrency. Every contribution helps fund ongoing development and long-term maintenance. GitHub Sponsors is the preferred way to support the project, but cryptocurrency donations are also appreciated.
ETH/USDT
0xF315F5d986c790bB3A58DbE60F1B2760997dEd82
BTC
bc1qmr9k8899njys5ny63xsues4jgmkk96erslrkmv
Contributing
Before opening an issue or pull request, please read our contribution guidelines:
The guide covers:
- Coding style and formatting
- AI-assisted contributions
- Pull request expectations
- Testing guidelines
- Legal and reverse engineering policy




