Gates: test stubs for frame generation; comment wrapping; TLS and password patches renumbered 0129/0130

- tests/input_ps5_test.cpp: ps5_fg_record_request stub (the pad script's
  RECORD calls PS5_FrameGen's recorder, not linked in the host test).
- tests/test_webui_qr.py: stubs for the frame generation entries 0120 binds
  beside the WebUI's (ps5_fg_menu_is_label/_is_folder, action_ok_ps5_fg,
  action_ok_push_default).
- src/main.cpp, src/ps5_framegen_menu.c: tools/lint-format.sh --write
  (comments re-wrapped to the line limit; no code changed).
- The frame generation code already names patches 0122-0128, which
  patches/series does not list; 47879d1's TLS and password patches took
  0122/0123 and are now 0129 (TLS verification) and 0130 (password).

lint-format PASS; tests test_input_ps5, test_webui_qr, test_frontend,
test_webui_secrets: OK.
This commit is contained in:
Mihawk committed 2026-10-14 19:27:23 -04:00
1 parent 47879d118e
commit 0bca2863e6
8 files changed
+63 -38

No files matched your search

+2 -2
View File
@@ -278,6 +278,6 @@
0121 Frame generation Output Rate Auto: the video output picks the presents per game frame from the display's rate over the game's (video_framegen_auto), and frame generation is on by default.
0122 HTTPS refuses a server whose certificate does not chain to the bundled roots (cacert.h): MBEDTLS_SSL_VERIFY_REQUIRED instead of upstream's optional check whose result was ignored, so nobody on the network path can stand in for RetroAchievements.
0129 HTTPS refuses a server whose certificate does not chain to the bundled roots (cacert.h): MBEDTLS_SSL_VERIFY_REQUIRED instead of upstream's optional check whose result was ignored, so nobody on the network path can stand in for RetroAchievements.
0123 A RetroAchievements sign-in that returns a token also removes the password from /app0/config/webui.cfg (with the empty token the WebUI put beside it) and from retroarch.cfg, which keeps its token (src/ps5_cheevos.c).
0130 A RetroAchievements sign-in that returns a token also removes the password from /app0/config/webui.cfg (with the empty token the WebUI put beside it) and from retroarch.cfg, which keeps its token (src/ps5_cheevos.c).
+4 -3
View File
@@ -486,9 +486,10 @@ int main(int process_argc, char **process_argv)
setenv("RADV_THREADED_RECORDING", "1", 1);
ps5::debug::mark("radv: threaded recording on");
}
/* Testing: /app0/framegen-record-width.txt holds the width the present-stream recorder (pad script RECORD) writes its
* pictures at, 640 when absent; a wider one shows what the small pictures hide (a recording is width x height x 4 bytes a
* picture, and the pad script's count of them, in memory). */
/* Testing: /app0/framegen-record-width.txt holds the width the present-stream recorder (pad
* script RECORD) writes its pictures at, 640 when absent; a wider one shows what the small
* pictures hide (a recording is width x height x 4 bytes a picture, and the pad script's count
* of them, in memory). */
if (std::FILE *width = std::fopen("/app0/framegen-record-width.txt", "r"))
{
char value[16] = "";
+1 -1
View File
@@ -4,7 +4,7 @@
* new account signs in with it), and the title appends that file to RetroArch's config at
* every start. Once RetroArch has signed in it keeps a token and clears its password, but
* only in its own settings, and retroarch.cfg holds the old password until RetroArch next
* saves it: patches/series 0123 calls this then, so the password stays in neither file
* saves it: patches/series 0130 calls this then, so the password stays in neither file
* (/app0/config, a folder FTP can read). retroarch.cfg keeps its token.
* Copyright (C) 2026 Mihawk
* SPDX-License-Identifier: GPL-3.0-or-later
+38 -27
View File
@@ -194,9 +194,10 @@ void ps5_fg_menu_help(const char *label, char *s, size_t len)
len);
}
/* The floor is off unless PS5_FRAMEGEN_FLOOR=1 names it (a test): every picture of the output rate is generated, whatever rate
* the core makes its frames at. The rates a core makes with and without generation were compared in
* docs/design.md and did not tell a core that generation slows from a game that changed its own rate. */
/* The floor is off unless PS5_FRAMEGEN_FLOOR=1 names it (a test): every picture of the output rate
* is generated, whatever rate the core makes its frames at. The rates a core makes with and without
* generation were compared in docs/design.md and did not tell a core that generation slows from a
* game that changed its own rate. */
static bool floor_enabled(void)
{
static int enabled = -1;
@@ -208,11 +209,13 @@ static bool floor_enabled(void)
return enabled == 1;
}
/* A core that blocks until its next frame is made says so (the private environment command of patches/series, 0123); the
* runloop notes the instant it calls the core. */
/* A core that blocks until its next frame is made says so (the private environment command of
* patches/series, 0123); the runloop notes the instant it calls the core. */
int ps5_fg_core_blocks;
unsigned ps5_fg_core_period_us; /* the microseconds the core took to make the next frame handed over (0x25002) */
unsigned ps5_fg_core_gap_frames; /* the frames the next frame handed over covers, from the core (0x25002); 0: not said */
unsigned ps5_fg_core_period_us; /* the microseconds the core took to make the next frame handed over
(0x25002) */
unsigned ps5_fg_core_gap_frames; /* the frames the next frame handed over covers, from the core
(0x25002); 0: not said */
uint64_t ps5_fg_core_run_begin_ns;
/* The runloop calls this with the time of each call of the core (patches/series, 0122) */
@@ -307,23 +310,27 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
"%.1f calls/s, governor level %u (%.2f ms a picture)\n",
(double)presents / seconds, (double)(generated - last_generated) / seconds,
new_per_s, calls_per_s, level, gen_ms);
/* The floor: a core that cannot keep its own rate gains nothing from frames made between its frames if the work
* only slows it more. Whether it does is measured, not assumed: a core whose game steps at 30 while it declares 60
* (a core that blocks for its next frame) also makes fewer calls a second than the rate it declares, and the
* generator costs it nothing. Two slow windows turn generation off for one window; the rate then, and the rate
* with generation back, are compared: generation that costs the core under a tenth of its rate stays on, and
* stays on while the core holds that rate. Generation that slows the core is off for ten seconds, then tried
* again. */
/* The floor: a core that cannot keep its own rate gains nothing from frames made between
* its frames if the work only slows it more. Whether it does is measured, not assumed: a
* core whose game steps at 30 while it declares 60 (a core that blocks for its next frame)
* also makes fewer calls a second than the rate it declares, and the generator costs it
* nothing. Two slow windows turn generation off for one window; the rate then, and the rate
* with generation back, are compared: generation that costs the core under a tenth of its
* rate stays on, and stays on while the core holds that rate. Generation that slows the
* core is off for ten seconds, then tried again. */
{
static int phase; /* 0 generating, 1 off for the measure, 2 generating again, to be compared */
static int
phase; /* 0 generating, 1 off for the measure, 2 generating again, to be compared */
static unsigned verify_windows, off_windows;
static double last_slow_rate;
static double rate_off, rate_kept; /* calls a second: without generation; the rate generation was found harmless at */
static double rate_off, rate_kept; /* calls a second: without generation; the rate
generation was found harmless at */
if (ps5_fg_floor)
{
if (phase == 1)
{
/* the first window with generation off is a mix of both: the second is the core's rate without it */
/* the first window with generation off is a mix of both: the second is the
* core's rate without it */
if (++off_windows >= 2)
{
rate_off = calls_per_s;
@@ -347,7 +354,8 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
if (calls_per_s >= 0.9 * rate_off)
{
rate_kept = rate_off;
RARCH_LOG("[FrameGen] floor: the core makes %.1f calls/s with generation and %.1f without; generation "
RARCH_LOG("[FrameGen] floor: the core makes %.1f calls/s with generation "
"and %.1f without; generation "
"costs it nothing and stays on\n",
calls_per_s, rate_off);
}
@@ -356,7 +364,8 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
rate_kept = 0.0;
ps5_fg_floor = 1;
floor_until = t.tv_sec + 10;
RARCH_LOG("[FrameGen] floor: the core makes %.1f calls/s with generation and %.1f without; frames are "
RARCH_LOG("[FrameGen] floor: the core makes %.1f calls/s with generation "
"and %.1f without; frames are "
"shown as it makes them for 10 s\n",
calls_per_s, rate_off);
}
@@ -365,8 +374,8 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
else if (floor_enabled() && plan && ps5_fg_core_fps > 20.0f &&
calls_per_s < 0.85 * (rate_kept > 0.0 ? rate_kept : (double)ps5_fg_core_fps))
{
/* the core's rate must have settled: a game that has just changed its rate (a level loaded, a state
* loaded) is not yet a rate to judge */
/* the core's rate must have settled: a game that has just changed its rate (a level
* loaded, a state loaded) is not yet a rate to judge */
if (slow_windows == 0 || fabs(calls_per_s - last_slow_rate) <= 0.1 * last_slow_rate)
slow_windows++;
else
@@ -378,10 +387,12 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
slow_windows = 0;
off_windows = 0;
if (rate_kept > 0.0)
rate_kept = 0.0; /* it slowed below the rate generation was found harmless at: measure again */
rate_kept = 0.0; /* it slowed below the rate generation was found harmless
at: measure again */
phase = 1;
floor_until = t.tv_sec + 4;
RARCH_LOG("[FrameGen] floor: the core runs at %.1f of %.1f frames/s; generation off for two windows to "
RARCH_LOG("[FrameGen] floor: the core runs at %.1f of %.1f frames/s; "
"generation off for two windows to "
"see whether it is the cause\n",
calls_per_s, (double)ps5_fg_core_fps);
}
@@ -389,11 +400,11 @@ void ps5_fg_osd(bool plan, unsigned subframes, unsigned period, unsigned width,
else
slow_windows = 0;
}
RARCH_LOG("[FrameGen] core run: %u calls, mean %.2f ms, max %.2f ms, %u over 20 ms\n", run_calls,
run_calls ? run_sum_ms / run_calls : 0.0, run_max_ms, run_long);
RARCH_LOG("[FrameGen] core run: %u calls, mean %.2f ms, max %.2f ms, %u over 20 ms\n",
run_calls, run_calls ? run_sum_ms / run_calls : 0.0, run_max_ms, run_long);
{
/* the CPU the title's threads used over the window: this thread (the frontend and the generator's recording)
* and every thread (with the core's), in cores */
/* the CPU the title's threads used over the window: this thread (the frontend and the
* generator's recording) and every thread (with the core's), in cores */
static double thread_prev, process_prev;
struct timespec ct, cp;
double thread_now, process_now;
+5
View File
@@ -685,6 +685,11 @@ bool exit_requested()
return request_update_exit;
}
} // namespace ps5_update
/* PS5_FrameGen's present-stream recorder (the pad script's RECORD): not linked here. */
extern "C" void ps5_fg_record_request(unsigned pictures)
{
(void)pictures;
}
/* src/webui_link.cpp: no daemon here; the in-process request above is the one tested. */
extern "C" int ps5_webui_link_install_requested(void)
{
+8
View File
@@ -186,6 +186,14 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *c, const ch
static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *c, const char *l,
const char *m, unsigned t)
{ return -1; }
/* The frame generation entries (patches/series, 0120) bound beside the WebUI's: none here. */
#include <stdbool.h>
static bool ps5_fg_menu_is_label(const char *l) { return false; }
static bool ps5_fg_menu_is_folder(const char *l) { return false; }
static int action_ok_push_default(const char *p, const char *l, unsigned t, size_t i, size_t e)
{ return 0; }
static int action_ok_ps5_fg(const char *p, const char *l, unsigned t, size_t i, size_t e)
{ return 0; }
"""
code += function(callbacks, 'static int action_ok_ps5_webui(')
code += function(callbacks, 'int menu_cbs_init_bind_ok(')
+1 -1
View File
@@ -62,7 +62,7 @@ class Secrets(unittest.TestCase):
self.assertNotIn(b'correct horse', call('GET')[1])
# The new password signs in, not the old account's token...
self.assertIn('cheevos_token = ""', (root / 'config/webui.cfg').read_text())
# ...and once RetroArch has its own token (patches/series 0123) the password
# ...and once RetroArch has its own token (patches/series 0130) the password
# leaves webui.cfg; the other settings stay.
helper = Path(temp) / 'forget'
(Path(temp) / 'forget.c').write_text(
+4 -4
View File
@@ -37,25 +37,25 @@ EDITS = [
(
"libretro-common/net/net_socket_ssl_mbed.c",
" mbedtls_ssl_conf_authmode(&state->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);\n",
" /* patches/series, 0122: a server whose certificate does not chain to the bundled\n"
" /* patches/series, 0129: a server whose certificate does not chain to the bundled\n"
" * roots (cacert.h) is refused, so nobody on the network path can stand in for\n"
" * RetroAchievements and read a password or sign-in token. Upstream verifies\n"
" * optionally and ignores the result. */\n"
" mbedtls_ssl_conf_authmode(&state->conf, MBEDTLS_SSL_VERIFY_REQUIRED);\n",
"patches/series, 0122: a server whose certificate does not chain",
"patches/series, 0129: a server whose certificate does not chain",
),
(
"cheevos/cheevos.c",
" settings->arrays.cheevos_password[0] = '\\0';\n",
" settings->arrays.cheevos_password[0] = '\\0';\n"
" {\n"
" /* patches/series, 0123: the password the WebUI saved is not kept once\n"
" /* patches/series, 0130: the password the WebUI saved is not kept once\n"
" * RetroArch has a token (src/ps5_cheevos.c). */\n"
" extern int ps5_cheevos_forget_password(const char *path, int token_too);\n"
" ps5_cheevos_forget_password(\"/app0/config/webui.cfg\", 1);\n"
" ps5_cheevos_forget_password(\"/app0/config/retroarch.cfg\", 0);\n"
" }\n",
"patches/series, 0123: the password the WebUI saved is not kept",
"patches/series, 0130: the password the WebUI saved is not kept",
),
(
"menu/drivers/xmb.c",