mirror of
https://github.com/fstat13/PSCapture.git
synced 2026-10-17 12:00:39 +02:00
- docs/GUIDE.md: step-by-step usage (what you see at every step), tuning, symptom-by-symptom troubleshooting, uninstall - docs/BUILD.md: complete build chain (payload via docker, PC toolchain install, exact commands, verification, gotchas) - docs/index.html: rebuilt with quick-start detail, log-line table, troubleshooting, build section, anchors - README: detailed quick start, corrected build commands (static dll, luxtheme, embed order) and links
351 lines
17 KiB
HTML
351 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>PSCapture by fstat13 — PS5 screen as a capture card on PC</title>
|
|
<style>
|
|
:root{
|
|
--bg:#0d1015; --card:#151a22; --card2:#1b222d; --line:#242c38;
|
|
--fg:#e8edf4; --dim:#96a0b0; --accent:#0070d1; --accent2:#35a3ff;
|
|
--rec:#e22236; --ok:#1fbf6b;
|
|
}
|
|
*{box-sizing:border-box}
|
|
body{margin:0;background:var(--bg);color:var(--fg);
|
|
font:16px/1.65 "Segoe UI",system-ui,-apple-system,Roboto,sans-serif;}
|
|
a{color:var(--accent2);text-decoration:none}
|
|
a:hover{text-decoration:underline}
|
|
.wrap{max-width:880px;margin:0 auto;padding:0 20px}
|
|
header{background:
|
|
radial-gradient(900px 320px at 20% -40%, rgba(0,112,209,.35), transparent 60%),
|
|
radial-gradient(700px 300px at 90% -30%, rgba(226,34,54,.22), transparent 60%),
|
|
var(--bg);
|
|
border-bottom:1px solid var(--line);padding:56px 0 40px}
|
|
.brand{display:flex;align-items:center;gap:18px}
|
|
.brand img{width:84px;height:84px;border-radius:20px;box-shadow:0 8px 30px rgba(0,0,0,.5)}
|
|
h1{font-size:44px;margin:0;letter-spacing:.5px}
|
|
.tag{color:var(--dim);font-size:18px;margin-top:6px}
|
|
.badges{margin-top:22px;display:flex;gap:10px;flex-wrap:wrap}
|
|
.badge{border:1px solid var(--line);background:var(--card);
|
|
padding:5px 12px;border-radius:999px;font-size:13px;color:var(--dim)}
|
|
.badge b{color:var(--fg)}
|
|
h2{margin:52px 0 14px;font-size:26px}
|
|
h3{margin:26px 0 10px;font-size:19px}
|
|
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:14px}
|
|
.card{background:var(--card);border:1px solid var(--line);border-radius:14px;padding:18px 20px}
|
|
.card h3{margin:0 0 8px;font-size:17px}
|
|
.card p{margin:0;color:var(--dim);font-size:14.5px}
|
|
.flow{display:flex;gap:10px;align-items:stretch;flex-wrap:wrap;margin-top:16px}
|
|
.box{flex:1;min-width:180px;background:var(--card2);border:1px solid var(--line);
|
|
border-radius:12px;padding:14px 16px}
|
|
.box b{display:block;margin-bottom:6px}
|
|
.box div{color:var(--dim);font-size:13.5px}
|
|
.arrow{align-self:center;color:var(--accent2);font-size:22px;padding:0 2px}
|
|
ol.steps{counter-reset:s;list-style:none;padding:0;margin:18px 0 0}
|
|
ol.steps li{counter-increment:s;position:relative;padding:0 0 18px 54px}
|
|
ol.steps li::before{content:counter(s);position:absolute;left:0;top:0;
|
|
width:34px;height:34px;border-radius:10px;background:var(--accent);
|
|
color:#fff;font-weight:600;display:flex;align-items:center;justify-content:center}
|
|
ol.steps b{color:var(--fg)}
|
|
ol.steps span{color:var(--dim)}
|
|
ul.plain{color:var(--dim);padding-left:22px}
|
|
ul.plain b{color:var(--fg)}
|
|
table{width:100%;border-collapse:collapse;margin-top:14px;font-size:14.5px}
|
|
th,td{text-align:left;padding:10px 12px;border-bottom:1px solid var(--line);
|
|
vertical-align:top}
|
|
th{color:var(--dim);font-weight:500}
|
|
td code,th code{white-space:nowrap}
|
|
code,kbd{background:#0a0d12;border:1px solid var(--line);border-radius:6px;
|
|
padding:1px 7px;font:13.5px/1.5 Consolas,monospace;color:#cfe3ff}
|
|
pre{background:#0a0d12;border:1px solid var(--line);border-radius:12px;
|
|
padding:14px 16px;overflow-x:auto;font:13.5px/1.6 Consolas,monospace;
|
|
color:#cfe3ff}
|
|
pre .c{color:#5f7186}
|
|
details{background:var(--card);border:1px solid var(--line);border-radius:12px;
|
|
padding:14px 18px;margin:10px 0}
|
|
summary{cursor:pointer;font-weight:600}
|
|
details p{color:var(--dim);margin:10px 0 0}
|
|
.note{background:linear-gradient(0deg,rgba(0,112,209,.08),rgba(0,112,209,.08)),
|
|
var(--card);border:1px solid #23405f;border-radius:12px;padding:14px 18px;color:#cfe3ff}
|
|
.warn{background:linear-gradient(0deg,rgba(226,34,54,.07),rgba(226,34,54,.07)),
|
|
var(--card);border:1px solid #5f2330;border-radius:12px;padding:14px 18px;color:#f3cdd3}
|
|
footer{color:var(--dim);border-top:1px solid var(--line);margin-top:70px;
|
|
padding:26px 0 40px;font-size:13.5px}
|
|
.dot{display:inline-block;width:9px;height:9px;border-radius:50%;
|
|
background:var(--rec);margin-right:8px;vertical-align:1px}
|
|
.ok{color:var(--ok);font-weight:600}
|
|
.toc{display:flex;gap:8px;flex-wrap:wrap;margin-top:18px}
|
|
.toc a{border:1px solid var(--line);background:var(--card);border-radius:999px;
|
|
padding:4px 12px;font-size:13px}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<header>
|
|
<div class="wrap">
|
|
<div class="brand">
|
|
<img src="pscapture.png" alt="PSCapture">
|
|
<div>
|
|
<h1>PSCapture</h1>
|
|
<div class="tag">The PlayStation 5 screen, live on your PC — as a real capture card.</div>
|
|
</div>
|
|
</div>
|
|
<div class="badges">
|
|
<span class="badge"><b>PS5</b> jailbroken</span>
|
|
<span class="badge"><b>Windows</b> 10 / 11</span>
|
|
<span class="badge"><span class="dot"></span><b>No</b> capture card</span>
|
|
<span class="badge"><b>No</b> Remote Play</span>
|
|
<span class="badge">1080p · ~30 fps</span>
|
|
</div>
|
|
<div class="toc">
|
|
<a href="#start">Quick start</a>
|
|
<a href="#daily">Daily use</a>
|
|
<a href="#trouble">Troubleshooting</a>
|
|
<a href="#build">Build from source</a>
|
|
<a href="#faq">FAQ</a>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="wrap">
|
|
|
|
<h2>What it is</h2>
|
|
<div class="cards">
|
|
<div class="card">
|
|
<h3>🎥 Virtual capture card</h3>
|
|
<p>PSCapture registers a DirectShow device named <b>PS5 Capture</b>.
|
|
Discord, OBS and ffmpeg see it like an Elgato — pick it and go live.</p>
|
|
</div>
|
|
<div class="card">
|
|
<h3>⚡ Straight from the GPU</h3>
|
|
<p>The console payload reads the display engine's scan-out buffer directly
|
|
and streams NV12 frames over your LAN. No re-encode delay, no cloud.</p>
|
|
</div>
|
|
<div class="card">
|
|
<h3>🖱️ One executable</h3>
|
|
<p><b>PSCapture.exe</b> carries the console payload inside itself:
|
|
install the driver, push the payload, start streaming — one window,
|
|
one click.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>How it works</h2>
|
|
<div class="flow">
|
|
<div class="box"><b>PS5 · payload</b>
|
|
<div>reads the DCE scan-out ring, builds NV12 frames, serves them on a TCP
|
|
port, pops a toast: <i>“PSCapture is streaming on:PORT”</i>.</div></div>
|
|
<div class="arrow">→</div>
|
|
<div class="box"><b>PC · feeder</b>
|
|
<div>receives frames and publishes them into a shared-memory ring.</div></div>
|
|
<div class="arrow">→</div>
|
|
<div class="box"><b>PC · driver</b>
|
|
<div>DirectShow filter exposes the ring as a camera every app can use.</div></div>
|
|
</div>
|
|
|
|
<h2 id="start">Quick start — step by step</h2>
|
|
|
|
<div class="note" style="margin-bottom:20px">
|
|
<b>What you need first.</b> A jailbroken PS5 with the standard setup:
|
|
a payload loader on TCP <code>9021</code> (<code>elfldr</code>-style),
|
|
anonymous FTP on TCP <code>2121</code>, and optionally the
|
|
<code>pldmgr</code> autoloader so the payload starts on every boot.
|
|
PC and console on the same LAN. Download <b>PSCapture.exe</b> from the
|
|
Releases page — <b>it's one single file</b>: the console payload and the
|
|
Windows driver are inside it.
|
|
</div>
|
|
|
|
<ol class="steps">
|
|
<li><b>Jailbreak the console</b><br>
|
|
<span>Any kernel-capable jailbreak that gives you the payload loader
|
|
(:9021), anonymous FTP (:2121) and — optionally — the
|
|
<code>pldmgr</code> autoloader.</span></li>
|
|
<li><b>Double-click <code>PSCapture.exe</code></b><br>
|
|
<span>Windows asks <i>“Do you want to allow this app to make changes?”</i>
|
|
→ <b>Yes</b>. The app elevates itself; admin is needed once, to register
|
|
the virtual camera for every program on the machine.</span></li>
|
|
<li><b>Check the IP</b><br>
|
|
<span>If your PS5 is not at <code>192.168.0.36</code>, type its address
|
|
in the <b>PS5 IP</b> field and press <b>Apply</b>.</span></li>
|
|
<li><b>Watch it work — press nothing</b><br>
|
|
<span>The app does everything alone, and narrates it in the dark log pane
|
|
(see the table below). On the console you will also see the system
|
|
notification <i>“PSCapture is streaming on:PORT”</i>.</span></li>
|
|
<li><b>Use it in any app</b><br>
|
|
<span>Discord (call): <i>Settings → Voice & Video → Camera</i> →
|
|
<b>PS5 Capture</b> (720p — Discord asks every camera for 720p, capture
|
|
cards included). OBS: add a <i>Video Capture Device</i> → full
|
|
<b>1920x1080</b>. ffmpeg:
|
|
<code>-f dshow -i video="PS5 Capture"</code>.</span></li>
|
|
</ol>
|
|
|
|
<h3>What you should see in the app log</h3>
|
|
<table>
|
|
<tr><th>Line</th><th>Meaning</th></tr>
|
|
<tr><td><code>driver gia' installato</code></td>
|
|
<td>camera already registered — nothing to do</td></tr>
|
|
<tr><td><code>driver estratto dall'eseguibile (… byte)</code><br>
|
|
<code>driver registrato - la webcam 'PS5 Capture' e' pronta</code></td>
|
|
<td>first run: the driver was unpacked from the exe and registered</td></tr>
|
|
<tr><td><code>payload dall'eseguibile (… byte)</code></td>
|
|
<td>the console payload is on its way to the PS5</td></tr>
|
|
<tr><td><code>payload avviato - la PS5 deve mostrare la notifica PSCapture</code></td>
|
|
<td>the payload is running on the console</td></tr>
|
|
<tr><td><code>porta stream: 9xxx</code> → <code>collegato a …:9xxx</code></td>
|
|
<td>stream connected — the pill turns <span class="ok">green: STREAMING</span></td></tr>
|
|
</table>
|
|
|
|
<div class="warn" style="margin-top:18px">
|
|
<b>Pill stuck on “IN ATTESA DELLA PS5 — accesa e col jailbreak avviato?”</b><br>
|
|
The console is off, not jailbroken yet, or the IP is wrong. The app keeps
|
|
retrying every 2 seconds: the moment the console is ready it connects by
|
|
itself. Ports to check on the console: <code>9021</code> and
|
|
<code>2121</code> must be open.
|
|
</div>
|
|
|
|
<h2 id="daily">Daily use & tuning</h2>
|
|
<ul class="plain">
|
|
<li>Open <b>PSCapture.exe</b> (UAC → Yes). If the payload is already on the
|
|
console (autoloader), the stream starts by itself; otherwise press
|
|
<b>Deploy payload</b> once.</li>
|
|
<li><b>Stop</b> / closing the app stops the stream — the camera freezes on
|
|
the last frame and consumers keep the device listed.</li>
|
|
<li><b>gain</b> — chroma strength. <b>Leave it at 1.0</b> (raw) unless
|
|
colors look off.</li>
|
|
<li><b>shift px</b> — horizontal alignment. <b>Even numbers only</b> (an
|
|
odd value inverts the colors). Applies live, saved in
|
|
<code>pscapture.ini</code> next to the exe.</li>
|
|
</ul>
|
|
|
|
<h2 id="trouble">Troubleshooting — symptom → fix</h2>
|
|
<table>
|
|
<tr><th>Symptom</th><th>Cause → fix</th></tr>
|
|
<tr><td>Pill stays <code>AVVIO…</code> / <code>IN ATTESA DELLA PS5</code></td>
|
|
<td>Console off or not jailbroken, or wrong IP → turn it on, run the
|
|
jailbreak, check the IP field</td></tr>
|
|
<tr><td>Log repeats <code>PS5 non raggiungibile</code></td>
|
|
<td>Same as above — the app retries by itself</td></tr>
|
|
<tr><td>No <b>PS5 Capture</b> camera in Discord/OBS</td>
|
|
<td>Driver never registered → press <b>Install driver</b>; the log now
|
|
reports the real error</td></tr>
|
|
<tr><td><code>ERRORE: driver non scrivibile in C:\Program Files\PSCapture (serve admin?)</code></td>
|
|
<td>App not elevated → restart PSCapture.exe and accept the UAC prompt</td></tr>
|
|
<tr><td><code>ERRORE caricando la dll (err=126)</code></td>
|
|
<td>Antivirus quarantined the extracted dll → allow
|
|
<code>pscapture.dll</code> in the antivirus, then press
|
|
<b>Install driver</b> again</td></tr>
|
|
<tr><td>Camera listed but image is black</td>
|
|
<td>Stream not started → check the pill, press <b>Deploy payload</b>
|
|
and/or <b>START STREAMING</b></td></tr>
|
|
<tr><td>Colors look wrong</td>
|
|
<td><code>gain</code> was moved → set it back to 1.0 and Apply</td></tr>
|
|
<tr><td>Image off-center / black bar</td>
|
|
<td>Alignment → tune <code>shift px</code> with even numbers</td></tr>
|
|
<tr><td>Discord shows 720p</td>
|
|
<td>Discord's engine caps every camera at 720p → use OBS for 1080p</td></tr>
|
|
<tr><td>OBS sees the camera, Discord doesn't</td>
|
|
<td>Discord was open before the driver install → fully quit Discord
|
|
(tray included) and reopen</td></tr>
|
|
<tr><td>Anything else</td>
|
|
<td>Read <code>pscapture-app.log</code> (next to the exe or in
|
|
<code>%TEMP%</code>) and the console log
|
|
<code>/data/pscapture.log</code> over FTP</td></tr>
|
|
</table>
|
|
|
|
<h2 id="build">Build from source</h2>
|
|
|
|
<p style="color:var(--dim)">Sources only — the repo contains no binaries.
|
|
Two halves, two toolchains. The full walk-through (toolchain install,
|
|
verification, gotchas) is in <a href="BUILD.md">docs/BUILD.md</a>.</p>
|
|
|
|
<h3>1 · Console payload → <code>pscapture.elf</code></h3>
|
|
<pre><span class="c"># needs Docker + the PS5 payload SDK image (prospero-clang; here tagged ps5sdk:18)</span>
|
|
docker run --rm -v "<repo>/payload:/payload" -w /payload ps5sdk:18 make</pre>
|
|
|
|
<h3>2 · PC side → <code>pscapture.exe</code> + <code>pscapture.dll</code></h3>
|
|
<p style="color:var(--dim)">Needs MinGW-w64 (<code>gcc</code> +
|
|
<code>windres</code>). <b>The order is mandatory</b>: the
|
|
<code>.res</code> embeds the driver and the payload as they are on disk.</p>
|
|
<pre><span class="c"># from the repo root</span>
|
|
cp payload/pscapture.elf pc/ <span class="c"># it gets embedded as-is</span>
|
|
cd pc
|
|
|
|
<span class="c"># 1) the capture-card driver (DirectShow source filter)</span>
|
|
gcc -O2 -shared -static -static-libgcc -o pscapture.dll ps5cam.c \
|
|
-lole32 -loleaut32 -luser32 -ladvapi32 -lws2_32
|
|
|
|
<span class="c"># 2) bundle icon + payload + driver into the resource object</span>
|
|
windres pscapture.rc -O coff -o pscapture.res
|
|
|
|
<span class="c"># 3) the single-file app</span>
|
|
gcc -O2 -mwindows -o pscapture.exe pscapture.c pscapture.res \
|
|
-lws2_32 -lshell32 -ladvapi32 -luxtheme</pre>
|
|
|
|
<details>
|
|
<summary>Why the order? (and the two classic build mistakes)</summary>
|
|
<p><b>windres embeds files as they are on disk:</b> if the DLL or the
|
|
payload is rebuilt after step 2, the exe still carries the old ones.
|
|
Rebuild = DLL → windres → exe, every time.<br>
|
|
<b><code>-static -static-libgcc</code> on the DLL is mandatory:</b>
|
|
without it Windows can fail to load the driver with the cryptic
|
|
“the specified module could not be found” (missing mingw runtime).</p>
|
|
</details>
|
|
|
|
<h2>Requirements</h2>
|
|
<table>
|
|
<tr><th>Where</th><th>What</th></tr>
|
|
<tr><td>PS5</td><td>Jailbroken (payload loader + FTP + pldmgr autoloader)</td></tr>
|
|
<tr><td>PS5</td><td>Latest tested firmware: <b>13.60</b> — see the FAQ for other versions</td></tr>
|
|
<tr><td>PC</td><td>Windows 10/11 64-bit, wired network recommended</td></tr>
|
|
<tr><td>Network</td><td>Both on the same LAN (gigabit is plenty for 1080p30)</td></tr>
|
|
</table>
|
|
|
|
<h2 id="faq">FAQ</h2>
|
|
|
|
<details>
|
|
<summary>Does it work on firmware versions older than 13.60?</summary>
|
|
<p>The PC side works on every firmware: the app and the driver only speak
|
|
TCP/FTP and shared memory. The console payload is the version-specific
|
|
part — it was built and tuned on <b>13.60</b>, using display-engine
|
|
anchors found on that firmware. On other firmwares it may need a small
|
|
porting pass (the fix is finding the same anchors on that system).
|
|
If you have another firmware, open an issue with your version and we
|
|
can add a profile.</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Why is the call camera 720p and not 1080p?</summary>
|
|
<p>That cap is Discord's voice engine, not PSCapture: it requests 1280x720
|
|
from every camera. For full-quality capture use OBS (where PS5 Capture
|
|
runs at 1920x1080) or Discord's screen-share, which goes up to
|
|
1080p60 with Nitro.</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Is a capture card or Remote Play needed?</summary>
|
|
<p>No. PSCapture never touches Remote Play: the payload reads the display
|
|
engine on the console itself and streams raw frames over your LAN.</p>
|
|
</details>
|
|
|
|
<details>
|
|
<summary>How do I uninstall it?</summary>
|
|
<p>Close the app, then <code>rundll32 "%ProgramFiles%\PSCapture\pscapture.dll",DllUnregisterServer</code>,
|
|
delete <code>C:\Program Files\PSCapture</code>, and optionally delete
|
|
<code>/data/pldmgr/payloads/pscapture/</code> on the console so the
|
|
autoloader stops starting the payload.</p>
|
|
</details>
|
|
|
|
<footer>
|
|
PSCapture — bring your PS5 screen anywhere on your LAN, no card, no cloud.
|
|
<br><b>by fstat13</b> · source-available. Built for the homebrew community. <span class="ok">Play responsibly.</span>
|
|
<br><br>
|
|
Docs: <a href="GUIDE.md">fool-proof guide (md)</a> ·
|
|
<a href="BUILD.md">build from source (md)</a> ·
|
|
<a href="INSTALLER.md">what the installer does inside</a> ·
|
|
<a href="REVERSE_ENGINEERING.md">reverse engineering</a> ·
|
|
<a href="ENGINEERING_LOG.md">engineering log</a>
|
|
</footer>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|