It's an alternative implementation of original ps3netsrv which needed to install games using WebMAN/IrisMAN over network (without copying files to console).
I made it because original code is way hard to read and hard to build for some platforms. And for fun and education (understanding and implementation custom network protocols, generating/serving iso image on-the-fly) of course.
This project written in Go because it's (cross-)compilation is much easier than C/C++ and resulting binaries will run without any external library on target system.
- Write protection. Enabled by default, use flag
--allow-writeor corresponding parameter. - TCP data exchange timeouts / auto-close of idle connections: configured by
--read-timeoutparameter. - Compressed images - save your disk space without filesystem-level compression.
- Socket activation - run service on-demand, only when client (console) connects.
- Natively runs as Windows Service
- Built-in protocol client. See
clientsubcommand.
- Simple file transfer / directory listing
- File streaming including game images in
PS3ISO - PSX images streaming
- Client addresses whitelist, capping amount of connections
- Virtual ISO: games in directory format (residing in
GAMES). - 3k3y/Redump images: if iso path is
<root>/PS3ISO/game.isothan dedicated key expected at<root>/PS3ISO/game.dkeyor at<root>/REDKEY/game.dkey - "Search remote subfolders" WebMAN feature
- Drag-N-Drop directory to an executable to create an iso image like in original ps3netsrv
- Multipart files
*.666xx - Virtual linked directories (
.inifile with path instead of directory). IMHO it's absolutely pointless feature. On *nix systems symlinks or bind-mounts can be used. On Windows symlinks and junctions can do the same thing.
ps3netsrv-go supports compressed images to help save disk space. Currently following formats are supported:
CHD is a format for space-efficient lossless compression that preserves ability to randomly access data without full decompression of whole file. Originally developed as part of MAME but today used in many emulators: ScePSX, Duckstation, PCSX2 and others. Space-efficiency is achieved by combining multiple comression algorithms to different data types (audio, data, ...) inside a raw disk image.
Powered by:
- libchdr - a C-library used to read and decompress CHD files
- purego - a loader that allows to call functions in a dynamically-loaded shared libraries without CGO.
- zig cc - C toolchain with fantastic cross-compilation abilities.
Important
webMAN MOD version must be at least 1.47.48q
libchdr is required to be installed on the system. See Installation for more details how to do this.
Just put your .chd images into necessary directory under server root: PSXISO, PS2ISO or even PS3ISO.
In case of successful libchdr loading you will see a following log message on server start:
Mar 23 00:00:00.000 INF libchdr loaded, enabling chd support
Use chdman tool maintained by MAME to compress your existing images.
- PS1 (PSX) images: tested and working ✅ (kudos to @turbosagat for assistance)
- PS2 images: tested and working ✅ (copies whole image to console without streaming, expected behaviour)
- PS3 images: untested ❔ (technically should work because uses same codebase as PS1 images)
puregodoes not work on some platforms supported by Go (i.e.aixandppc64). However, they're pretty exotic nowdays and it's highly unlikely to seeps3netsrv-gorunning on them.libchdrdoes not supportAVHuffcompression codec: rtissera/libchdr#69. However it's used mainly for laserdiscs so it's very unlikely to meet it in videogame images.- Mixed CD/non-CD codecs (
cdlzandlzma) and mixed CD modes (MODE1,MODE1/RAW, etc. in image metadata) are not supported. It's possible to create such image only by specifying-coption inchdmanand probably such images are not supported by other emulators as well.
These formats came from PSP and currently supported in multiple projects, i.e. Open PS2 Loader.
Unlike CHD these formats are pretty simple and uses only 1 or 2 compressiom algorithms to compress blocks: DEFLATE and/or LZ4. So compression ratio may be worse than one for CHD images. But these formats does not require external libraries and supproted on all platforms.
Supported formats: CSO v1, CSO v2, ZSO. No specific limitations on block size is imposed: 8K blocks are working as well as 2K blocks.
Just put your .cso or .zso images into necessary directory under server root: PSXISO, PS2ISO or even PS3ISO.
PS3 will see such images as .cso.iso or .zso.iso - server intentionally adds .iso extension to help console properly detecting a file type.
Use maxcso or any appropriate tool to compress existing images. You can play with multiple parameters and find out which ones gives a better compression.
This is basically an add-on to regular Zstandard that brings ability to randomly access data within compressed file without total decompression. It is backward-compatible to Zstandard so such archives can be unpacked by all zstd-supporting tools. Basic idea behind this format is almost similar to CSO: use zstd frames to compress blocks of original file and put frame offsets into a file.
Format specification is here.
This format is (currently) not supported by emulators. I've decided to support it because zstd is a great modern compression algotirhm that can offer good compression ratio with good compression/decompression speeds. And there's a good Go-library to read such archives.
Images may be compressed by using t2sz or Go-tool zstdseek shipped with library used to read such files.
Recommended block size is 2048 as usual. However zstdseek comes with Content-Defined Chunking (FastCDC to be more specific) and may give even better compression ratio with dynamic blocks. I've tested with 128:2048:8192 parameter and it gave a bit better results than t2zs.
Resulting .zst file may be put into necessary directory under server root: PSXISO, PS2ISO or even PS3ISO.
PS3 will see such images as .zst.iso - server intentionally adds .iso extension to help console properly detecting a file type.
This is the way to run service only if incomoming connection arrives. It may be useful if you want to lower resource usage because ps3netsrv-go
consumes some CPU and RAM even in idle (without active clients). Key components that used to run service in socket activation mode:
- Supervisor: Systemd on Linux, Launchd on MacOS or any that can pass file descriptor in via fork/exec without accepting connection.
- Ability accept connections using inherited listener. In
ps3netsrv-goit's implemented by usingfd:<id>oractivated:<name>as listen address. - Optional auto-shutdown after some idle time. In
ps3netsrv-goit's configured by--shutdown-idle-timeoutflag or corresponding env variable/config entry.
For example how to run under systemd see Systemd service or MacOS Launchd service.
This project shipped in a multiple ways for convenient installation:
- Docker images:
docker pull ghcr.io/xakep666/ps3netsrv-go.amd64andarm64images are available. - Linux packages: deb, rpm and archlinux. See Releases. If your distro is based on other package manager you may want to use a simple binary and a systemd unit.
- Archived binaries are also available in Releases.
- AOSC OS package maintained by @okamikidfc
- QNAP NAS packages (qpkg) are available at @Hirador's repo
This libarary is required to enable CHD images support. It's included in a following release types:
- Docker: present in a container image, should work out of the box
- Release archive: contains compiled version of library except Windows/arm64 build.
libchdr is not included in Linux packages but declared as a dependancy. Most distros contain it in their repos.
If necessary, getting it compiled on Linux is pretty straightforward if you're familiar with CMake.
Server supports configuration via environment variables and command line flags.
Environment variables names can be found in output of ps3netsrv-go server --help command.
I.e. in line:
--root="." Root directory with games ($PS3NETSRV_ROOT).
PS3NETSRV_ROOT is environment variable name.
Also server supports configuration via config file. Example:
[server]
root = /home/user/games
client-whitelist = 192.168.1.0/24
max-clients = 10
allow-write = trueConfiguration keys names are the same as command line flags names without -- prefix.
Config file discovered in following order:
--configflag orPS3NETSRV_CONFIG_FILEenvironment variableconfig.inifile in current directory<user config directory>/ps3netsrv-go/config.ini, where<user config directory>is OS-specific directory for user configuration files:%APPDATA%on Windows$XDG_CONFIG_HOMEor~/.configon Linux~/Library/Application Supporton macOS
Download necessary archive from Releases, unpack it and run
$ ps3netsrv-go serverfrom your working directory to serve it.
Or specify custom root directory in --root flag of server subcommand:
$ ps3netsrv-go server --root=/home/user/gamesTo get help run:
$ ps3netsrv-go --helpTo run "debug" server (for pprof, etc.) specify --debug-server-listen-addr flag.
Recommended way to serve your directory is:
$ docker run \
-u $(id -u):$(id -g) \
-v <data directory>:/srv/ps3data \
-p 38008:38008 \
ghcr.io/xakep666/ps3netsrv-goBut note that listen address displayed in logs is not an address you can connect to because it's container internal address.
In-container persistent volume is also available in /srv/ps3data.
Deb, rpm and archlinux packages are shipped with systemd unit. Run
$ systemctl daemon-reload
$ systemctl enable ps3netsrv-go@.serviceto enable automatic startup.
Config file location is /etc/ps3netsrv-go/config.ini. Data location is /srv/ps3data. Service is running under separate user ps3netsrv. Systemd unit is templated, template is a config file name. I.e. for ps3netsrv-go@myconfig.service it will be /etc/ps3netsrv-go/myconfig.ini
If you want to run service in socket-activation mode use
$ systemctl daemon-reload
$ systemctl enable ps3netsrv-go.socketBy default it's configured to listen on port 0.0.0.0:38008 and auto-shutdown after 1 minute of idle. In this case config file path is /etc/ps3netsrv-go/activated.ini.
Launchd (system supervisor on macOS) also supports socket-activation and there is a .plist manifest in this repo to run service in socket-activation mode.
Important
purego is required to run ps3netsrv-go in socket-activation mode on macOS. So if you used nopurego tag during build service won't start.
Currently it's you need to install service manually. Installation steps:
- Build an executable or get a release
- Copy
ps3netsrv-goexecutable to/usr/local/bin - Create a root layout:
cp -R <project-root>/package/layout ~/ps3data - Place config:
mkdir -p "~/Library/Application Support/ps3netsrv-go" && cp <project-root>/package/macos/config.ini "~/Library/Application Support/ps3netsrv-go" - Place launchd manifest:
cp <project-root>/package/macos/com.xakep666.ps3netsrv-go.plist ~/Library/LaunchAgents - Enable launchd service:
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.xakep666.ps3netsrv-go.plist - Verify if it's enabled:
launchctl print gui/$(id -u)/com.xakep666.ps3netsrv-go(should print service details) - Done!
Due to usage of purego all Linux executables in releases are dynamically linked ones.
By default they're linked to run with glibc because it's most popular and widespread libc.
However, some distros like Alpine uses different libc (musl in case of Alpine).
If you try to run ps3netsrv-go executable from release directly on such distro, you'll get an error like
exec /path/to/ps3netsrv-go: no such file or directory
There are two ways to resolve this issue:
- Compile from source code for necessary libc. Recommended way. See Building for more details.
- Run with loader:
/lib/ld-musl-<arch>.so.1 /path/to/ps3netsrv-go. Downside:libchdrlikely will not be loaded so CHD support will be disabled.
To install ps3netsrv-go as Windows Service use svc install subcommand.
It requires --config flag to be set to explicitly point which config should be used.
Auto-start is disabled by default for security reasons. However it could be enabled with --auto-start flag.
There are some other subcommands in svc to control service, check out --help for detailed usage.
Nothing special is needed for the project to run on FreeBSD.
- Build an executable
- Copy
ps3netsrv-goexecutable to/usr/local/bin - Install libchdr
- (optional) Add an rc script
cp <project-root>/package/freebsd/ps3netsrv /usr/local/etc/rc.d/
mkdir -vp /var/run/ps3netsrv
mkdir -vp /usr/local/ps3netsrv
cp <project-root>/package/freebsd/config.ini /usr/local/ps3netsrv/
sysrc ps3netsrv_enable=YES- (optional) Add a special user for the rc script
pw useradd ps3 -m -s /usr/sbin/nologin -c "ps3netsrv user" -u 361- Connect your console to the network using ethernet cable. To achieve maximum performance server and console should be connected with 1Gbps network.
- Use SSD or NVMe drive to store games. It will reduce loading times.
- Use decrypted ISOs. It will reduce CPU usage and loading times. You can decrypt images using
decryptsubcommand. - Use "compiled" ISOs instead of folder with files. It will reduce loading times.
You can build ISO image using
makeisosubcommand.
- Use limits:
- strict root to prevent possible directory traversal outside provided root:
--strict-rootflag - by IP address(es) using
--client-whitelistflag:$ ps3netsrv-go server --root=/home/games --client-whitelist=192.168.0.123 - by number of clients using
--max-clientsflag - idle connection time:
--read-timeoutflag
- strict root to prevent possible directory traversal outside provided root:
- To expose over NAT (non-public or "grey" IP) you can use:
- ngrok TCP tunnels
- Reverse SSH tunnel to host with public IP
- any other options
- To secure connection using TLS you may use two TLS-terminators (like Stunnel or HAProxy) configured with mutual TLS authentication. Note that desired terminator must support "wrapping" plain TCP connection to TLS with client certificate.
$ go mod download
$ go build -o ps3netsrv-go ./cmd/ps3netsrv-go/...Important
Some platforms require extra build flags to be compiled successfully due to purego usage. See support notes for details.
To disable purego usage you can use nopurego build tag. I.e.
$ go build -tags "nopurego" -o ps3netsrv-go ./cmd/ps3netsrv-go/...If you're building for non-glibc Linux distro (like Alpine) or building on non-glibc distro for glibc-based distro (like on Alpine for Ubuntu) you need to properly specify ldso path via GO_LDSO environment variable:
GO_LDSO=/lib/ld-musl-x86_64.so.1for Alpine on x86_64 architectureGO_LDSO=/lib64/ld-linux-x86-64.so.2for any glibc-based distro (Ubuntu/Debian/Arch/...) on x86_64 architecture