Compare commits

..
26 Commits
Author SHA1 Message Date
Manos 4403d86be5 Update README for v3.2.0 - Storage display fix, mobile improvements, bug fixes 2026-01-24 01:24:50 +02:00
Manos af252efc9a Clean up README - remove source code references and building instructions 2026-01-20 04:11:59 +02:00
Manos 2da27aed13 Remove old release files and zips 2026-01-20 04:05:11 +02:00
Manos 264ad6210d Remove source code - keep only compiled binaries in releases 2026-01-20 04:01:47 +02:00
Manos db48bc6fb2 Update README.md for v3.1.0 - parallel chunked uploads, real-time progress 2026-01-20 04:00:11 +02:00
Manos 4ac43ebb8b v3.1.0: Parallel chunked uploads (104 MB/s), real-time speed/ETA, storage display fixes 2026-01-20 03:54:44 +02:00
Manos 20caced5f4 Keep only screenshot3 and mobile screenshot in README 2026-01-19 17:24:25 +02:00
Manos 285279788f Add mobile app screenshot to README 2026-01-19 17:22:41 +02:00
Manos 70d174cecc v3.0.0 - Rename release to version 3.0.0 2026-01-19 17:14:53 +02:00
manos555555 f128c6a6b4 Delete .gitignore 2026-01-19 17:00:00 +02:00
Manos c211c086ac v2.2.0 - Critical path fix, Android Mobile App with Multi-PS5 Profiles 2026-01-19 16:58:51 +02:00
manos555555 4ca30876c7 Update README.md 2026-01-19 01:26:59 +02:00
manos555555 5ae3c1709e Delete PROTOCOL.md 2026-01-19 01:25:27 +02:00
Manos 3374e87bfe Update to v2.1.0: Add screenshot, update README, remove old release files 2026-01-19 01:23:51 +02:00
Manos c21d73f41d Resolved merge conflict - keeping v2.0.0 ZIP 2026-01-18 03:34:02 +02:00
Manos 5ce9d470bc v2.0.0 - Added Download Files, File Search, Favorites/Bookmarks, Multi-PS5 Support 2026-01-18 03:33:33 +02:00
manos555555 0eb159bf88 Delete PS5Upload-Windows-x64-v1.0.zip 2026-01-14 01:37:31 +02:00
manos555555 4ff160232f Delete PS5Upload-Windows-x64-v1.1-BugFix.zip 2026-01-14 01:37:21 +02:00
manos555555 a5e40ce245 Delete PS5Upload-Windows-x64-v1.2-Complete.zip 2026-01-14 01:37:13 +02:00
manos555555 bb7d90411c Delete PS5Upload-Windows-x64-v1.3.0-Stable.zip 2026-01-14 01:37:06 +02:00
manos555555 00013aae76 Delete GITHUB_UPLOAD_INSTRUCTIONS.md 2026-01-14 01:36:42 +02:00
manos555555 6d8d802962 Delete create_v1.1_release.ps1 2026-01-14 01:36:32 +02:00
manos555555 f3a1d5e436 Delete create_github_release.ps1 2026-01-14 01:36:22 +02:00
manos555555 bad3029e32 Delete create_release.bat 2026-01-14 01:36:13 +02:00
manos555555 a51fffef83 Delete create_v1.2_release.ps1 2026-01-14 01:35:43 +02:00
manos555555 f89eaf4e31 Delete upload_to_github.py 2026-01-14 01:35:22 +02:00
30 changed files with 196 additions and 5434 deletions

No files matched your search

-60
View File
@@ -1,60 +0,0 @@
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio cache/options
.vs/
*.suo
*.user
*.userosscache
*.sln.docstates
# Build results
*.dll
*.exe
*.pdb
*.cache
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# Files built by Visual Studio
*.pidb
*.svclog
*.scc
# Caches
*.swp
*~
# OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Temporary files
*.tmp
*.log
*.bak
*.old
# PowerShell script
convert_to_ico.ps1
-263
View File
@@ -1,263 +0,0 @@
# GitHub Upload Instructions - PS5 Upload Suite
## 📁 Correct Folder to Upload
**Source Path:**
```
C:\Users\HACKMAN\Desktop\ps5 test\ps5_rom_keys\ps5_upload_suite\client\bin\Release\net6.0-windows\win-x64\
```
This folder contains the **complete, self-contained Windows executable** with all dependencies.
---
## 🗑️ Step 1: Delete Old Release on GitHub
1. Go to your GitHub repository
2. Navigate to **Releases** tab
3. Find the old/incorrect release
4. Click **Delete** on the old release
5. Confirm deletion
**Or delete via Git:**
```bash
# Delete old tag
git tag -d v1.0
git push origin :refs/tags/v1.0
# Delete old files from repository
git rm -r ps5upload-windows-x64/
git commit -m "Remove incorrect Windows build"
git push origin main
```
---
## 📦 Step 2: Create Release Package
### Option A: Via PowerShell (Automated)
```powershell
# Navigate to project root
cd "C:\Users\HACKMAN\Desktop\ps5 test\ps5_rom_keys\ps5_upload_suite"
# Create release directory
New-Item -ItemType Directory -Force -Path ".\github_release"
# Copy correct files
Copy-Item -Path ".\client\bin\Release\net6.0-windows\win-x64\*" -Destination ".\github_release\" -Recurse
# Copy payload
Copy-Item -Path ".\payload\ps5_upload_server.elf" -Destination ".\github_release\"
# Create ZIP
Compress-Archive -Path ".\github_release\*" -DestinationPath ".\PS5Upload-Windows-x64-v1.0.zip" -Force
Write-Host "Release package created: PS5Upload-Windows-x64-v1.0.zip"
```
### Option B: Manual
1. Create new folder: `PS5Upload-Windows-x64`
2. Copy **ALL files** from `win-x64\` folder
3. Add `ps5_upload_server.elf` from `payload\` folder
4. Create ZIP: `PS5Upload-Windows-x64-v1.0.zip`
---
## ⬆️ Step 3: Upload to GitHub
### Via GitHub Web Interface:
1. Go to your repository on GitHub
2. Click **Releases** → **Create a new release**
3. Fill in:
- **Tag:** `v1.0`
- **Title:** `PS5 Upload Suite v1.0 - Windows x64`
- **Description:**
```markdown
# PS5 Upload Suite v1.0
## Windows x64 Release
Self-contained executable for Windows 10/11 (64-bit)
No .NET Runtime installation required!
## What's Included:
- PS5Upload.exe (Windows GUI client)
- ps5_upload_server.elf (PS5 server payload)
- All required dependencies
## How to Use:
1. Extract ZIP file
2. Run PS5Upload.exe
3. Load ps5_upload_server.elf to PS5 (via etaHEN)
4. Connect and upload files!
## Requirements:
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN
- Network connection to PS5
## File Size:
- Full package: ~50 MB
- Includes all .NET 6.0 dependencies
```
4. **Attach files:**
- Upload `PS5Upload-Windows-x64-v1.0.zip`
5. Click **Publish release**
### Via Git Command Line:
```bash
# Navigate to repository
cd "C:\Users\HACKMAN\Desktop\ps5 test\ps5_rom_keys\ps5_upload_suite"
# Add correct files
git add client/bin/Release/net6.0-windows/win-x64/
git commit -m "Add correct Windows x64 build with all dependencies"
git push origin main
# Create and push tag
git tag -a v1.0 -m "PS5 Upload Suite v1.0 - Windows x64"
git push origin v1.0
# Upload release asset via GitHub CLI (if installed)
gh release create v1.0 PS5Upload-Windows-x64-v1.0.zip --title "PS5 Upload Suite v1.0" --notes "Self-contained Windows x64 release"
```
---
## 📝 Step 4: Update Repository README
Add download link to main README.md:
```markdown
## Download
### Latest Release: v1.0
**Windows (x64):**
- [PS5Upload-Windows-x64-v1.0.zip](https://github.com/YOUR_USERNAME/ps5_upload_suite/releases/download/v1.0/PS5Upload-Windows-x64-v1.0.zip)
- Size: ~50 MB
- Self-contained (no .NET installation required)
**PS5 Server:**
- Included in Windows package: `ps5_upload_server.elf`
- Load via etaHEN or GoldHEN
### System Requirements:
- **Windows:** 10/11 (64-bit)
- **PS5:** Firmware with etaHEN 2.0+ or GoldHEN
```
---
## ✅ Verification Checklist
Before uploading, verify:
- [ ] Folder contains `PS5Upload.exe` (8+ MB)
- [ ] Folder contains `PS5Upload.dll`
- [ ] Folder contains `PS5Upload.runtimeconfig.json`
- [ ] Folder contains all DLL dependencies (100+ files)
- [ ] `ps5_upload_server.elf` is included
- [ ] ZIP file is created correctly
- [ ] Test: Extract ZIP and run `PS5Upload.exe` - should work without errors
---
## 🐛 Common Issues
### "The application requires .NET Runtime"
**Problem:** Wrong folder uploaded (missing dependencies)
**Solution:** Use the `win-x64` folder, not `release` folder
### "Missing DLL files"
**Problem:** Incomplete upload
**Solution:** Make sure ALL files from `win-x64` folder are included
### "Application won't start"
**Problem:** Corrupted ZIP or missing files
**Solution:** Re-create ZIP from scratch, include all files
---
## 📊 File Structure for GitHub
```
PS5Upload-Windows-x64-v1.0.zip
├── PS5Upload.exe (Main executable)
├── PS5Upload.dll (Application library)
├── PS5Upload.runtimeconfig.json (Runtime configuration)
├── ps5_upload_server.elf (PS5 server payload)
├── Accessibility.dll (Dependency)
├── D3DCompiler_47_cor3.dll (Dependency)
├── DirectWriteForwarder.dll (Dependency)
├── Microsoft.*.dll (100+ Microsoft dependencies)
├── PresentationCore.dll (WPF dependency)
├── PresentationFramework.dll (WPF dependency)
├── ReachFramework.dll (WPF dependency)
├── System.*.dll (System dependencies)
├── UIAutomationClient.dll (UI dependency)
├── UIAutomationProvider.dll (UI dependency)
├── UIAutomationTypes.dll (UI dependency)
├── WindowsBase.dll (Windows dependency)
├── WindowsFormsIntegration.dll (Windows dependency)
├── api-ms-win-*.dll (Windows API dependencies)
├── clrcompression.dll (Compression)
├── clretwrc.dll (ETW)
├── clrjit.dll (JIT compiler)
├── coreclr.dll (CoreCLR runtime)
├── createdump.exe (Debug tool)
├── hostfxr.dll (Host)
├── hostpolicy.dll (Host policy)
├── mscordaccore.dll (DAC)
├── mscordaccore_amd64_amd64_*.dll (DAC)
├── mscordbi.dll (Debugger)
├── mscorlib.dll (Core library)
├── msquic.dll (QUIC)
├── ucrtbase.dll (C runtime)
├── vcruntime140.dll (VC runtime)
└── vcruntime140_cor3.dll (VC runtime)
```
**Total:** ~150 files, ~50 MB
---
## 🎯 Quick Commands Summary
```powershell
# 1. Create release package
cd "C:\Users\HACKMAN\Desktop\ps5 test\ps5_rom_keys\ps5_upload_suite"
Compress-Archive -Path ".\client\bin\Release\net6.0-windows\win-x64\*" -DestinationPath ".\PS5Upload-Windows-x64-v1.0.zip" -Force
# 2. Test locally
Expand-Archive -Path ".\PS5Upload-Windows-x64-v1.0.zip" -DestinationPath ".\test_extract" -Force
.\test_extract\PS5Upload.exe
# 3. Upload to GitHub (manual via web interface)
# Go to: https://github.com/YOUR_USERNAME/ps5_upload_suite/releases/new
# Upload: PS5Upload-Windows-x64-v1.0.zip
```
---
## ✅ Final Steps
1. **Delete old release** on GitHub
2. **Create ZIP** from `win-x64` folder
3. **Test ZIP** locally (extract and run)
4. **Upload to GitHub** as new release
5. **Update README** with download link
6. **Announce** the correct release
---
**The correct folder is:**
```
C:\Users\HACKMAN\Desktop\ps5 test\ps5_rom_keys\ps5_upload_suite\client\bin\Release\net6.0-windows\win-x64\
```
**This contains everything needed for a working Windows release!**
-83
View File
@@ -1,83 +0,0 @@
# PS5 Upload Protocol Specification
## Overview
Custom binary protocol for high-speed file transfers between PC and PS5.
Port: 9113
## Message Format
All messages follow this structure:
```
[Command (1 byte)][Data Length (4 bytes)][Data (variable)]
```
## Commands
### Client → Server
| Command | Value | Description | Data Format |
|---------|-------|-------------|-------------|
| PING | 0x01 | Test connection | None |
| LIST_STORAGE | 0x02 | Get storage info | None |
| LIST_DIR | 0x03 | List directory | Path (null-terminated string) |
| CREATE_DIR | 0x04 | Create directory | Path (null-terminated string) |
| DELETE_FILE | 0x05 | Delete file | Path (null-terminated string) |
| DELETE_DIR | 0x06 | Delete directory | Path (null-terminated string) |
| START_UPLOAD | 0x10 | Start file upload | Path (null-terminated) + File size (8 bytes) |
| UPLOAD_CHUNK | 0x11 | Upload file chunk | Chunk data (raw bytes) |
| END_UPLOAD | 0x12 | Finish upload | None |
| SHUTDOWN | 0xFF | Shutdown server | None |
### Server → Client
| Response | Value | Description | Data Format |
|----------|-------|-------------|-------------|
| OK | 0x01 | Success | Optional message |
| ERROR | 0x02 | Error occurred | Error message (null-terminated) |
| DATA | 0x03 | Response data | Variable format |
| READY | 0x04 | Ready for next chunk | None |
| PROGRESS | 0x05 | Upload progress | Bytes written (8 bytes) |
## Data Formats
### LIST_STORAGE Response
```
[Drive count (4 bytes)]
For each drive:
[Path length (2 bytes)][Path][Total space (8 bytes)][Free space (8 bytes)]
```
### LIST_DIR Response
```
[Entry count (4 bytes)]
For each entry:
[Type (1 byte: 0=file, 1=dir)][Name length (2 bytes)][Name][Size (8 bytes)][Timestamp (8 bytes)]
```
## Flow Examples
### Upload File
```
Client: START_UPLOAD "/data/test.bin" size=1048576
Server: READY
Client: UPLOAD_CHUNK [4MB data]
Server: PROGRESS bytes=4194304
Client: UPLOAD_CHUNK [remaining data]
Server: PROGRESS bytes=1048576
Client: END_UPLOAD
Server: OK
```
### List Directory
```
Client: LIST_DIR "/data"
Server: DATA [directory listing]
```
## Performance Optimizations
- 4MB socket buffers
- SO_NOSIGPIPE enabled
- TCP_NODELAY for low latency
- Direct disk writes (no temp files)
- Streaming chunks (no full file buffering)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+196 -98
View File
@@ -2,41 +2,45 @@
**By Manos**
**Version 1.3.0 - Stable Release**
**Version 3.2.0 - Mobile Improvements & Bug Fixes**
Custom high-speed file transfer system for PS5 with etaHEN. Achieves **100+ MB/s** transfer speeds using a custom binary protocol.
Custom high-speed file transfer system for PS5 with etaHEN. Achieves **104+ MB/s** upload speeds for large files using parallel chunked uploads!
⭐ **NEW in v1.3.0:** Complete stability overhaul - **42,801+ files uploaded with ZERO errors!**
⭐ **NEW in v3.2.0:** Accurate storage display (848 GB), mobile multi-select, folder browser, bug fixes!
![PS5 Upload Client](screenshots/screenshot1.png)
![Upload in Progress](screenshots/screenshot2.png)
📱 **Android Mobile Client available!**
![Transfer History & Multi-PS5 Support](screenshots/screenshot3.png)
![Mobile App](screenshots/mobile_screenshot.jpg)
---
## 📦 What's Included
## 📦 Downloads
Download the latest release from the [Releases](https://github.com/manos555555/PS5-Upload-Suite/releases) page:
### 1. PS5 Server Payload
- **File:** `payload/ps5_upload_server.elf`
- **File:** `ps5_upload_server.elf`
- **Port:** 9113
- **Protocol:** Custom binary (optimized for speed)
- **Features:**
- 4MB socket buffers
- SO_NOSIGPIPE enabled
- TCP_NODELAY for low latency
- Direct disk writes (no temp files)
- Multi-threaded client handling
- High-speed custom binary protocol
- 16MB socket buffers for maximum throughput
- Multi-threaded client handling
### 2. Windows GUI Client
- **File:** `client/bin/Release/net6.0-windows/win-x64/publish/PS5Upload.exe`
- **Framework:** .NET 6.0 WPF
- **Features:**
- Modern dark theme UI
- Drag & drop file/folder upload
- Browse PS5 filesystem
- Real-time upload progress
- Speed indicator (MB/s)
- Storage space display
- Recursive folder upload
- **File:** `PS5Upload.exe`
- Self-contained executable (no .NET installation required)
- Modern dark theme UI
- Drag & drop file/folder upload
- Real-time upload progress with speed tracking
- Transfer History with success/failed tracking
- Storage space display
### 3. 📱 Android Mobile Client
- **File:** `PS5UploadMobile.apk`
- Upload/download files from your phone
- Multi-PS5 Profiles support
- Browse PS5 filesystem
- Favorites for quick navigation
---
@@ -44,17 +48,13 @@ Custom high-speed file transfer system for PS5 with etaHEN. Achieves **100+ MB/s
### Step 1: Load PS5 Payload
1. Copy `payload/ps5_upload_server.elf` to your PS5:
```
/data/etaHEN/payloads/ps5_upload_server.elf
```
1. Download `ps5_upload_server.elf` from the [Releases](https://github.com/manos555555/PS5-Upload-Suite/releases) page
2. Load the payload with elfldr
2. Copy it to your PS5: `/data/etaHEN/payloads/ps5_upload_server.elf`
3. You should see notification:
```
PS5 Upload Server: 192.168.0.XXX:9113 - By Manos
```
3. Load the payload with elfldr
4. You should see notification: `PS5 Upload Server: 192.168.0.XXX:9113 - By Manos`
### Step 2: Run Windows Client
@@ -80,81 +80,45 @@ Custom high-speed file transfer system for PS5 with etaHEN. Achieves **100+ MB/s
✅ **Robust Error Handling** - Graceful failures
### Windows Client
✅ **Modern UI** - Dark theme, clean design
✅ **Modern UI** - Dark theme, maximized window for better visibility
✅ **Drag & Drop** - Files and folders
✅ **Browse PS5** - Navigate filesystem
✅ **Real-time Progress** - Speed & percentage
✅ **Real-time Progress** - Speed & percentage tracking
✅ **Optimized Upload** - 8 parallel connections for 88-110 MB/s aggregate speed (NEW v2.1)
✅ **Transfer History** - Track all uploads/downloads with success/failed status (NEW v2.1)
✅ **Auto-Clear History** - Optional auto-clear on startup (NEW v2.1)
✅ **Folder Upload** - Recursive directory upload
✅ **Storage Info** - Free space display
✅ **Download Files** - Download from PS5 to PC (v2.0)
✅ **File Search** - Real-time filtering of PS5 files (v2.0)
✅ **Favorites/Bookmarks** - Quick navigation to saved paths (v2.0)
✅ **Multi-PS5 Support** - Save and switch between multiple PS5 profiles (v2.0)
---
## 📊 Performance
### v1.3.0 Tested Results:
- ✅ **42,801 files** uploaded successfully
- ✅ **Zero errors** - 100% success rate
- ✅ **60-150 MB/s** sustained throughput
- ✅ **Peak:** 190 MB/s per connection
### v3.1.0 Optimized Results:
- ✅ **104+ MB/s** upload speed for large files (parallel chunked uploads)
- ✅ **4 parallel chunk connections** for maximum throughput
- ✅ **500MB chunks** - optimal size for PS5 disk performance
- ✅ **Real-time progress** - Speed/ETA updates during upload
- ✅ **Zero chunk failures** - Fixed race conditions
- ✅ **Fully responsive UI** throughout upload
- ✅ **No memory leaks** - stable operation
| Network | Expected Speed |
|---------|----------------|
| **Gigabit Ethernet** | 100-120 MB/s |
| **WiFi 6 (5GHz)** | 60-80 MB/s |
| **WiFi 5 (5GHz)** | 40-60 MB/s |
### Previous Results (v1.3.0):
- ✅ **42,801 files** uploaded successfully
- ✅ **60-150 MB/s** sustained throughput
**Note:** Speeds depend on network quality and PS5 disk performance.
| Network | Expected Upload Speed | Expected Download Speed |
|---------|----------------------|------------------------|
| **Gigabit Ethernet** | 88-110 MB/s (aggregate) | 100-120 MB/s |
| **WiFi 6 (5GHz)** | 32-70 MB/s (aggregate) | 60-80 MB/s |
| **WiFi 5 (5GHz)** | 20-50 MB/s (aggregate) | 40-60 MB/s |
---
**Note:** Upload speeds depend on network quality and PS5 disk write performance. WiFi has ~40-60% overhead compared to Ethernet.
## 🔧 Building from Source
### PS5 Payload
Requirements:
- PS5 SDK (prospero-clang)
- WSL or Linux
```bash
cd payload
bash compile.sh
```
### Windows Client
Requirements:
- .NET 6.0 SDK or later
- Windows 10/11
```cmd
cd client
build.bat
```
Or manually:
```cmd
dotnet publish -c Release -r win-x64 --self-contained true
```
---
## 📋 Protocol Specification
See [PROTOCOL.md](PROTOCOL.md) for detailed protocol documentation.
### Commands
- `PING` - Test connection
- `LIST_STORAGE` - Get storage info
- `LIST_DIR` - List directory contents
- `CREATE_DIR` - Create directory
- `DELETE_FILE` - Delete file
- `DELETE_DIR` - Delete directory
- `START_UPLOAD` - Begin file upload
- `UPLOAD_CHUNK` - Upload file chunk
- `END_UPLOAD` - Finish upload
- `SHUTDOWN` - Shutdown server
---
@@ -186,22 +150,156 @@ See [PROTOCOL.md](PROTOCOL.md) for detailed protocol documentation.
---
## 📝 What's New in v1.3.0
## 📝 What's New in v3.2.0
See [CHANGELOG.md](CHANGELOG.md) for complete list of all 15 bug fixes.
### 🎯 Improvements:
### Highlights:
#### 1. 💾 Accurate Storage Display
- **Storage now matches PS5 UI** - Shows ~848 GB instead of raw 872 GB
- **Accounts for reserved space** - Same calculation as PS5 system
#### 2. 📱 Mobile App Improvements
- **Multi-select mode** - Toggle button to select multiple files/folders
- **Folder browser** - Visual folder picker for Copy/Move destinations
- **Sorted file list** - Folders always displayed at top
- **Exit confirmation** - Prompt when pressing back button
- **Delete folders** - Now supports folder deletion (not just files)
- **Batch operations** - Delete/download multiple items at once
#### 3. 🐛 Bug Fixes
- **Fixed empty folder deletion** - No more "Unexpected response" error
- **Fixed Copy/Move crash** - No longer crashes when selecting destination
- **Fixed multi-select count** - Correct item count in delete confirmation
- **Fixed folder navigation** - Can enter folders after actions complete
---
## 📝 What's New in v3.1.0
### 🚀 Performance Improvements:
#### 1. ⚡ Parallel Chunked Uploads (104 MB/s!)
- **Large files (>100MB)** are now split into 500MB chunks
- **4 parallel connections** upload chunks simultaneously
- **Result:** ~104 MB/s upload speed (2x faster than before!)
- **Fixed race condition:** First chunk creates file before others start
- **Fixed closure bug:** Correct offset/size capture for parallel tasks
#### 2. 📊 Real-time Progress Display
- **Speed display** now updates in real-time during chunked uploads
- **ETA display** shows accurate time remaining
- **Progress bar** correctly shows 0-100% for chunked files
- No more speed dropping to 0 during large file uploads
#### 3. 💾 Storage Display Improvements
- **Changed label** to "Data Storage (/data)" for clarity
- **Uses statfs with f_bavail** for more accurate available space
- **Real-time updates** every 5 seconds when connected
---
## 📝 What's New in v3.0.0
### 🐛 Critical Bug Fixes:
#### 1. 🔧 Path Normalization Fix
- **Fixed:** Double-slash paths (`//mnt/ext1/...`) that caused directory creation to fail
- **Affected:** All file operations (upload, download, delete, rename, copy, move)
- **Solution:** Added `NormalizePath()` function in both client and server
- **Result:** 100% reliable directory creation and file uploads
#### 2. 📱 Android Mobile Client
- **NEW:** Full-featured Android app for PS5 file management
- **Multi-PS5 Profiles** - Save and switch between multiple PS5 consoles
- Upload files from phone to PS5
- Download files from PS5 with Share option
- Browse PS5 filesystem
- Favorites for quick navigation
- Debug Log with Copy to clipboard
- Transfer History tracking
#### 3. 🛠️ Server Improvements
- Path normalization in all handler functions
- More robust error handling
- Improved stability for parallel uploads
---
## 📝 What's New in v2.1.0
### 🚀 Performance Optimizations:
#### 1. ⚡ Massive Upload Speed Boost (88-110 MB/s)
- **Server-side:** Replaced `fwrite()` with direct `write()` syscalls
- **Client-side:** 8 parallel large file uploads (optimal for PS5 disk)
- **Result:** 80-110 MB/s aggregate upload speed on Gigabit Ethernet
- **Peak bursts:** Up to 2.05 GB/s when hitting disk cache
- **Per-file:** 11-14 MB/s sustained per connection
#### 2. 📊 Transfer History
- Complete history of all uploads and downloads
- Success/Failed status tracking with error messages
- Speed statistics (average, min, max)
- Export to CSV/JSON for analysis
- Persistent storage across sessions
#### 3. 🔄 Auto-Clear History on Startup
- Optional checkbox to clear history automatically
- Useful for keeping UI clean between sessions
- Setting saved in `ps5_upload_settings.json`
#### 4. 🖥️ Maximized Window UI
- Application opens in full-screen mode by default
- Better visibility for large file transfers
- Can be resized/restored as needed
### Technical Improvements:
- ✅ **16MB socket buffers** (up from 4MB) for maximum throughput
- ✅ **Per-file mutex locking** - Parallel writes without race conditions
- ✅ **File pre-allocation** - Reduces disk fragmentation for large files
- ✅ **Direct syscalls** - Bypasses stdio buffering overhead
---
## 📝 What's New in v2.0.0
### 🎉 4 Major New Features:
#### 1. 📥 Download Files (PS5 → PC)
- Right-click any file → "⬇️ Download to PC"
- Save file dialog for destination selection
- Real-time progress tracking with speed display
- Optimized with sendfile for maximum speed
#### 2. 🔍 File Search
- Search box in PS5 Files panel
- Real-time filtering as you type
- Case-insensitive search
- Quick "Clear" button to reset
#### 3. ⭐ Favorites/Bookmarks
- Save frequently used PS5 paths
- Quick dropdown navigation
- Add/Remove favorite paths
- Persistent storage in JSON
#### 4. 🎮 Multi-PS5 Support
- Save multiple PS5 profiles (IP + name)
- Quick switch between different PS5 consoles
- Dropdown profile selector
- Persistent profile storage
### Previous Stability (v1.3.0):
- ✅ **Zero connection drops** - 5 minute socket timeout + aggressive keepalive
- ✅ **Fully responsive UI** - Async updates + throttled logging
- ✅ **No memory leaks** - Proper resource disposal
- ✅ **Optimal stability** - 6 parallel single-connection uploads
- ✅ **Tested:** 42,801 files uploaded with 100% success rate
---
## 📝 License
MIT License - Free to use and modify
This software is provided as-is for personal use.
---
-8
View File
@@ -1,8 +0,0 @@
<Application x:Class="PS5Upload.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
-8
View File
@@ -1,8 +0,0 @@
using System.Windows;
namespace PS5Upload
{
public partial class App : Application
{
}
}
-79
View File
@@ -1,79 +0,0 @@
<Window x:Class="PS5Upload.DuplicateFileDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="File Already Exists"
Height="320"
Width="550"
WindowStartupLocation="CenterOwner"
ResizeMode="NoResize"
Background="#1E1E1E">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="#2D2D30"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#3F3F46"/>
<Setter Property="Padding" Value="15,8"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Cursor" Value="Hand"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#3E3E42"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Icon and Message -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="0,0,0,15">
<TextBlock Text="⚠️" FontSize="32" Margin="0,0,15,0"/>
<TextBlock x:Name="MessageTextBlock"
Text="This file already exists on PS5:"
Foreground="White"
FontSize="14"
VerticalAlignment="Center"/>
</StackPanel>
<!-- File Name -->
<TextBlock Grid.Row="1"
x:Name="FileNameTextBlock"
Foreground="#4EC9B0"
FontSize="13"
FontWeight="Bold"
Margin="0,0,0,10"
TextWrapping="Wrap"/>
<!-- File Info -->
<StackPanel Grid.Row="2" Margin="0,0,0,20">
<TextBlock x:Name="LocalSizeTextBlock"
Foreground="#9CDCFE"
FontSize="12"
Margin="0,0,0,5"/>
<TextBlock x:Name="RemoteSizeTextBlock"
Foreground="#9CDCFE"
FontSize="12"/>
</StackPanel>
<!-- Buttons -->
<StackPanel Grid.Row="4" Orientation="Vertical">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,0,0,10">
<Button Content="Replace" Width="120" Click="Replace_Click"/>
<Button Content="Skip" Width="120" Click="Skip_Click"/>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="Replace All" Width="120" Click="ReplaceAll_Click"/>
<Button Content="Skip All" Width="120" Click="SkipAll_Click"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
-67
View File
@@ -1,67 +0,0 @@
using System.Windows;
namespace PS5Upload
{
public partial class DuplicateFileDialog : Window
{
public enum FileAction
{
Replace,
Skip,
ReplaceAll,
SkipAll
}
public FileAction UserAction { get; private set; }
public DuplicateFileDialog(string fileName, long localSize, long remoteSize)
{
InitializeComponent();
FileNameTextBlock.Text = fileName;
LocalSizeTextBlock.Text = $"Local file: {FormatFileSize(localSize)}";
RemoteSizeTextBlock.Text = $"Remote file: {FormatFileSize(remoteSize)}";
}
private void Replace_Click(object sender, RoutedEventArgs e)
{
UserAction = FileAction.Replace;
DialogResult = true;
Close();
}
private void Skip_Click(object sender, RoutedEventArgs e)
{
UserAction = FileAction.Skip;
DialogResult = true;
Close();
}
private void ReplaceAll_Click(object sender, RoutedEventArgs e)
{
UserAction = FileAction.ReplaceAll;
DialogResult = true;
Close();
}
private void SkipAll_Click(object sender, RoutedEventArgs e)
{
UserAction = FileAction.SkipAll;
DialogResult = true;
Close();
}
private string FormatFileSize(long bytes)
{
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
double len = bytes;
int order = 0;
while (len >= 1024 && order < sizes.Length - 1)
{
order++;
len = len / 1024;
}
return $"{len:0.##} {sizes[order]}";
}
}
}
-473
View File
@@ -1,473 +0,0 @@
<Window x:Class="PS5Upload.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PS5 Upload - High-Speed File Transfer" Height="600" Width="1200"
WindowStartupLocation="CenterScreen"
Background="#1E1E1E"
Icon="ps5_logo.png">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="#007ACC"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="15,8"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
CornerRadius="4"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#1C97EA"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#3E3E42"/>
<Setter Property="Foreground" Value="#666666"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox">
<Setter Property="Background" Value="#2D2D30"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#3E3E42"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="8"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<Style TargetType="ListBox">
<Setter Property="Background" Value="#2D2D30"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="BorderBrush" Value="#3E3E42"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</Window.Resources>
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Header -->
<StackPanel Grid.Row="0" Margin="0,0,0,20" Orientation="Horizontal" HorizontalAlignment="Center">
<Image Source="ps5_logo.png"
Width="80"
Height="80"
Margin="0,0,15,0"
VerticalAlignment="Center"/>
<StackPanel VerticalAlignment="Center">
<TextBlock Text="PS5 Upload - High-Speed File Transfer"
FontSize="24"
FontWeight="Bold"
Foreground="#007ACC"/>
<TextBlock Text="By Manos"
FontSize="12"
Foreground="#999999"
Margin="0,5,0,0"/>
</StackPanel>
</StackPanel>
<!-- Connection Panel -->
<Border Grid.Row="1"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="4"
Padding="15"
Margin="0,0,0,15">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="PS5 IP Address:"
VerticalAlignment="Center"
Margin="0,0,10,0"/>
<TextBox Grid.Column="1"
x:Name="IpAddressTextBox"
Text="192.168.0.160"
VerticalAlignment="Center"
Margin="0,0,10,0"/>
<Button Grid.Column="2"
x:Name="ConnectButton"
Content="Connect"
Click="ConnectButton_Click"
Width="100"
Margin="0,0,10,0"/>
<StackPanel Grid.Column="3"
Orientation="Horizontal"
VerticalAlignment="Center">
<Ellipse x:Name="StatusIndicator"
Width="12"
Height="12"
Fill="#DC3545"
Margin="0,0,8,0"/>
<TextBlock x:Name="StatusText"
Text="Disconnected"
Foreground="#999999"/>
</StackPanel>
</Grid>
</Border>
<!-- Main Content -->
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="300"/>
</Grid.ColumnDefinitions>
<!-- Local Files -->
<Border Grid.Column="0"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Background="#2D2D30"
Padding="10"
BorderBrush="#3E3E42"
BorderThickness="0,0,0,1">
<TextBlock Text="📁 Local Files"
FontSize="16"
FontWeight="SemiBold"/>
</Border>
<ListBox Grid.Row="1"
x:Name="LocalFilesListBox"
BorderThickness="0"
AllowDrop="True"
Drop="LocalFilesListBox_Drop"
DragEnter="LocalFilesListBox_DragEnter"
MouseRightButtonUp="LocalFilesListBox_RightClick">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="{Binding Icon}"
FontSize="16"
Margin="0,0,10,0"/>
<TextBlock Text="{Binding Name}"
VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="🗑️ Remove" Click="RemoveLocalFile_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<StackPanel Grid.Row="2"
Orientation="Horizontal"
Margin="10"
HorizontalAlignment="Center">
<Button Content="Browse Files"
Click="BrowseFilesButton_Click"
Margin="0,0,5,0"/>
<Button Content="Browse Folder"
Click="BrowseFolderButton_Click"
Margin="0,0,5,0"/>
<Button Content="Clear All"
Click="ClearLocalFiles_Click"
Background="#DC3545"/>
</StackPanel>
</Grid>
</Border>
<!-- PS5 Files -->
<Border Grid.Column="2"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Background="#2D2D30"
Padding="10"
BorderBrush="#3E3E42"
BorderThickness="0,0,0,1">
<TextBlock Text="🎮 PS5 Files"
FontSize="16"
FontWeight="SemiBold"/>
</Border>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
Margin="10"
Background="#2D2D30">
<TextBlock Text="Current Path:"
VerticalAlignment="Center"
Margin="0,0,10,0"/>
<TextBox x:Name="CurrentPathTextBox"
Text="/data"
Width="200"
VerticalAlignment="Center"
Margin="0,0,10,0"/>
<Button Content="Go"
Click="GoButton_Click"
Width="60"/>
</StackPanel>
<ListBox Grid.Row="2"
x:Name="PS5FilesListBox"
BorderThickness="0"
MouseDoubleClick="PS5FilesListBox_MouseDoubleClick">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="📝 Rename" Click="RenameMenuItem_Click"/>
<MenuItem Header="📋 Copy" Click="CopyMenuItem_Click"/>
<MenuItem Header="✂️ Move" Click="MoveMenuItem_Click"/>
<Separator/>
<MenuItem Header="🗑️ Delete" Click="DeleteMenuItem_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5">
<TextBlock Text="{Binding Icon}"
FontSize="16"
Margin="0,0,10,0"/>
<StackPanel>
<TextBlock Text="{Binding Name}"
FontWeight="SemiBold"/>
<TextBlock Text="{Binding SizeText}"
FontSize="11"
Foreground="#999999"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="3"
Margin="10">
<TextBlock x:Name="StorageInfoText"
Text="Storage: --"
FontSize="12"
Foreground="#999999"
HorizontalAlignment="Center"/>
</StackPanel>
</Grid>
</Border>
<!-- Log Panel -->
<Border Grid.Column="4"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Background="#2D2D30"
Padding="10"
BorderBrush="#3E3E42"
BorderThickness="0,0,0,1">
<TextBlock Text="📋 Debug Log"
FontSize="16"
FontWeight="SemiBold"/>
</Border>
<TextBox Grid.Row="1"
x:Name="LogTextBox"
Text=""
FontFamily="Consolas"
FontSize="11"
Foreground="#CCCCCC"
Background="#1E1E1E"
BorderThickness="0"
Padding="10"
TextWrapping="Wrap"
IsReadOnly="True"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"/>
<StackPanel Grid.Row="2"
Orientation="Horizontal"
Margin="10"
HorizontalAlignment="Center">
<Button Content="📋 Copy Log"
Click="CopyLogButton_Click"
Margin="0,0,10,0"
Background="#28A745"/>
<Button Content="Clear Log"
Click="ClearLogButton_Click"
Background="#3E3E42"/>
</StackPanel>
</Grid>
</Border>
</Grid>
<!-- Upload Progress -->
<Border Grid.Row="3"
Background="#252526"
BorderBrush="#3E3E42"
BorderThickness="1"
CornerRadius="4"
Padding="15"
Margin="0,15,0,0"
x:Name="ProgressPanel"
Visibility="Collapsed">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Files Remaining Counter -->
<TextBlock Grid.Row="0"
x:Name="FilesRemainingText"
Text="Files: 0 / 0 (0 remaining)"
FontSize="13"
FontWeight="SemiBold"
Foreground="#FFC107"
Margin="0,0,0,8"/>
<!-- Total Folder Progress -->
<TextBlock Grid.Row="1"
x:Name="TotalProgressText"
Text="Total: 0 / 0 files"
FontSize="14"
FontWeight="SemiBold"
Foreground="#28A745"
Margin="0,0,0,5"/>
<ProgressBar Grid.Row="2"
x:Name="TotalProgressBar"
Height="20"
Minimum="0"
Maximum="100"
Value="0"
Foreground="#17A2B8"
Background="#2D2D30"
BorderBrush="#3E3E42"
Margin="0,0,0,10"/>
<!-- Current File -->
<TextBlock Grid.Row="3"
x:Name="UploadFileNameText"
Text="Uploading: filename.bin"
FontSize="13"
Margin="0,0,0,5"/>
<ProgressBar Grid.Row="4"
x:Name="UploadProgressBar"
Height="20"
Minimum="0"
Maximum="100"
Value="0"
Foreground="#28A745"
Background="#2D2D30"
BorderBrush="#3E3E42"/>
<!-- Speed and Progress -->
<Grid Grid.Row="5" Margin="0,8,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
x:Name="UploadSpeedText"
Text="Speed: 0 MB/s | Avg: 0 MB/s"
FontSize="12"
Foreground="#999999"/>
<TextBlock Grid.Column="1"
x:Name="UploadProgressText"
Text="0 / 0 MB (0%)"
FontSize="12"
Foreground="#999999"/>
</Grid>
<!-- ETA -->
<TextBlock Grid.Row="6"
x:Name="UploadETAText"
Text="ETA: Calculating..."
FontSize="12"
Foreground="#999999"
Margin="0,5,0,0"/>
</Grid>
</Border>
<!-- Upload Buttons -->
<Grid Grid.Row="4" Margin="0,15,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0"
x:Name="UploadButton"
Content="⬆️ Upload to PS5"
Click="UploadButton_Click"
Height="45"
FontSize="16"
FontWeight="SemiBold"
IsEnabled="False"/>
<Button Grid.Column="2"
x:Name="CancelButton"
Content="❌ Cancel"
Click="CancelButton_Click"
Height="45"
FontSize="16"
FontWeight="SemiBold"
Background="#DC3545"
IsEnabled="False"/>
</Grid>
</Grid>
</Window>
File diff suppressed because it is too large. Load diff
-29
View File
@@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<AssemblyName>PS5Upload</AssemblyName>
<RootNamespace>PS5Upload</RootNamespace>
<Version>1.0.0</Version>
<Authors>Manos</Authors>
<Description>High-Speed File Upload Tool for PS5</Description>
<Copyright>Copyright © 2026 Manos</Copyright>
<Nullable>enable</Nullable>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishReadyToRun>true</PublishReadyToRun>
<ApplicationIcon>ps5_logo_fixed.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Resource Include="ps5_logo.png" />
<None Include="ps5_logo.ico">
<Link>ps5_logo.ico</Link>
</None>
</ItemGroup>
</Project>
-529
View File
@@ -1,529 +0,0 @@
using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace PS5Upload
{
// Protocol commands
public enum Command : byte
{
Ping = 0x01,
ListStorage = 0x02,
ListDir = 0x03,
CreateDir = 0x04,
DeleteFile = 0x05,
DeleteDir = 0x06,
Rename = 0x07,
CopyFile = 0x08,
MoveFile = 0x09,
StartUpload = 0x10,
UploadChunk = 0x11,
EndUpload = 0x12,
Shutdown = 0xFF
}
// Protocol responses
public enum Response : byte
{
Ok = 0x01,
Error = 0x02,
Data = 0x03,
Ready = 0x04,
Progress = 0x05
}
public class PS5Protocol : IDisposable
{
private TcpClient? _client;
private NetworkStream? _stream;
private const int BufferSize = 32 * 1024 * 1024; // 32MB for maximum throughput
public bool IsConnected => _client?.Connected ?? false;
public async Task<bool> ConnectAsync(string ipAddress, int port = 9113)
{
try
{
_client = new TcpClient();
_client.ReceiveBufferSize = 64 * 1024 * 1024; // 64MB for maximum TCP throughput
_client.SendBufferSize = 64 * 1024 * 1024; // 64MB for maximum TCP throughput
_client.NoDelay = true;
_client.LingerState = new System.Net.Sockets.LingerOption(false, 0);
// BUG FIX #1: Add 5 second timeout for connection to fail fast on wrong IP
var connectTask = _client.ConnectAsync(ipAddress, port);
var timeoutTask = Task.Delay(5000); // 5 second timeout
var completedTask = await Task.WhenAny(connectTask, timeoutTask);
if (completedTask == timeoutTask)
{
// Timeout occurred
_client?.Close();
_client?.Dispose();
_client = null;
return false;
}
// Check if connection actually succeeded
if (!_client.Connected)
{
return false;
}
_stream = _client.GetStream();
return true;
}
catch
{
_client?.Close();
_client?.Dispose();
_client = null;
return false;
}
}
public void Disconnect()
{
_stream?.Dispose();
_client?.Dispose();
_stream = null;
_client = null;
}
private async Task SendCommandAsync(Command cmd, byte[]? data = null)
{
if (_stream == null) throw new InvalidOperationException("Not connected");
byte[] header = new byte[5];
header[0] = (byte)cmd;
uint dataLen = data != null ? (uint)data.Length : 0;
BitConverter.GetBytes(dataLen).CopyTo(header, 1);
await _stream.WriteAsync(header, 0, 5);
if (data != null && data.Length > 0)
{
await _stream.WriteAsync(data, 0, data.Length);
}
}
private async Task<(Response response, byte[] data)> ReceiveResponseAsync()
{
if (_stream == null) throw new InvalidOperationException("Not connected");
byte[] header = new byte[5];
await ReadExactAsync(header, 5);
Response response = (Response)header[0];
uint dataLen = BitConverter.ToUInt32(header, 1);
byte[] data = new byte[dataLen];
if (dataLen > 0)
{
await ReadExactAsync(data, (int)dataLen);
}
return (response, data);
}
private async Task ReadExactAsync(byte[] buffer, int count, int timeoutMs = 30000)
{
if (_stream == null) throw new InvalidOperationException("Not connected");
int offset = 0;
using var cts = new CancellationTokenSource(timeoutMs);
try
{
while (offset < count)
{
int read = await _stream.ReadAsync(buffer, offset, count - offset, cts.Token);
if (read == 0) throw new IOException("Connection closed");
offset += read;
}
}
catch (OperationCanceledException)
{
throw new TimeoutException("Read timeout");
}
}
public async Task<bool> PingAsync()
{
await SendCommandAsync(Command.Ping);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public async Task<StorageInfo[]> ListStorageAsync()
{
await SendCommandAsync(Command.ListStorage);
var (response, data) = await ReceiveResponseAsync();
if (response != Response.Data) return Array.Empty<StorageInfo>();
using var ms = new MemoryStream(data);
using var br = new BinaryReader(ms);
int count = br.ReadInt32();
var result = new StorageInfo[count];
for (int i = 0; i < count; i++)
{
ushort pathLen = br.ReadUInt16();
string path = Encoding.UTF8.GetString(br.ReadBytes(pathLen));
long total = br.ReadInt64();
long free = br.ReadInt64();
result[i] = new StorageInfo { Path = path, TotalBytes = total, FreeBytes = free };
}
return result;
}
public async Task<FileEntry[]> ListDirAsync(string path)
{
byte[] pathBytes = Encoding.UTF8.GetBytes(path + "\0");
await SendCommandAsync(Command.ListDir, pathBytes);
var (response, data) = await ReceiveResponseAsync();
if (response != Response.Data) return Array.Empty<FileEntry>();
using var ms = new MemoryStream(data);
using var br = new BinaryReader(ms);
int count = br.ReadInt32();
// Handle empty directory
if (count <= 0) return Array.Empty<FileEntry>();
var result = new FileEntry[count];
for (int i = 0; i < count; i++)
{
byte type = br.ReadByte();
ushort nameLen = br.ReadUInt16();
string name = Encoding.UTF8.GetString(br.ReadBytes(nameLen));
long size = br.ReadInt64();
long timestamp = br.ReadInt64();
// Clamp timestamp to valid DateTimeOffset range
DateTime dt;
try
{
if (timestamp < -62135596800 || timestamp > 253402300799)
{
dt = DateTime.Now; // Use current time for invalid timestamps
}
else
{
dt = DateTimeOffset.FromUnixTimeSeconds(timestamp).DateTime;
}
}
catch
{
dt = DateTime.Now;
}
result[i] = new FileEntry
{
Name = name,
IsDirectory = type == 1,
Size = size,
Timestamp = dt
};
}
return result;
}
public async Task<bool> CreateDirAsync(string path)
{
byte[] pathBytes = Encoding.UTF8.GetBytes(path + "\0");
await SendCommandAsync(Command.CreateDir, pathBytes);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public async Task<bool> DeleteFileAsync(string path)
{
byte[] pathBytes = Encoding.UTF8.GetBytes(path + "\0");
await SendCommandAsync(Command.DeleteFile, pathBytes);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public event Action<string> OnProgressMessage;
public async Task<bool> DeleteDirAsync(string path)
{
byte[] pathBytes = Encoding.UTF8.GetBytes(path + "\0");
await SendCommandAsync(Command.DeleteDir, pathBytes);
// Receive initial OK response
var (response, _) = await ReceiveResponseAsync();
if (response != Response.Ok)
{
return false;
}
// Now listen for progress messages synchronously
// Keep reading until we get the final OK/ERROR response
bool deletionComplete = false;
try
{
while (!deletionComplete)
{
var (progressResponse, progressData) = await ReceiveResponseAsync();
if (progressResponse == Response.Progress)
{
string message = Encoding.UTF8.GetString(progressData).TrimEnd('\0');
OnProgressMessage?.Invoke(message);
}
else if (progressResponse == Response.Ok)
{
// Final OK response received - deletion complete
OnProgressMessage?.Invoke("🔚 Received final OK - deletion complete");
deletionComplete = true;
}
else if (progressResponse == Response.Error)
{
// Error response received
OnProgressMessage?.Invoke("❌ Received error response");
deletionComplete = true;
}
else
{
// Unexpected response - log it
OnProgressMessage?.Invoke($"⚠️ Unexpected response: {progressResponse}");
deletionComplete = true;
}
}
}
catch (Exception ex)
{
// Connection closed - log it
OnProgressMessage?.Invoke($"⚠️ Connection closed: {ex.Message}");
}
// Give server a moment to fully close the deletion thread
await Task.Delay(100);
return true;
}
public async Task<bool> RenameAsync(string oldPath, string newPath)
{
byte[] oldBytes = Encoding.UTF8.GetBytes(oldPath + "\0");
byte[] newBytes = Encoding.UTF8.GetBytes(newPath + "\0");
byte[] data = new byte[oldBytes.Length + newBytes.Length];
Array.Copy(oldBytes, 0, data, 0, oldBytes.Length);
Array.Copy(newBytes, 0, data, oldBytes.Length, newBytes.Length);
await SendCommandAsync(Command.Rename, data);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public async Task<bool> CopyFileAsync(string srcPath, string dstPath)
{
byte[] srcBytes = Encoding.UTF8.GetBytes(srcPath + "\0");
byte[] dstBytes = Encoding.UTF8.GetBytes(dstPath + "\0");
byte[] data = new byte[srcBytes.Length + dstBytes.Length];
Array.Copy(srcBytes, 0, data, 0, srcBytes.Length);
Array.Copy(dstBytes, 0, data, srcBytes.Length, dstBytes.Length);
await SendCommandAsync(Command.CopyFile, data);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public async Task<bool> MoveFileAsync(string srcPath, string dstPath)
{
byte[] srcBytes = Encoding.UTF8.GetBytes(srcPath + "\0");
byte[] dstBytes = Encoding.UTF8.GetBytes(dstPath + "\0");
byte[] data = new byte[srcBytes.Length + dstBytes.Length];
Array.Copy(srcBytes, 0, data, 0, srcBytes.Length);
Array.Copy(dstBytes, 0, data, srcBytes.Length, dstBytes.Length);
await SendCommandAsync(Command.MoveFile, data);
var (response, _) = await ReceiveResponseAsync();
return response == Response.Ok;
}
public async Task<bool> UploadFileAsync(string localPath, string remotePath, IProgress<UploadProgress>? progress = null, CancellationToken cancellationToken = default, long chunkOffset = 0, long chunkSize = 0)
{
FileInfo fileInfo = new FileInfo(localPath);
if (!fileInfo.Exists) return false;
// Determine actual upload size
long uploadSize = chunkSize > 0 ? chunkSize : fileInfo.Length;
// Send START_UPLOAD with optional chunk offset
byte[] pathBytes = Encoding.UTF8.GetBytes(remotePath);
byte[] startData = new byte[pathBytes.Length + 1 + 8 + 8]; // path + null + size + offset
Array.Copy(pathBytes, 0, startData, 0, pathBytes.Length);
BitConverter.GetBytes(fileInfo.Length).CopyTo(startData, pathBytes.Length + 1);
BitConverter.GetBytes(chunkOffset).CopyTo(startData, pathBytes.Length + 9);
await SendCommandAsync(Command.StartUpload, startData);
var (response, _) = await ReceiveResponseAsync();
if (response != Response.Ready) return false;
// Upload chunks - simple async approach
long totalSent = 0;
var startTime = DateTime.Now;
double avgSpeed = 0;
byte[] sendBuffer = new byte[5 + BufferSize];
sendBuffer[0] = (byte)Command.UploadChunk;
using (FileStream fs = new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.SequentialScan))
{
// Seek to chunk offset if specified
if (chunkOffset > 0)
{
fs.Seek(chunkOffset, SeekOrigin.Begin);
}
int chunksSent = 0;
int bytesRead;
long bytesRemaining = uploadSize;
while (bytesRemaining > 0 && (bytesRead = await fs.ReadAsync(sendBuffer, 5, (int)Math.Min(BufferSize, bytesRemaining), cancellationToken)) > 0)
{
if (cancellationToken.IsCancellationRequested) return false;
BitConverter.GetBytes((uint)bytesRead).CopyTo(sendBuffer, 1);
if (_stream == null) return false;
await _stream.WriteAsync(sendBuffer, 0, 5 + bytesRead, cancellationToken);
totalSent += bytesRead;
bytesRemaining -= bytesRead;
chunksSent++;
if (chunksSent % 5 == 0 || bytesRemaining == 0)
{
var elapsed = DateTime.Now - startTime;
double currentSpeed = elapsed.TotalSeconds > 0 ? totalSent / elapsed.TotalSeconds : 0;
avgSpeed = currentSpeed;
TimeSpan eta = currentSpeed > 0
? TimeSpan.FromSeconds(bytesRemaining / currentSpeed)
: TimeSpan.Zero;
progress?.Report(new UploadProgress
{
BytesSent = chunkOffset + totalSent,
TotalBytes = fileInfo.Length,
SpeedBytesPerSecond = currentSpeed,
AverageSpeedBytesPerSecond = avgSpeed,
ElapsedTime = elapsed,
EstimatedTimeRemaining = eta,
CurrentFileName = fileInfo.Name
});
}
}
}
// Send END_UPLOAD - fire-and-forget for maximum speed
// Don't wait for response to avoid PS5 payload bottleneck
try
{
await SendCommandAsync(Command.EndUpload);
// Immediately return success without waiting for response
// This eliminates the PS5 response handling bottleneck
return true;
}
catch
{
return true; // Assume success if connection issues
}
}
public void Dispose()
{
Disconnect();
}
}
public class StorageInfo
{
public string Path { get; set; } = "";
public long TotalBytes { get; set; }
public long FreeBytes { get; set; }
}
public class FileEntry
{
public string Name { get; set; } = "";
public bool IsDirectory { get; set; }
public long Size { get; set; }
public DateTime Timestamp { get; set; }
}
public class UploadProgress
{
public long BytesSent { get; set; }
public long TotalBytes { get; set; }
public double SpeedBytesPerSecond { get; set; }
public double AverageSpeedBytesPerSecond { get; set; }
public TimeSpan ElapsedTime { get; set; }
public TimeSpan EstimatedTimeRemaining { get; set; }
public string CurrentFileName { get; set; } = "";
// For folder progress
public int CurrentFileIndex { get; set; }
public int TotalFiles { get; set; }
public long TotalFolderBytes { get; set; }
public long TotalFolderBytesSent { get; set; }
}
// High-speed parallel uploader using multiple connections
public class ParallelUploader : IDisposable
{
private readonly string _ipAddress;
private readonly int _port;
private readonly int _connectionCount;
private const int ChunkSize = 4 * 1024 * 1024; // 4MB chunks per connection
public ParallelUploader(string ipAddress, int port = 9113, int connectionCount = 4)
{
_ipAddress = ipAddress;
_port = port;
_connectionCount = connectionCount;
}
public async Task<bool> UploadFileAsync(string localPath, string remotePath, IProgress<UploadProgress>? progress = null, CancellationToken cancellationToken = default)
{
FileInfo fileInfo = new FileInfo(localPath);
if (!fileInfo.Exists) return false;
// For small files, use single connection
if (fileInfo.Length < ChunkSize * 2)
{
using var protocol = new PS5Protocol();
if (!await protocol.ConnectAsync(_ipAddress, _port)) return false;
return await protocol.UploadFileAsync(localPath, remotePath, progress, cancellationToken);
}
// For large files, use parallel connections
// This requires server support for chunked/parallel uploads
// For now, fall back to single connection
using var proto = new PS5Protocol();
if (!await proto.ConnectAsync(_ipAddress, _port)) return false;
return await proto.UploadFileAsync(localPath, remotePath, progress, cancellationToken);
}
public void Dispose() { }
}
}
-29
View File
@@ -1,29 +0,0 @@
@echo off
echo ================================================
echo PS5 Upload Client - Building
echo By Manos
echo ================================================
echo.
echo [+] Building Windows GUI Client...
dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true /p:IncludeNativeLibrariesForSelfExtract=true
if exist "bin\Release\net6.0-windows\win-x64\publish\PS5Upload.exe" (
echo.
echo ================================================
echo [+] SUCCESS! Built PS5Upload.exe
echo ================================================
echo.
echo Location: bin\Release\net6.0-windows\win-x64\publish\PS5Upload.exe
echo.
echo Copy PS5Upload.exe to any location and run it!
) else (
echo.
echo ================================================
echo [-] BUILD FAILED
echo ================================================
echo.
echo Make sure .NET 6.0 SDK is installed:
echo https://dotnet.microsoft.com/download/dotnet/6.0
exit /b 1
)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

-160
View File
@@ -1,160 +0,0 @@
# PS5 Upload Suite - GitHub Release Package Creator
# Creates a clean, ready-to-upload ZIP file for GitHub releases
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "PS5 Upload Suite - Release Packager" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Configuration
$sourceFolder = ".\client\bin\Release\net6.0-windows\win-x64"
$payloadFile = ".\payload\ps5_upload_server.elf"
$outputZip = ".\PS5Upload-Windows-x64-v1.0.zip"
$tempFolder = ".\github_release_temp"
# Check if source folder exists
if (-not (Test-Path $sourceFolder)) {
Write-Host "[ERROR] Source folder not found: $sourceFolder" -ForegroundColor Red
Write-Host "Please build the project first!" -ForegroundColor Yellow
exit 1
}
Write-Host "[1/5] Checking source files..." -ForegroundColor Yellow
# Count files in source
$fileCount = (Get-ChildItem -Path $sourceFolder -File).Count
Write-Host " Found $fileCount files in source folder" -ForegroundColor Green
# Check for main executable
$mainExe = Join-Path $sourceFolder "PS5Upload.exe"
if (-not (Test-Path $mainExe)) {
Write-Host "[ERROR] PS5Upload.exe not found!" -ForegroundColor Red
exit 1
}
$exeSize = (Get-Item $mainExe).Length / 1MB
Write-Host " PS5Upload.exe: $([math]::Round($exeSize, 2)) MB" -ForegroundColor Green
# Check for payload
if (Test-Path $payloadFile) {
$payloadSize = (Get-Item $payloadFile).Length / 1KB
Write-Host " ps5_upload_server.elf: $([math]::Round($payloadSize, 2)) KB" -ForegroundColor Green
} else {
Write-Host " [WARN] ps5_upload_server.elf not found - will skip" -ForegroundColor Yellow
}
Write-Host ""
Write-Host "[2/5] Creating temporary folder..." -ForegroundColor Yellow
# Clean up old temp folder
if (Test-Path $tempFolder) {
Remove-Item -Path $tempFolder -Recurse -Force
}
# Create temp folder
New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null
Write-Host " Created: $tempFolder" -ForegroundColor Green
Write-Host ""
Write-Host "[3/5] Copying files..." -ForegroundColor Yellow
# Copy all files from source
Copy-Item -Path "$sourceFolder\*" -Destination $tempFolder -Recurse -Force
Write-Host " Copied $fileCount files from win-x64 build" -ForegroundColor Green
# Copy payload if exists
if (Test-Path $payloadFile) {
Copy-Item -Path $payloadFile -Destination $tempFolder -Force
Write-Host " Copied ps5_upload_server.elf" -ForegroundColor Green
}
# Create README for the release
$readmeContent = @"
# PS5 Upload Suite v1.0 - Windows x64
## What's This?
Self-contained Windows application for uploading files to PS5 console via network.
## Requirements
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN
- Network connection between PC and PS5
## Installation
1. Extract all files to a folder
2. Run PS5Upload.exe
## First Time Setup
1. Load ps5_upload_server.elf to your PS5 (via etaHEN payload injector)
2. Note the IP address shown on PS5 screen
3. Open PS5Upload.exe on Windows
4. Enter PS5 IP address
5. Click Connect
## Usage
1. Click "Browse" to select files
2. Click "Upload" to transfer to PS5
3. Files will be saved to /data/ on PS5
## Troubleshooting
- **Connection failed:** Make sure PS5 server is running and IP is correct
- **Upload failed:** Check PS5 has enough free space
- **App won't start:** Make sure all files are extracted
## Support
GitHub: https://github.com/YOUR_USERNAME/ps5_upload_suite
Issues: https://github.com/YOUR_USERNAME/ps5_upload_suite/issues
## License
MIT License - See repository for details
"@
Set-Content -Path "$tempFolder\README.txt" -Value $readmeContent -Encoding UTF8
Write-Host " Created README.txt" -ForegroundColor Green
Write-Host ""
Write-Host "[4/5] Creating ZIP archive..." -ForegroundColor Yellow
# Remove old ZIP if exists
if (Test-Path $outputZip) {
Remove-Item -Path $outputZip -Force
Write-Host " Removed old ZIP file" -ForegroundColor Yellow
}
# Create ZIP
Compress-Archive -Path "$tempFolder\*" -DestinationPath $outputZip -CompressionLevel Optimal -Force
if (Test-Path $outputZip) {
$zipSize = (Get-Item $outputZip).Length / 1MB
Write-Host " Created: $outputZip" -ForegroundColor Green
Write-Host " Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
} else {
Write-Host "[ERROR] Failed to create ZIP file!" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "[5/5] Cleaning up..." -ForegroundColor Yellow
# Remove temp folder
Remove-Item -Path $tempFolder -Recurse -Force
Write-Host " Removed temporary files" -ForegroundColor Green
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "SUCCESS!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Release package created: $outputZip" -ForegroundColor Green
Write-Host "Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host "1. Test the ZIP file locally (extract and run PS5Upload.exe)" -ForegroundColor White
Write-Host "2. Go to GitHub: https://github.com/YOUR_USERNAME/ps5_upload_suite/releases/new" -ForegroundColor White
Write-Host "3. Create new release with tag 'v1.0'" -ForegroundColor White
Write-Host "4. Upload: $outputZip" -ForegroundColor White
Write-Host "5. Publish release" -ForegroundColor White
Write-Host ""
Write-Host "Press any key to exit..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
-33
View File
@@ -1,33 +0,0 @@
@echo off
cd /d "%~dp0"
"C:\Program Files\GitHub CLI\gh.exe" release create v1.2 PS5Upload-Windows-x64-v1.2-Complete.zip --title "PS5 Upload Suite v1.2 - Complete Bug Fix" --notes "# PS5 Upload Suite v1.2 - Complete Bug Fix Release
## What's Fixed:
### CLIENT FIXES:
- Bug #1: Connection timeout reduced to 5 seconds (fast fail on wrong IP)
- Bug #2: Folder deletion timeout increased to 60 seconds
### SERVER FIXES:
- Bug #3: Async folder deletion - NO MORE TIMEOUT on large folders!
- Server responds immediately
- Deletion happens in background thread
- PS5 notification when complete
## What's Included:
- PS5Upload.exe - Windows client with bug fixes
- ps5_upload_server.elf - PS5 server with async deletion
- All dependencies included
## Installation:
1. Extract ZIP file
2. Run PS5Upload.exe on Windows
3. Upload ps5_upload_server.elf to PS5 via FTP
4. Load with etaHEN payload injector
## IMPORTANT:
You MUST update BOTH files (client and server)
## Requirements:
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN"
-122
View File
@@ -1,122 +0,0 @@
# PS5 Upload Suite v1.1 - Bug Fix Release Package Creator
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "PS5 Upload Suite v1.1 - Bug Fix Release" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Configuration
$sourceFolder = ".\client\bin\Release\net6.0-windows\win-x64"
$payloadFile = ".\payload\ps5_upload_server.elf"
$outputZip = ".\PS5Upload-Windows-x64-v1.1-BugFix.zip"
$tempFolder = ".\github_release_v1.1_temp"
Write-Host "[INFO] Bug Fixes in v1.1:" -ForegroundColor Yellow
Write-Host " 1. Connection timeout: 5 seconds (fast fail on wrong IP)" -ForegroundColor Green
Write-Host " 2. Folder deletion timeout: 60 seconds (handles large folders)" -ForegroundColor Green
Write-Host ""
# Check if source folder exists
if (-not (Test-Path $sourceFolder)) {
Write-Host "[ERROR] Source folder not found: $sourceFolder" -ForegroundColor Red
exit 1
}
Write-Host "[1/5] Checking source files..." -ForegroundColor Yellow
$fileCount = (Get-ChildItem -Path $sourceFolder -File).Count
Write-Host " Found $fileCount files" -ForegroundColor Green
# Clean up old temp folder
if (Test-Path $tempFolder) {
Remove-Item -Path $tempFolder -Recurse -Force
}
Write-Host ""
Write-Host "[2/5] Creating temporary folder..." -ForegroundColor Yellow
New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null
Write-Host ""
Write-Host "[3/5] Copying files..." -ForegroundColor Yellow
Copy-Item -Path "$sourceFolder\*" -Destination $tempFolder -Recurse -Force
Write-Host " Copied $fileCount files" -ForegroundColor Green
if (Test-Path $payloadFile) {
Copy-Item -Path $payloadFile -Destination $tempFolder -Force
Write-Host " Copied ps5_upload_server.elf" -ForegroundColor Green
}
# Create CHANGELOG
$changelogContent = @"
# PS5 Upload Suite v1.1 - Bug Fix Release
## What's Fixed:
### Bug #1: Connection Timeout
- **Problem:** Application took 30+ seconds to detect wrong IP address
- **Fix:** Added 5-second timeout for connection attempts
- **Result:** Fast failure on incorrect IP - immediate feedback
### Bug #2: Folder Deletion Timeout
- **Problem:** Deleting large game folders caused timeout errors
- **Fix:** Increased timeout to 60 seconds for folder operations
- **Result:** Successfully handles large folders (10GB+ games)
## Installation:
Same as v1.0 - extract and run PS5Upload.exe
## Upgrading from v1.0:
Simply replace your old PS5Upload.exe with the new one.
No other changes needed.
## Requirements:
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN
- Network connection
## Support:
GitHub: https://github.com/YOUR_USERNAME/ps5_upload_suite
"@
Set-Content -Path "$tempFolder\CHANGELOG.txt" -Value $changelogContent -Encoding UTF8
Write-Host " Created CHANGELOG.txt" -ForegroundColor Green
Write-Host ""
Write-Host "[4/5] Creating ZIP archive..." -ForegroundColor Yellow
if (Test-Path $outputZip) {
Remove-Item -Path $outputZip -Force
}
Compress-Archive -Path "$tempFolder\*" -DestinationPath $outputZip -CompressionLevel Optimal -Force
if (Test-Path $outputZip) {
$zipSize = (Get-Item $outputZip).Length / 1MB
Write-Host " Created: $outputZip" -ForegroundColor Green
Write-Host " Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
} else {
Write-Host "[ERROR] Failed to create ZIP!" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "[5/5] Cleaning up..." -ForegroundColor Yellow
Remove-Item -Path $tempFolder -Recurse -Force
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "SUCCESS!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Release package created: $outputZip" -ForegroundColor Green
Write-Host "Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
Write-Host ""
Write-Host "Bug Fixes:" -ForegroundColor Yellow
Write-Host " [FIXED] Connection timeout: 5 seconds" -ForegroundColor Green
Write-Host " [FIXED] Folder deletion timeout: 60 seconds" -ForegroundColor Green
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Yellow
Write-Host "1. Test locally: Extract and run PS5Upload.exe" -ForegroundColor White
Write-Host "2. Upload to GitHub as v1.1 release" -ForegroundColor White
Write-Host "3. Tag: v1.1" -ForegroundColor White
Write-Host ""
-199
View File
@@ -1,199 +0,0 @@
# PS5 Upload Suite v1.2 - Complete Bug Fix Release
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "PS5 Upload Suite v1.2 - Complete Fix" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Configuration
$sourceFolder = ".\client\bin\Release\net6.0-windows\win-x64"
$payloadFile = ".\payload\ps5_upload_server.elf"
$outputZip = ".\PS5Upload-Windows-x64-v1.2-Complete.zip"
$tempFolder = ".\github_release_v1.2_temp"
Write-Host "[INFO] Bug Fixes in v1.2:" -ForegroundColor Yellow
Write-Host " CLIENT:" -ForegroundColor Cyan
Write-Host " 1. Connection timeout: 5 seconds (fast fail on wrong IP)" -ForegroundColor Green
Write-Host " 2. Folder deletion timeout: 60 seconds client-side" -ForegroundColor Green
Write-Host " SERVER:" -ForegroundColor Cyan
Write-Host " 3. Async folder deletion (no more timeout on large folders!)" -ForegroundColor Green
Write-Host ""
# Check files
if (-not (Test-Path $sourceFolder)) {
Write-Host "[ERROR] Client folder not found!" -ForegroundColor Red
exit 1
}
if (-not (Test-Path $payloadFile)) {
Write-Host "[ERROR] Server payload not found!" -ForegroundColor Red
exit 1
}
Write-Host "[1/5] Checking files..." -ForegroundColor Yellow
$fileCount = (Get-ChildItem -Path $sourceFolder -File).Count
$payloadSize = (Get-Item $payloadFile).Length / 1KB
Write-Host " Client files: $fileCount" -ForegroundColor Green
Write-Host " Server payload: $([math]::Round($payloadSize, 2)) KB" -ForegroundColor Green
# Clean up
if (Test-Path $tempFolder) {
Remove-Item -Path $tempFolder -Recurse -Force
}
Write-Host ""
Write-Host "[2/5] Creating package..." -ForegroundColor Yellow
New-Item -ItemType Directory -Path $tempFolder -Force | Out-Null
Write-Host ""
Write-Host "[3/5] Copying files..." -ForegroundColor Yellow
Copy-Item -Path "$sourceFolder\*" -Destination $tempFolder -Recurse -Force
Write-Host " Copied client files" -ForegroundColor Green
Copy-Item -Path $payloadFile -Destination $tempFolder -Force
Write-Host " Copied server payload" -ForegroundColor Green
# Create detailed changelog
$changelogContent = @"
# PS5 Upload Suite v1.2 - Complete Bug Fix Release
## What's Fixed:
### CLIENT FIXES:
#### Bug #1: Connection Timeout
- **Problem:** Application took 30+ seconds to detect wrong IP address
- **Fix:** Added 5-second connection timeout
- **Result:** Immediate feedback on connection failure
#### Bug #2: Client-Side Timeout
- **Problem:** Client timeout on folder operations
- **Fix:** Increased client timeout to 60 seconds
- **Result:** Better handling of server operations
### SERVER FIXES:
#### Bug #3: Folder Deletion Timeout (MAJOR FIX!)
- **Problem:** Deleting large game folders (10GB+) caused "Read timeout" error
- **Fix:** Folder deletion now runs asynchronously in background thread
- **How it works:**
1. Server responds immediately: "Deleting folder in background..."
2. Deletion happens in separate thread
3. PS5 notification appears when complete
- **Result:** NO MORE TIMEOUT! Works with any folder size!
## Installation:
1. Extract ZIP file
2. Run PS5Upload.exe on Windows
3. Upload ps5_upload_server.elf to PS5 (via FTP or USB)
4. Load ps5_upload_server.elf with etaHEN payload injector
5. Connect and enjoy!
## Upgrading from v1.0/v1.1:
Replace both:
- PS5Upload.exe (Windows client)
- ps5_upload_server.elf (PS5 server)
IMPORTANT: You MUST update BOTH files for the fixes to work!
## Testing the Fixes:
1. **Connection timeout:** Try wrong IP - should fail in 5 seconds
2. **Folder deletion:** Delete large game folder - should work without timeout
## Requirements:
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN
- Network connection
## Support:
GitHub: https://github.com/YOUR_USERNAME/ps5_upload_suite
Issues: Report bugs on GitHub Issues page
---
**Version:** 1.2
**Release Date:** January 12, 2026
**Build:** Complete Bug Fix Release
"@
Set-Content -Path "$tempFolder\CHANGELOG_v1.2.txt" -Value $changelogContent -Encoding UTF8
Write-Host " Created CHANGELOG_v1.2.txt" -ForegroundColor Green
# Create quick start guide
$quickStartContent = @"
# PS5 Upload Suite v1.2 - Quick Start
## Step 1: Load Server on PS5
1. Copy ps5_upload_server.elf to USB drive
2. Insert USB into PS5
3. Open etaHEN payload injector
4. Load ps5_upload_server.elf
5. Note the IP address shown on screen
## Step 2: Connect from Windows
1. Run PS5Upload.exe
2. Enter PS5 IP address
3. Click Connect
4. You're ready!
## Step 3: Upload Files
1. Click "Browse Folder" to select files
2. Click "Upload" to transfer
3. Files appear in /data/etaHEN/games on PS5
## Deleting Large Folders:
- Now works perfectly with async deletion!
- Server responds immediately
- Deletion happens in background
- PS5 notification when complete
Enjoy! 🎮
"@
Set-Content -Path "$tempFolder\QUICK_START.txt" -Value $quickStartContent -Encoding UTF8
Write-Host " Created QUICK_START.txt" -ForegroundColor Green
Write-Host ""
Write-Host "[4/5] Creating ZIP..." -ForegroundColor Yellow
if (Test-Path $outputZip) {
Remove-Item -Path $outputZip -Force
}
Compress-Archive -Path "$tempFolder\*" -DestinationPath $outputZip -CompressionLevel Optimal -Force
if (Test-Path $outputZip) {
$zipSize = (Get-Item $outputZip).Length / 1MB
Write-Host " Created: $outputZip" -ForegroundColor Green
Write-Host " Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
} else {
Write-Host "[ERROR] Failed to create ZIP!" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "[5/5] Cleaning up..." -ForegroundColor Yellow
Remove-Item -Path $tempFolder -Recurse -Force
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "SUCCESS!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Release: $outputZip" -ForegroundColor Green
Write-Host "Size: $([math]::Round($zipSize, 2)) MB" -ForegroundColor Green
Write-Host ""
Write-Host "Bug Fixes Applied:" -ForegroundColor Yellow
Write-Host " [CLIENT] Connection timeout: 5 seconds" -ForegroundColor Green
Write-Host " [CLIENT] Folder deletion timeout: 60 seconds" -ForegroundColor Green
Write-Host " [SERVER] Async folder deletion (NO MORE TIMEOUT!)" -ForegroundColor Green
Write-Host ""
Write-Host "IMPORTANT: Update BOTH client and server!" -ForegroundColor Yellow
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Cyan
Write-Host "1. Test locally" -ForegroundColor White
Write-Host "2. Upload ps5_upload_server.elf to PS5" -ForegroundColor White
Write-Host "3. Load with etaHEN" -ForegroundColor White
Write-Host "4. Test folder deletion with large folder" -ForegroundColor White
Write-Host "5. Upload to GitHub as v1.2" -ForegroundColor White
Write-Host ""
-30
View File
@@ -1,30 +0,0 @@
#!/bin/bash
echo "================================================"
echo "PS5 Upload Server - Compilation"
echo "By Manos"
echo "================================================"
echo ""
echo "[+] Compiling..."
rm -f ps5_upload_server.elf
/home/hackman/ps5sdk_copy/bin/prospero-clang -Wall -O3 -pthread -o ps5_upload_server.elf main.c
if [ -f "ps5_upload_server.elf" ]; then
echo ""
echo "================================================"
echo "[+] SUCCESS! Compiled ps5_upload_server.elf"
echo "================================================"
echo ""
ls -lh ps5_upload_server.elf
file ps5_upload_server.elf
echo ""
echo "Upload to PS5 and run with elfldr"
echo "Server will listen on port 9113"
else
echo ""
echo "================================================"
echo "[-] COMPILATION FAILED"
echo "================================================"
exit 1
fi
-1187
View File
File diff suppressed because it is too large. Load diff
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

-195
View File
@@ -1,195 +0,0 @@
#!/usr/bin/env python3
"""
GitHub Release Uploader for PS5 Upload Suite
Uploads v1.2 release to GitHub using GitHub API
"""
import os
import sys
import json
import requests
from pathlib import Path
# GitHub Configuration
GITHUB_TOKEN = "YOUR_GITHUB_TOKEN_HERE" # Replace with your token
GITHUB_REPO = "manos555555/PS5-Upload-Suite"
RELEASE_TAG = "v1.2"
RELEASE_NAME = "PS5 Upload Suite v1.2 - Complete Bug Fix"
RELEASE_BODY = """# PS5 Upload Suite v1.2 - Complete Bug Fix Release
## 🐛 What's Fixed:
### CLIENT FIXES:
- **Bug #1:** Connection timeout reduced to 5 seconds (fast fail on wrong IP)
- **Bug #2:** Folder deletion timeout increased to 60 seconds
### SERVER FIXES:
- **Bug #3:** Async folder deletion - NO MORE TIMEOUT on large folders! ✅
- Server responds immediately
- Deletion happens in background thread
- PS5 notification when complete
## 📦 What's Included:
- `PS5Upload.exe` - Windows client with bug fixes
- `ps5_upload_server.elf` - PS5 server with async deletion
- All dependencies included
- Self-contained (no .NET installation required)
## 🚀 Installation:
1. Extract ZIP file
2. Run `PS5Upload.exe` on Windows
3. Upload `ps5_upload_server.elf` to PS5 via FTP
4. Load with etaHEN payload injector
5. Connect and enjoy!
## ⚠️ IMPORTANT:
**You MUST update BOTH files:**
- Windows client: `PS5Upload.exe`
- PS5 server: `ps5_upload_server.elf`
## 💡 Testing:
- **Connection timeout:** Try wrong IP - fails in 5 seconds
- **Folder deletion:** Delete large game folder - works without timeout!
## 📋 Requirements:
- Windows 10/11 (64-bit)
- PS5 with etaHEN 2.0+ or GoldHEN
- Network connection
## 🔗 Links:
- [Report Issues](https://github.com/manos555555/PS5-Upload-Suite/issues)
- [Documentation](https://github.com/manos555555/PS5-Upload-Suite/blob/main/README.md)
---
**Version:** 1.2
**Release Date:** January 12, 2026
**Build:** Complete Bug Fix Release
"""
def create_github_release(token, repo, tag, name, body):
"""Create a GitHub release"""
url = f"https://api.github.com/repos/{repo}/releases"
headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json"
}
data = {
"tag_name": tag,
"name": name,
"body": body,
"draft": False,
"prerelease": False
}
print(f"Creating release {tag}...")
response = requests.post(url, headers=headers, json=data)
if response.status_code == 201:
print(f"✅ Release created successfully!")
return response.json()
else:
print(f"❌ Failed to create release: {response.status_code}")
print(f"Response: {response.text}")
return None
def upload_release_asset(token, upload_url, file_path):
"""Upload a file to GitHub release"""
# Remove the {?name,label} template from upload_url
upload_url = upload_url.split("{")[0]
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path) / (1024 * 1024) # MB
print(f"\nUploading {file_name} ({file_size:.2f} MB)...")
headers = {
"Authorization": f"token {token}",
"Content-Type": "application/zip"
}
params = {"name": file_name}
with open(file_path, 'rb') as f:
response = requests.post(
upload_url,
headers=headers,
params=params,
data=f
)
if response.status_code == 201:
print(f"✅ {file_name} uploaded successfully!")
return True
else:
print(f"❌ Failed to upload {file_name}: {response.status_code}")
print(f"Response: {response.text}")
return False
def main():
print("=" * 70)
print("PS5 Upload Suite - GitHub Release Uploader")
print("=" * 70)
print()
# Check token
if GITHUB_TOKEN == "YOUR_GITHUB_TOKEN_HERE":
print("❌ ERROR: Please set your GitHub token in the script!")
print()
print("To get a token:")
print("1. Go to: https://github.com/settings/tokens")
print("2. Generate new token (classic)")
print("3. Select 'repo' scope")
print("4. Copy token and paste in this script")
return 1
# Check if release file exists
release_file = Path("PS5Upload-Windows-x64-v1.2-Complete.zip")
if not release_file.exists():
print(f"❌ ERROR: Release file not found: {release_file}")
return 1
print(f"📦 Release file: {release_file}")
print(f"📊 Size: {release_file.stat().st_size / (1024*1024):.2f} MB")
print()
# Create release
release_data = create_github_release(
GITHUB_TOKEN,
GITHUB_REPO,
RELEASE_TAG,
RELEASE_NAME,
RELEASE_BODY
)
if not release_data:
return 1
# Upload asset
upload_url = release_data.get("upload_url")
if not upload_url:
print("❌ ERROR: No upload URL in release response")
return 1
success = upload_release_asset(
GITHUB_TOKEN,
upload_url,
str(release_file)
)
if success:
print()
print("=" * 70)
print("✅ SUCCESS! Release published to GitHub")
print("=" * 70)
print()
print(f"🔗 Release URL: {release_data.get('html_url')}")
print()
return 0
else:
return 1
if __name__ == "__main__":
sys.exit(main())