mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
rewind support
This commit is contained in:
@@ -2220,7 +2220,7 @@ UserSettings load_user_settings(const fs::path& path) {
|
||||
});
|
||||
if (v.contains("rewind_depth")) try_get([&]{
|
||||
int d = toml::find<int>(v, "rewind_depth");
|
||||
static const int opts[4] = {25, 50, 75, 100};
|
||||
static const int opts[4] = {50, 100, 150, 200};
|
||||
int best = opts[0];
|
||||
int best_d = d > best ? d - best : best - d;
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
@@ -2230,6 +2230,18 @@ UserSettings load_user_settings(const fs::path& path) {
|
||||
s.rewind_depth = best;
|
||||
s.has_rewind_depth = true;
|
||||
});
|
||||
if (v.contains("rewind_interval")) try_get([&]{
|
||||
int d = toml::find<int>(v, "rewind_interval");
|
||||
static const int opts[5] = {1, 4, 8, 12, 15};
|
||||
int best = opts[0];
|
||||
int best_d = d > best ? d - best : best - d;
|
||||
for (int i = 1; i < 5; ++i) {
|
||||
int dd = d > opts[i] ? d - opts[i] : opts[i] - d;
|
||||
if (dd < best_d) { best_d = dd; best = opts[i]; }
|
||||
}
|
||||
s.rewind_interval = best;
|
||||
s.has_rewind_interval = true;
|
||||
});
|
||||
}
|
||||
if (doc.contains("audio")) {
|
||||
const toml::value& a = toml::find(doc, "audio");
|
||||
@@ -2455,6 +2467,8 @@ bool save_user_settings(const fs::path& path, const UserSettings& s) {
|
||||
f << "adaptive_view = " << (s.adaptive_view ? "true" : "false") << "\n";
|
||||
if (s.has_rewind_depth)
|
||||
f << "rewind_depth = " << s.rewind_depth << "\n";
|
||||
if (s.has_rewind_interval)
|
||||
f << "rewind_interval = " << s.rewind_interval << "\n";
|
||||
f << "\n[audio]\n";
|
||||
if (s.has_spu_hq)
|
||||
f << "spu_hq = " << (s.spu_hq ? "true" : "false") << "\n";
|
||||
|
||||
@@ -1104,8 +1104,11 @@ struct UserSettings {
|
||||
int aspect_den = 3; // (4:3 = native)
|
||||
bool has_adaptive_view = false; bool adaptive_view = false;
|
||||
// [video] rewind_depth: local rewind snap-ring capacity. UI offers
|
||||
// 25 / 50 / 75 / 100 (default 50). Runtime clamps + snaps to those steps.
|
||||
// 50 / 100 / 150 / 200 (default 50). Runtime clamps + snaps to those steps.
|
||||
bool has_rewind_depth = false; int rewind_depth = 50;
|
||||
// [video] rewind_interval: frames between local rewind snaps. UI offers
|
||||
// 1 / 4 / 8 / 12 / 15 (default 15).
|
||||
bool has_rewind_interval = false; int rewind_interval = 15;
|
||||
// [audio]
|
||||
bool has_spu_hq = false; bool spu_hq = false;
|
||||
// [bios] / [disc] / [memcard]
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
* Keyboard: F8 (config.ini [KeyMap] Rewind). Controller: View/Back or L3.
|
||||
* While open: D-pad / left-stick Left/Right, Cross/A load, Circle/B/Back close.
|
||||
*
|
||||
* Env: PSX_REWIND=0 disables; PSX_REWIND_INTERVAL (frames, default 15);
|
||||
* Env: PSX_REWIND=0 disables; PSX_REWIND_INTERVAL (1/4/8/12/15, default 15);
|
||||
* PSX_REWIND_FMV_INTERVAL (frames while depth24/MDEC/XA, default 4);
|
||||
* PSX_REWIND_DEPTH (snaps; UI offers 25/50/75/100, default 50, max 100).
|
||||
* settings.toml [video] rewind_depth overrides the default (env still wins).
|
||||
* PSX_REWIND_DEPTH (50/100/150/200, default 50, max 200).
|
||||
* settings.toml [video] rewind_depth / rewind_interval (env still wins).
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -25,6 +25,7 @@ extern "C" {
|
||||
|
||||
/* Snap count kept in the local rewind ring. UI values: 25 / 50 / 75 / 100. */
|
||||
void psx_rewind_set_depth(uint32_t depth);
|
||||
void psx_rewind_set_interval(uint32_t interval);
|
||||
|
||||
void psx_rewind_configure(uint32_t bios_checksum, uint32_t entry_pc);
|
||||
void psx_rewind_shutdown(void);
|
||||
|
||||
@@ -1001,8 +1001,10 @@ function(psxrecomp_add_runtime_target target)
|
||||
endif()
|
||||
|
||||
# Per-game netplay/local pad ceiling. Default 2 (MotK / dual-shock path).
|
||||
# Games that need multitap N-player (e.g. Bomberman Party Edition) pass
|
||||
# MAX_PLAYERS 5. Clamped to the framework absolute max of 5.
|
||||
# Single-player titles (Tomba, Ape Escape, …) pass MAX_PLAYERS 1 so rewind
|
||||
# / rbengine still link without advertising multiplayer. Multitap N-player
|
||||
# (Bomberman Party Edition) uses 5; dual SCPH-1070 uses 8. Range matches
|
||||
# sio.h (1..8).
|
||||
if(NOT PSXRT_MAX_PLAYERS)
|
||||
if(DEFINED PSX_MAX_PLAYERS AND NOT PSX_MAX_PLAYERS STREQUAL "")
|
||||
set(PSXRT_MAX_PLAYERS "${PSX_MAX_PLAYERS}")
|
||||
@@ -1010,9 +1012,9 @@ function(psxrecomp_add_runtime_target target)
|
||||
set(PSXRT_MAX_PLAYERS 2)
|
||||
endif()
|
||||
endif()
|
||||
if(PSXRT_MAX_PLAYERS LESS 2 OR PSXRT_MAX_PLAYERS GREATER 5)
|
||||
if(PSXRT_MAX_PLAYERS LESS 1 OR PSXRT_MAX_PLAYERS GREATER 8)
|
||||
message(FATAL_ERROR
|
||||
"MAX_PLAYERS must be in 2..5 (got ${PSXRT_MAX_PLAYERS})")
|
||||
"MAX_PLAYERS must be in 1..8 (got ${PSXRT_MAX_PLAYERS})")
|
||||
endif()
|
||||
message(STATUS "psxrecomp ${target}: PSX_MAX_PLAYERS=${PSXRT_MAX_PLAYERS}")
|
||||
|
||||
|
||||
+16
-1
@@ -1059,7 +1059,8 @@ static int g_video_screen = 0; /* 0=raw,1=crt,2=composite,3=trinitr
|
||||
static int g_video_win_w = 1280; /* window width (height follows aspect) */
|
||||
static bool g_audio_spu_hq = false; /* SPU float-shadow (env overrides) */
|
||||
static int g_auto_skip_fmv = 0; /* skip FMVs the instant they're detected */
|
||||
static int g_rewind_depth = 50; /* local rewind snap count (25/50/75/100) */
|
||||
static int g_rewind_depth = 50; /* local rewind snap count (50/100/150/200) */
|
||||
static int g_rewind_interval = 15; /* frames between snaps (1/4/8/12/15) */
|
||||
static int g_headless = 0; /* debug/CI frontend: no SDL window/audio */
|
||||
/* FMV instant-skip via the game's OWN end-of-movie path. Tomba's MDEC player
|
||||
* (FUN_8001efe8) tears a movie down when the streamed frame number reaches that
|
||||
@@ -10256,6 +10257,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
if (us.has_spu_hq) g_audio_spu_hq = us.spu_hq;
|
||||
if (us.has_rewind_depth) g_rewind_depth = us.rewind_depth;
|
||||
if (us.has_rewind_interval) g_rewind_interval = us.rewind_interval;
|
||||
if (us.has_bios_path && !bios_from_cli && !us.bios_path.empty()) {
|
||||
settings_bios_storage = us.bios_path.string();
|
||||
bios_path = settings_bios_storage.c_str();
|
||||
@@ -10663,6 +10665,7 @@ int main(int argc, char** argv) {
|
||||
seed.aspect_den = g_video_aspect_den; seed.has_aspect_ratio = true;
|
||||
seed.spu_hq = g_audio_spu_hq; seed.has_spu_hq = true;
|
||||
seed.rewind_depth = g_rewind_depth; seed.has_rewind_depth = true;
|
||||
seed.rewind_interval = g_rewind_interval; seed.has_rewind_interval = true;
|
||||
seed.skip_launcher = skip_launcher_setting; seed.has_skip_launcher = true;
|
||||
if (has_netplay_player_name) {
|
||||
seed.netplay_player_name = netplay_player_name;
|
||||
@@ -10816,6 +10819,7 @@ int main(int argc, char** argv) {
|
||||
ls.frame_interp_fps = seed.frame_interpolation_fps;
|
||||
ls.spu_hq = seed.spu_hq ? 1 : 0;
|
||||
ls.rewind_depth = seed.rewind_depth > 0 ? seed.rewind_depth : 50;
|
||||
ls.rewind_interval = seed.rewind_interval > 0 ? seed.rewind_interval : 15;
|
||||
ls.auto_skip_fmv = seed.auto_skip_fmv ? 1 : 0;
|
||||
ls.turbo_loads = seed.turbo_loads ? 1 : 0;
|
||||
/* Localization: index of resolved_language within lang_menu_options
|
||||
@@ -11045,6 +11049,8 @@ int main(int argc, char** argv) {
|
||||
seed.spu_hq = ls.spu_hq != 0; seed.has_spu_hq = true;
|
||||
seed.rewind_depth = ls.rewind_depth > 0 ? ls.rewind_depth : 50;
|
||||
seed.has_rewind_depth = true;
|
||||
seed.rewind_interval = ls.rewind_interval > 0 ? ls.rewind_interval : 15;
|
||||
seed.has_rewind_interval = true;
|
||||
seed.auto_skip_fmv = ls.auto_skip_fmv != 0;
|
||||
seed.has_auto_skip_fmv = skip_fmv_offered;
|
||||
seed.turbo_loads = ls.turbo_loads != 0;
|
||||
@@ -11244,6 +11250,8 @@ int main(int argc, char** argv) {
|
||||
g_audio_spu_hq = seed.spu_hq;
|
||||
g_rewind_depth = seed.has_rewind_depth && seed.rewind_depth > 0
|
||||
? seed.rewind_depth : 50;
|
||||
g_rewind_interval = seed.has_rewind_interval && seed.rewind_interval > 0
|
||||
? seed.rewind_interval : 15;
|
||||
skip_launcher_setting = seed.skip_launcher;
|
||||
if (seed.has_bios_path) {
|
||||
settings_bios_storage = seed.bios_path.string();
|
||||
@@ -12231,6 +12239,7 @@ session_reboot:
|
||||
memory_get_bios_checksum(), game_entry_pc,
|
||||
bios_token, openbios_ws);
|
||||
psx_rewind_set_depth((uint32_t)g_rewind_depth);
|
||||
psx_rewind_set_interval((uint32_t)g_rewind_interval);
|
||||
psx_rewind_configure(memory_get_bios_checksum(), game_entry_pc);
|
||||
/* Headless / agent load: PSX_LOAD_SLOT=N stages F1..F12 load (0..11)
|
||||
* at the next safe block boundary after boot. */
|
||||
@@ -12826,6 +12835,8 @@ soft_return_lobby:
|
||||
us.has_spu_hq = true;
|
||||
us.rewind_depth = ls.rewind_depth > 0 ? ls.rewind_depth : 50;
|
||||
us.has_rewind_depth = true;
|
||||
us.rewind_interval = ls.rewind_interval > 0 ? ls.rewind_interval : 15;
|
||||
us.has_rewind_interval = true;
|
||||
us.auto_skip_fmv = ls.auto_skip_fmv != 0;
|
||||
us.has_auto_skip_fmv = skip_fmv_offered;
|
||||
us.turbo_loads = ls.turbo_loads != 0;
|
||||
@@ -12875,6 +12886,10 @@ soft_return_lobby:
|
||||
g_rewind_depth = ls.rewind_depth;
|
||||
psx_rewind_set_depth((uint32_t)g_rewind_depth);
|
||||
}
|
||||
if (ls.rewind_interval > 0) {
|
||||
g_rewind_interval = ls.rewind_interval;
|
||||
psx_rewind_set_interval((uint32_t)g_rewind_interval);
|
||||
}
|
||||
switch (ls.aspect_index) {
|
||||
case 2: g_video_aspect_num = 21; g_video_aspect_den = 9; break;
|
||||
case 1: g_video_aspect_num = 16; g_video_aspect_den = 9; break;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#define RW_THUMB_W 128
|
||||
#define RW_THUMB_H 96
|
||||
#define RW_MAX_DEPTH 100
|
||||
#define RW_MAX_DEPTH 200
|
||||
#define RW_DEF_DEPTH 50
|
||||
#define RW_DEF_INTERVAL 15
|
||||
/* Match netplay §96 FMV media snaps (default 4; MEDIA_KF uses 2). */
|
||||
@@ -102,6 +102,7 @@ static const uint8_t FONT8[59][8] = {
|
||||
#if !defined(PSX_HAS_RBENGINE_SNAP)
|
||||
|
||||
void psx_rewind_set_depth(uint32_t depth) { (void)depth; }
|
||||
void psx_rewind_set_interval(uint32_t interval) { (void)interval; }
|
||||
void psx_rewind_configure(uint32_t bios_checksum, uint32_t entry_pc)
|
||||
{
|
||||
(void)bios_checksum;
|
||||
@@ -151,6 +152,7 @@ static uint32_t s_interval = RW_DEF_INTERVAL;
|
||||
static uint32_t s_fmv_interval = RW_DEF_FMV_INTERVAL;
|
||||
static uint32_t s_depth = RW_DEF_DEPTH;
|
||||
static int s_depth_pref = -1; /* -1 = unset; else from settings.toml / launcher */
|
||||
static int s_interval_pref = -1;
|
||||
static uint32_t s_frame;
|
||||
static uint32_t s_last_capture_frame = 0xffffffffu;
|
||||
static int s_capture_due;
|
||||
@@ -190,10 +192,10 @@ static uint32_t env_u32(const char *name, uint32_t def, uint32_t lo, uint32_t hi
|
||||
return v;
|
||||
}
|
||||
|
||||
/* UI offers 25/50/75/100; nearest match keeps hand-edited toml values sane. */
|
||||
/* UI offers 50/100/150/200; nearest match keeps hand-edited toml values sane. */
|
||||
static uint32_t normalize_rewind_depth(uint32_t v)
|
||||
{
|
||||
static const uint32_t opts[4] = {25u, 50u, 75u, 100u};
|
||||
static const uint32_t opts[4] = {50u, 100u, 150u, 200u};
|
||||
uint32_t best = opts[0];
|
||||
uint32_t best_d = v > best ? v - best : best - v;
|
||||
unsigned i;
|
||||
@@ -207,6 +209,23 @@ static uint32_t normalize_rewind_depth(uint32_t v)
|
||||
return best;
|
||||
}
|
||||
|
||||
/* UI offers 1/4/8/12/15. */
|
||||
static uint32_t normalize_rewind_interval(uint32_t v)
|
||||
{
|
||||
static const uint32_t opts[5] = {1u, 4u, 8u, 12u, 15u};
|
||||
uint32_t best = opts[0];
|
||||
uint32_t best_d = v > best ? v - best : best - v;
|
||||
unsigned i;
|
||||
for (i = 1; i < 5; i++) {
|
||||
uint32_t d = v > opts[i] ? v - opts[i] : opts[i] - v;
|
||||
if (d < best_d) {
|
||||
best_d = d;
|
||||
best = opts[i];
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
void psx_rewind_set_depth(uint32_t depth)
|
||||
{
|
||||
s_depth_pref = (int)normalize_rewind_depth(depth);
|
||||
@@ -215,6 +234,13 @@ void psx_rewind_set_depth(uint32_t depth)
|
||||
s_depth = (uint32_t)s_depth_pref;
|
||||
}
|
||||
|
||||
void psx_rewind_set_interval(uint32_t interval)
|
||||
{
|
||||
s_interval_pref = (int)normalize_rewind_interval(interval);
|
||||
if (s_enabled >= 0)
|
||||
s_interval = (uint32_t)s_interval_pref;
|
||||
}
|
||||
|
||||
static int rewind_wanted(void)
|
||||
{
|
||||
const char *e;
|
||||
@@ -224,7 +250,12 @@ static int rewind_wanted(void)
|
||||
s_enabled = 0;
|
||||
else
|
||||
s_enabled = 1;
|
||||
s_interval = env_u32("PSX_REWIND_INTERVAL", RW_DEF_INTERVAL, 1u, 60u);
|
||||
{
|
||||
uint32_t iv_def = s_interval_pref > 0 ? (uint32_t)s_interval_pref
|
||||
: RW_DEF_INTERVAL;
|
||||
s_interval = normalize_rewind_interval(
|
||||
env_u32("PSX_REWIND_INTERVAL", iv_def, 1u, 60u));
|
||||
}
|
||||
s_fmv_interval =
|
||||
env_u32("PSX_REWIND_FMV_INTERVAL", RW_DEF_FMV_INTERVAL, 1u, 16u);
|
||||
{
|
||||
@@ -251,7 +282,10 @@ static int rewind_fmv_media_active(void)
|
||||
|
||||
static uint32_t rewind_capture_interval(void)
|
||||
{
|
||||
return rewind_fmv_media_active() ? s_fmv_interval : s_interval;
|
||||
if (!rewind_fmv_media_active())
|
||||
return s_interval;
|
||||
/* FMV densifies toward s_fmv_interval but never sparser than the user pick. */
|
||||
return s_interval < s_fmv_interval ? s_interval : s_fmv_interval;
|
||||
}
|
||||
|
||||
static int resume_pc_ok(uint32_t pc)
|
||||
|
||||
Reference in New Issue
Block a user