Releases: sainsaji/EVO-PLAYER-PS5
Release list
EVO Player v0.7.0
Emby password authentication, native HTTPS/TLS streaming, master-detail hierarchical changelog viewer, direct memory buffer streaming, and native PS5 IME keyboard.
Download EVOPlayer-0.7.0-InstallTile.elf to register the Media tile on the home screen, or EVOPlayer-0.7.0-player-only.elf for homebrew app slot launch.
Emby Password Authentication & Setup
Account Password Support: Dedicated interactive password configuration row in Emby Setup screen with virtual keyboard input and secure asterisk masking (
********).Robust cJSON Authentication: Server authentication payloads formatted with
cJSONfor compliant user session tokens against password-protected Emby and Jellyfin servers.Config Persistence: Safe loading and saving of passwords in
/data/evoplayer/emby.confand USB configurations with key-value and legacy positional compatibility.
Hierarchical Changelog Viewer
Master-Detail Version Architecture: Replaced legacy flat cards with a clean dual-pane layout: a version selector on the left and a dedicated release notes inspector card on the right.
Categorized Visual Badges: Clear
[NEW],[FIXED],[IMPROVED], and[REMOVED]indicator pills with accent color coding.Instant Version Switching: Fluid D-pad navigation across all releases with automatic detail panel updates.
Core Subsystems & Network Engine
Native HTTPS & TLS Support: Integrated OpenSSL (
libssl.a/libcrypto.a) with TLS 1.2/1.3 handshakes, SNI extension, and secure communication for remote HTTPS media servers.Direct Memory Region Manager: High-throughput streaming buffer allocations leveraging native PS5 direct memory (
dmem).Native PS5 IME Keyboard Support: Seamless integration with
libSceImeDialog.sprxsupporting multilingual input and USB keyboards, with automatic fallback to custom virtual keyboard.Media Directory Search: Interactive search modal in file browser for fast folder and item filtering.
Streaming Stability: Fixed custom AVIO lifecycle conflict and stabilized network streaming playback.
CPU SIMD Vectorized YUV Pipeline: 8-wide AVX2 SIMD workgroups for high-throughput video presentation (7.4ms per 4K frame).
Install — start here
Download EVOPlayer-0.7.0-InstallTile.elf. That is the one to run.
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Copy
EVOPlayer-0.7.0-InstallTile.elfto a USB stick. - Start it from your payload manager — the on-console one, typically at
http://<ps5>:8084. Anything that sends an ELF to elfldr works. - It says "EVO Player ready in Media". Open EVO Player from the console's Media row.
Which file is which
| File | Use it for |
|---|---|
EVOPlayer-0.7.0-InstallTile.elf |
Normal install. Payload manager → tile in Media |
EVOPlayer-0.7.0-UninstallTile.elf |
Removes the tile completely |
EVOPlayer-0.7.0-homebrew.zip |
The websrv route: extract to a USB stick as /homebrew/EVOPlayer/, launch from http://<ps5>:8080 |
EVOPlayer-0.7.0-player-only.elf |
The bare player. Runs via hbldr in PS Now app slot |
EVO Player v0.6.0
Direct Emby streaming, on-screen virtual keyboard, and a dedicated Surround Sound Studio for 5.1 and 7.1 speaker calibration.
Download EVOPlayer-0.6.0-InstallTile.elf to register the Media tile on the home screen, or EVOPlayer-0.6.0-player-only.elf for homebrew app slot launch.
New — Emby Media Server Add-on
- Native Emby LAN streaming & browsing. Connect directly to your local Emby server, browse media libraries with dynamic cover art and backdrops, and direct-stream video files without transcode overhead.
- On-screen Virtual Keyboard. Full controller-driven keyboard with character, numeric, and symbol sets for convenient entering of server IP addresses, ports, usernames, and passwords.
- Playstate reporting. Real-time playback progress and resume position synchronization back to Emby server.
- Custom Emby branding. Dedicated section icon and navigation rail entry.
New — Surround Sound Studio
- 360° Top-Down Soundstage Theater. Bespoke visual calibration interface featuring a top-down view of listener sweet spot, concentric acoustic range rings, front display soundbar, and 8 positional speaker modules (
FL,FC,FR,LFE,SL,SR,BL,BR). - PS5 8-Channel Hardware Audio Output (
S16_8CH). Verified hardware tone generator with smooth 50ms attack/decay envelope fades to prevent audio clicking. - Sequential 5.1 & 7.1 Auto-Calibration. Automated channel sweep across each speaker with live frequency and status monitoring.
- 360° Perimeter Rotation Sweep. Continuous circular pan around the room perimeter to verify surround transitions.
- Dynamic 5.1 Speaker Hiding & 2D D-Pad Room Traversal. Seamlessly hides inactive side speakers in 5.1 mode and adjusts D-pad traversal grid to navigate directly between active physical channels.
New & Improved — Settings & Subtitles
- Structured Settings Hierarchy. Organized preferences into dedicated sub-sections: Playback & Video, Subtitles, Interface & Controls, System & Hardware, and Developer Tools.
- Default Subtitle Sizing. Configurable and persistent default subtitle size preference (
SMALL,MEDIUM,LARGE) with improved base scaling for high-resolution displays.
Install — start here
Download EVOPlayer-*-InstallTile.elf. That is the one to run.
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Copy
EVOPlayer-*-InstallTile.elfto a USB stick. - Start it from your payload manager — the on-console one,
typically athttp://<ps5>:8084. Anything that sends an ELF to
elfldr works. - It says "EVO Player ready in Media". Open EVO Player from the
console's Media row.
That is the whole install. No websrv, no FTP, nothing to extract,
and no second device beyond whatever runs your payload manager — the
tile installer carries the player inside it.
Keep the payload running. It is resident by design — it is what
starts the player when you open the tile. Your payload manager may
show it as still running; that is correct.Re-run it after every reboot, along with the jailbreak.
Which file is which
| File | Use it for |
|---|---|
EVOPlayer-*-InstallTile.elf |
Normal install. Payload manager → tile in Media |
EVOPlayer-*-UninstallTile.elf |
Removes the tile completely |
EVOPlayer-*-homebrew.zip |
The websrv route: extract to a USB stick as /homebrew/EVOPlayer/, launch from http://<ps5>:8080 |
EVOPlayer-*-player-only.elf |
The bare player. Do not send this to a payload manager — with elfldr alone it runs headless with no display plane and nothing appears. It needs hbldr, which the tile installer and websrv provide |
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.5.0
If a previous release did nothing when you ran it, this is the fix. The
release shipped the bare player, which needs hbldr to be given a display
plane — sent straight to elfldr by a payload manager it started headless and
never drew anything. Download EVOPlayer-0.5.0-InstallTile.elf instead: it
registers the Media tile and carries the player inside it.
Also: a text reader, and a font that can finally spell a comma.
Fixed — install
- The release now ships the ELF that works from a payload manager.
EVOPlayer.elfis the bare player and needshbldrfor a display plane;
elfldr alone runs it headless, so nothing appears. The old release notes
documented this in a footnote under a step pointing at that very file.
The tile launcher already carried its own copy of websrv'shbldrand works
from elfldr alone — it just was never built or shipped. Verified on 12.70 on
a console where only elfldr was reachable. - The bare player is renamed
-player-only.elfso it cannot be picked by
mistake, and the release notes now say which file is which. - The tile launcher announced the wrong version — a hardcoded
0.2.0that
had drifted two releases behind the player it embeds. It now takes the
version from the same file CI checks against the release tag. - CI verified only one of the three payloads. It now checks all of them,
and asserts the launcher is larger than the player it embeds — a launcher
that suddenly shrinks means the.incbinpicked up nothing, which would
ship a tile that opens to a black screen and pass every other check.
New
-
A text reader. Opening a
.txt,.log,.md,.nfo,.json,.csv,
.ini/.cfgor a subtitle file from the browser now reads it instead of
doing nothing — those extensions were listed and selectable and CROSS on
them was silently ignored, which read as the browser being broken.D-pad scrolls a line, the shoulders page (with one line of overlap, so a
paragraph keeps a landmark), the triggers jump a tenth of the file, and
TRIANGLE cycles three reading sizes. Changing size re-wraps and keeps the
top of the view on the same words, because losing your place is the one
thing a size control must not do. The scrollbar thumb is sized to how much
of the document is on screen, which is what tells you whether "half way"
means five more pages or five hundred.Text is decoded as UTF-8 and folded to what the font can draw: curly quotes
become straight ones, em dashes hyphens, ellipses three periods, accented
Latin letters their base letter. A file that is not valid UTF-8 still opens.
Reads at most 2 MB and says so rather than appearing to end early; refuses
binaries instead of showing a screen of dots. -
The UI font has punctuation. It had 69 glyphs — letters, digits and
/._:-+— and drew everything else as a 12px gap. Survivable in a filename,
unreadable in prose, and a text reader is nothing but prose. 26 glyphs
(,'"!?();[]{}<>=*#|\
~^`%&@$) are now generated bytools/gen_icons.pyat
all four sizes.The original atlas is a pre-generated asset with no generator in the tree, so
these live in a second atlas that the text routines fall back to. They sit on
the letters' baseline becausetools/measure_font.pyreads the real baseline,
cap height and stroke weight out of the atlas ink rather than guessing, and
their advances are measured from the rasterised glyph rather than declared —
the first pass declared them and$4.50 (approxcame out with the bracket
touching the zero.
Changed
- Glyph lookup is shared between the player and
tools/uiview.c. Both
carried their ownrr_idxscan and their own four-way face switch; with two
atlases to choose between that would have been two more places to drift.
Both now callevo_font.h. - The browser labels a file "DOCUMENT" if the reader will open it. The two
lists had drifted the moment the reader learned new extensions, so a.json
was labelled "FILE" right up until you pressed CROSS on it and it opened.
Documentation
- The README is about the player again. It had grown into a twenty-section
setup manual — Windows prerequisites, Docker, LLVM version rationale, FFmpeg
profiles, a validation checklist — with the player itself covered in the
first forty lines. Someone who wants to use EVO Player needed none of it.
707 lines to 175: what it is, how to install it, what it does, the controls.
Nothing was deleted; the developer guide moved intact to
docs/building.md. - docs/architecture.md is new — the layers inside
the player, whymain.cis carved in the order it is (with the measurement
that argues against the obvious first cut), the draw vtable, the two font
atlases, and what can be verified without a console. - Eight screenshots, all real
uiviewrenders rather than mock-ups. EVO_TEXT_CHARSETis generated, not hand-maintained. It listed 69
characters and would have gone on reporting a comma as unsupported long
after the comma was added;tools/gen_icons.pynow emits the punctuation
alphabet into a header small enough for the UI layer to include.- The font warnings in docs/ui-handoff.md said prose
could not be written and a prompt "cannot ask a question mark's worth of
question". Both were true and are not any more.
Install — start here
Download EVOPlayer-*-InstallTile.elf. That is the one to run.
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Copy
EVOPlayer-*-InstallTile.elfto a USB stick. - Start it from your payload manager — the on-console one,
typically athttp://<ps5>:8084. Anything that sends an ELF to
elfldr works. - It says "EVO Player ready in Media". Open EVO Player from the
console's Media row.
That is the whole install. No websrv, no FTP, nothing to extract,
and no second device beyond whatever runs your payload manager — the
tile installer carries the player inside it.
Keep the payload running. It is resident by design — it is what
starts the player when you open the tile. Your payload manager may
show it as still running; that is correct.Re-run it after every reboot, along with the jailbreak.
Which file is which
| File | Use it for |
|---|---|
EVOPlayer-*-InstallTile.elf |
Normal install. Payload manager → tile in Media |
EVOPlayer-*-UninstallTile.elf |
Removes the tile completely |
EVOPlayer-*-homebrew.zip |
The websrv route: extract to a USB stick as /homebrew/EVOPlayer/, launch from http://<ps5>:8080 |
EVOPlayer-*-player-only.elf |
The bare player. Do not send this to a payload manager — with elfldr alone it runs headless with no display plane and nothing appears. It needs hbldr, which the tile installer and websrv provide |
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.4.0
Playback does less work per frame, and the code that does it lives in fewer
places.
The measurable part: the 4K converter stopped computing pixel addresses in
floating point, the tiling path that runs on every 1080p frame stopped
creating twelve threads to do it, and the player stopped blacking two million
pixels it was about to overwrite. The structural part: 87.7 MB of assets
nothing included are gone, icons draw from a generated table instead of three
hand-written switches, and the first module has left main.c.
Interface work too — CIRCLE asks before it stops playback, and cover art is
large enough to read as cover art.
Performance
Every change here is verified on the host by ./tools/bench.sh, which hashes
the output plane and refuses to print timings if the pixels moved. Host
timings are not the console's; they compare changes against each other.
- The 4K swizzle stopped doing a
doubledivide per pixel. The fused
converter calledpp_tiled_pixel_offsetfour times per 2×2 block, and each
call evaluated a double divide and multiply purely to compute an address —
8.3M of them per frame at 2160p. It now walks whole tile spans, so the tile
base is computed once per 512 pixels.tile_copy.chad already made this
move for the linear path and carries the proof that the integer form is
identical. 4K single-thread 38.2 ms → 20.9 ms; at 4 workers 12.4 → 10.4;
1080p at 4 workers 3.0 → 2.1. Plane hashes unchanged. - The tiling path that actually runs stopped spawning 12 threads a frame.
pp_converter_parallel.cnames per-framepthread_create/joinas the
Soft-UHD freeze root cause, and both converters were rewritten around
persistent pools because of it.pp_draw_pixels_as_tileswas missed — and it
is not dormant:pp_videoout_presentcalls it for every 1080p frame, so at
60fps it asked the scheduler for 720 thread creations a second on the render
thread. (The dormant one is the similarly namedPS5_DrawPixelsAsTilesin
main.c; they are different functions.) Now on a pool: 2.00 ms → 1.68 ms
on the host, and the console is where the stalls were actually observed. - The player no longer blacks 2M pixels it is about to overwrite.
draw_player_screencleared the whole frame and then had every pixel of it
replaced by the video on the next line. The clear could not simply be
deleted — it is load-bearing when no frame is ready, and the render thread
cannot ask "is one ready?" first, because the seek thread can retire the
display between the question and the answer. So the guarantee moved down:
pp_playback_copy_displaynow leaves every pixel of its target defined,
decided under the lock that owns the display. Worth 0.28 ms of a 2.49 ms
render thread — real, and smaller than it was billed as. - The full-frame display copy is one
memcpyrather than 1080 row-sized
ones, which is what it had always been in the case that runs every frame. - Glyph lookup is a table, not a linear scan of the 69-character
RR_CHARSrun once per character drawn — and the miss case, which is most
punctuation in a filename, paid all 69 comparisons. There were two hand-
copied implementations of that scan; there is now one function.
Changed
-
The thumbnail worker is its own translation unit.
main.cwas ~18k
lines in one file, and the received wisdom was to pull decode/demux out
first. Measuring the file says otherwise: half its 263 file-scope globals
are referenced across spans of more than 5,000 lines, and the most smeared
of them are the playback ones —g_pp_pbis touched across 17,899 lines,
player_pausedacross 17,311. Cutting there first would publish sixty
globals through a header and turn a tangle into a tangle with an API.The scrub-preview thumbnail worker measured as the real seam: 1,096 lines,
39 symbols, and a total dependency on the rest of the program of two helpers
and two screen constants. It owns its thread, mutex, condition variable and
request queue, so the boundary already existed — it just wasn't a file. It
is nowmedia/src/prospero_thumbnail.cbehind a six-function header.
main.cis 16,815 lines and 199 file-scope statics, from 17,985 and 229.Nothing about the code changed: the move is checked mechanically against the
original region, and differs only by the four substitutions its header
documents. -
Source-over pixel blending is in one header.
main.ccarried two copies
of it, the second commented "duplicated rather than shared … because that one
is defined ~3000 lines further down" — a workaround for declaration order
inside a single translation unit, which is exactly the problem a header does
not have. Both are nowevo_blend_pixel()inui/include/evo_blend.h, with
identical arithmetic to what they both already did. -
Icon drawing goes through a generated table.
tools/gen_icons.pynow
emitsEVO_ICON_TABLE/EVO_CTRL_TABLE, and both the player and
tools/uiview.cindex them. There were three hand-writtenswitch (idx)
copies naming the same macros — and one had already drifted:rr_icon()in
main.c stopped at case 12, so it drew nothing for HOME or LOGO. It is
reachable throughEVO_DRAW_VTABLE, so that was a defect waiting for its
first caller rather than a live one. Adding an icon is now one edit to the
generator; it can no longer land in the mock and be forgotten in the player. -
87.7 MB of unreferenced assets are gone —
approved_raw_assets.h,
approved_ui_assets.h,pp_ui_assets.h,pp2_ui_assets.h,
pp_font_metrics.hand three.bmps. Nothing included any of them; the
asset directory went from 117 MB to 30 MB.pp_font_metrics.hgoing with
them settles the "two font systems exist" warning in the handoff doc — there
was one, plus a header nothing read.
New
- CIRCLE during playback asks before it stops. It was the one
irreversible thing CIRCLE did anywhere in the app — tearing down the
decoder, the audio port and your position in the file — on a single press
of the button that means "back" everywhere else. It now opens a prompt over
the paused frame: CIRCLE (the button that opened it) keeps watching, CROSS
stops. The action order is deliberate: the destructive answer is not the one
you reach by repeating what you just did. - Cover art is large enough to be cover art. The cache moved from 80×80 to
320×180 and the recent shelf draws it full bleed instead of as an inset
thumbnail, so tiles are posters. 320×180 is 16:9 — the shape the source
frames actually are — and it minifies into the tile's 270×162 drawing
area rather than magnifying, which is what the old 3.4× upscale could never
do. The cache is 16 slots rather than 48: only the eight recent tiles ever
ask for one, and the trade is 3.7 MB against 1.2 MB. - The application mark is the EVO logo. The top-left of the rail and of
the launch header drew two concentric circles standing in for a logo. Both
now drawEVO_ICON_LOGO— the ring-and-play mark from the home-screen icon,
generated bytools/gen_icons.pyas one monochrome glyph so it tints with
the theme like every other icon. - Sound and lightbar survive a relaunch. Appended to the settings file
after the theme name, and written when the Tools rows are toggled.
Fixed
- Tools' DEBUG OVERLAY toggle did not save, though Settings' DEVELOPER
MODE row — which flips the same variable — always had. Which page you used
decided whether it stuck. - Full-bleed tile artwork is cropped, not stretched. Scaling a 16:9 cover
into a 5:3 tile is a ~7% horizontal squash: invisible on a gradient,
obvious on a face.evo_widget_tilenow takes the centred source rectangle
that fills the tile, the same way the hero backdrop already did. - LEFT no longer opens the navigation rail over the subtitle picker.
Neither it nor the new stop prompt was listed inevo_screen_is_modal(), so
the rail could open as a third layer over a panel floating over video. - The 4K-surface dance around a modal overlay is written once. Media Info
and the stop prompt both have to leave a 4K plane and hold the presentation
clock; that was ~25 lines transcribed by hand, and a second copy is exactly
how a 4K session comes back from an overlay stuck in 1080. Both go through
pp_product_overlay_enter()/_leave()now.
Tooling
tools/uiplay.shcovers the new prompt (Mcycles to it), and the fixture
artwork is 320×180 with a ring drawn in it — a gradient could not show
whether a cover had been squashed, and 128×72 magnified into everything it
was drawn on. The hero gets its own 960×540 fixture, matching
EVO_HERO_ART_W/_H, so the mock stops rendering stair-stepping the console
never produces.
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.3.0
The player starts from the console now, and tells you what changed.
New
- A home-screen tile. EVO Player registers a Media-category title and
appears in the console's own Media row, so it starts from the controller.
Until now launching meant opening a browser on a second device to reach the
websrv launcher. The tile is titleEVOP10001on loopback port 9056,
deliberately distinct from ProsperoPlayer'sPRSP10001/9055 so both can be
installed on the same console; nothing here touches upstream's registration.
Build and install with./scripts/build-media-tile.sh --install. - The uninstaller ships with it, and is built first. Sony usually hides
Options → Delete for Media hosts, so removal is--uninstall, or the
one-shotEVOPlayer_UninstallTile.elfwhen the launcher is not resident.
It is built before the launcher, unconditionally, so the way back exists
before it is needed. - A changelog in the app, under About. Release notes per version with the
emphasis inverted the way the other informational rows work — the change is
what you came to read, soNEW/FIXEDsteps back. - A real application icon, generated by
tools/gen_app_icon.pyfrom vector
shapes using the same signed-distance rasteriser as the UI icons. The
repository previously had no EVO icon at all, so packaging fell back to a
1×1 placeholder and the Media launcher carried upstream's branded artwork. ./scripts/update-console.sh— rebuilds and updates both install paths
in one command.
Fixed
- The Media launcher's Makefile could never have worked. It depended on
assets/ProsperoPlayer.elfwhile the source embedsassets/EVOPlayer.elf,
somakefailed on a missing prerequisite. A missing player now explains
itself instead of surfacing as an assembler error about a file it cannot
open. - The tile and the development install no longer fight over one directory.
The launcher embeds the player and rewrites it on every launch; with both
pointing at/data/homebrew/EVOPlayerthe tile silently overwrote whatever
install-homebrew.shhad just pushed, with nothing to say which binary had
actually started. The tile's copy lives at/data/evoplayer/app, and
uninstalling the tile no longer deletes the development install. uiviewreported version 0.0.2 for every render, because the version was
hardcoded intools/uiview.shrather than read fromVERSION. Its About
fixture had also drifted from the real screen.- Installing the tile never returned.
prospero-deployis
socat -t 9999999, which waits for the far end to close, and elfldr does not
close while the payload it spawned is alive. The launcher is resident by
design — that is what serves the tile's deeplink — so the deploy ran until it
was killed, long after the payload was up. Console deploys are bounded now
(--timeout, default 90s), andtimeout's exit 124 is reported as what it
actually means: still resident, detached.
Known gaps
- The launcher is a payload, so it must be re-injected after every jailbreak;
the tile stays registered but does nothing without it. Autoload is the
answer, and is the exploit host's job rather than this repository's. - The tile embeds the player whole, so the launcher payload is player-sized
(~34 MB) and updating the tile means re-injecting all of it. PP_VERSIONin the launcher is a separate constant fromVERSION.
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.2.0
Subtitles, and the interface for choosing them.
New
- Subtitle track picker. DOWN during playback lists every track in the
file with the number of cues it declares, the active one marked, and the
film still playing behind it. It replaces cycling, which reopened the file
on every step - on a disc rip with thirty-four tracks that meant thirty-odd
reopens to reach the one you wanted. - Track names are built from the language code, not the container's title.
The font atlas has no accents or parentheses, so a track really titled
Español (España)would draw as a row of holes; fifty language codes map
to ASCII names, and same-language tracks are numbered rather than shown as
duplicate rows.
Fixed
- Subtitles appeared to be broken and were not. A release group ships a
vanity track tagged English, flagged default, holding two cues whose first
lands thirty-seven minutes in. Selection picked it on metadata alone and
then correctly displayed nothing for a whole episode. mkvmerge records
NUMBER_OF_FRAMESper track, so the cue count is readable before a packet
is demuxed, and it now outranks every other signal: a track with fewer than
ten cues loses even when it is English and flagged default. Tracks that
lose this way are still offered in the picker, dimmed and marked
SIGNS ONLY, because the count can itself be wrong. - The marquee scrolled at whatever speed the render loop happened to be
running. It advanced a fixed number of pixels per frame, and the loop
runs anywhere from 36fps with a preview decoding to 60fps on a settled
list, so one filename scrolled at two visibly different rates. It measures
milliseconds now and travels 180px/s regardless. - The marquee also stepped a glyph at a time, because the offset was
computed in pixels and then applied by dropping whole characters. The
sub-character remainder is applied as a negative x, with the glyph
overhanging each end clipped by keeping and restoring the strips either
side. Checked on the host: no ink outside the box across 376 phases,
largest step 3px against a 17px advance. EXTRA_CFLAGSnever reached the compiler when building from Windows.
The re-exec into the dev container forwardedPS5_HOSTandPS5_PORTand
dropped everything else, so a-Dswitch produced a successful build, a
clean install, and a binary without it. Forwarded now, and the build greps
its own compile line and fails if a requested flag did not land.
Known gaps
- Cue counts come from mkvmerge's statistics tags. Containers written by
other tools do not carry them; those tracks are ranked on metadata as
before and show no count in the picker. - Switching tracks reopens the file and seeks back, so it costs the same
pause as a seek. Cues are collected as packets stream past, so a track
selected mid-film has no cues from earlier in it.
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.1.0
A rebuild of the interface, and the tooling to work on it without a console.
New
- Launch screen. A hero that resumes what you were last watching, a
Jump back in shelf, and a Library shelf. Two-dimensional cursor: each
shelf remembers its own column, and empty shelves are skipped rather than
becoming dead stops. - File browser inspector. Selecting a file shows a frame from it plus
type, container, size, length, resolution and codecs, read from the
container itself. Probing is debounced, so scrolling never stalls. - Side navigation rail. Sections are reachable from each other instead of
each being a dead end you had to back out of. Back is a stack now, so a
screen opened from two places returns to the right one. - Hold to scroll. Every list moved one item per physical press before.
Shoulder buttons page; L2/R2 jump to the next initial in the browser. - Themed toast, and a
dangertheme token for failure states. Existing
.themefiles inherit it. - Playback OSD follows the theme — panel, seek bar, scrubber, chapter
marks, captions and the music visualiser. - Theme swatches on the settings row, so cycling themes is not blind.
- L3 captures a screenshot during playback (R3 keeps subtitle delay).
Fixed
- The eighth settings row was visible but unreachable — navigation wrapped at
a hardcoded count that had drifted from the real one. That whole class of
bug is gone; counts now live with the cursor. - Audio failures were all blamed on E-AC3, including files with no audio
track at all. The message was hardcoded and overwrote the accurate one.
E-AC3, AC-3, DTS, TrueHD, FLAC, Opus and ALAC are all present and linked. - Pixelated previews — thumbnails were point-sampled twice, once down and
once up. Minification now box-filters and the preview is presented 1:1. - The 4K converter created and joined worker threads every frame, the
pattern already documented here as causing a freeze. It uses a persistent
pool: 4K conversion measured 11.57 ms → 9.15 ms per frame on the host. - Commas and parentheses rendered as gaps: the font atlas has neither, and an
unknown glyph leaves a hole rather than being skipped. - Scrims painted as hard black slabs —
evo_ui_vgradreplaces rather than
blends, so a transparent colour was written straight into the framebuffer. - The expanded rail was not quite opaque, letting the page title ghost
through it.
Removed
- Haptics. Built, tested on hardware, and taken out: every vibration
entry point inlibScePadeither reports success and does nothing or
rejects the call, whilescePadSetLightBarsucceeds on the same handle.
Sound and lightbar remain. Evidence is indocs/ui-handoff.mdso nobody
re-derives it.
Tooling
tools/uiplay.sh— the UI as a navigable page in a browser, on any
machine. Real renderer, real font atlas, real icons.tools/uiview.sh— render any screen to a PNG.tools/shot.sh— fetch captures and interrogate them numerically: probe a
coordinate, scan pixel runs, crop, diff.tools/klog.sh— console log, timestamped, append-only, survives payload
restarts.tools/launch.sh— refuses to stack app instances, which is what
kernel-panicked a console during development.tools/bench.sh— host benchmark for the converter, with correctness
hashing and ASan/TSan modes.
Known gaps
- The player OSD is themed but still draws its own layout rather than the
shared chrome. gpu-notes.mdpreviously recommended an SDL2/mesa path for GPU YUV
conversion. That does not work: the sysroot ships OSMesa (llvmpipe), a
software rasteriser, with noradeonsi. The document now records the
measurements.
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.0.2
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.
EVO Player v0.0.1
Install
- Jailbreak the console (12.70) and start
ps5-payload-elfldr. - Deploy ps5-payload-websrv.
- Extract the homebrew zip to a USB stick as
/homebrew/EVOPlayer/,
or copy it to/data/homebrew/EVOPlayer/over FTP. - Launch it from
http://<ps5>:8080/index.html.
EVOPlayer-*.elf is the bare payload. Note that sending it with
elfldr alone runs it headless — it needs the homebrew launcher to
get a display plane. See the README.
Requirements
- PS5 on firmware 12.70, jailbroken (re-run after every reboot)
- A USB stick for media
Verification
Built reproducibly in CI from the pinned toolchain (clang 18.1.3,
PS5 Payload SDK v0.42, FFmpeg 7.0.1). CI has no console, so these
binaries are not hardware-tested. Checksums in SHA256SUMS.txt.
Licensed GPL-3.0-or-later. Derived from ProsperoPlayer; see NOTICE.