6 Commits
Author SHA1 Message Date
Pedro Santos c989b2e10d Merge pull request #2 from s0liton/v1.0.1-rest-mode-hotfix 2026-10-02 09:28:21 -04:00
Pedro Santos 46246c663c Hotfix for issue #1 - Re-open socket after resume from rest mode + resume toast added 2026-10-02 09:28:21 -04:00
Pedro Santos 03b58ed93b Fix the goddamn instructions...again.
Updated instructions for starting RomM Sync and removed redundant running section.
2026-10-02 02:20:07 -04:00
Pedro Santos 747a6f4393 Add library screenshot PNG 2026-10-02 02:12:49 -04:00
Pedro Santos da23045902 Enhance README with screenshot and running instructions
Added a project screenshot and running instructions to the README.
2026-10-02 02:12:00 -04:00
Pedro Santos 472331944b Clarify RomM references in README
Updated references to RomM for clarity and consistency.
2026-10-02 01:50:09 -04:00
5 changed files with 92 additions and 27 deletions

No files matched your search

+5 -4
View File
@@ -1,5 +1,7 @@
# RomM Sync for PS5
![Project Screenshot](assets/library.png)
A [RomM](https://romm.app) companion client for jailbroken PS5 consoles (etaHEN + kstuff). Through my insatiable need to mod everything electronic I encounter, I had my 12.70 PS5 jailbroken the minute that P2JB was out. I maintain a RomM server to centralize all my _legal_ ROMs, saves, and savestates which all my devices sync with, and the PS5 needs similar treatment.
- **Background save sync**
@@ -15,7 +17,7 @@ Technically, this RomM client will work with all emulators, but the PS5 is curre
## PS4/PS5 Games
If you are interested in downloading PS4 and PS5 games from your RomM server, the server has direct FPKGi support, simply add it as a library. This sync client does NOT handle PS4/PS5 save syncing at this time, but is being researched for potential future inclusion.
If you are interested in downloading PS4 and PS5 games from your RomM server, RomM has direct FPKGi support, simply add it as a library. This sync client does NOT handle PS4/PS5 save syncing at this time, but is being researched for potential future inclusion.
## Requirements
@@ -31,9 +33,8 @@ If you are interested in downloading PS4 and PS5 games from your RomM server, th
nc -w 1 <ps5-ip> 9021 < romm-sync.elf
```
3. A RomM Sync tile appears on the home screen after about 30 seconds. Open it, or go to `http://<ps5-ip>:8780` from another device.
4. Complete setup.
To start RomM Sync with the console, copy the payload to etaHEN's autostart folder. You can do this from the last setup step, or with `make install PS5_HOST=<ps5-ip>` if you build it yourself.
To start RomM Sync with the console, copy the payload to etaHEN's autostart folder or use the autoloader. You can do this from the last setup step, or with `make install PS5_HOST=<ps5-ip>` if you build it yourself.
If your RomM server uses HTTPS, copy `cacert.pem` from the release to `/data/romm-sync/cacert.pem`.
@@ -56,7 +57,7 @@ LRPS2 keeps every game on one shared memory card by default. RomM stores saves p
- **One card per game.** Works with any RomM version. In RetroArch, open the LRPS2 core options and turn off _Shared Memory Cards_. After that, each game's card syncs like any other save. Saves already on the shared card stay there.
- **Back up the shared card.** Needs RomM 5.3.0 or newer. The whole card is uploaded when it changes, and you can restore it from Settings. It isn't merged with other devices.
PSP, GameCube and Wii saves are synced as one zip per game, the same format other RomM clients use.
PSP, GameCube and Wii saves are synced as one zip per game, the same format other RomM clients use. Depending on the client, they may or may not support unzipping the saves (I don't truly know), but this client does!
## Emulator Profiles
Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

+25 -2
View File
@@ -22,6 +22,12 @@
#include "web.h"
#define MONITOR_INTERVAL_SEC 3
/* The loop ticks every few seconds, so a longer gap means the console slept. */
#define RESUME_GAP_SEC 60
/* Ticks to wait for the network after waking before notifying anyway. */
#define RESUME_NOTIFY_TICKS 10
/* Both resume signals usually fire on the same wake; notify only once. */
#define RESUME_NOTIFY_QUIET_SEC 120
/* System apps, the browser and our own tile don't count as games. */
static int is_game_title(const char *t) {
@@ -112,11 +118,28 @@ int main(void) {
sync_request("startup");
char current[32] = "";
time_t game_start = 0, exit_at = 0, now;
int have_title = 1;
time_t game_start = 0, exit_at = 0, now, last_tick = time(NULL), resume_notified = 0;
int have_title = 1, resume_ticks = 0;
for (;;) {
sleep(MONITOR_INTERVAL_SEC);
now = time(NULL);
int resumed = 0;
if (now - last_tick > RESUME_GAP_SEC) {
LOGI("resumed from rest mode after %lds", (long)(now - last_tick));
resumed = 1;
}
if (web_take_reopened()) resumed = 1;
last_tick = now;
if (resumed && !resume_ticks && now - resume_notified > RESUME_NOTIFY_QUIET_SEC)
resume_ticks = RESUME_NOTIFY_TICKS;
if (resume_ticks > 0) {
plat_local_ip(ip, sizeof ip);
if (ip[0] || --resume_ticks == 0) {
resume_ticks = 0;
resume_notified = now;
plat_notify("RomM Sync resumed - http://%s:%d", ip[0] ? ip : "127.0.0.1", port);
}
}
char title[32] = "";
int fg = have_title ? plat_running_title(title, sizeof title) : -1;
+59 -21
View File
@@ -622,23 +622,7 @@ static void *conn_thread(void *arg) {
return NULL;
}
static void *accept_thread(void *arg) {
int srv = (int)(long)arg;
for (;;) {
int fd = accept(srv, NULL, NULL);
if (fd < 0) {
if (errno == EINTR) continue;
LOGE("accept failed: %s", strerror(errno));
sleep(1);
continue;
}
if (thread_start(conn_thread, (void *)(long)fd) != 0) close(fd);
}
return NULL;
}
int web_start(int port) {
g_started = time(NULL);
static int open_listener(int port) {
int srv = socket(AF_INET, SOCK_STREAM, 0);
if (srv < 0) return -1;
int one = 1;
@@ -649,11 +633,65 @@ int web_start(int port) {
a.sin_port = htons((uint16_t)port);
a.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(srv, (struct sockaddr *)&a, sizeof a) != 0 || listen(srv, 16) != 0) {
LOGE("cannot listen on port %d: %s", port, strerror(errno));
int err = errno;
close(srv);
errno = err;
return -1;
}
thread_start(accept_thread, (void *)(long)srv);
LOGI("web UI listening on port %d", port);
return 0;
return srv;
}
static int g_port, g_srv = -1, g_reopened;
int web_take_reopened(void) {
return __atomic_exchange_n(&g_reopened, 0, __ATOMIC_SEQ_CST);
}
/* Issue #1 - Rest mode tears down the console's sockets, and the listener never accepts
* again after wake-up. When accept keeps failing, open a fresh listener (ftpsrv
* does the same). A single failure (an aborted connection, running out of fds)
* is not enough, or we would announce a resume that never happened. */
#define ACCEPT_FAILS_BEFORE_REOPEN 3
static void *accept_thread(void *arg) {
(void)arg;
int fails = 0;
for (;;) {
if (g_srv < 0) {
g_srv = open_listener(g_port);
if (g_srv < 0) {
sleep(3);
continue;
}
LOGI("web UI listening again on port %d", g_port);
__atomic_store_n(&g_reopened, 1, __ATOMIC_SEQ_CST);
}
int fd = accept(g_srv, NULL, NULL);
if (fd < 0) {
if (errno == EINTR) continue;
if (++fails < ACCEPT_FAILS_BEFORE_REOPEN) {
LOGW("accept failed: %s", strerror(errno));
usleep(250 * 1000);
continue;
}
LOGW("accept failed (%s), reopening the listener", strerror(errno));
close(g_srv);
g_srv = -1;
fails = 0;
continue;
}
fails = 0;
if (thread_start(conn_thread, (void *)(long)fd) != 0) close(fd);
}
return NULL;
}
int web_start(int port) {
g_started = time(NULL);
g_port = port;
g_srv = open_listener(port);
if (g_srv < 0) LOGE("cannot listen on port %d: %s; retrying", port, strerror(errno));
else LOGI("web UI listening on port %d", port);
thread_start(accept_thread, NULL);
return g_srv < 0 ? -1 : 0;
}
+3
View File
@@ -7,4 +7,7 @@ int web_start(int port);
/* Foreground title shown on the status page. */
void web_set_foreground(const char *title_id);
/* 1 once after the listener had to be reopened (e.g. after rest mode), else 0. */
int web_take_reopened(void);
#endif