mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Include fixed scaled-charge batching profile in netplay compatibility
This commit is contained in:
@@ -983,6 +983,12 @@ race) agree on `cyc`, `mmio` and `mc` on every frame. They also end with
|
||||
identical ordered write hashes. The only differences are one-frame VBlank
|
||||
straddles of `wc`/`sc`, as documented for batched code.
|
||||
|
||||
The scale and selected batching profile are fixed at session startup and
|
||||
included in the existing netplay compatibility fingerprint. Peers with
|
||||
different batching choices cannot start together. Both paths use portable C;
|
||||
this does not authorize compatibility between otherwise different builds or
|
||||
replace the existing game/core/config identity checks.
|
||||
|
||||
Gates (all present gates must be open; with none the scale always applies):
|
||||
|
||||
- `guest_cycle_scale_gate` — RAM predicates on aligned main-RAM words
|
||||
|
||||
@@ -124,6 +124,13 @@ static inline uint32_t psx_gcs_recip_for(uint32_t scale) {
|
||||
}
|
||||
/* [timing] guest_cycle_scale_batch: batch scaled CPU charges (psx_cyc.h). */
|
||||
extern int g_psx_gcs_batch;
|
||||
/* Fixed session timing profile. Both implementations are portable C and are
|
||||
* present in every build; peers must agree on the selected one before frame 0.
|
||||
* Preserve the existing scale-only tag for the unbatched path. */
|
||||
static inline uint32_t psx_gcs_session_profile(uint32_t scale, int batch) {
|
||||
if (scale <= 1u) return 0u;
|
||||
return 0x6C000000u | (batch ? 0x00800000u : 0u) | scale;
|
||||
}
|
||||
static inline uint32_t psx_gcs_scale(uint32_t cpu_cycles) {
|
||||
uint64_t t = (uint64_t)cpu_cycles * g_psx_gcs_recip_q16 + g_psx_gcs_frac;
|
||||
g_psx_gcs_frac = (uint32_t)(t & 0xFFFFu);
|
||||
|
||||
@@ -19631,7 +19631,8 @@ session_reboot:
|
||||
// exactly as before.
|
||||
if (psx_guest_cycle_scale_config() != 1u) {
|
||||
char tag[9];
|
||||
std::snprintf(tag, sizeof tag, "%08x", 0x6C000000u | psx_guest_cycle_scale_config());
|
||||
std::snprintf(tag, sizeof tag, "%08x",
|
||||
psx_gcs_session_profile(psx_guest_cycle_scale_config(), g_psx_gcs_batch));
|
||||
if (std::strlen(net_cfg.content_fingerprint) != 64)
|
||||
std::snprintf(net_cfg.content_fingerprint, sizeof(net_cfg.content_fingerprint),
|
||||
"%s", "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c00000000");
|
||||
@@ -19640,8 +19641,8 @@ session_reboot:
|
||||
auto hv = [](char c) { return c <= '9' ? c - '0' : (c | 0x20) - 'a' + 10; };
|
||||
*d = "0123456789abcdef"[hv(*d) ^ hv(tag[i])];
|
||||
}
|
||||
std::printf("psxrecomp: netplay requires guest_cycle_scale %u on every peer\n",
|
||||
psx_guest_cycle_scale_config());
|
||||
std::printf("psxrecomp: netplay requires guest_cycle_scale %u, batch profile %d on every peer\n",
|
||||
psx_guest_cycle_scale_config(), g_psx_gcs_batch != 0);
|
||||
}
|
||||
const int nrc = psx_netplay_start(&net_cfg);
|
||||
if (nrc != 0) {
|
||||
|
||||
@@ -129,6 +129,11 @@ static void check_batch_ignores_host_stack(uint32_t scale, uint32_t charges, uin
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
assert(psx_gcs_session_profile(1, 0) == 0u);
|
||||
assert(psx_gcs_session_profile(1, 1) == 0u); /* no scaled path */
|
||||
assert(psx_gcs_session_profile(2, 0) == (0x6C000000u | 2u));
|
||||
assert(psx_gcs_session_profile(2, 1) != psx_gcs_session_profile(2, 0));
|
||||
assert(psx_gcs_session_profile(3, 1) != psx_gcs_session_profile(2, 1));
|
||||
assert(psx_gcs_recip_for(1) == 65536u);
|
||||
assert(psx_gcs_recip_for(0) == 65536u); /* never slower than faithful */
|
||||
assert(psx_gcs_recip_for(2) == 32768u);
|
||||
|
||||
Reference in New Issue
Block a user