Compare commits

..
8 Commits
38 changed files with 4893 additions and 2939 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: true
+18
View File
@@ -0,0 +1,18 @@
---
name: Mac (versión en pruebas / testing)
about: Cuéntanos cómo va PS5 Directo en tu Mac / Tell us how PS5 Directo works on your Mac
title: "[Mac] "
labels: mac
---
**Mac y macOS / Mac and macOS version:** (por ejemplo / e.g. MacBook Air M2, macOS 15.1)
**¿Abre? / Does it open?** (sí / no / con avisos — yes / no / with warnings)
**¿Qué funciona y qué falla? / What works and what fails?**
**Informe de fallo / Problem report:** en el programa pulsa «Crear informe de fallo» y arrastra aquí el .zip / in the program click "Create problem report" and drag the .zip here.
Si no llega a abrirse, adjunta si puedes / If it doesn't open, please attach if you can:
`~/Library/Application Support/PS5 Directo/lanzador.log` y / and `~/.ps5directo/ps5directo.log`
+212
View File
@@ -0,0 +1,212 @@
# Publica una version: al subir una etiqueta vX.Y.Z (o con "Run workflow" en Actions) crea o rehace
# la release de GitHub con:
# - PS5Directo-X.Y.Z-Setup.exe el instalador: doble clic, «Instalar» y listo. Es la descarga normal.
# - PS5Directo-X.Y.Z-Windows.zip lo mismo sin instalar (con Python incluido). Tambien lo usa
# «Actualizar» dentro del programa, que solo copia los archivos.
# - PS5Directo-X.Y.Z-Linux.tar.gz Linux x86-64, con Python y 7-Zip incluidos (se abre con ps5directo.sh).
# - PS5Directo-X.Y.Z-macOS.dmg Mac (Apple Silicon e Intel), en pruebas: la app con Python y 7-Zip.
name: Publicar version
on:
push:
tags: ["v*"]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
outputs:
ver: ${{ steps.v.outputs.ver }}
steps:
- uses: actions/checkout@v4
- name: Version de app.py
id: v
run: echo "ver=$(grep -m1 -oP '^VERSION = "\K[^"]+' app.py)" >> "$GITHUB_OUTPUT"
- name: La etiqueta tiene que coincidir con la version
if: startsWith(github.ref, 'refs/tags/')
run: test "${GITHUB_REF_NAME#v}" = "${{ steps.v.outputs.ver }}"
- name: Archivos del programa
run: |
mkdir -p dist/PS5Directo
git archive HEAD | tar -x -C dist/PS5Directo
rm -rf dist/PS5Directo/.github dist/PS5Directo/installer
- name: Python incluido
run: |
PY=3.12.10
curl -fsSL -o py.zip "https://www.python.org/ftp/python/$PY/python-$PY-embed-amd64.zip"
mkdir -p dist/PS5Directo/python
unzip -q py.zip -d dist/PS5Directo/python
# que el Python incluido vea la carpeta del programa
for f in dist/PS5Directo/python/python*._pth; do printf '..\n' >> "$f"; done
- name: Zip para Windows
run: (cd dist && zip -qr "PS5Directo-${{ steps.v.outputs.ver }}-Windows.zip" PS5Directo)
# Linux (x86-64): la app con Python y 7-Zip incluidos. Se abre con ps5directo.sh y la primera
# vez se añade sola al menu de aplicaciones.
- name: Paquete para Linux
env:
GH_TOKEN: ${{ github.token }}
run: |
set -e
L=build/linux/PS5Directo
mkdir -p "$L"
git archive HEAD | tar -x -C "$L"
rm -rf "$L/.github" "$L/installer" "$L"/*.bat "$L"/*.vbs
chmod +x "$L/ps5directo.sh"
PBS=20250604; PYV=3.12.11
curl -fsSL -o pyl.tgz "https://github.com/astral-sh/python-build-standalone/releases/download/$PBS/cpython-$PYV+$PBS-x86_64-unknown-linux-gnu-install_only_stripped.tar.gz"
tar -xzf pyl.tgz -C "$L"
P="$L/python/lib/python3.12"
rm -rf "$P/test" "$P/idlelib" "$P/ensurepip" "$P/lib2to3" "$P/pydoc_data" "$P/turtledemo" \
"$P"/site-packages/pip* "$P/tkinter/test" "$L/python/share" "$L/python/include"
find "$L/python" -name __pycache__ -prune -exec rm -rf {} +
"$L/python/bin/python3" -c "import ssl, sqlite3, ftplib, tkinter, lzma, bz2, ctypes; print('python ok')"
url=$(gh api repos/ip7z/7zip/releases/latest --jq '.assets[] | select(.name | test("linux-x64\\.tar\\.xz$")) | .browser_download_url' | head -1)
mkdir -p "$L/bin" sz
curl -fsSL -o sz.tar.xz "$url"
tar -xJf sz.tar.xz -C sz
cp sz/7zz "$L/bin/7zz"
chmod +x "$L/bin/7zz"
(cd build/linux && tar -czf "../../dist/PS5Directo-${{ steps.v.outputs.ver }}-Linux.tar.gz" PS5Directo)
ls -la dist
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
retention-days: 3
setup:
needs: build
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: dist
path: dist
- name: Instalador (Inno Setup)
shell: pwsh
run: |
$iscc = Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\ISCC.exe'
if (-not (Test-Path $iscc)) { choco install innosetup -y --no-progress | Out-Null }
& $iscc /Q "/DMyVer=${{ needs.build.outputs.ver }}" installer\PS5Directo.iss
if ($LASTEXITCODE -ne 0) { exit 1 }
Get-ChildItem dist\*.exe, dist\*.zip | Format-Table Name, Length
- uses: actions/upload-artifact@v4
with:
name: setup
path: dist/PS5Directo-*-Setup.exe
retention-days: 3
# Mac: "PS5 Directo.app" con Python para Apple Silicon e Intel y 7-Zip, dentro de un .dmg.
# El lanzador (installer/macos/launcher.sh) copia el programa a ~/Library/Application Support
# para que «Actualizar» funcione. Firmada solo "ad hoc" (sin cuenta de desarrollador de Apple).
mac:
needs: build
runs-on: macos-latest
env:
VER: ${{ needs.build.outputs.ver }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
- name: Montar la app
run: |
set -e
A="build/PS5 Directo.app"; C="$A/Contents"; R="$C/Resources"
mkdir -p "$C/MacOS" "$R/app" "$R/bin"
git archive HEAD | tar -x -C "$R/app"
rm -rf "$R/app/.github" "$R/app/installer" "$R/app"/*.bat "$R/app"/*.vbs "$R/app/ps5directo.sh"
cp installer/macos/launcher.sh "$C/MacOS/PS5 Directo"
chmod +x "$C/MacOS/PS5 Directo"
sed "s/__VERSION__/$VER/g" installer/macos/Info.plist > "$C/Info.plist"
plutil -lint "$C/Info.plist"
# icono
mkdir -p ps5.iconset
for s in 16 32 128 256 512; do
sips -z $s $s web/icon-512.png --out "ps5.iconset/icon_${s}x${s}.png" >/dev/null
d=$((s*2)); sips -z $d $d web/icon-512.png --out "ps5.iconset/icon_${s}x${s}@2x.png" >/dev/null
done
iconutil -c icns ps5.iconset -o "$R/ps5directo.icns"
# Python para cada procesador
PBS=20250604; PYV=3.12.11
for pair in aarch64:arm64 x86_64:x86_64; do
src=${pair%%:*}; dst=${pair##*:}
curl -fsSL -o py.tgz "https://github.com/astral-sh/python-build-standalone/releases/download/$PBS/cpython-$PYV+$PBS-$src-apple-darwin-install_only_stripped.tar.gz"
rm -rf python && tar -xzf py.tgz
P=python/lib/python3.12
rm -rf "$P/test" "$P/idlelib" "$P/ensurepip" "$P/lib2to3" "$P/pydoc_data" "$P/turtledemo" \
"$P"/site-packages/pip* "$P/tkinter/test" python/share python/include
find python -name __pycache__ -prune -exec rm -rf {} +
mv python "$R/python-$dst"
done
"$R/python-$(uname -m)/bin/python3" -c "import ssl, sqlite3, ftplib, lzma, bz2, ctypes; print('python ok')"
# 7-Zip
url=$(gh api repos/ip7z/7zip/releases/latest --jq '.assets[] | select(.name | test("mac\\.tar\\.xz$")) | .browser_download_url' | head -1)
mkdir -p sz && curl -fsSL -o sz.tar.xz "$url" && tar -xJf sz.tar.xz -C sz
cp sz/7zz "$R/bin/7zz" && chmod +x "$R/bin/7zz"
"$R/bin/7zz" | head -2
codesign --force --deep --sign - "$A"
codesign --verify --deep --verbose=1 "$A"
- name: Prueba de arranque en un Mac
run: |
export HOME="$RUNNER_TEMP/casa"; mkdir -p "$HOME"
"build/PS5 Directo.app/Contents/MacOS/PS5 Directo" --no-browser &
ok=""
for i in $(seq 1 30); do
sleep 1
if grep -q "PS5 Directo $VER" "$HOME/.ps5directo/ps5directo.log" 2>/dev/null; then ok=1; break; fi
done
cat "$HOME/.ps5directo/ps5directo.log" || true
cat "$HOME/Library/Application Support/PS5 Directo/lanzador.log" || true
pkill -f "PS5 Directo/app/app.py" || true
test -n "$ok"
- name: Crear el .dmg
run: |
set -e
mkdir -p dmg dist
cp -R "build/PS5 Directo.app" dmg/
ln -s /Applications dmg/Applications
cp installer/macos/LEEME-Mac.txt "dmg/Si no abre - LEEME.txt"
hdiutil create -volname "PS5 Directo" -srcfolder dmg -ov -format UDZO "dist/PS5Directo-$VER-macOS.dmg"
ls -la dist
- uses: actions/upload-artifact@v4
with:
name: mac
path: dist/PS5Directo-*-macOS.dmg
retention-days: 3
release:
needs: [build, setup, mac]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
# Con una etiqueta crea la release. Pulsando "Run workflow" en Actions añade (o rehace) los archivos
# de la release de la version que pone app.py, aunque ya exista.
- uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.build.outputs.ver }}
files: |
dist/PS5Directo-*-Setup.exe
dist/PS5Directo-*-Windows.zip
dist/PS5Directo-*-Linux.tar.gz
dist/PS5Directo-*-macOS.dmg
View File
File renamed without changes.
+136 -12
View File
@@ -10,8 +10,7 @@ Lo que necesitas antes:
Paso 1. Descarga
En la página de GitHub del programa, entra en "Releases" y descarga
PS5Directo-X.Y.Z-portable-windows.zip (trae todo, no hay que instalar
nada más). Descomprímelo en una carpeta, por ejemplo en Documentos.
PS5Directo-X.Y.Z-Windows.zip (trae todo, no hay que instalar nada más). Descomprímelo en una carpeta, por ejemplo en Documentos.
Paso 2. Ábrelo
Doble clic en "PS5 Directo.vbs". Se abre en su propia ventana y crea un
@@ -120,8 +119,7 @@ lo tiene y que sabes cargar payloads (.elf).
EN EL PC
- Windows 10 u 11.
- Python 3.9 o superior: https://www.python.org/downloads/
Al instalarlo marca "Add python.exe to PATH".
- Nada más: el instalador lo trae todo (también Python).
- 7-Zip (solo si usas "Descomprimir en el PC"): https://www.7-zip.org/
EN LA PS5 (se cargan como payloads, por ejemplo con Payload Manager:
@@ -155,9 +153,15 @@ BFpilot, sin PS5 Directo.
PRIMERA VEZ
-----------
Doble clic en "Crear accesos directos.bat". Crea:
- Un icono "PS5 Directo" en el escritorio.
Abre PS5Directo-X.Y.Z-Setup.exe y pulsa "Instalar". No pide permisos de
administrador. Crea:
- Un icono "PS5 Directo" en el escritorio y en el menú Inicio.
- "Enviar a > PS5 Directo" en el clic derecho de los archivos.
Si Windows dice "Windows protegió su PC": "Más información" > "Ejecutar
de todos modos" (el instalador no está firmado; es el aviso normal en
programas pequeños y gratuitos).
Con el .zip en vez del instalador: descomprímelo donde quieras y haz
doble clic en "Crear accesos directos.bat".
Desde entonces abre PS5 Directo con el icono del escritorio: sale en su
propia ventana, sin pestañas y sin ventana negra.
@@ -293,13 +297,133 @@ PAYLOADS, DIAGNÓSTICO, MÓVIL Y PROGRAMAR
suspende solo.
VERSIÓN PORTABLE
----------------
En cada versión hay dos descargas: PS5Directo-X.Y.Z.zip (necesita Python
instalado) y PS5Directo-X.Y.Z-portable-windows.zip, que trae Python dentro:
descomprimir y abrir, sin instalar nada.
QUÉ DESCARGAR
-------------
- PS5Directo-X.Y.Z-Setup.exe: el instalador. Es el que debes bajar. Lo
trae todo (también Python): ábrelo, pulsa "Instalar" y listo.
- PS5Directo-X.Y.Z-Windows.zip: lo mismo sin instalar, para quien
prefiera descomprimirlo en una carpeta. También lo usa "Actualizar".
Para quitarlo: Configuración de Windows > Aplicaciones > PS5 Directo >
Desinstalar. Tus ajustes se conservan por si vuelves a instalarlo.
- PS5Directo-X.Y.Z-macOS.dmg: para Mac (Apple Silicon e Intel, macOS 11
o posterior). EN PRUEBAS: todavía no se ha probado en un Mac de verdad.
Ábrelo y arrastra PS5 Directo a Aplicaciones. La primera vez macOS la
bloquea porque no está firmada por Apple: en macOS 15 o posterior,
Ajustes del Sistema > Privacidad y seguridad > "Abrir igualmente"; en
anteriores, clic derecho en la app > Abrir. Si algo falla, "Crear
informe de fallo" y adjúntalo en github.com/jstrdev/ps5directo/issues.
- PS5Directo-X.Y.Z-Linux.tar.gz: para Linux (x86-64, distribuciones
recientes como Ubuntu 22.04 o posterior). Descomprímelo donde quieras
y ábrelo una vez con ./ps5directo.sh en una terminal (o clic derecho
> Ejecutar como programa). Esa vez se añade al menú de aplicaciones y
desde entonces lo abres desde ahí. Trae Python y 7-Zip.
Para la ventana sin pestañas usa Chrome, Chromium, Edge o Brave si los
tienes (si no, se abre en tu navegador). Para los torrents hace falta
aria2: sudo apt install aria2. En Linux no hay "Enviar a" ni el aviso
del cortafuegos de Windows.
NOVEDADES 1.21.0
- Versión para Mac EN PRUEBAS (PS5Directo-1.21.0-macOS.dmg), para Apple
Silicon e Intel, con Python y 7-Zip incluidos. Aún no se ha probado en
un Mac de verdad: se agradece cualquier aviso en GitHub.
- El informe de fallo incluye ahora el registro técnico del programa
(sin el código de acceso de la sesión).
- Arreglado: si cerrabas el programa en la Biblioteca, al abrirlo salía
marcada «Transferencias» con la Biblioteca vacía debajo.
- Versión para Linux (PS5Directo-1.21.0-Linux.tar.gz), con Python y 7-Zip
incluidos. Se añade sola al menú de aplicaciones y se actualiza igual
que en Windows.
- Las descargas al PC van a tu carpeta de Descargas real (en Linux puede
llamarse "Descargas").
NOVEDADES 1.20.4
- Icono propio en la barra de tareas: la ventana ya no se mete dentro del
icono de Edge o Chrome, y al anclarla se ancla PS5 Directo.
- Si ya está abierto y lo vuelves a abrir, trae al frente la ventana que
tenías en vez de abrir otra.
- Si lo anclaste antes de esta versión, desáncla el icono viejo y ancla
el nuevo (clic derecho en el icono de la barra > Anclar).
- Capturas: salen también las hechas con la pantalla en HDR (.jxr), que se
ven convertidas a JPG (al bajarlas al PC se guarda el original). Cada una
dice de qué aplicación es y la fecha, los vídeos llevan la portada de la
aplicación y ya no salen las copias temporales que hace la consola al
compartir.
- Arreglado: en «Archivos de la consola», calcular el tamaño de una
carpeta, borrarla, copiarla, arreglar sus permisos y «Reemplazar» una
carpeta que ya existía fallaban desde la 1.20.3.
NOVEDADES 1.20.3
- Instalador para Windows (PS5Directo-1.20.3-Setup.exe): doble clic,
"Instalar" y listo, con todo incluido. Sigue habiendo .zip para quien
no quiera instalar.
- Biblioteca: «Comprobar» en cada aplicación, para cuando no abre o se
cierra al arrancar. Revisa la carpeta (ejecutable, param.json, permisos,
firmware, backports y el empaquetado LZ4), muestra los registros (.log) y
las capturas de los últimos minutos, explica el código de error que salió
en la tele y guarda un informe .zip. Solo lee: no cambia nada.
- Ventana de bienvenida la primera vez: resume qué es PS5 Directo y qué hace.
- Biblioteca: también lo instalado en la consola (PS4 y PS5), con portada,
versión y firmware, y filtro para verlo.
- Biblioteca, «En tu PC»: eliges carpetas del PC o del NAS, marca lo que ya
está en la consola y lo que no, y lo envías con un clic.
- Biblioteca: «Ver actualizaciones» abre en el navegador la lista pública de
actualizaciones oficiales de cada título (Prospero Patches). Avisa de que
las que piden firmware 14.00 o más no se pueden instalar. El programa no
descarga nada.
- Biblioteca: si tienes PS5 Game Updater en la consola, un botón lo abre; si
su carpeta está mal colocada, lo detecta y la coloca bien.
- Biblioteca: las imágenes y las carpetas sin param.json salen con nombre,
portada y firmware.
- Nueva pestaña «Copia de seguridad»: guarda en el PC las partidas, los
ajustes de ShadowMountPlus y de los payloads y la base de datos de
aplicaciones, a mano o una vez al día. Las partidas se pueden restaurar en
la misma consola (antes guarda las de ahora).
- Nueva pestaña «Capturas»: capturas y vídeos de la consola con miniaturas,
para verlos y bajarlos al PC.
- «Diagnóstico» en las transferencias con error: qué ha pasado, códigos y cómo
arreglarlo, y un informe .zip (sin contraseñas) para pasar a quien te ayude.
En Ajustes, «Crear informe de fallo».
- Torrents: pega un magnet o un .torrent. Se baja primero al PC con aria2 (se
descarga solo) y luego se envía, descomprime o convierte. No comparte al
terminar y lo borra del PC.
- PS5 Dump Forge se actualiza solo (una vez al día como mucho), comprobando
antes que la versión nueva funciona; si no, sigue con la anterior.
- Las versiones nuevas de PS5 Directo se avisan solas con una ventana y sus
novedades.
- Avisa si la velocidad hacia la PS5 cae de golpe (suele ser la consola
inactiva: pulsa un botón del mando).
- «Formato en la PS5» empieza plegado y dice cuánto tarda: sin convertir,
descarga y envío a la vez; convirtiendo, 3 pasos. Tarjetas ordenadas por lo
más usado y «¿Cuál elijo?» por necesidades.
- Firmware de tu PS5 junto al título (se guarda solo) y la tarjeta .fpkg dice
si te vale.
- En la cola, «Convertir a …» dice a qué formato, y avisa si algo no se pudo
convertir.
- Arreglado: un comprimido con versión normal y backport no se convertía;
ahora separa la que toca.
- Arreglado: lo convertido se mezclaba con una carpeta anterior del mismo
nombre.
- Arreglado: muchas carpetas de la Biblioteca salían sin nombre.
NOVEDADES 1.20.1
- Si no conecta y el PC y la PS5 están en redes distintas (por ejemplo
192.168.50.x y 192.168.1.x), lo dice y explica cómo arreglarlo.
- Botones «Usar en el móvil» y «Extensión del navegador» más visibles, y el
asistente de inicio los ofrece al final.
- «Descargar de nuevo» en la cola (terminados, con error o cancelados) y en
Actividad: vuelve a empezar desde cero sin tener que pegar el enlace.
- Si al colocar ya existe esa carpeta, pregunta (colocar igualmente con otro
nombre, reemplazar o cancelar) en vez de dar error.
- Arreglado: si el comprimido trae la versión normal y un «backport», ya no
da «Ya existe»: coloca la normal y aparta el backport (o lo descarta si tu
firmware no lo necesita). Y si en el destino hay un envío anterior a
medias, lo sustituye.
- «Guía de uso» renovada: explica el convertidor de formatos, cada pestaña,
el uso desde el móvil y la extensión del navegador.
- La ventana «¿Cuál elijo?» añade velocidades estimadas donde no había datos
y textos más claros sobre LZ4 y .ffpfsc.
NOVEDADES 1.20.0
- Asistente de primeros pasos (IP, comprobar la conexión y cargar lo que
falta, firmware) y una guía más corta y sencilla.
@@ -438,7 +562,7 @@ NOVEDADES 1.14.1
NOVEDADES 1.14
- Guía de bienvenida la primera vez que se abre: enseña para qué es cada
parte. Se puede volver a ver con el botón "Guía" de arriba.
parte. Se puede volver a ver con el botón "Guía de uso" de arriba.
NOVEDADES 1.13.1
- El logo de la cabecera va dentro de la página (al actualizar desde una
+23 -23
View File
@@ -1,23 +1,23 @@
' Abre PS5 Directo sin ventana negra (en su propia ventana de aplicacion).
' Puedes arrastrar archivos encima de este archivo o de su acceso directo.
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
dir = fso.GetParentFolderName(WScript.ScriptFullName)
sh.CurrentDirectory = dir
args = ""
For Each a In WScript.Arguments
args = args & " """ & a & """"
Next
py = ""
If fso.FileExists(dir & "\python\pythonw.exe") Then
py = """" & dir & "\python\pythonw.exe"""
ElseIf sh.Run("cmd /c where pyw >nul 2>nul", 0, True) = 0 Then
py = "pyw -3"
ElseIf sh.Run("cmd /c where pythonw >nul 2>nul", 0, True) = 0 Then
py = "pythonw"
End If
If py = "" Then
MsgBox "No encuentro Python. Descarga la version portable (trae Python) o instala Python 3 (marca 'Add to PATH').", 48, "PS5 Directo"
Else
sh.Run py & " """ & dir & "\app.py""" & args, 0, False
End If
' Abre PS5 Directo sin ventana negra (en su propia ventana de aplicacion).
' Puedes arrastrar archivos encima de este archivo o de su acceso directo.
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
dir = fso.GetParentFolderName(WScript.ScriptFullName)
sh.CurrentDirectory = dir
args = ""
For Each a In WScript.Arguments
args = args & " """ & a & """"
Next
py = ""
If fso.FileExists(dir & "\python\pythonw.exe") Then
py = """" & dir & "\python\pythonw.exe"""
ElseIf sh.Run("cmd /c where pyw >nul 2>nul", 0, True) = 0 Then
py = "pyw -3"
ElseIf sh.Run("cmd /c where pythonw >nul 2>nul", 0, True) = 0 Then
py = "pythonw"
End If
If py = "" Then
MsgBox "Faltan archivos de PS5 Directo (la carpeta python). Vuelve a instalarlo con PS5Directo-Setup.exe desde github.com/jstrdev/ps5directo/releases", 48, "PS5 Directo"
Else
sh.Run py & " """ & dir & "\app.py""" & args, 0, False
End If
+55 -37
View File
@@ -2,40 +2,38 @@
**English** · [Español](#español)
A Windows file-transfer tool for jailbroken PS5 consoles. It sends files to the console over FTP **while they download**, without storing them on your PC. It then extracts them, either on the console with BFpilot or on the PC with 7-Zip, and places apps in `/data/homebrew` so ShadowMountPlus shows them in the menu.
An all-in-one Windows tool for jailbroken PS5 consoles: it **downloads, converts and sends** in a single step. Sent as is, files go to the console over FTP **while they download**, without storing them on your PC; or it **converts them on the fly** (LZ4, `.exfat`, folder, `.ffpfsc`…) as part of the same job, no second program needed. It extracts on the console (BFpilot) or on the PC (7-Zip), places apps in `/data/homebrew` so ShadowMountPlus shows them in the menu, and lets you browse your console's library with covers and control everything from your phone.
![PS5 Directo: paste a link, it's sent, extracted and shows up in the library](docs/demo_en.gif)
![PS5 Directo: paste a link, send it as is or convert it, and it shows up in the library](docs/demo_en.gif)
<sub>Demo with a sample homebrew app served from a NAS on the local network.</sub>
- ✅ Streams downloads straight to the console: nothing is saved on the PC
- ✅ Works from download links, ftp:// links (e.g. a NAS) or files on your PC
- ✅ Joins split parts (.part1, .part2… / .001, .002…) and extracts RAR, 7z, ZIP and tar (.gz/.bz2/.xz)
- ✅ Extracts on the console (BFpilot) or on the PC (7-Zip, every file CRC-checked)
- ✅ Fixes the file permissions that stop BFpilot-extracted content from launching (CE-107750-0)
- ✅ Pause, resume and retry where it left off, even after a dropped connection
- ✅ Built-in console file browser (works over plain FTP, BFpilot optional): right-click menu, shortcuts, move/copy to…, extract archives on the console, drag & drop uploads, download to PC
- ✅ Notification bell: finished or failed transfers, disconnections and new versions
- ✅ Storage view: a pie chart of what fills the console, by app name and size, flagging duplicates and leftovers you can delete
- ✅ Send whole PC folders over several connections, skipping what's already there and resuming what got cut off
- ✅ Watches free space so the console never fills up
- ✅ Speed limit and built-in speed test
- ✅ Download-manager style downloads: several reused connections per file, auto-backoff when a host complains
- ✅ Optional browser extension: links arrive by themselves with your browser session (same speed and access as the browser)
- ✅ Drag and drop, or "Send to" from Explorer
- ✅ Welcome guide, one-click updates, English and Spanish
- ✅ **Library tab**: covers, versions and the firmware each app needs, flagging what won't launch on your console (backport-aware), duplicates and incomplete folders
- ✅ **Images and LZ4** with [PS5 Dump Forge](https://github.com/quer3q/ps5-dump-forge) (optional): send an app as a single `.ffpkg` / `.ffpfsc` image or LZ4-packed, prepared on the PC
- ✅ Asks before sending something that's already on the console (send anyway, replace or cancel)
- ✅ Checks every part against its `.sfv` / `.md5` / `.sha1` while sending
- ✅ "Make room": suggests what to delete when space runs out
- ✅ Loads ftpsrv and BFpilot on the PS5 from the app (ELF loader, port 9021)
- ✅ "Why is it slow?" network diagnostics (Wi-Fi band and signal, 100 Mb/s cables, VPNs, ping)
- ✅ Open it from your phone with a QR code; schedule the queue and sleep or shut down the PC when it's done
### ⚡ One step instead of three tools
- ✅ **Download and send at once:** files go straight to the console while they download, nothing stored on your PC
- ✅ **Or convert on the fly** with [PS5 Dump Forge](https://github.com/quer3q/ps5-dump-forge) (downloaded and updated automatically): folder, `.exfat`, LZ4, `.ffpfsc`, `.ffpkg`, `.ffpfs` or `.fpkg`, with a "Which one?" guide by need
- ✅ **Any source:** download links, `ftp://` (e.g. a NAS), torrents (magnet or `.torrent`) or files and folders on your PC (drag and drop or "Send to")
- ✅ **Extracts and places:** joins split parts, extracts RAR, 7z, ZIP and tar on the console (BFpilot) or on the PC (7-Zip, CRC-checked), splits archives with a backport and places apps in `/data/homebrew` for ShadowMountPlus
- ✅ **Reliable:** pause, resume and retry where it left off, several connections per file, `.sfv`/`.md5` checks, free-space watch and permission fixes (CE-107750-0)
### 📚 Your console from your PC and phone
- ✅ **Library:** covers, versions and required firmware for everything on the console, including images and installed PS4/PS5 content; flags what won't launch on your firmware, duplicates and broken folders, and links to each title's public update list
- ✅ **On your PC:** point it at your PC/NAS folders, see what's missing on the console and send it with one click
- ✅ **Backup:** saved data, ShadowMountPlus/payload settings and the app database copied to the PC, manually or daily; restore saved data to the same console
- ✅ **Console files, Space and Captures:** file browser (copy, move, rename, upload, download), storage chart with "Make room", and the console's screenshots and videos
- ✅ **Phone and browser:** use it from your phone with a QR code, and send links from your browser with the optional extension
### 🩺 When something goes wrong
- ✅ **Diagnosis** on failed transfers: cause, error codes and how to fix it
- ✅ **Launch check:** if an app closes on launch, it checks the folder (executable, permissions, firmware, backports, LZ4 packing) and shows recent logs and captures
- ✅ **Problem report** in one click (.zip, no passwords) to share when asking for help
- ✅ **Warnings:** your PS5 firmware always visible, speed-drop alerts, "Why is it slow?" network check, and it loads ftpsrv/BFpilot from the app
- ✅ **Self-updating**, with a welcome window and a user guide, in English and Spanish
## Requirements
- **PC:** Windows 10/11. Get the `-portable-windows.zip` (Python included, nothing to install), or the plain `.zip` with [Python 3.9+](https://www.python.org/downloads/) installed (tick "Add python.exe to PATH"). For extracting on the PC, also install [7-Zip](https://www.7-zip.org/).
- **PC:** Windows 10/11. Nothing else to install: the download includes everything it needs. Optional: [7-Zip](https://www.7-zip.org/), only if you want to extract on the PC instead of on the console.
- **Mac (new, in testing — not tested on a real Mac yet, [feedback welcome](../../issues/new?template=mac.md)):** macOS 11 or later, Apple Silicon or Intel. Python and 7-Zip are included. Torrents need `aria2` (`brew install aria2`).
- **Linux (new, x86-64):** any recent distro (glibc 2.35+, e.g. Ubuntu 22.04+). Python and 7-Zip are included. For the app window without tabs, Chrome, Chromium, Edge or Brave (otherwise it opens in your default browser). Torrents need `aria2` (`sudo apt install aria2`).
- **Jailbroken PS5:**
- An FTP server, for example [ftpsrv](https://github.com/ps5-payload-dev/ftpsrv) on port 2121.
- [BFpilot](https://github.com/ItsBlurf/BFpilot) on port 5905.
@@ -44,10 +42,17 @@ A Windows file-transfer tool for jailbroken PS5 consoles. It sends files to the
## Getting started
1. Download the `-portable-windows.zip` (or the plain `.zip` if you have Python) from the latest [release](../../releases) and extract it anywhere.
2. Run `Crear accesos directos.bat` ("create shortcuts"). It adds a desktop icon and a "Send to → PS5 Directo" entry.
3. Open **PS5 Directo** from the desktop. The language follows Windows; switch it with the **English / Español** button at the top.
4. Follow the welcome guide, enter your PS5's IP in Settings, then paste links or drop files.
1. Download **`PS5Directo-X.Y.Z-Setup.exe`** from the latest [release](../../releases), open it and click **Install**. No admin rights needed, nothing else to install.
2. Open **PS5 Directo** from the desktop or the Start menu. The language follows Windows; switch it with the **English / Español** button at the top.
3. Follow the welcome guide, enter your PS5's IP in Settings, then paste links or drop files.
> If Windows shows "Windows protected your PC", click **More info → Run anyway**. The installer isn't signed (signing costs money); it's the usual warning for small free programs.
>
> Rather not install? Download `PS5Directo-X.Y.Z-Windows.zip` instead, extract it anywhere and run `Crear accesos directos.bat`. Both update themselves the same way.
**Mac (in testing):** download `PS5Directo-X.Y.Z-macOS.dmg`, open it and drag **PS5 Directo** into Applications. The app isn't signed by Apple, so the first time macOS blocks it: on macOS 15+ go to *System Settings → Privacy & Security → Open Anyway*; on older versions right-click the app → *Open*. **It hasn't been tested on a real Mac yet:** if something fails, click *Create problem report* in the program and attach it to an [issue](../../issues/new?template=mac.md). Thanks!
**Linux:** download `PS5Directo-X.Y.Z-Linux.tar.gz`, extract it anywhere (for example in your home folder) and open it once with `./ps5directo.sh` in a terminal (or right-click → *Run as a Program*). That first time it adds **PS5 Directo** to your applications menu, so from then on you open it from there. It updates itself like on Windows.
> **About BFpilot and permissions:** up to at least v0.4.4, BFpilot's archive extractor leaves files without the execute bit, so the PS5 refuses to launch them (CE-107750-0). This also happens when you extract from BFpilot's own web UI. PS5 Directo fixes it automatically after every extraction. For content you already have, use **Settings → Fix permissions**.
@@ -55,7 +60,7 @@ The full guide is in [README_EN.txt](README_EN.txt) (Spanish: [LEEME.txt](LEEME.
## Publishing a release
Bump `VERSION` in `app.py`, add the notes to `LEEME.txt` / `README_EN.txt`, then push a tag (`git tag v1.20.0 && git push --tags`). The GitHub Action builds both zips (plain and portable with Python) and creates the release.
Bump `VERSION` in `app.py`, add the notes to `LEEME.txt` / `README_EN.txt`, then push a tag (`git tag v1.20.3 && git push --tags`). The GitHub Action builds the installer `PS5Directo-X.Y.Z-Setup.exe`, `PS5Directo-X.Y.Z-Windows.zip`, `PS5Directo-X.Y.Z-Linux.tar.gz` and `PS5Directo-X.Y.Z-macOS.dmg` (all with Python included; the Mac app is built and smoke-tested on a GitHub macOS runner) and creates the release. The installer script is `installer/PS5Directo.iss` (Inno Setup).
## Disclaimer
@@ -70,14 +75,27 @@ Independent project, not affiliated with Sony or with the authors of the tools m
## Español
![PS5 Directo: pegas un enlace, se envía, se descomprime y aparece en la biblioteca](docs/demo_es.gif)
![PS5 Directo: pegas un enlace, lo envías tal cual o lo conviertes, y aparece en la biblioteca](docs/demo_es.gif)
Herramienta de transferencia de archivos para Windows: envía archivos a una PS5 con jailbreak por FTP **mientras se descargan**, sin pasar por el disco del PC. Después los descomprime (en la consola con BFpilot, o en el PC con 7-Zip) y coloca las aplicaciones en `/data/homebrew` para que ShadowMountPlus las muestre en el menú.
Herramienta todo en uno para Windows y PS5 con jailbreak: **descarga, convierte y envía** en un solo paso. Tal cual, los archivos van a la consola por FTP **mientras se descargan**, sin pasar por el disco del PC; o los **convierte sobre la marcha** (LZ4, `.exfat`, carpeta, `.ffpfsc`…) dentro del mismo trabajo, sin usar otro programa. Descomprime en la consola (BFpilot) o en el PC (7-Zip), coloca las aplicaciones en `/data/homebrew` para que ShadowMountPlus las muestre en el menú, y te deja ver la biblioteca de la consola con portadas y controlarlo todo desde el móvil.
**Novedades 1.20:** pestaña Biblioteca con portadas y aviso de firmware, imágenes `.ffpkg`/`.ffpfsc` y LZ4 con [PS5 Dump Forge](https://github.com/quer3q/ps5-dump-forge), pregunta si ya está en la consola, comprobación con `.sfv`/`.md5`, "Hacer sitio", cargar ftpsrv/BFpilot desde el programa, diagnóstico de red, acceso desde el móvil con QR y programar la cola.
**Un programa en vez de tres:** descarga y envío a la vez sin ocupar el PC, o conversión sobre la marcha (carpeta, `.exfat`, LZ4, `.ffpfsc`, `.ffpkg`, `.ffpfs`, `.fpkg`) con [PS5 Dump Forge](https://github.com/quer3q/ps5-dump-forge). Vale con enlaces, `ftp://`, torrents o archivos del PC; une partes, descomprime y lo deja colocado.
**Requisitos:** Windows 10/11. Descarga el `-portable-windows.zip` (trae Python, no hay que instalar nada) o el `.zip` normal con [Python 3.9+](https://www.python.org/downloads/). Para descomprimir en el PC, [7-Zip](https://www.7-zip.org/). En la PS5: servidor FTP ([ftpsrv](https://github.com/ps5-payload-dev/ftpsrv)), [BFpilot](https://github.com/ItsBlurf/BFpilot) y [ShadowMountPlus](https://github.com/drakmor/ShadowMountPlus).
**Tu consola desde el PC y el móvil:** Biblioteca con portadas, versión y firmware (también lo instalado de PS4 y PS5), vista «En tu PC» para enviar lo que falta, copias de seguridad de partidas y ajustes, explorador de archivos, espacio, capturas y modo móvil con QR.
**Uso:** descarga el `.zip` de la última [release](../../releases), ejecuta `Crear accesos directos.bat` y abre **PS5 Directo** desde el escritorio. La guía completa está en [LEEME.txt](LEEME.txt).
**Cuando algo falla:** diagnóstico de errores con causa y solución, «Comprobar» si algo se cierra al abrirlo, informe de fallo en un clic y avisos automáticos de versiones y de bajadas de velocidad.
**Requisitos:** Windows 10/11, sin instalar nada más: la descarga lo trae todo. Opcional: [7-Zip](https://www.7-zip.org/), solo si quieres descomprimir en el PC en vez de en la consola. En la PS5: servidor FTP ([ftpsrv](https://github.com/ps5-payload-dev/ftpsrv)), [BFpilot](https://github.com/ItsBlurf/BFpilot) y [ShadowMountPlus](https://github.com/drakmor/ShadowMountPlus).
**Cómo instalarlo:**
1. Descarga **`PS5Directo-X.Y.Z-Setup.exe`** de la última [release](../../releases), ábrelo y pulsa **Instalar**. No pide permisos de administrador ni hay que instalar nada más.
2. Abre **PS5 Directo** desde el escritorio o el menú Inicio.
3. Sigue la ventana de bienvenida y pon la IP de tu PS5 en Ajustes.
Si Windows dice «Windows protegió su PC», pulsa **Más información → Ejecutar de todos modos** (el instalador no está firmado, que cuesta dinero; es el aviso normal en programas pequeños y gratuitos). ¿Prefieres no instalar? Descarga el `.zip`, descomprímelo y ejecuta `Crear accesos directos.bat`. La guía completa está en [LEEME.txt](LEEME.txt).
**Mac (nuevo, en pruebas):** descarga `PS5Directo-X.Y.Z-macOS.dmg`, ábrelo y arrastra **PS5 Directo** a Aplicaciones. No está firmada por Apple, así que la primera vez macOS la bloquea: en macOS 15 o posterior ve a *Ajustes del Sistema → Privacidad y seguridad → Abrir igualmente*; en versiones anteriores, clic derecho en la app → *Abrir*. **Todavía no se ha podido probar en un Mac de verdad:** si algo falla, pulsa *Crear informe de fallo* en el programa y adjúntalo en un [aviso](../../issues/new?template=mac.md). ¡Gracias!
**Linux (nuevo):** descarga `PS5Directo-X.Y.Z-Linux.tar.gz`, descomprímelo donde quieras y ábrelo una vez con `./ps5directo.sh` en una terminal (o clic derecho → *Ejecutar como programa*). Esa primera vez se añade solo al menú de aplicaciones, y desde entonces lo abres desde ahí. Trae Python y 7-Zip; para los torrents hace falta `aria2` (`sudo apt install aria2`).
**Aviso:** proyecto independiente, sin relación con Sony ni con los autores de las herramientas citadas. No incluye contenido de terceros, claves ni archivos de Sony, ni enlaces a sitios de descargas. Úsalo solo con contenido que tengas derecho a usar (copias de seguridad propias y homebrew). No hace el jailbreak ni salta ninguna protección: solo copia archivos a una consola que ya has modificado tú. No se da ayuda para conseguir contenido sin licencia. Se ofrece tal cual, sin garantías, y lo que hagas con él es responsabilidad tuya.
+134 -18
View File
@@ -6,7 +6,7 @@ QUICK START (5 MINUTES)
You need: a PS5 that is already jailbroken (PS5 Directo doesn't do that)
and a Windows 10/11 PC on the same network.
1. Download PS5Directo-X.Y.Z-portable-windows.zip from the GitHub Releases
1. Download PS5Directo-X.Y.Z-Windows.zip from the GitHub Releases
page (nothing else to install) and extract it, e.g. into Documents.
2. Double-click "PS5 Directo.vbs". If Windows asks whether to open a file
downloaded from the internet, click "Open".
@@ -96,8 +96,7 @@ jailbroken and that you know how to load payloads (.elf).
ON THE PC
- Windows 10 or 11.
- Python 3.9 or newer: https://www.python.org/downloads/
When installing, tick "Add python.exe to PATH".
- Nothing else: the installer includes everything (Python too).
- 7-Zip (only for "Extract on the PC"): https://www.7-zip.org/
ON THE PS5 (loaded as payloads, for example with Payload Manager:
@@ -130,9 +129,15 @@ BFpilot's own web page, without PS5 Directo.
FIRST TIME
----------
Double-click "Crear accesos directos.bat" ("create shortcuts"). It adds:
- A "PS5 Directo" icon on the desktop.
Open PS5Directo-X.Y.Z-Setup.exe and click "Install". No admin rights
needed. It adds:
- A "PS5 Directo" icon on the desktop and in the Start menu.
- "Send to > PS5 Directo" in the right-click menu of your files.
If Windows says "Windows protected your PC": "More info" > "Run anyway"
(the installer isn't signed; it's the usual warning for small free
programs).
With the .zip instead of the installer: extract it anywhere and
double-click "Crear accesos directos.bat" ("create shortcuts").
From then on, open PS5 Directo from the desktop icon: it runs in its own
window, with no tabs and no black console window.
@@ -152,7 +157,7 @@ HOW TO USE IT
-------------
1. Extract this folder anywhere you like.
2. Open PS5 Directo from the desktop icon. A short welcome guide explains
each part (you can see it again with the "Guide" button).
each part (you can see it again with the "User guide" button).
3. The first time, Settings opens: enter your PS5's IP (on the PS5:
Settings > Network > View Connection Status), click "Save" and then
"Test connection". Both dots at the top should turn green.
@@ -306,27 +311,137 @@ PAYLOADS, DIAGNOSTICS, PHONE AND SCHEDULE
- "Schedule" (queue): start at a set time and sleep or shut down the PC when
done. The PC doesn't go to sleep while transfers are running.
PORTABLE VERSION
WHAT TO DOWNLOAD
----------------
Each release has PS5Directo-X.Y.Z.zip (needs Python installed) and
PS5Directo-X.Y.Z-portable-windows.zip, which includes Python: extract and run.
- PS5Directo-X.Y.Z-Setup.exe: the installer. This is the one to get.
Everything included (Python too): open it, click "Install", done.
- PS5Directo-X.Y.Z-Windows.zip: the same without installing, if you'd
rather extract it to a folder. "Update" uses it too.
To remove it: Windows Settings > Apps > PS5 Directo > Uninstall. Your
settings are kept in case you install it again.
- PS5Directo-X.Y.Z-macOS.dmg: for Mac (Apple Silicon and Intel, macOS 11
or later). IN TESTING: not tested on a real Mac yet. Open it and drag
PS5 Directo into Applications. The first time macOS blocks it because
it isn't signed by Apple: on macOS 15 or later, System Settings >
Privacy & Security > "Open Anyway"; on older ones, right-click the app
> Open. If something fails, "Create problem report" and attach it at
github.com/jstrdev/ps5directo/issues.
- PS5Directo-X.Y.Z-Linux.tar.gz: for Linux (x86-64, recent distros such
as Ubuntu 22.04 or later). Extract it anywhere and open it once with
./ps5directo.sh in a terminal (or right-click > Run as a Program).
That first time it adds itself to the applications menu, so from then
on you open it from there. Python and 7-Zip are included.
For the window without tabs it uses Chrome, Chromium, Edge or Brave if
you have one (otherwise your browser). Torrents need aria2:
sudo apt install aria2. Linux has no "Send to" and no Windows firewall
prompt.
WHAT'S NEW
----------
1.21.0 - Mac version IN TESTING (PS5Directo-1.21.0-macOS.dmg), for Apple
Silicon and Intel, with Python and 7-Zip included. Not tested on
a real Mac yet: any report on GitHub is welcome.
- The problem report now includes the program's technical log
(without the session access code).
- Fixed: if you closed the program on the Library tab, on reopening
it showed "Transfers" selected with an empty Library below.
- Linux version (PS5Directo-1.21.0-Linux.tar.gz), with Python and
7-Zip included. It adds itself to the applications menu and
updates itself like on Windows.
- Downloads to the PC go to your real Downloads folder (on Linux it
may have another name).
1.20.4 - Its own taskbar icon: the window no longer hides inside the Edge
or Chrome icon, and pinning it pins PS5 Directo.
- If it's already open and you open it again, it brings the existing
window to the front instead of opening another one.
- If you pinned it before this version, unpin the old icon and pin
the new one (right-click the taskbar icon > Pin).
- Captures: screenshots taken with HDR on (.jxr) now show up,
previewed as JPG (downloading keeps the original). Each one shows
the app and the date, videos show the app's cover, and the
temporary copies the console makes when sharing are hidden.
- Fixed: in "Console files", folder size, deleting, copying, fixing
permissions and "Replace" on an existing folder failed since 1.20.3.
1.20.3 - Windows installer (PS5Directo-1.20.3-Setup.exe): double-click,
"Install", done, everything included. The .zip is still there if
you'd rather not install.
- Library: "Check" on each app, for when it won't open or closes on
launch. It checks the folder (executable, param.json, permissions,
firmware, backports and LZ4 packing), shows logs (.log) and captures
from the last minutes, explains the error code shown on the TV and
saves a .zip report. Read-only: it changes nothing.
- Welcome window on first launch: sums up what PS5 Directo is and does.
- Library: also what's installed on the console (PS4 and PS5), with
cover, version and firmware, and a filter for it.
- Library, "On your PC": pick PC or NAS folders, see what's already on
the console and what isn't, and send it with one click.
- Library: "See updates" opens each title's public official update list
in your browser (Prospero Patches). Warns that updates needing
firmware 14.00 or higher can't be installed. The program downloads
nothing.
- Library: if PS5 Game Updater is on the console, a button opens it; if
its folder is misplaced, it detects and fixes it.
- Library: images and folders without param.json show name, cover and
firmware.
- New "Backup" tab: saves saved data, ShadowMountPlus and payload
settings and the app database to the PC, manually or daily. Saved data
can be restored to the same console (current data is backed up first).
- New "Captures" tab: the console's screenshots and videos with
thumbnails, to view and download to the PC.
- "Diagnosis" on failed transfers: what happened, codes and how to fix
it, plus a .zip report (no passwords) to send to whoever helps you. In
Settings, "Create problem report".
- Torrents: paste a magnet or a .torrent. It's downloaded to the PC
first with aria2 (fetched automatically) and then sent, extracted or
converted. No seeding afterwards; deleted from the PC.
- PS5 Dump Forge updates itself (at most daily), checking first the new
version works; otherwise it keeps the previous one.
- New PS5 Directo versions are announced by themselves in a window with
what's new.
- Warns if the speed to the PS5 suddenly drops (usually the console
idling: press a controller button).
- "Format on the PS5" starts folded and says how long it takes: no
conversion downloads and sends at once; converting takes 3 steps.
Cards sorted by most used and "Which one?" by need.
- Your PS5 firmware next to the title (saves automatically) and the
.fpkg card tells you if it works.
- In the queue, "Convert to …" names the format, and it warns if
something couldn't be converted.
- Fixed: an archive with a normal version plus a backport wasn't
converted; now it picks the right one.
- Fixed: converted files got mixed into an older folder with the same
name.
- Fixed: many Library folders showed no name.
1.20.1 - If it can't connect and the PC and PS5 are on different networks,
it says so and explains how to fix it.
- Clearer "Use on your phone" and "Browser extension" buttons, also
offered at the end of the first-steps wizard.
- "Download again" in the queue and in Activity: starts over without
pasting the link again. If the target already exists when placing,
it asks (keep both, replace or cancel) instead of failing.
- Fixed: archives with the normal app plus a "backport" folder no
longer fail with "Already exists"; half-sent leftovers are
replaced.
- Updated "User guide": explains the format converter, every tab,
phone access and the browser extension.
- The "Which one?" window adds estimated speeds where there was no
data, with clearer notes on LZ4 and .ffpfsc.
1.20.0 - First-steps wizard (IP, connection check and loading what's
missing, firmware) and a shorter, simpler guide.
- New Library tab: what's on the console with cover, version, format
and required firmware, flagging what won't launch on yours.
- .ffpkg / .ffpfsc images and LZ4 with PS5 Dump Forge (optional):
prepared on the PC and sent as a single file. Picked with cards under
the destination, each explained, with the room needed on the PC; the
first time it warns that converting takes PC space until it's done.
A download that's already an image is sent as is or converted to
the chosen format, and placed even without BFpilot.
prepared on the PC and sent as a single file. Picked with cards
under the destination, each explained, with the room needed on the
PC; the first time it warns that converting takes PC space until
it's done. A download that's already an image is sent as is or
converted to the chosen format, and placed even without BFpilot.
- New formats: plain folder, .exfat, .ffpfs and .fpkg (with a
compression choice). Without 7-Zip, PS5 Dump Forge extracts it.
- Formats are grouped (space savers first) and "Which one?"
compares the pros and cons of each.
- Formats are grouped (space savers first) and "Which one?" compares
the pros and cons of each.
- Time left (and rough finish time) when sending, extracting and
converting. On the phone, a big alert with vibration and a beep
when something finishes or fails (with the page open).
@@ -346,8 +461,9 @@ WHAT'S NEW
- Schedule the queue, sleep or shut down when done, no sleep while
sending.
- Portable version with Python included.
- Fixed: with FTP only (no BFpilot), ftpsrv returned the console's root
when listing a folder; it affected the file browser and folder uploads.
- Fixed: with FTP only (no BFpilot), ftpsrv returned the console's
root when listing a folder; it affected the file browser and
folder uploads.
- Phone access: a button to allow it in Windows Firewall if the page
stays blank.
1.19.2 - Fixed "504 Option not supported" in Console files when BFpilot is
Binary file not shown.
+2047 -56
View File
File diff suppressed because it is too large. Load diff
-84
View File
@@ -1,84 +0,0 @@
const EN = !(navigator.language || "es").toLowerCase().startsWith("es");
// PS5 Directo - captura de enlaces.
// Cuando el navegador empieza a descargar un archivo comprimido o paquete (.rar, .7z, .zip, .pkg...),
// manda el enlace FINAL (despues de redirecciones) a PS5 Directo y cancela la descarga.
// Si PS5 Directo no esta abierto, no toca nada: la descarga sigue normal.
const WANTED_FILE = /\.(part\d+\.rar|rar|r\d{2,3}|7z(\.\d{3})?|zip|z\d{2}|\d{3}|pkg|exfat|ffpkg|ffpfsc?|ufs)$/i;
const PORTS = [8777, 8778, 8779];
async function settings() {
return chrome.storage.local.get({ enabled: true, captured: 0 });
}
async function findApp() {
for (const port of PORTS) {
try {
const r = await fetch(`http://127.0.0.1:${port}/api/ext/ping`, { cache: "no-store" });
if (r.ok) {
const j = await r.json();
if (j.app === "PS5 Directo") return { port, version: j.version };
}
} catch (e) { /* no esta en ese puerto */ }
}
return null;
}
function fileName(item) {
const f = (item.filename || "").split(/[\\/]/).pop();
if (f) return f;
try { return decodeURIComponent(new URL(item.finalUrl || item.url).pathname.split("/").pop()); }
catch (e) { return ""; }
}
async function handle(item) {
const cfg = await settings();
if (!cfg.enabled) return;
const url = item.finalUrl || item.url;
if (!/^https?:/i.test(url)) return;
const name = fileName(item);
const path = url.split("?")[0];
if (!WANTED_FILE.test(name) && !WANTED_FILE.test(path)) return; // no es un archivo que nos interese
const app = await findApp();
if (!app) { // PS5 Directo cerrado: no tocar
chrome.action.setBadgeText({ text: "off" });
return;
}
// Como los gestores de descargas: pasamos las cookies de ese alojamiento (sesion, cuenta
// premium), el navegador y la pagina de origen, para que el servidor nos trate igual.
// Solo van a PS5 Directo en este PC (127.0.0.1), a ningun otro sitio.
const cookies = {};
for (const u of [url, item.url]) {
try {
const host = new URL(u).host.toLowerCase();
if (host in cookies) continue;
const list = await chrome.cookies.getAll({ url: u });
cookies[host] = list.map(c => `${c.name}=${c.value}`).join("; ");
} catch (e) { /* sin permiso o enlace raro: sin cookies */ }
}
try {
const r = await fetch(`http://127.0.0.1:${app.port}/api/ext/capture`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url, original: item.url, name, cookies,
ua: navigator.userAgent, referrer: item.referrer || "" })
});
if (!r.ok) return;
} catch (e) { return; }
try { await chrome.downloads.cancel(item.id); } catch (e) {}
try { await chrome.downloads.erase({ id: item.id }); } catch (e) {}
const n = (cfg.captured || 0) + 1;
await chrome.storage.local.set({ captured: n, last: name });
chrome.action.setBadgeBackgroundColor({ color: "#2563eb" });
chrome.action.setBadgeText({ text: String(n % 1000) });
chrome.notifications.create({
type: "basic", iconUrl: "icon128.png", title: EN ? "Sent to PS5 Directo" : "Enviado a PS5 Directo",
message: (name || (EN ? "Link" : "Enlace")) + (EN ? " — not downloaded to the PC." : " — no se descarga en el PC.")
});
}
// Cuando ya se sabe el nombre del archivo y el enlace final (tras las redirecciones)
chrome.downloads.onDeterminingFilename.addListener((item, suggest) => {
suggest(); // no cambiamos el nombre
handle(item);
});
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 266 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 896 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 928 KiB

+184 -17
View File
@@ -547,9 +547,32 @@ def ftp_read(f, path, offset=0, n=256 * 1024):
f.voidresp()
except ftplib.all_errors:
pass
if len(buf) >= n:
_ftp_resync(f)
return bytes(buf)
def _ftp_resync(f):
"""Al cortar una descarga a medias algunos servidores mandan una respuesta de mas (426 y luego 226),
y la siguiente orden recibiria la respuesta equivocada. Manda un NOOP y lee hasta su 200."""
old = None
try:
old = f.sock.gettimeout()
f.sock.settimeout(5)
f.putcmd("NOOP")
for _ in range(4):
line = f.getmultiline()
if line.startswith("200"):
break
except Exception:
pass
finally:
try:
f.sock.settimeout(old)
except Exception:
pass
def title_from_param(text):
try:
j = json.loads(text) if isinstance(text, str) else text
@@ -585,6 +608,40 @@ def param_facts(text):
}
def parse_sfo(data):
"""param.sfo (PS4): diccionario con sus claves (TITLE, TITLE_ID, APP_VER, SYSTEM_VER, CATEGORY...)."""
import struct
out = {}
if len(data) < 20 or data[:4] != b"\0PSF":
return out
_, _, key_off, data_off, n = struct.unpack_from("<4sIIII", data, 0)
for i in range(min(n, 256)):
e = 20 + i * 16
if e + 16 > len(data):
break
k_off, fmt, ln, _mx, d_off = struct.unpack_from("<HHIII", data, e)
ks = key_off + k_off
key = data[ks:data.find(b"\0", ks)].decode("ascii", "replace")
raw = data[data_off + d_off:data_off + d_off + ln]
if fmt == 0x0404 and len(raw) >= 4:
out[key] = struct.unpack_from("<I", raw)[0]
else:
out[key] = raw.split(b"\0", 1)[0].decode("utf-8", "replace")
return out
def sfo_facts(data):
s = parse_sfo(data)
sv = s.get("SYSTEM_VER")
fw = None
if isinstance(sv, int) and sv:
fw = "%x.%02x" % (sv >> 24, (sv >> 16) & 0xFF)
cat = str(s.get("CATEGORY") or "")
return {"title": s.get("TITLE") or None, "tid": s.get("TITLE_ID") or None,
"version": s.get("APP_VER") or s.get("VERSION") or None, "fw_param": fw, "need_fw": fw,
"extra": cat in ("ac", "gp", "sd")}
def inspect_remote_game(f, path, listing=None):
"""Datos de una aplicacion en carpeta en la consola, por FTP. listing: entradas de 'path'."""
names = {n: x for n, x in (listing if listing is not None else E.ftp_listdir(f, path))}
@@ -597,7 +654,11 @@ def inspect_remote_game(f, path, listing=None):
out["icon"] = "icon0.png" in sce
if "param.json" in sce:
raw = ftp_read(f, path + "/sce_sys/param.json", 0, 512 * 1024)
out.update(param_facts(raw.decode("utf-8", "replace")))
out.update(param_facts(raw.decode("utf-8-sig", "replace")))
if not out.get("tid"):
out["param_err"] = "param.json: %d bytes leídos (%r)" % (len(raw), raw[:60])
elif sce:
out["param_err"] = "sce_sys no tiene param.json"
if out["has_eboot"]:
try:
out["fw_exe"] = exe_firmware(lambda off, n: ftp_read(f, path + "/eboot.bin", off, n))
@@ -763,7 +824,25 @@ def forge_cli_name():
return "ps5-dump-forge.exe" if os.name == "nt" else "ps5-dump-forge"
def find_forge(custom, data_dir):
FORGE_NEEDED_FLAGS = ("--to", "--lz4-pack", "--lz4-unpack", "--kraken", "--level")
def forge_cli_ok(exe):
"""Comprueba que una version de Forge sigue entendiendo las opciones que usa PS5 Directo.
True = vale, False = le faltan opciones, None = no se ha podido saber."""
import subprocess
try:
p = subprocess.run([exe, "convert", "--help"], stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, timeout=60, creationflags=E._NOWIN)
except Exception:
return None
out = p.stdout.decode("utf-8", "replace")
if "--to" not in out:
return None
return all(f in out for f in FORGE_NEEDED_FLAGS)
def find_forge(custom, data_dir, skip=()):
custom = (custom or "").strip().strip('"')
if custom and os.path.isfile(custom):
return custom
@@ -771,6 +850,8 @@ def find_forge(custom, data_dir):
best = None
if os.path.isdir(root):
for d in os.listdir(root):
if d in skip:
continue
p = os.path.join(root, d, forge_cli_name())
if os.path.isfile(p) and (best is None or os.path.getmtime(p) > os.path.getmtime(best)):
best = p
@@ -794,8 +875,8 @@ def _forge_asset(assets):
return None
def download_forge(data_dir, log=None, progress=None):
tag, assets = github_release(FORGE_REPO)
def download_forge(data_dir, log=None, progress=None, release=None):
tag, assets = release or github_release(FORGE_REPO)
a = _forge_asset(assets)
if not a:
raise E.PipeError("La última versión de PS5 Dump Forge no trae descarga para este sistema")
@@ -1130,13 +1211,41 @@ def diagnose(ps5_ip, cfg, speed=None, active=0):
# Energia: no dormir mientras hay trabajo y apagar/suspender al acabar
# ---------------------------------------------------------------------------
_AWAKE = {"proc": None}
def keep_awake(on):
if os.name != "nt":
"""Que el PC no se suspenda mientras hay envios. En Linux/Mac se hace con un proceso
(systemd-inhibit / caffeinate) que dura mientras haga falta."""
if os.name == "nt":
try:
import ctypes
ES_CONTINUOUS, ES_SYSTEM_REQUIRED = 0x80000000, 0x00000001
ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS | (ES_SYSTEM_REQUIRED if on else 0))
return True
except Exception:
return False
p = _AWAKE["proc"]
if not on:
if p is not None:
try:
p.terminate()
except Exception:
pass
_AWAKE["proc"] = None
return True
if p is not None and p.poll() is None:
return True
if sys.platform == "darwin":
cmd = ["caffeinate", "-i", "-w", str(os.getpid())]
elif shutil.which("systemd-inhibit"):
cmd = ["systemd-inhibit", "--what=sleep:idle", "--who=PS5 Directo", "--why=Enviando a la PS5",
"--mode=block", "sleep", "infinity"]
else:
return False
try:
import ctypes
ES_CONTINUOUS, ES_SYSTEM_REQUIRED = 0x80000000, 0x00000001
ctypes.windll.kernel32.SetThreadExecutionState(ES_CONTINUOUS | (ES_SYSTEM_REQUIRED if on else 0))
_AWAKE["proc"] = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL)
return True
except Exception:
return False
@@ -1144,15 +1253,73 @@ def keep_awake(on):
def power_action(kind):
"""'sleep' (suspender) o 'shutdown' (apagar). Devuelve un texto de lo hecho."""
if os.name != "nt":
return "Solo funciona en Windows"
if kind == "shutdown":
subprocess.Popen(["shutdown", "/s", "/t", "0", "/c", "PS5 Directo: cola terminada"], creationflags=NO_WINDOW)
return "Apagando el PC"
if kind == "sleep":
subprocess.Popen(["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"], creationflags=NO_WINDOW)
return "Suspendiendo el PC"
return ""
if os.name == "nt":
if kind == "shutdown":
subprocess.Popen(["shutdown", "/s", "/t", "0", "/c", "PS5 Directo: cola terminada"], creationflags=NO_WINDOW)
return "Apagando el PC"
if kind == "sleep":
subprocess.Popen(["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"], creationflags=NO_WINDOW)
return "Suspendiendo el PC"
return ""
keep_awake(False)
if sys.platform == "darwin":
cmd = {"shutdown": ["osascript", "-e", 'tell application "System Events" to shut down'],
"sleep": ["pmset", "sleepnow"]}.get(kind)
else:
cmd = {"shutdown": ["systemctl", "poweroff"], "sleep": ["systemctl", "suspend"]}.get(kind)
if not cmd:
return ""
try:
subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
except Exception as e:
return "No pude: %s" % e
return "Apagando el PC" if kind == "shutdown" else "Suspendiendo el PC"
def open_path(path):
"""Abre una carpeta o archivo del PC con el programa del sistema (Explorador, Finder...)."""
if os.name == "nt":
os.startfile(path)
return
cmd = ["open", path] if sys.platform == "darwin" else ["xdg-open", path]
subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
def pick_native(kind, title):
"""Selector de archivos/carpeta del sistema en Linux (zenity/kdialog) o Mac (osascript).
Devuelve la lista elegida ([] si se cancela) o None si no hay ninguno disponible."""
title = title or "PS5 Directo"
if sys.platform == "darwin":
if kind == "folder":
script = 'POSIX path of (choose folder with prompt %s)' % _as_str(title)
else:
script = ('set l to choose file with prompt %s with multiple selections allowed\n'
'set o to ""\nrepeat with f in l\nset o to o & POSIX path of f & linefeed\nend repeat\nreturn o'
% _as_str(title))
args = ["osascript"]
for ln in script.split("\n"):
args += ["-e", ln]
p = subprocess.run(args, capture_output=True, timeout=3600)
if p.returncode != 0:
return []
return [x.rstrip("/") or "/" for x in p.stdout.decode("utf-8", "replace").splitlines() if x.strip()]
if shutil.which("zenity"):
cmd = ["zenity", "--file-selection", "--title=" + title, "--separator=\n"]
cmd += ["--directory"] if kind == "folder" else ["--multiple"]
elif shutil.which("kdialog"):
home = os.path.expanduser("~")
cmd = (["kdialog", "--title", title, "--getexistingdirectory", home] if kind == "folder" else
["kdialog", "--title", title, "--getopenfilename", home, "--multiple", "--separate-output"])
else:
return None
p = subprocess.run(cmd, capture_output=True, timeout=3600)
if p.returncode != 0:
return []
return [x for x in p.stdout.decode("utf-8", "replace").splitlines() if x.strip()]
def _as_str(t):
return '"' + str(t).replace("\\", "\\\\").replace('"', '\\"') + '"'
# ---------------------------------------------------------------------------
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

-2369
View File
File diff suppressed because it is too large. Load diff
+74
View File
@@ -0,0 +1,74 @@
; Instalador de PS5 Directo (Inno Setup 6). Lo compila GitHub Actions en cada version:
; ISCC /DMyVer=X.Y.Z installer\PS5Directo.iss
; Espera la carpeta del programa ya montada (con Python incluido) en dist\PS5Directo
; y deja dist\PS5Directo-X.Y.Z-Setup.exe.
; Se instala para el usuario actual (sin pedir permisos de administrador), en
; %LOCALAPPDATA%\Programs\PS5 Directo, para que «Actualizar» pueda escribir en la carpeta.
#ifndef MyVer
#define MyVer "0.0.0"
#endif
#ifndef SrcDir
#define SrcDir "..\dist\PS5Directo"
#endif
[Setup]
AppId={{BD789BF5-0254-4A4C-92CB-332BB22CEE42}
AppName=PS5 Directo
AppVersion={#MyVer}
AppVerName=PS5 Directo {#MyVer}
AppPublisher=PS5 Directo
AppPublisherURL=https://github.com/jstrdev/ps5directo
AppSupportURL=https://github.com/jstrdev/ps5directo/issues
AppUpdatesURL=https://github.com/jstrdev/ps5directo/releases
DefaultDirName={localappdata}\Programs\PS5 Directo
DefaultGroupName=PS5 Directo
DisableProgramGroupPage=yes
DisableReadyPage=no
DisableDirPage=yes
UsePreviousAppDir=yes
PrivilegesRequired=lowest
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
MinVersion=10.0
OutputDir=..\dist
OutputBaseFilename=PS5Directo-{#MyVer}-Setup
SetupIconFile={#SrcDir}\web\ps5directo.ico
WizardSmallImageFile=small.bmp,small2x.bmp
UninstallDisplayIcon={app}\web\ps5directo.ico
UninstallDisplayName=PS5 Directo
Compression=lzma2/max
SolidCompression=yes
WizardStyle=modern
CloseApplications=yes
RestartApplications=no
ShowLanguageDialog=no
LanguageDetectionMethod=uilanguage
[Languages]
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "en"; MessagesFile: "compiler:Default.isl"
[Files]
Source: "{#SrcDir}\*"; DestDir: "{app}"; Excludes: "Crear accesos directos.bat,__pycache__"; Flags: ignoreversion recursesubdirs createallsubdirs
[InstallDelete]
; restos de una version anterior que ya no se usan
Type: files; Name: "{app}\Crear accesos directos.bat"
[Icons]
Name: "{autoprograms}\PS5 Directo"; Filename: "{sys}\wscript.exe"; Parameters: """{app}\PS5 Directo.vbs"""; WorkingDir: "{app}"; IconFilename: "{app}\web\ps5directo.ico"; Comment: "PS5 Directo"; AppUserModelID: "PS5Directo.App"
Name: "{autodesktop}\PS5 Directo"; Filename: "{sys}\wscript.exe"; Parameters: """{app}\PS5 Directo.vbs"""; WorkingDir: "{app}"; IconFilename: "{app}\web\ps5directo.ico"; Comment: "PS5 Directo"; AppUserModelID: "PS5Directo.App"
Name: "{usersendto}\PS5 Directo"; Filename: "{sys}\wscript.exe"; Parameters: """{app}\PS5 Directo.vbs"""; WorkingDir: "{app}"; IconFilename: "{app}\web\ps5directo.ico"; Comment: "PS5 Directo"; AppUserModelID: "PS5Directo.App"
[Run]
Filename: "{sys}\wscript.exe"; Parameters: """{app}\PS5 Directo.vbs"""; WorkingDir: "{app}"; Description: "{cm:LaunchProgram,PS5 Directo}"; Flags: postinstall nowait skipifsilent
[UninstallRun]
; cierra PS5 Directo si sigue abierto, para poder borrar sus archivos
Filename: "{sys}\WindowsPowerShell\v1.0\powershell.exe"; Parameters: "-NoProfile -ExecutionPolicy Bypass -Command ""Get-Process python,pythonw -ErrorAction SilentlyContinue | Where-Object {{ $_.Path -like '{app}\*' } | Stop-Process -Force"""; Flags: runhidden; RunOnceId: "CerrarPS5Directo"
[UninstallDelete]
; tambien lo que añadio «Actualizar» despues de instalar. Los ajustes del usuario
; (carpeta .ps5directo) no se tocan.
Type: filesandordirs; Name: "{app}"
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key><string>PS5 Directo</string>
<key>CFBundleDisplayName</key><string>PS5 Directo</string>
<key>CFBundleIdentifier</key><string>io.github.jstrdev.ps5directo</string>
<key>CFBundleExecutable</key><string>PS5 Directo</string>
<key>CFBundleIconFile</key><string>ps5directo</string>
<key>CFBundlePackageType</key><string>APPL</string>
<key>CFBundleShortVersionString</key><string>__VERSION__</string>
<key>CFBundleVersion</key><string>__VERSION__</string>
<key>CFBundleInfoDictionaryVersion</key><string>6.0</string>
<key>LSMinimumSystemVersion</key><string>11.0</string>
<key>NSHighResolutionCapable</key><true/>
<key>LSApplicationCategoryType</key><string>public.app-category.utilities</string>
</dict>
</plist>
+64
View File
@@ -0,0 +1,64 @@
PS5 DIRECTO PARA MAC (EN PRUEBAS)
=================================
Esta versión todavía no se ha podido probar en un Mac de verdad. Si algo
falla, en el programa pulsa "Crear informe de fallo" y adjúntalo en un
aviso en GitHub: https://github.com/jstrdev/ps5directo/issues
Con eso se arregla rápido. ¡Gracias por probarla!
INSTALAR
1. Arrastra "PS5 Directo" a la carpeta Aplicaciones (Applications).
2. Ábrelo desde Aplicaciones.
SI MACOS NO TE DEJA ABRIRLO
La app no está firmada por Apple (eso cuesta 99 $ al año), así que la
primera vez macOS la bloquea. Es normal en programas gratuitos.
- macOS 15 (Sequoia) o posterior: intenta abrirla, cierra el aviso y ve a
Ajustes del Sistema > Privacidad y seguridad. Abajo verás "Se ha
bloqueado PS5 Directo": pulsa "Abrir igualmente".
- macOS 14 o anterior: clic derecho (o Control + clic) sobre la app >
Abrir > Abrir.
- Si aun así no abre, en Terminal:
xattr -dr com.apple.quarantine "/Applications/PS5 Directo.app"
NOTAS
- Funciona en Mac con Apple Silicon (M1, M2...) e Intel, macOS 11 o
posterior. Trae Python y 7-Zip.
- Para la ventana sin pestañas usa Chrome, Edge o Brave si los tienes; si
no, se abre en Safari.
- Para los torrents hace falta aria2: instala Homebrew (brew.sh) y luego
"brew install aria2".
- Se actualiza solo desde el propio programa, como en Windows.
PS5 DIRECTO FOR MAC (TESTING)
=============================
This version hasn't been tested on a real Mac yet. If something fails,
click "Create problem report" in the program and attach it to an issue
on GitHub: https://github.com/jstrdev/ps5directo/issues
That makes it quick to fix. Thanks for trying it!
INSTALL
1. Drag "PS5 Directo" into the Applications folder.
2. Open it from Applications.
IF MACOS WON'T OPEN IT
The app isn't signed by Apple (that costs $99 a year), so macOS blocks it
the first time. That's normal for free programs.
- macOS 15 (Sequoia) or later: try to open it, close the warning and go
to System Settings > Privacy & Security. Near the bottom you'll see
"PS5 Directo was blocked": click "Open Anyway".
- macOS 14 or earlier: right-click (or Control-click) the app > Open >
Open.
- If it still won't open, in Terminal:
xattr -dr com.apple.quarantine "/Applications/PS5 Directo.app"
NOTES
- Works on Apple Silicon (M1, M2...) and Intel Macs, macOS 11 or later.
Python and 7-Zip are included.
- For the window without tabs it uses Chrome, Edge or Brave if you have
one; otherwise it opens in Safari.
- Torrents need aria2: install Homebrew (brew.sh), then
"brew install aria2".
- It updates itself from the program, like on Windows.
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
# Lanzador de "PS5 Directo.app" (va en Contents/MacOS/PS5 Directo).
# - Python incluido para Apple Silicon (python-arm64) e Intel (python-x86_64), en Contents/Resources.
# - El programa se copia a ~/Library/Application Support/PS5 Directo/app y se ejecuta desde ahi,
# para que «Actualizar» pueda escribir aunque la app este en /Applications. Si la app trae una
# version mas nueva que la copiada, se vuelve a copiar.
RES="$(cd "$(dirname "$0")/../Resources" && pwd)"
SUP="$HOME/Library/Application Support/PS5 Directo"
APP="$SUP/app"
LOG="$SUP/lanzador.log"
mkdir -p "$SUP"
case "$(uname -m)" in
arm64) PY="$RES/python-arm64/bin/python3" ;;
*) PY="$RES/python-x86_64/bin/python3" ;;
esac
[ -x "$PY" ] || PY="$RES/python-x86_64/bin/python3" # Rosetta, por si acaso
ver() { sed -n 's/^VERSION = "\([^"]*\)".*/\1/p' "$1" 2>/dev/null | head -1; }
newer() { # 0 si $1 es mas nueva que $2
[ -z "$2" ] && return 0
[ "$1" = "$2" ] && return 1
[ "$(printf '%s\n%s\n' "$1" "$2" | sort -t. -k1,1n -k2,2n -k3,3n | tail -1)" = "$1" ]
}
BUNDLED="$(ver "$RES/app/app.py")"
COPIED="$(ver "$APP/app.py")"
if [ ! -f "$APP/app.py" ] || newer "$BUNDLED" "$COPIED"; then
echo "$(date) copio la version $BUNDLED (habia: ${COPIED:-ninguna})" >> "$LOG"
rm -rf "$APP.nuevo"
cp -R "$RES/app" "$APP.nuevo" && rm -rf "$APP" && mv "$APP.nuevo" "$APP"
fi
export PATH="$RES/bin:$PATH" # 7-Zip incluido
export PYTHONUNBUFFERED=1
cd "$APP" || exit 1
if [ ! -x "$PY" ]; then
osascript -e 'display alert "PS5 Directo" message "No encuentro el Python incluido en la app. Vuelve a descargarla de github.com/jstrdev/ps5directo/releases"' >/dev/null 2>&1
exit 1
fi
mkdir -p "$HOME/.ps5directo"
# El programa sigue en segundo plano y el lanzador termina: asi cada clic en el icono vuelve a
# entrar aqui y, si ya estaba abierto, solo trae su ventana (si no, macOS creeria que la app
# sigue abierta y no haria nada).
nohup "$PY" "$APP/app.py" "$@" >> "$HOME/.ps5directo/ps5directo.log" 2>&1 < /dev/null &
exit 0
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

-30
View File
@@ -1,30 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#3a7bff"/>
<stop offset=".55" stop-color="#4b4fe6"/>
<stop offset="1" stop-color="#7b3fe4"/>
</linearGradient>
<radialGradient id="glow" cx=".3" cy=".2" r=".9">
<stop offset="0" stop-color="#fff" stop-opacity=".35"/>
<stop offset=".5" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
<linearGradient id="arrow" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="1" stop-color="#dfe6ff"/>
</linearGradient>
</defs>
<rect x="8" y="8" width="240" height="240" rx="58" fill="url(#bg)"/>
<rect x="8" y="8" width="240" height="240" rx="58" fill="url(#glow)"/>
<rect x="9.5" y="9.5" width="237" height="237" rx="56.5" fill="none" stroke="#fff" stroke-opacity=".22" stroke-width="3"/>
<!-- estelas de velocidad -->
<g stroke="#fff" stroke-linecap="round" stroke-opacity=".45" stroke-width="9">
<line x1="62" y1="58" x2="62" y2="92"/>
<line x1="194" y1="58" x2="194" y2="92"/>
</g>
<!-- flecha -->
<path d="M128 44 c9 0 15 6 15 15 v58 h22 c11 0 16 13 8 21 l-35 37 c-6 6-14 6-20 0 l-35-37 c-8-8-3-21 8-21 h22 v-58 c0-9 6-15 15-15z" fill="url(#arrow)"/>
<!-- bandeja / consola -->
<path d="M52 168 v18 c0 14 10 24 24 24 h104 c14 0 24-10 24-24 v-18" fill="none" stroke="#fff" stroke-width="16" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="176" cy="190" r="5.5" fill="#7dffb2"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

-32
View File
@@ -1,32 +0,0 @@
{
"manifest_version": 3,
"name": "PS5 Directo - Capturar enlaces",
"version": "1.1.0",
"description": "Cuando descargas un .rar/.7z/.zip/.pkg, manda el enlace (con la sesion del navegador) a PS5 Directo en vez de bajarlo al PC.",
"permissions": [
"downloads",
"storage",
"notifications",
"cookies"
],
"host_permissions": [
"http://127.0.0.1/*",
"<all_urls>"
],
"background": {
"service_worker": "bg.js"
},
"action": {
"default_popup": "popup.html",
"default_title": "PS5 Directo",
"default_icon": {
"16": "icon16.png",
"32": "icon32.png"
}
},
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
}
}
-20
View File
@@ -1,20 +0,0 @@
<!doctype html>
<html lang="es"><head><meta charset="utf-8">
<style>
body{font:14px system-ui,sans-serif;background:#0d1117;color:#e6edf3;margin:0;padding:14px;width:280px}
h1{font-size:15px;margin:0 0 10px}
.row{display:flex;align-items:center;justify-content:space-between;margin:8px 0}
.st{font-size:13px;opacity:.85}
.ok{color:#4ade80}.bad{color:#f87171}
small{opacity:.6;display:block;margin-top:10px;line-height:1.4}
button{background:#1f2937;color:#e6edf3;border:1px solid #374151;border-radius:6px;padding:4px 10px;cursor:pointer}
</style></head>
<body>
<h1>PS5 Directo</h1>
<div class="row"><label for="en" id="lblEn">Capturar enlaces</label><input type="checkbox" id="en"></div>
<div class="st" id="st">Comprobando…</div>
<div class="st" id="cnt"></div>
<div class="row"><span></span><button id="reset">Poner contador a 0</button></div>
<small id="help">Pasa el captcha y pulsa Descargar como siempre: si es un .rar, .7z, .zip, .pkg… y PS5 Directo está abierto, el enlace va a su cuadro de enlaces y el navegador no descarga nada. Si PS5 Directo está cerrado, la descarga sigue normal.</small>
<script src="popup.js"></script>
</body></html>
-42
View File
@@ -1,42 +0,0 @@
const EN = !(navigator.language || "es").toLowerCase().startsWith("es");
const T = EN ? {
capture: "Capture links", checking: "Checking…", reset: "Reset counter",
help: "Pass the captcha and click Download as usual: if it's a .rar, .7z, .zip, .pkg… and PS5 Directo is open, the link goes to its link box and the browser downloads nothing. If PS5 Directo is closed, the download goes ahead normally.",
sent: "Sent", last: "last", connected: "● Connected", to: "to PS5 Directo", closed: "● PS5 Directo is not open", normal: "(downloads will work normally)"
} : {
capture: "Capturar enlaces", checking: "Comprobando…", reset: "Poner contador a 0",
help: null, sent: "Enviados", last: "último", connected: "● Conectado", to: "a PS5 Directo", closed: "● PS5 Directo no está abierto", normal: "(las descargas seguirán normales)"
};
if (EN) {
document.documentElement.lang = "en";
document.getElementById("lblEn").textContent = T.capture;
document.getElementById("st").textContent = T.checking;
document.getElementById("reset").textContent = T.reset;
document.getElementById("help").textContent = T.help;
}
async function findApp() {
for (const port of [8777, 8778, 8779]) {
try {
const r = await fetch(`http://127.0.0.1:${port}/api/ext/ping`, { cache: "no-store" });
if (r.ok) { const j = await r.json(); if (j.app === "PS5 Directo") return j; }
} catch (e) {}
}
return null;
}
(async () => {
const cfg = await chrome.storage.local.get({ enabled: true, captured: 0, last: "" });
const en = document.getElementById("en");
en.checked = cfg.enabled;
en.onchange = () => chrome.storage.local.set({ enabled: en.checked });
document.getElementById("cnt").textContent =
cfg.captured ? `${T.sent}: ${cfg.captured}${cfg.last ? " (" + T.last + ": " + cfg.last + ")" : ""}` : "";
document.getElementById("reset").onclick = async () => {
await chrome.storage.local.set({ captured: 0, last: "" });
chrome.action.setBadgeText({ text: "" });
document.getElementById("cnt").textContent = "";
};
const app = await findApp();
const st = document.getElementById("st");
if (app) { st.innerHTML = `<span class="ok">${T.connected}</span> ${T.to} v${app.version}`; chrome.action.setBadgeText({ text: "" }); }
else st.innerHTML = `<span class="bad">${T.closed}</span> ${T.normal}`;
})();
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

+25
View File
@@ -0,0 +1,25 @@
#!/bin/sh
# Abre PS5 Directo en Linux (y en Mac, si lo usas desde la carpeta).
# Usa el Python que viene incluido (carpeta python/) o, si no esta, el python3 del sistema.
# Puedes pasarle archivos: ./ps5directo.sh juego.rar
DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$DIR" || exit 1
# 7-Zip incluido (carpeta bin/), para "Descomprimir en el PC"
[ -d "$DIR/bin" ] && PATH="$DIR/bin:$PATH" && export PATH
if [ -x "$DIR/python/bin/python3" ]; then
PY="$DIR/python/bin/python3"
elif command -v python3 >/dev/null 2>&1; then
PY="python3"
else
MSG="No encuentro Python 3. Instálalo (por ejemplo: sudo apt install python3) o baja la versión de PS5 Directo para Linux, que ya lo trae."
command -v zenity >/dev/null 2>&1 && zenity --error --title="PS5 Directo" --text="$MSG" 2>/dev/null
echo "$MSG" >&2
exit 1
fi
export PYTHONUNBUFFERED=1
# Abierto desde el menu (sin terminal): el registro va al mismo archivo que en Windows
if [ ! -t 1 ]; then
mkdir -p "$HOME/.ps5directo"
exec "$PY" "$DIR/app.py" "$@" >> "$HOME/.ps5directo/ps5directo.log" 2>&1
fi
exec "$PY" "$DIR/app.py" "$@"
-48
View File
@@ -1,48 +0,0 @@
# Publica una version: al subir una etiqueta vX.Y.Z crea la release de GitHub con dos .zip:
# - PS5Directo-X.Y.Z.zip la app (la que usa "Actualizar" dentro del programa)
# - PS5Directo-X.Y.Z-portable-windows.zip la app + Python incluido: descomprimir y abrir, sin instalar nada
name: Publicar version
on:
push:
tags: ["v*"]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Version de app.py
id: v
run: echo "ver=$(grep -oP 'VERSION = "\K[^"]+' app.py)" >> "$GITHUB_OUTPUT"
- name: La etiqueta tiene que coincidir con la version
if: startsWith(github.ref, 'refs/tags/')
run: test "${GITHUB_REF_NAME#v}" = "${{ steps.v.outputs.ver }}"
- name: Paquete normal
run: |
mkdir -p dist/PS5Directo
git archive HEAD | tar -x -C dist/PS5Directo
rm -rf dist/PS5Directo/.github
(cd dist && zip -qr "PS5Directo-${{ steps.v.outputs.ver }}.zip" PS5Directo)
- name: Paquete portable (con Python para Windows)
run: |
PY=3.12.10
curl -fsSL -o py.zip "https://www.python.org/ftp/python/$PY/python-$PY-embed-amd64.zip"
mkdir -p dist/PS5Directo/python
unzip -q py.zip -d dist/PS5Directo/python
# que el Python incluido vea la carpeta del programa
for f in dist/PS5Directo/python/python*._pth; do printf '..\n' >> "$f"; done
(cd dist && zip -qr "PS5Directo-${{ steps.v.outputs.ver }}-portable-windows.zip" PS5Directo)
- uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: dist/*.zip
View File
File renamed without changes.
View File
File renamed without changes.
View File
File renamed without changes.
+1857 -151
View File
File diff suppressed because it is too large. Load diff