mirror of
https://github.com/valentderah/totk-pc-recomp.git
synced 2026-11-11 01:41:02 +00:00
recomp/patches-v143.txt ports MacNativeGames' 1.4.3 fps60, real-time step, cloth and bounce sites; the real-time producer reads the nominal interval from patch page +8, which frame_rate.c now writes as seconds * 60. make_romfs_patches.py takes --version (Common.Product.140 on 1.4.3). SDK 20.5 grew KeyboardConfig to 0x518 bytes, so ShowKeyboardArg's work buffer is at +0x518; swkbd_win.c and the services probe pick the offset by version. 1.4.3's movie::Decoder vtable names the complete-object destructor D1, which gets the D2 override. The loader probe has the measured 1.4.3 import and relocation counts, and probe-ipc expects REV15 from the 1.4.3 SDK and skips the 1.2.1 sf heap constructors (1.4.3 creates the audio heap lazily). A non-1.2.1 build defaults to its own profile, build/profile-<version>: 1.4.3 rewrites the saves it loads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
85 lines
3.0 KiB
C
85 lines
3.0 KiB
C
// Code patch sets (recomp/patches.py, gen.py --patches). The generator lifts both the original and the replacement
|
|
// instructions of every patched site, and rt_patch_on[set] picks one when the site runs, so a set is switched at start
|
|
// without touching code, and also while the game runs (rt_patch_switch: the frame-limit setting of the menu). The sets,
|
|
// their environment switches and defaults, and the patch page come from the generated patches.h; without it (C
|
|
// generated without --patches) there are no sets and every site runs the original.
|
|
//
|
|
// The patch page is the first 4 KiB page after main's image, inside the module window memory.c reserved: replacement
|
|
// code reaches it with one adrp, as MacNativeGames' data page after main (games/totk/runtime/game_patches.c). Its
|
|
// layout belongs to the sets that use it (frame_rate.c: +0 the 30 Hz ratio, +4 the frame step in seconds, +8 the
|
|
// step in 60 Hz ticks).
|
|
// Probe modes never call rt_patches_init: every set stays off.
|
|
#include "cfg.h"
|
|
#include "platform/platform.h"
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "host.h"
|
|
|
|
#if __has_include("patches.h")
|
|
#include "patches.h"
|
|
#endif
|
|
#ifndef RT_PATCH_COUNT
|
|
#define RT_PATCH_COUNT 0
|
|
#endif
|
|
|
|
uint8_t rt_patch_on[RT_PATCH_COUNT > 0 ? RT_PATCH_COUNT : 1]; // read by the generated C at every patched site
|
|
|
|
#if RT_PATCH_COUNT
|
|
static const struct { const char *name, *env; int on; } sets[] = {
|
|
#define X(i, n, e, d) {#n, e, d},
|
|
RT_PATCH_SETS(X)
|
|
#undef X
|
|
};
|
|
static void *page;
|
|
#endif
|
|
|
|
void rt_patches_init(void) {
|
|
#if RT_PATCH_COUNT
|
|
if (!plat_mem_commit(RT_PATCH_PAGE, 0x1000))
|
|
rt_fatal("patches: cannot commit the patch page at %#llx", RT_PATCH_PAGE);
|
|
page = (void *)(uintptr_t)RT_PATCH_PAGE;
|
|
char list[512];
|
|
size_t n = 0;
|
|
list[0] = 0;
|
|
for (int i = 0; i < RT_PATCH_COUNT; i++) {
|
|
const char *e = cfg_get(sets[i].env);
|
|
// a set with a row in the settings table takes its default from there; the generated default serves the rest
|
|
rt_patch_on[i] = (uint8_t)(cfg_meta(sets[i].env) ? cfg_bool(sets[i].env) : e && *e ? strcmp(e, "0") != 0 : sets[i].on);
|
|
n += (size_t)snprintf(list + n, sizeof list - n, "%s%s %s", i ? ", " : "", sets[i].name,
|
|
rt_patch_on[i] ? "on" : "off");
|
|
if (n >= sizeof list) n = sizeof list - 1;
|
|
}
|
|
rt_log("patches: %s (page %#llx)", list, RT_PATCH_PAGE);
|
|
#endif
|
|
}
|
|
|
|
int rt_patch_set(const char *name) {
|
|
#if RT_PATCH_COUNT
|
|
for (int i = 0; i < RT_PATCH_COUNT; i++)
|
|
if (!strcmp(sets[i].name, name)) return i;
|
|
#endif
|
|
(void)name;
|
|
return -1;
|
|
}
|
|
|
|
int rt_patch_enabled(int set) { return set >= 0 && set < RT_PATCH_COUNT && rt_patch_on[set]; }
|
|
|
|
void rt_patch_disable(int set) {
|
|
if (set >= 0 && set < RT_PATCH_COUNT) rt_patch_on[set] = 0;
|
|
}
|
|
|
|
void rt_patch_switch(int set, int on) {
|
|
if (set >= 0 && set < RT_PATCH_COUNT) __atomic_store_n(&rt_patch_on[set], (uint8_t)(on != 0), __ATOMIC_RELAXED);
|
|
}
|
|
|
|
void *rt_patch_page(void) {
|
|
#if RT_PATCH_COUNT
|
|
return page;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|