Skip to content

pull reqyest fine young man - #406

Open
xellow78-lgtm wants to merge 22 commits into
NotRexed:mainfrom
xellow78-lgtm:main
Open

xellow78-lgtm wants to merge 22 commits into
NotRexed:mainfrom
xellow78-lgtm:main

Conversation

@xellow78-lgtm

Copy link
Copy Markdown

No description provided.

xellow78-lgtm and others added 22 commits November 7, 2026 08:00
A corrupt record in hookshot_programs.bin crashed the Presentation Thread
in program_cache_load: Reader::list read a garbage byte count for st.c1
and copied past the record's buffer into an unmapped page
(hookshot_vk.dll+0x190fe1, exception 0xc0000005).

- Reader now carries an end pointer; reads past it set `bad`, counts are
  capped by the bytes left, and a bad record is logged, skipped and
  translated again instead of crashing.
- disk_init takes a per-path named mutex. A second Hookshot started while
  the first is writing used to see the record being written as cut short
  and truncate the file under the running instance; it now runs without
  the cache instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
Brings in the GPU pointer window at 0x7f00000000 (cbed9ad), the 8 GB VRAM
mirror cap and the Resolution 100% black-screen fix (c02f290), on top of
the program cache crash fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
…one button

launcher/launcher.py runs on the builder package's own Python
(tools\python) with the standard library only, and shows its page in the
browser on 127.0.0.1. It checks the newest commit of the chosen source
(the fork, or NotRexed's repository) against the one tools\ holds,
downloads that commit as a zip, writes only the files whose bytes changed
into gpu, host, nx2, scripts, third_party and launcher (keeping what they
replace in launcher_backups, the last three updates), then runs
nx2\make_game.py with the settings in launcher.json as HookshotBuilder.exe
does. Files the update never wrote are never removed. It updates itself
along with the rest. POSTs need the page's token and a 127.0.0.1 Host.

Start it with "Hookshot Launcher.bat" beside HookshotBuilder.exe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
One player's mouse did nothing (keys worked). The log said nothing about
the mouse, so where it stops is unknown. Now logged:
- whether raw mouse input registered (it was unchecked), with the error
- each capture and release, and why (click, Esc, focus lost, cancel mode),
  and a failed ClipCursor
- every 5 s while the mouse did anything: clicks, raw reports (all, while
  captured, absolute ones, which are not used), the motion taken, the
  mouse stick and the right stick the game was given

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
v1 used the last check's answer, which could be minutes old: a commit
pushed after that check was missed (the mouse diagnostics build installed
the commit before them).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
… memory

Native mouse look needs the camera's own angles, and nothing names where
they are. F6 starts a ~25 s run that has the controls: for yaw and then
pitch it snapshots the heap's used pages, leaves out what changes with
nothing pressed, turns the camera one way, back, and the first way again,
and keeps the floats that moved with each turn by a similar amount and
stayed still between them (an angle that wraps counts the short way). The
candidates are logged with the floats around them.

Tested on a simulated heap: the yaw (wrapping past pi) and pitch were
found, the animation noise and a value that only follows one direction
were left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
…y candidate to a file

v1 turned one way, back and the first way again, which a flag that says
which way the camera last turned passes as well as an angle: most of its
best were such flags. Now the second turn goes on the same way (an angle
moves on, a flag does not), then back. Floats that were 0 before or after
the first turn (fresh objects) are left out. The yaw candidates are
watched while the pitch is found and must hold still, and a last yaw turn
must leave the pitch candidates alone. Every candidate left is written to
<user>/camfind.txt with the 512 bytes before it as 64-bit words (the
object and its vtable). Several threads read the controller: one does a
step's work at a time.

Tested on a simulated heap with such a flag, a value that moves with both
axes, and fresh values: only the yaw and the pitch were left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
…own angles

The camera finder found the player camera in Kokiri Forest: its
controller holds the pitch limits {-85, 89, -85, 89} (degrees), its pitch
at +0x14 from them and its yaw at +0x2c, which the stick turns about 90
degrees a second (yaw falling to the right, pitch falling as the stick
goes up); its output (pitch and yaw side by side) follows. With
HOS_MOUSE_NATIVE=1 the captured mouse adds to those (0.1 degree a count
at sensitivity 1; - and = as before) instead of standing in for the right
stick: no decay, no response curve, no top speed. The limits are looked
for in the heap when the mouse first moves and again when they move (a new
scene). Which copy the game reads is not known yet: F7 cycles the target
(the controller, the output copies, both).

camfind.c: the used-page walk shared (hos_heap_find).
nn_hid.c: the mouse's setup out of mouse_stick, for both paths.

Launcher v3: "Game built from" (the commit of the last finished build),
a warning when it is older than the build tools, no "Up to date" while a
build runs, and an update that changes only the launcher skips the
rebuild.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
The test build's answers: the controller's angles are what the game
reads (target 1 turned the camera like a mouse; the output copies, target
2, did nothing: the game recomputes them), and the pitch was the wrong way
round (it rises as the view tilts down). Now:
- the mouse turns the controller only (no F7, no output copies), pitch
  the right way; HOS_MOUSE_INVERT_Y=1 flips it
- on by default; HOS_MOUSE_NATIVE=0 for the mouse as the right stick
- the heap is searched for the camera on a thread of its own (it held the
  game's thread ~950 ms on the first motion), at most every 3 s, then
  less often while none is found (up to 30 s)
- until a camera is found the motion is given back and the mouse turns
  the camera as the stick does (display.c: hos_mouse_give_back)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
The Insert/F1 menu was a list worked with the arrow keys alone (60%
keyboards have none) and no controller. Now:
- three tabs: Display, Performance, Camera & Mouse; a switch for on/off
  rows, a slider for the long ranges, arrows for choices; the help under
  them; the pause menu's colours (still only rectangles and text: the
  POSIX GDI stand-in has nothing else)
- the mouse (Windows): hover selects, a click flips a switch, steps a
  choice (the left or right half) or sets a slider, which drags; tabs and
  a close box. The window lets the mouse go while the menu is open and
  does not take it with a click then (display.c)
- the controllers: both sticks pressed in open and close it; the d-pad,
  A, B, L and R work it (vk_api.h: menu_pad). The game gets nothing from
  the pads while it is open (before: only the keyboard was kept from it)
- the keyboard: as before, plus Tab (next tab) and Enter; held arrows
  repeat
- Camera & Mouse: Mouse camera (Native / As the stick), Mouse sensitivity
  (one for every camera, 0.10 to 5.00) and Invert vertical, kept in
  hookshot_options.ini (rx_option 4, 5, 6). - and = change the
  sensitivity there (vk_api.h: option_set); mouse_sens.txt's value is
  moved in once; HOS_MOUSE_SENS, HOS_MOUSE_INVERT_Y and HOS_MOUSE_NATIVE
  still win

Rendered on Linux through the GDI stand-in to check the layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
…hanged

Two new tabs (the tabs are now Display, Performance, Camera, Keyboard,
Controller; the menu 540 wide):
- Keyboard: each of the game's 16 buttons, the four moves and the four
  camera directions has two keys (keys or mouse buttons: left, right,
  middle, 4, 5). Enter, A or a click on a key waits for the new one (the
  press that began it is let go first; Esc keeps the old one, Backspace
  clears it, 8 s give up); left and right choose the first or second key;
  Backspace or the pad's X clears the selected one. A mouse button counts
  only while the mouse is captured, as before.
- Controller: each of the game's buttons can be pressed by any pad
  button, named by where it is (Bottom face (B / A / Cross) ...). The menu
  itself keeps working with the pad's usual buttons, so no change can lock
  it.
- Reset rows on both; the long tabs scroll (the selection is kept in
  view; the mouse wheel scrolls: display.c passes it, option 10).

nn_hid.c: the fixed key table, the mouse's Y and ZL and the WASD,
arrow and IJKL sticks are now the bindings (rx_option 100 + action * 2 +
slot, 200 + button), with the same defaults (checked against the old
table); without the Vulkan back end the defaults are used.

Rendered on Linux through the GDI stand-in to check the layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
… upstream's binding table

Upstream added its own Controls page, the menu from a controller (Home, or Back and Start) and a
"Controller in background" option, in the same files as the fork's control remapping and menu.

Kept from upstream: the binding table in host/nn_hid.c (gamepads by position, HOS_PAD_*;
pad_<button> and key_<button> lines in hookshot_options.ini; host->binding, bind and pad_raw),
the menu from a controller, the pads kept from the game while the menu is open, and option 4
(controllers behind other windows), now a row on the Controller tab.

Kept from the fork: the tabbed menu with the mouse, the native mouse camera, the sensitivity,
the camera finder. The menu's Keyboard and Controller tabs show and change upstream's table.
The table gains eight keys only controls (HOS_KEY_*: the left stick's and the camera's
directions) and takes mouse buttons as keys, which count only while the mouse is captured
(left button Y and right button ZL by default, as before). bind with button -2 resets one set
(the Reset rows of each tab). The fork's options move to 20 (sensitivity), 21 (invert) and 22
(mouse camera); option_set 29 is the wheel. menu_pad and options 100+ and 200+ are gone.

The fork's first menu wrote key_<row>_1/_2 and pad_<row> lines, its pad_ values Switch buttons:
read as positions they would have moved Plus, Minus and the d-pad. A file with key_plus_1 has
its keys taken over and its pad_ lines left alone until the menu saves it again.

The program cache's one-process lock is a file lock on Linux (CreateMutexA is Windows-only).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
…abbed menu

Upstream's Text speed (option 5) and Quality preset rows go on the Performance tab. A preset
sets its settings and GPU memory limits; changing one of the settings it sets, by arrows, a
click or a slider drag, makes it Custom (only those: upstream's menu also reset it on rows
the preset never touches, such as text speed). The fork's options stay at 20 to 22.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgQM2zLG8uS929WRQ7nxPQ
@NotRexed

NotRexed commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Thanks for the work! I can't review +2105/-396 lines across the renderer, input, display and a launcher with no description: could you split it into small PRs, one change each, with what it fixes and how you tested it (as the other PRs here do)? Several parts may already be on main now (controller rebinding #335/#343/#350, input in the background #359, Alt+Enter #405, quality presets #398), so rebasing on main first will show what's still new.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants