mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-18 23:09:29 -05:00
Fix Saturn BIOS paths, JIT execution and cropped video frames
Create content/Saturn and system/Saturn at startup. Route the default core system directory and menu BIOS preflight consistently, retaining custom paths. Patch Saturn's x86 code pools to use the SDK executable allocator and release. Keep cropped frames in core-owned storage to avoid resized lent texture reuse. Include the patch in core stamps, provenance and shipped notices. Two deliberate frontend patch blocks increase the expected count 232 to 234. Verification: bash tools/verify.sh, all five gates PASS, 96 tests. Evidence: evidence/saturn-runtime; replay with python3 tools/evidence.py compare evidence/. Console: 100s controlled gameplay with clean captures; final frontend repeats 100s boot/demo and exits0; explicit BIOS preflight passes. Settings restored.
This commit is contained in:
1 parent
cf649dd5d7
commit
a34661795a
10 files changed
+201
-10
No files matched your search
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"step": "saturn-runtime",
|
||||
"command": "bash tools/verify.sh; python3 tools/deploy-title.py; python3 klog/saturn-fix/test-final.py",
|
||||
"raw_capture": "klog/saturn-fix/final-20261002-133455/trace-current-run.txt",
|
||||
"build_identity": "b1f7383ea02846dc2bab315a886950860e36ec87cea279fa45abacdbdce72a49",
|
||||
"lines": [
|
||||
"host: all five verification gates pass; 96 tests pass",
|
||||
"paths: startup creates content/Saturn and system/Saturn with FTP-writable permissions",
|
||||
"paths: default BIOS lookup and menu preflight use system/Saturn; custom paths remain unchanged",
|
||||
"runtime: Saturn JITs use SDK executable allocation and matching release",
|
||||
"video: cropped Saturn output uses core-owned storage instead of resized frontend texture",
|
||||
"console: BIOS preflight enabled; regional BIOS found in system/Saturn",
|
||||
"console: clean controlled gameplay in rendering-fix run; final build repeats 100-second boot/demo with normal exit",
|
||||
"console: no new signal fault; native audio reports zero output errors; WebUI stops on exit"
|
||||
],
|
||||
"frame_window": {
|
||||
"seconds": 35.019000000000005,
|
||||
"frames": 1756,
|
||||
"core_frames_per_second": 50.144,
|
||||
"marks": [
|
||||
[
|
||||
"50.000",
|
||||
"2513",
|
||||
"31.8",
|
||||
"0"
|
||||
],
|
||||
[
|
||||
"85.019",
|
||||
"4269",
|
||||
"31.9",
|
||||
"0"
|
||||
]
|
||||
]
|
||||
},
|
||||
"core_sha256": "c85d47389b962a6b1561f034051bf291daa5228d2181a934b030a8e4cbf71d81",
|
||||
"screenshots": {
|
||||
"pad-shot-1.png": "1954f266b2cd6afdbad8eadb2377c4a8fd70de4cce741f1cf7370297b5e56308",
|
||||
"pad-shot-2.png": "67ea798d6163a2292b4110b7f104c8a55a32f8d1e620458559565f9c14d871cc",
|
||||
"pad-shot-3.png": "7c8726cfdb4449282e2e681b3a5b146490e3f40f5903994fbcae434d5ce83fdc",
|
||||
"pad-shot-4.png": "7d50492a343b22c7d6ef1269b640cff087fc5b26e00adaeb690e599f239ded6f"
|
||||
},
|
||||
"prior_failures": {
|
||||
"missing_bios": "Baseline exited1 because BIOS was searched in general system root.",
|
||||
"jit_execution": "After fixing the BIOS path, executing anonymous non-executable JIT memory raised signal11 in the sound DSP.",
|
||||
"borrowed_frame": "After executable allocation fix, gameplay ran but screenshots showed reused/resized video storage corruption."
|
||||
},
|
||||
"scope": "One PAL disc, short controlled gameplay; not a compatibility sweep or long soak. Raw console data stays ignored.",
|
||||
"controlled_gameplay": {
|
||||
"raw_capture": "klog/saturn-fix/render-20261002-133134/trace.txt",
|
||||
"build_identity": "c846fbfedb42f8fb3c872ee642234e0dc7cd7af43f8aa2e0ee25c5faf0fd487a",
|
||||
"duration_seconds": 100,
|
||||
"gameplay_screenshot_sha256": "fcff50036ecc8e6d052adc8b608ea4d6ba2509fc16eab43fbd30106fa8052554",
|
||||
"difference_from_final": "Final frontend also corrects menu BIOS preflight; Saturn core binary is unchanged."
|
||||
},
|
||||
"preflight": {
|
||||
"raw_capture": "klog/saturn-fix/preflight-20261002-133737/trace.txt",
|
||||
"enabled_verified_in_effective_saved_config": true,
|
||||
"normal_exit": true
|
||||
},
|
||||
"cleanup": {
|
||||
"global_and_core_configs_readback_match_backups": true,
|
||||
"temporary_launch_files_restored": true,
|
||||
"test_screenshots_archived_and_removed_from_console": true,
|
||||
"control_helper_stopped": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"step": "saturn-runtime",
|
||||
"must_contain": [
|
||||
"host: all five verification gates pass; 96 tests pass",
|
||||
"paths: startup creates content/Saturn and system/Saturn with FTP-writable permissions",
|
||||
"paths: default BIOS lookup and menu preflight use system/Saturn; custom paths remain unchanged",
|
||||
"runtime: Saturn JITs use SDK executable allocation and matching release",
|
||||
"video: cropped Saturn output uses core-owned storage instead of resized frontend texture",
|
||||
"console: BIOS preflight enabled; regional BIOS found in system/Saturn",
|
||||
"console: clean controlled gameplay in rendering-fix run; final build repeats 100-second boot/demo with normal exit",
|
||||
"console: no new signal fault; native audio reports zero output errors; WebUI stops on exit"
|
||||
],
|
||||
"must_not_contain": [
|
||||
"crash: signal",
|
||||
"rarch_main returned = 1"
|
||||
],
|
||||
"human_check": "Agent inspected the captured startup and gameplay frames for the prior duplication/corruption; physical audio quality was not independently listened to."
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
--- a/mednafen/ss/x86emit.c
|
||||
+++ b/mednafen/ss/x86emit.c
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "x86emit.h"
|
||||
+#ifdef SATURN_PS5
|
||||
+#include <ps5platform/exec.h>
|
||||
+#endif
|
||||
|
||||
#if X86EMIT_HOST
|
||||
|
||||
@@ -41,7 +44,10 @@
|
||||
x86_codegen* cg = (x86_codegen*)calloc(1, sizeof *cg);
|
||||
void* mem;
|
||||
if(!cg) return NULL;
|
||||
-#if defined(_WIN32)
|
||||
+#if defined(SATURN_PS5)
|
||||
+ mem = ps5_exec_allocate(bytes, (uintptr_t)&x86_codegen_create);
|
||||
+ if(!mem) { free(cg); return NULL; }
|
||||
+#elif defined(_WIN32)
|
||||
mem = VirtualAlloc(NULL, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if(!mem) { free(cg); return NULL; }
|
||||
#else
|
||||
@@ -57,7 +63,9 @@
|
||||
void x86_codegen_destroy(x86_codegen* cg)
|
||||
{
|
||||
if(!cg) return;
|
||||
-#if defined(_WIN32)
|
||||
+#if defined(SATURN_PS5)
|
||||
+ ps5_exec_release(cg->base);
|
||||
+#elif defined(_WIN32)
|
||||
VirtualFree(cg->base, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(cg->base, cg->size);
|
||||
@@ -839,7 +847,9 @@
|
||||
#if X86EMIT_64
|
||||
static void* rwx_alloc_at(void* hint, size_t bytes)
|
||||
{
|
||||
-#if defined(_WIN32)
|
||||
+#if defined(SATURN_PS5)
|
||||
+ return ps5_exec_allocate(bytes, (uintptr_t)hint);
|
||||
+#elif defined(_WIN32)
|
||||
return VirtualAlloc(hint, bytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
void* p = mmap(hint, bytes, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
@@ -849,7 +859,9 @@
|
||||
|
||||
static void rwx_free(void* p, size_t bytes)
|
||||
{
|
||||
-#if defined(_WIN32)
|
||||
+#if defined(SATURN_PS5)
|
||||
+ (void)bytes; ps5_exec_release(p);
|
||||
+#elif defined(_WIN32)
|
||||
(void)bytes; VirtualFree(p, 0, MEM_RELEASE);
|
||||
#else
|
||||
munmap(p, bytes);
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -74,7 +74,7 @@
|
||||
# PS5 (a homebrew title's libretro core): the console's libraries resolve at
|
||||
# load time, so no --no-undefined; no LTO.
|
||||
ifeq ($(platform), ps5)
|
||||
- FLAGS += -DHAVE_MMAP
|
||||
+ FLAGS += -DHAVE_MMAP -DSATURN_PS5
|
||||
TARGET := $(TARGET_NAME)_libretro.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=link.T
|
||||
--- a/libretro.c
|
||||
+++ b/libretro.c
|
||||
@@ -183,6 +183,12 @@
|
||||
{
|
||||
struct retro_framebuffer fb;
|
||||
|
||||
+#ifdef SATURN_PS5
|
||||
+ /* Vulkan resizes its lent texture to the cropped output dimensions before
|
||||
+ * upload. A pointer into that old texture would then reference freed storage.
|
||||
+ * Keep the core-owned surface and let the frontend copy the visible rows. */
|
||||
+ return NULL;
|
||||
+#endif
|
||||
if (!surf || !environ_cb)
|
||||
return NULL;
|
||||
if (last_frame_interlaced || PrevInterlaced)
|
||||
@@ -242,3 +242,7 @@
|
||||
# for the WebUI; no HTTP access to live emulator state
|
||||
# runloop.c
|
||||
0105-webui-core-metadata
|
||||
|
||||
# 0106 route the default Saturn BIOS directory to system/Saturn
|
||||
# runloop.c, core_info.c; explicit user paths remain unchanged
|
||||
0106-saturn-system-directory
|
||||
+11
-3
@@ -38,9 +38,9 @@ void set_directory(default_dirs slot, const char *path)
|
||||
|
||||
void initialize(void *)
|
||||
{
|
||||
const char *directories[] = {"/app0/config", "/app0/cores", "/app0/content",
|
||||
"/app0/system", "/app0/savefiles", "/app0/savestates",
|
||||
"/app0/playlists"};
|
||||
const char *directories[] = {"/app0/config", "/app0/cores", "/app0/content",
|
||||
"/app0/system", "/app0/savefiles", "/app0/savestates",
|
||||
"/app0/playlists", "/app0/content/Saturn", "/app0/system/Saturn"};
|
||||
for (const char *path : directories)
|
||||
{
|
||||
if (mkdir(path, 0777) != 0 && errno != EEXIST)
|
||||
@@ -133,6 +133,14 @@ int drives(void *data, bool content)
|
||||
|
||||
extern "C"
|
||||
{
|
||||
const char *ps5_core_system_directory(const char *core, const char *directory)
|
||||
{
|
||||
if (core && directory && std::strcmp(core, "Beetle Saturn") == 0 &&
|
||||
std::strcmp(directory, "/app0/system") == 0)
|
||||
return "/app0/system/Saturn";
|
||||
return directory;
|
||||
}
|
||||
|
||||
frontend_ctx_driver_t frontend_ctx_ps5 = []
|
||||
{
|
||||
frontend_ctx_driver_t driver{};
|
||||
|
||||
@@ -99,8 +99,8 @@ int main(int argc, char **argv)
|
||||
std::filesystem::create_directories(fixture + "/app0/content");
|
||||
assert(__real_chmod((fixture + "/app0/content").c_str(), 0775) == 0);
|
||||
frontend_ctx_ps5.init(nullptr);
|
||||
for (const char *name :
|
||||
{"config", "cores", "content", "system", "savefiles", "savestates", "playlists"})
|
||||
for (const char *name : {"config", "cores", "content", "system", "savefiles", "savestates",
|
||||
"playlists", "content/Saturn", "system/Saturn"})
|
||||
{
|
||||
struct stat metadata{};
|
||||
assert(__real_stat((fixture + "/app0/" + name).c_str(), &metadata) == 0);
|
||||
@@ -116,6 +116,12 @@ int main(int argc, char **argv)
|
||||
frontend_ctx_ps5.init(nullptr);
|
||||
assert(read(fixture + "/app0/config/retroarch.cfg") == "user settings\n");
|
||||
assert(!std::filesystem::exists(fixture + "/app0/config/retroarch.cfg.tmp"));
|
||||
assert(std::string(ps5_core_system_directory("Beetle Saturn", "/app0/system")) ==
|
||||
"/app0/system/Saturn");
|
||||
assert(std::string(ps5_core_system_directory("Beetle Saturn", "/mnt/usb0/bios")) ==
|
||||
"/mnt/usb0/bios");
|
||||
assert(std::string(ps5_core_system_directory("PPSSPP", "/app0/system")) == "/app0/system");
|
||||
assert(ps5_core_system_directory(nullptr, nullptr) == nullptr);
|
||||
// A non-null environment callback prevents task_content's menu fallback from
|
||||
// rebuilding the title's startup argv. It must leave these arguments intact.
|
||||
int count = argc;
|
||||
|
||||
@@ -344,7 +344,7 @@ class PortPatches(unittest.TestCase):
|
||||
change deliberately, in a commit that says why.
|
||||
"""
|
||||
self.assertEqual(
|
||||
len(self.blocks()), 232,
|
||||
len(self.blocks()), 234,
|
||||
"the patch count changed: if a block was added or removed on purpose, "
|
||||
"update this number in the same commit and say why in its message")
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
"copyright": ["Copyright Mednafen Team and the beetle-saturn-libretro contributors"],
|
||||
"texts": [{"from": ".deps/beetle-saturn-src/COPYING", "to": "COPYING"}],
|
||||
"source": {"kind": "core", "build": "beetle-saturn", "tree": ".deps/beetle-saturn-src", "remote": "https://github.com/mihawk-99/PS5_BeetleSaturn"},
|
||||
"modifications": "The fork's commits over libretro/beetle-saturn-libretro."
|
||||
"modifications": "The fork's commits over libretro/beetle-saturn-libretro, plus patches/beetle-saturn/ps5-executable-memory.patch for SDK executable memory and core-owned cropped video frames."
|
||||
},
|
||||
{
|
||||
"id": "vice",
|
||||
|
||||
@@ -34,6 +34,8 @@ from pathlib import Path
|
||||
|
||||
# (file, anchor, inserted-before-anchor, already-present-marker)
|
||||
EDITS = [
|
||||
('core_info.c', ' for (i = 0; i < info->firmware_count; i++)\n {\n if (string_is_empty(info->firmware[i].path))', ' /* patches/series, 0106: BIOS preflight uses the same core directory. */\n {\n extern const char *ps5_core_system_directory(const char *, const char *);\n systemdir = ps5_core_system_directory(info->core_name, systemdir);\n }\n for (i = 0; i < info->firmware_count; i++)\n {\n if (string_is_empty(info->firmware[i].path))', 'patches/series, 0106: BIOS preflight'),
|
||||
('runloop.c', ' const char *dir_system = settings->paths.directory_system;', ' /* patches/series, 0106: Saturn BIOS default; custom paths stay intact. */\n extern const char *ps5_core_system_directory(const char *, const char *);\n const char *dir_system = ps5_core_system_directory(\n runloop_st->system.info.library_name, settings->paths.directory_system);', 'patches/series, 0106: Saturn BIOS'),
|
||||
('runloop.c', 'static core_option_manager_t *runloop_init_core_options(\n', '/* patches/series, 0105: snapshot core descriptions for the WebUI. */\nextern void ps5_webui_core_options(const char *, const struct retro_core_options_v2 *);\nextern void ps5_webui_core_variables(const char *, const struct retro_variable *);\n\nstatic core_option_manager_t *runloop_init_core_options(\n', 'patches/series, 0105: snapshot'),
|
||||
('runloop.c', ' if (!string_is_empty(options_path))\n return core_option_manager_new(options_path,', ' /* patches/series, 0105: v1/v2 metadata on the emulator thread. */\n ps5_webui_core_options(runloop_state.system.info.library_name, options_v2);\n if (!string_is_empty(options_path))\n return core_option_manager_new(options_path,', 'patches/series, 0105: v1/v2'),
|
||||
('runloop.c', ' if (!string_is_empty(options_path))\n return core_option_manager_new_vars(options_path, src_options_path, vars);', ' /* patches/series, 0105: legacy choices on the emulator thread. */\n ps5_webui_core_variables(runloop_state.system.info.library_name, vars);\n if (!string_is_empty(options_path))\n return core_option_manager_new_vars(options_path, src_options_path, vars);', 'patches/series, 0105: legacy'),
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# build-title.sh stages those in /app0.
|
||||
# It renders in software at the Saturn's own resolution: every Saturn core that
|
||||
# upscales (Kronos, YabaSanshiro) needs OpenGL, which the console does not have.
|
||||
# Saturn games need the BIOS in system/ (sega_101.bin, mpr-17933.bin).
|
||||
# Saturn games need the BIOS in system/Saturn/ (sega_101.bin, mpr-17933.bin).
|
||||
set -euo pipefail
|
||||
root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
cd "$root"
|
||||
@@ -16,14 +16,18 @@ source "$root/tools/core-fork.sh"
|
||||
core_stamp_skip beetle-saturn \
|
||||
"$root/build/cores/stage/cores/mednafen_saturn_libretro.so" \
|
||||
"$root/build/cores/stage/info/mednafen_saturn_libretro.info" \
|
||||
-- "$root/tools/build-beetle-saturn.sh" "$root/tools/core-fork.sh"
|
||||
-- "$root/tools/build-beetle-saturn.sh" "$root/tools/core-fork.sh" \
|
||||
"$root/patches/beetle-saturn/ps5-executable-memory.patch"
|
||||
[[ $# == 0 ]] || { echo "usage: ${0##*/}" >&2; exit 2; }
|
||||
|
||||
revision=41a8a4b6ea1629790da170af775061a25e3c91cb # ../PS5_BeetleSaturn main
|
||||
core_fork_setup
|
||||
core_fork_checkout PS5_BeetleSaturn "$revision"
|
||||
# Anonymous RWX mappings are not executable in a PS5 title. Use the SDK JIT pool.
|
||||
patch -d "$source_dir" -p1 < "$root/patches/beetle-saturn/ps5-executable-memory.patch"
|
||||
core_fork_info mednafen_saturn_libretro.info ec7785e6a9efd3000f730c463f6711273c1f7d28e87b73f8ee7e2ab6751fc779
|
||||
|
||||
# LDFLAGS goes in the environment: the makefiles add their own to it.
|
||||
LDFLAGS="$core_ldflags $core_libs" make -C "$source_dir" -j"${JOBS:-16}" platform=ps5 CC="$core_cc" CXX="$core_cxx" AR="$AR"
|
||||
core_fork_stage "$source_dir/mednafen_saturn_libretro.so" "$core_info" "$revision" tools/build-beetle-saturn.sh
|
||||
core_fork_stage "$source_dir/mednafen_saturn_libretro.so" "$core_info" "$revision" tools/build-beetle-saturn.sh \
|
||||
patches/beetle-saturn/ps5-executable-memory.patch
|
||||
Reference in new issue
Block a user