With lines batched, 8K widescreen still switched to the wide surface and
back for every textured or flat batch that reaches the margins (~29 per
frame at 21:9 in an R4 race; 32:9 flushes ~4x as many textured batches).
At 18x those surfaces are 10080x9216 and 15372x9216, and each switch ends a
render pass: with the mirror drawn into the hr surface instead (no switch,
gl_ws_ablate 3) 32:9 at 8K ran at 57 guest frames/s instead of 12.
In windowed mode a draw's native-wide mirror now rides in its window queue
entry (target surface, x shift, backdrop stretch) and is replayed in the
queue's flush, in order, one pass per wide surface (hiw_replay_wide). The
queue's sync points already cover what the mirror samples (the raw mirror)
and the stencil rebuild; every other write to a wide surface (the clears,
the full-screen overlay rect, reallocation) and every read of one
(present, capture, dumps) now flushes the queue first. Outside windowed
mode, and with the mirror ablated, the immediate mirror runs as before.
- gl_scale_invariance_test: the window runs' native-wide surfaces (the
scene's and the new lines runs') stay byte-identical to the full-VRAM
runs, and the lines runs check that the mirrors were queued. Mutations
fail it: no queueing (the queue check), a wrong x shift or no replay
(the wide digests).
- R4, same setup as the previous commit: 21:9 at 8K 34.2-37.7 -> 56.1-56.6
guest frames/s (4:3 at 8K: 59.4), 32:9 12.6-13.8 -> 45.1-45.9; mirror
passes per frame 29 -> 0.5. With the debug server's per-frame readback on
(the default debug build): 21:9 43.7, 32:9 40.0.
- test_gl_internal_scale_guards pins the queued path, the replay state and
the sync points.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In windowed mode (8K past a 16384 texture limit: VRAM at 1x plus the
high-resolution window at S) lines stayed immediate. Each one drew GL_LINES
on the 1x hr surface and then, with native-wide, switched to the wide
surface (10080x9216 at 21:9 and 18x, 15372x9216 at 32:9) and back for its
mirror. In an R4 Grand Prix race that was ~130 mirror passes per frame:
21:9 at 8K ran at 15 guest frames/s and 32:9 at 5.5.
A batched line now carries two vertex sets. Its one-native-pixel quad joins
the flat batch with the triangles, as above 1x, and is what the window and
the wide surfaces draw. Its two GL_LINES vertices go in s_fbl, with the
batch position of its quad in s_fbl_at. The 1x hr draw
(flat_batch_draw_hr_lines) walks the batch in order, drawing triangle runs
from s_fb and line runs as GL_LINES from the copy uploaded after the
batch's vertices, so painter order and the 1x pixels are unchanged. A batch
without windowed lines keeps its single draw; outside windowed mode nothing
changes (s_out_scale > 1 is the old gate there).
- gl_scale_invariance_test: new "lines" runs (lines interleaved with
triangles that overlap them, over a native-wide surface) at 1x and 9x on
the full-VRAM surface and 9x and 18x in windowed mode. The windowed runs'
native frame equals the 1x run's, and at 9x their frame and wide surface
equal the full-VRAM run's; above 1x the lines and the triangle must share
one flat batch, windowed lines with their GL_LINES vertices. Every
existing digest line is unchanged, and the lines runs give the same
digests against the renderer without this change (immediate lines).
Mutations fail it: drawing all triangles before all lines, or the quads
on the 1x surface.
- R4 (scratch merge with feat/adaptive-widescreen c042434c and the R4
widescreen mod, one race savestate, debug build, GL timer queries and the
debug server's per-frame VRAM readback off): 21:9 at 8K 15.0 -> 34.2-37.7
guest frames/s, 32:9 5.5 -> 12.6-13.8; mirror passes per frame 132 -> 29.
- test_gl_internal_scale_guards pins the gate, the second vertex set and
the ordered 1x draw.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The flat batch mirrors into whatever native-wide target is current when it
is flushed. glb_wide_set_target() and glb_wide_disable_target() drained only
the textured batch before switching, so flat triangles -- and, since the
previous commit, line quads above 1x -- still queued at a switch would be
mirrored into the new target. The draw-area change that normally precedes a
switch (GP0 E3 -> glb_set_draw_area) already flushes both batches, so this
is a guard rather than an observed fault; the identical change is on
feat/adaptive-widescreen, which batches native-wide lines at 1x.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found in the R4 integration build: widescreen 21:9 (native-wide) at 4K ran
a Grand Prix race at 22-30 guest frames/s instead of 60 (26 with the
debug build's GL timer queries off). A CPU sample put
~57% of the emulation thread in glb_draw_line -> gpu_geometry ->
glDrawArrays -> the driver ending a render pass: every line was drawn on
its own, flushing the textured batch and, with native-wide, binding the
wide surface and the hr surface again for its mirror. R4 draws hundreds of
lines per race frame; at 9x each of those render-pass switches stores and
reloads a 9216x4608 surface.
Above 1x (full-VRAM surface, s_hr_scale > 1, not windowed) a line is
already a quad of two triangles (line_to_quad), drawn with the GEO program
like a gouraud triangle. It now joins the flat batch: same vertices, same
program, same painter order and batch keys (semi, mask). A line the
backdrop-stretch gate would widen keeps the immediate path, since the flat
batch mirrors unstretched. 1x keeps GL_LINES unchanged and the windowed
high-resolution mode keeps its own path.
- run_gl_scale_invariance (real GL; its fixture draws horizontal,
diagonal, steep and side-by-side lines): passes, and all 48 digest lines
of its 14 probe runs are identical to the build without this change.
- R4 21:9 at 4K from one race savestate (debug build, GL timer queries
off, widescreen only): 26.1 -> 59.9 guest frames/s over 4-10 s; 4:3 at
4K stays 59.9.
- test_gl_internal_scale_guards pins the gate and that the batched path
issues no draw of its own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Windowed high-resolution mode kept one window over the union of displayed
columns. Two 512-wide buffers side by side need 18432 px at 18x, past a
16384 GPU limit, so the second buffer was refused and every other frame
presented at 1x.
- The window is now up to four tiles, each its own surface over a column
range. A new display first tries one surface over the union of all
displays (the old behaviour, so R4's 320-wide window is unchanged), then
a merge with the tiles it overlaps, then a tile of its own. Every
mirrored write (queued draws, fills, uploads, copies, the depth24 clear,
stencil rebuilds) goes to each tile it touches; present, captures,
screenshot_hires and the native-wide centre read the tile holding the
display. A display no tile can hold within the GPU limit, the memory
budget (all tiles together) or the tile cap still presents at 1x, logged.
- A copy into the window stages its S-scaled source in a scratch of its
own, in column chunks that fit the GPU limit, walked in memmove order so
an overlapping copy still reads pre-copy pixels. The shared scratch no
longer grows past the hr surface for it.
- Staging textures commit a new size only after the driver accepted the
storage; a size past the limit is refused with a log line and the
texture keeps its old storage (scratch_ensure used to record the size
before a glTexImage2D that could fail).
- PSX_GL_MAX_DIM lowers the GPU limit the backend plans with (testing a
layout for a smaller GPU). video_info adds display_x/display_y,
hires_window_tiles and hires_window_mib.
- gl_scale_invariance_test: side-by-side runs flip two 512-wide buffers
and require one surface at 5x and two tiles at 9x (PSX_GL_MAX_DIM=8192)
to equal the full-VRAM surface, including copies between the buffers
and 1000-column copies; at 18x both buffers must read back at S. A
scratch request past the limit must be refused and leave the texture
and its recorded size intact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The high-resolution window made the GL backend's single scale two: the
scale of s_hr_fbo (1 in windowed mode) and the scale presented (up to
32). The previous commit kept s_scale for the presented one, so code
written against the old contract (s_hr_fbo at s_scale) still compiled
after a merge and read the 1024x512 surface at 18x coordinates in
windowed 8K. The frame-rate branches add exactly such reads (render-pass
capture, backup, journal and verify).
Rename the presented scale to s_out_scale, keep s_hr_scale, document the
contract at the declarations, and #pragma GCC poison s_scale, so every
use of the old name fails to build and must pick one: s_hr_scale for
s_hr_fbo and whatever backs it up or mirrors it, s_out_scale for the
window, the wide surfaces and captures of the presented image. A VRAM
transaction must also back up and restore the window's rows while
hiw_on(), or refuse to run.
No behaviour change: a mechanical rename. gl_scale_invariance_test
(real GL, window forced at 2/3/5/9/18x) passes; new guards check the
poison and that a function binding s_hr_fbo at s_out_scale also handles
the window.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gl_scale_invariance_test also mirrors margin-reaching draws (flat, gouraud,
textured, a line across both margins) into a 16:9 native-wide surface and
requires its full dump at internal resolution to match between the
full-VRAM and windowed runs at the same scale. This covers the wide passes'
sample-grid shift in windowed mode and the centre blit from the window;
dropping the shift switch fails it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mirroring every batch into the window as it was flushed switched
framebuffers twice per batch. On Apple's GL (Metal underneath) each switch
ends a render pass, about 80 us: 10 ms of CPU per R4 frame at any window
scale, and the 8K preset ran at 21 fps (frame_perf total 47 ms,
cpu_flush 17.4 ms).
The window's copies of textured, flat and line draws are now queued
(vertices plus the state they were drawn with: blend key, set-mask,
mask-check, texture window, filter, sampled texture, draw area) and
replayed into the window in one pass at the next sync point: before the
raw mirror changes (pack, upload, depth24 clear), before any immediate
write to the window (fill, copy, upload, stencil rebuild), and before every
read of it (present, capture, growth, hires readback). Order within the
window is kept, so it equals an immediate mirror wherever it is observed.
tex_batch_draw_passes and mask_stencil take their mask state as
parameters (tex_draw_passes_ex, mask_stencil_ex) so the replay uses the
recorded state; the canonical pass calls them with the live state, the
same GL call sequence as before (native and 2x/4x digests unchanged).
Measured on an M4 in a race: 8K total 16.68 ms per present (60 Hz
cadence), cpu_flush 0.62 ms; forced window at 4K likewise. The invariance
test still finds the window's frame byte-identical to the full-VRAM
surface at 2/3/5/9x.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
8K is 18x at a 240-line reference, and a full-VRAM surface at 18x is
18432 px wide: over the 16384 limit of Apple's GL, Intel and MoltenVK. A
title only needs its displayed frame at 18x, so past the full-VRAM limit
the GL backend now splits the work:
- The authoritative VRAM stays the ordinary hr surface at 1x, i.e. the
native renderer unchanged: pack, CPU readback, render-to-texture and VRAM
copies are exactly the native results (s_hr_scale; s_scale stays the
presented scale gr_scale reports).
- A presentation-only surface at S covers the displayed columns W =
[x0, x1) x all 512 rows (R4: 0..319, 5760x9216 at 18x, 405 MiB). Every
GPU write touching W is mirrored into it: textured and flat batches,
lines (quads), fills, uploads, the depth24 clear, and VRAM copies (hi to
hi when the source is in W, otherwise the 1x source upscaled; both staged
before drawing so overlapping copies read pre-copy pixels). It keeps its
own stencil. A separate blit program carries the window projection, so
the canonical shaders are untouched.
- W grows (64-column aligned) the first time a display rectangle outside it
is presented, seeded by upscaling the 1x content. Present, hold-last,
interpolation capture, screenshot_hires and the native-wide centre read
it; a display it cannot hold presents at 1x.
It engages only when the full-VRAM surface cannot hold the request (driver
limit or budget), sized so a 320-wide window fits both; up to 16x on the
M4 nothing changes. PSX_GL_HIRES_WINDOW=0/1 disables or forces it. The
launcher note and video_info (hr_scale, windowed, hires_window_*, hires_fbo)
report it.
Default-off: at 1x and whenever the full-VRAM surface fits, the paths are
the previous ones (same native-VRAM and present digests on a fixed scene at
1x and 2x).
Tests: gl_scale_invariance_test now also forces the window at 2/3/5/9x and
requires its frame at internal resolution to be byte-identical to the
full-VRAM surface at the same scale (copies inside, into and across the
window edge, fills/uploads across it, mask, all blend modes) with native
VRAM identical to 1x, and runs it at 18x; gl_scale_limits_test covers the
window clamp; guards pin that it only engages past the full-VRAM limit.
Verified in R4 on an M4: the 8K preset renders 5760x4320 in a race (rear-
view mirror present) and 5760x8640 on a 480i menu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The capture dumps the wide surface from its top row into a buffer capped at
8192x8192 pixels, then cuts the displayed band out of it. A 21:9 surface at
18x is 10080 wide, so the cap held 6657 of its 9216 rows: with R4's lower
double buffer displayed (y 240, band rows 4320..8639) the capture came back
10080x2337 instead of 10080x4320. Size the buffer to the end of the displayed
band at the native-wide width (up to 256M pixels); smaller captures keep the
old budget.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A host built against a recomp-ui without the Internal resolution row
(RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION undefined) still seeded
internal_resolution on first boot and applied it after the launcher.
From a fresh start the seed was "native", so a Supersampling pick of 3x
was reset to 1x and "native" was saved; on the netplay soft-return the
sticky preset was re-applied at session_reboot. The legacy row stopped
working.
Both launcher exits now go through two pure helpers in
internal_resolution.h:
- psx_ir_launcher_seed_supersampling: with the row, the factor as before;
without it, the factor itself when no preset is configured (the
historical round trip), else the preset's scale capped at the row's 4x.
- psx_ir_adopt_launcher: with the row, the row's preset as before;
without it, a pick in the Supersampling row drops the preset, and an
untouched row keeps a preset the player cannot see (game.toml or a
hand-edited settings.toml). It also returns what settings.toml saves:
no internal_resolution key unless a preset is kept.
internal_resolution_test drives seed -> launcher -> adopt for both
launcher kinds, first boot and soft-return, against a model of the
legacy row (clamp to 1..4, cycle); keeping the old sticky preset fails
it. gl_internal_scale_guards pins both exits to the helpers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The environment override was written into g_video_internal_res, the
configured preset. On a netplay soft-return the launcher was seeded from
it and saved it to settings.toml, so one local peer started with
PSX_INTERNAL_RESOLUTION=8k left 8k in the settings.toml the other peer
shares: the case the override exists for.
Keep the override in g_video_internal_res_env. It still wins for the run
(scale, Match display, HiDPI window, video_info), but the launcher only
shows, and settings.toml only saves, the configured preset.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A preset id or a line count in PSX_INTERNAL_RESOLUTION overrides every
config layer, like the other validation env overrides (PSX_SCANLINES,
PSX_GEOMETRY_CORRECTION). Two local netplay peers share one settings.toml,
so this is how one runs at 4K beside another at Native. Also say
"measured when the game window opens" for Match display before the window
exists instead of logging a 1x request.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a player-facing internal resolution on top of the raised GL ceiling.
A preset is a target height; the runtime renders at the integer scale
S = ceil(target / reference_lines), reference 240 by default: 720p 3x,
1080p 5x (area-resolved to 1080), 1440p 6x, 4K 9x, 5K 12x, 8K 18x. The
backend then clamps S to what it can allocate.
- runtime/include/internal_resolution.h: the preset table, stable ids,
the value encoding shared with recomp-ui (0 unset, 1 native, -1 match
display, N target lines) and the pure resolver.
- config: [video] internal_resolution (a preset id or a number of lines)
and resolution_reference_lines in game.toml; internal_resolution in
settings.toml, written as a stable id beside supersampling = min(S, 4)
for older runtimes. Precedence: game default < player's legacy factor <
player's preset. settings.toml window_width now accepts up to 7680.
- main.cpp: resolve the preset before gpu_init; Match display re-resolves
from the game window's monitor (SDL3 mode height x pixel density) before
the GL context allocates. The launcher gets the vocabulary (with a
synthesized "Nx (L lines)" entry for a legacy factor no preset matches)
behind RECOMP_LAUNCHER_HAS_INTERNAL_RESOLUTION, on first boot and on the
netplay soft-return.
- The OpenGL game window gets SDL_WINDOW_HIGH_PIXEL_DENSITY (SDL2:
ALLOW_HIGHDPI) only when the player chose more than native, so the
drawable is in pixels on Retina; native keeps the window as it was.
- debug server: video_info (preset, requested and effective scale, GL
limit and clamp, hr surface, window points vs pixels), screenshot_hires
reads the GL hr FBO at full size, screenshot_wide_hires captures the
native-wide band at internal resolution.
- docs: config_schema (keys, precedence), NETPLAY (a per-peer presentation
setting), TCP_COMMANDS (index regenerated), ENHANCEMENTS IR1.
Default-off: with no internal_resolution anywhere the scale, the window
flags and the present path are unchanged.
Tests: internal_resolution_test (presets x reference 240/480 x backend
maxima, legacy mapping round trip), video_enhancement_settings_test (game
and settings keys, stable-id round trip, legacy key still written),
gl_internal_scale_guards (HiDPI only when opted in, launcher fields behind
the capability macro).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
run_gl_scale_invariance.py linked the probe with -undefined dynamic_lookup
(--unresolved-symbols=ignore-all on Linux), so a renderer call into a
source the probe did not build bound to NULL and crashed the run (-11)
instead of failing the link. Once the frame-rate render passes land, the
renderer calls render_pass_plan.c and frame_interpolation.c, and the
probe crashed on every run.
Link frame_interpolation.c (the fixture's stub for it goes) and
render_pass_plan.c whenever it exists, and drop the unresolved-symbol
flags: unused renderer functions are still removed (-dead_strip, or
per-function sections with --gc-sections), and anything left unresolved
is a link error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A native-wide surface is g_wide_w*S wide and the driver limit bounds it
(1024 native columns at 16x on a 16384 limit, about 38:9 at a 320-px
display). An uncapped Fit to Window aspect could ask for more; wide_fbo_for
then refused the surface and the frame fell back to a 1x CPU present with
no native-wide margins.
update_adaptive_widescreen now narrows the Fit aspect to the widest the
surface holds (gl_renderer_fit_wide_aspect: psx_gl_max_wide_width at the
context's scale, psx_gl_fit_wide_aspect at the current display width,
gpu_ws_display_width). It changes nothing unless the surface would be
refused. The refusal stays for a fixed aspect on a wide display mode; its
comment now gives the right limit and what the frame falls back to.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The OpenGL backend capped supersampling at 4, the software mirror's limit,
although its hr surface lives on the GPU. Raise the compile-time ceiling to
32 (gpu_render.h) and decide the real scale at context init:
- Query GL_MAX_TEXTURE_SIZE, GL_MAX_RENDERBUFFER_SIZE and
GL_MAX_VIEWPORT_DIMS and clamp S so the 1024*S x 512*S surface fits them
and a 2 GiB memory budget (PSX_GL_VRAM_BUDGET_MB overrides it). Apple's
GL on Metal reports 16384, so 16x is the most a full-VRAM surface can be.
The clamp is logged with the limit that applied.
- If the surface still fails to allocate, retry one scale lower inside GL.
Only a 1x failure drops the backend to software, as before.
- Draw lines above 1x as quads one native pixel thick covering both
endpoints. glLineWidth(S) is capped at 1 on core profiles, so every line
was one hr pixel thick (1/9 of native at 9x).
- Present a supersampled source with an area resolve when it is more than
1.25x the output (1200 lines into a 1080 window, 480i menus), and inset the
UV rect by half a texel instead of half a native pixel, which cropped and
zoomed the image by (S-1)/2 texels per edge.
- Size the copy scratch to the largest copy (copies stage at its origin) and
rebuild the mask stencil in tiles, only over the primitive bbox union, so a
large S does not cost another full-size surface.
- Refuse a native-wide surface wider than the driver limit (uncapped Fit at
a high scale) with one log line; the frame presents 4:3.
- main.cpp: the offline and dual-raster clamps no longer cap GL at the
software 4x. The CPU present path presents GL frames at 1x (its readout is
native) and its staging buffer stays sized for at most 4x.
- [video] supersampling accepts 1..32 in game.toml and settings.toml; the
runtime clamps per backend.
Every change is gated on S > 1: at 1x the renderer is byte-identical (same
native VRAM and presented framebuffer digests as the previous source on a
fixed GP0 scene).
Tests: gl_scale_limits_test (clamp arithmetic), gl_internal_scale_guards
(source guards + runner parsing), and gl_scale_invariance_test, a hidden
real-GL run at 1,2,3,5,9x that requires identical guest-visible VRAM at
every scale, one-native-pixel lines at internal resolution, and a 32x
request that stays on GL at the driver's clamp (16x on Apple).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Winsock sockets are inheritable by default. Any child process the runtime
spawns (e.g. the overlay autocompile's `cmd.exe /C python compile_overlays.py`)
inherits the debug server's listening socket; if the game exits while the
child is still running, the child keeps 127.0.0.1:<debug_port> bound and the
next launch cannot bind it (clients get connection refused / talk to a dead
listener).
Observed: after closing the game mid-autocompile, `netstat -ano` showed :4370
LISTENING under the exited game's PID, held by the surviving python child;
killing the compile freed it. Fix: SetHandleInformation(HANDLE_FLAG_INHERIT, 0)
right after socket(). No behavior change on non-Windows.
This change was made with AI assistance (Claude Opus 5.5, Anthropic) and
reviewed/tested by the submitter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found with the Khronos validation layer on AMD RX 7900 XT (Windows, mingw),
where D24S8 is unavailable and choose_ds_format() picks the combined
D32_SFLOAT_S8_UINT:
- VUID-VkImageMemoryBarrier-image-03320: every view/barrier/clear on the
canonical and wide depth-stencil images named only the STENCIL aspect.
Without separateDepthStencilLayouts, a combined depth/stencil format must
be transitioned with both aspects. Added DS_ASPECT and used it for the
image views, barriers and vkCmdClearDepthStencilImage ranges.
(vkCmdClearAttachments keeps the stencil-only mask - that is legal.)
- VUID-vkCmdClearDepthStencilImage-pRanges-02659: the canonical DS image is
cleared with vkCmdClearDepthStencilImage but lacked
VK_IMAGE_USAGE_TRANSFER_DST_BIT (the wide DS images already had it).
- VUID-vkCmdCopyImageToBuffer-dstBuffer-00191: staging buffers are used for
readbacks (vkCmdCopyImageToBuffer) but were created with TRANSFER_SRC only.
Validation messages over the same 20 s boot (SmackDown 2, Vulkan):
53 -> 3 (the remaining VUID-vkQueueSubmit-pSignalSemaphores-00067 swapchain
semaphore reuse is untouched). The fix also cleared the downstream
VkImageMemoryBarrier-oldLayout-01213 and vkCmdDraw-None-09600 reports.
This change was made with AI assistance (Claude Opus 5.5, Anthropic) and
reviewed/tested by the submitter.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adapt the 8 MB RAM work from the rbengine branch into a master-targeted change. The builtin package is disabled by default, activation requests expanded RAM before memory init, and runtime/state/digest/dispatch paths respect the live RAM map.
The setup host located itself with realpath("/proc/self/exe"), which only
exists on Linux. On macOS it failed, so a host launched from Finder (cwd =
$HOME) could not find its project tree: Generate & rebuild never appeared
and forward-to-built-game never fired. Take the path from dyld's
_NSGetExecutablePath there (as recomp-ui's launcher_model.c already does);
Linux and Windows are unchanged.
The netplay rollback "binary path" diagnostic had the same /proc read and
logged "(unknown)" on macOS; it uses the same source now.
No emulation or runtime behaviour changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
recomp-net now carries the peer-facing rollback modules that used to live in
retcomm-rbengine (RetroPortingToolKit/recomp-net#14). Switch the MotK shims and
psx_netplay_sched.c from rbe_sched_* / rbe_ih_* / rbe_hc_* /
rbe_rb_peer_post_tip_ok to their rnet_* names and recomp_net/ headers, and bump
lib/recomp-net to c2338c6.
The netplay_* / np_sched_* surface the rest of the runtime calls is unchanged.
The snap ring and rbe_mono_ms still come from retcomm-rbengine, which stays at
a7b9850 for now; the three moved-module unit tests link recomp_net directly
instead of reaching it through rbengine. RBE_RB_* env knobs keep their names.
Checked with PSX_NETPLAY=ON: psx-runtime links and the netplay tests pass
against both the current rbengine and the split one (rbengine
refactor/launcher-core), and the binary's 33 scheduler / history /
hash-confirm functions now resolve to rnet_* where they were rbe_*.
lobby_chat_ring_test does not compile on master either (chat_push arity) and
is untouched here.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Default = largest multiple of 240 lines within 2/3 of the usable height;
an explicit window_width is still honoured.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>