Nexus V1 Input Status

Retail evidence

The current input observations use the Japanese retail Saturn disc and BIOS in Ymir 0.4.1 with --debug. The evidence and paired screenshots are in parity-evidence/verification/keyboard-mouse-debug-20261024/.

A second controlled run loaded a hash-verified authentic Japanese retail gameplay savestate in a private Ymir profile. The no-input reload changed only 0.00175% of the captured pixels, while W-forward changed 3.08408% and A-left changed 5.08610%. The before/after captures and source hashes are recorded in parity-evidence/verification/nexus-savestate-input-20261025/. This independently confirms retail ControlPad movement from a stable gameplay state; it does not establish Firestaff runtime parity or ShuttleMouse actions.

The isolated Ymir ControlPad profile mapped W/S/A/D to Saturn D-pad up/down/left/right, J to A, O to Z, and F to Start. In a fresh profile with an empty BUP, F opened the title menu and S selected CONTINUE; a Right shoulder event (keyboard R in that profile) did not change the menu selection. Pressing J left the selected Continue row unchanged; no save-list transition was observed in this empty-BUP profile. In the retail dungeon view, W moved forward, A turned left, D turned right, and F displayed the game’s PAUSE overlay. O entered the game’s hand-cursor mode; W moved the cursor upward in that mode. The captures show real game output from the retail media, not generated or synthetic game state.

The ControlPad profile’s desktop click did not produce a separately attributable game action. A separate fresh profile configured Ymir port 1 as ShuttleMouse: after entering mouse-capture mode, a mouse-button event was followed by the retail title leaving its menu for the intro presentation. The ShuttleMouse BUP remained blank. This limited title-flow result does not prove pointer-coordinate targeting, in-dungeon mouse actions, or Firestaff mouse behavior. Attack, inventory, spell, champion-selection, and other non-movement button semantics remain unverified by these captures.

A separate authentic same-session Ymir --debug trace configured Port 1 as ShuttleMouse and drove keyboard bindings W, D, J, K and L. The raw 259-row SMPC trace records Y -30, X +30, and left/middle/right button reports, with five consecutive polls for each held input and no dropped trace entries. This confirms Ymir generated the corresponding Saturn peripheral report fields. It does not confirm that Nexus consumes them as pointer movement or gameplay actions, or that a physical desktop mouse is delivered through SDL. See the raw trace and its source hashes.

A later fresh-profile capture retained the actual orange Nexus hand cursor and measured its movement after O (Saturn Z) and D-pad input. W/S/A/D moved it up/down/left/right, and W+A moved it diagonally. The approximate per-press displacements and authentic screenshots are recorded in nexus-v1-hand-pointer-debug-20261025. The capture used Ymir fast-forward, so its host-time movement interval does not establish a normal-speed repeat rate. It does not establish mouse coordinates or button-to-action mapping.

A separate controlled gameplay-state sequence mapped K to ControlPad B and J to A. The --debug high-WRAM dumps show B queueing event 12 (EV_INVENTORY). A in that flow queues event 39 (EV_RING_SELECT) with argument 8; the visible retail view changes to an equipment page labelled 頭に装備 (“equip to head”). Context record 10 changes at +0x122/+0x124, but the capture does not join that record to a champion or prove a persistent item transfer. The screenshots, complete WRAM dumps, source hashes and event trace are recorded in nexus-v1-inventory-button-debug-20261025. Retail disassembly clarifies the boundary: event 12 validates and updates a global UI selection list, while event 39 invokes a callback on the current UI view to change pages. Neither handler writes a champion’s equipment slots in this capture, and the candidate champion slot pairs remain unchanged. Event 44 (EV_INV_EQUIP) is a separate retail slot-action route: its handler reads and writes context slot pairs, stages a displaced pair through the held-item path, and checks item compatibility. The live click-to-event route and the context-to-champion mapping have not yet been captured. The button trace therefore establishes menu navigation only; Firestaff inventory and equip actions remain disabled until those runtime joins are verified.

Firestaff title keyboard ingress

Firestaff maps F, Enter, keypad Enter, and Space to the Nexus startup Action while the Nexus title is active, including both SDL key-event paths. F matches the observed Ymir desktop binding for Saturn Start; Enter and Space are host keyboard aliases. At the ready title prompt, Action opens an internal retail-menu state with New Game selected. Up/Down arrows and W/S navigate the three choices. The English retail capture verifies Down from New Game to Continue and Up back to New Game with a pixel-identical final screenshot. The title-menu state is kept separate from Firestaff’s generic save/champion menu, and the shared Firestaff save mask is not treated as Saturn BKR availability. This input increment did not itself render the selected retail menu. Later capture-backed work added source-bound foreground sprites for English New Game/Continue and Japanese New Game/Continue/Configuration; full-screen composition and production destinations remain blocked. Mouse targeting also remains unverified. See the vertical navigation capture receipt.

Retail manual control model

The Japanese retail manual’s controller table (printed page 4) documents the input model independently of the Ymir experiments: D-pad directions move or turn in 3D mode and move the hand pointer in eight directions; L/R change the leader; Start pauses; A attacks in movement mode and inspects, searches, uses, or picks up in hand-pointer mode; B opens inventory; Y opens the magic window; Z toggles the hand pointer; and C stores a held item in the backpack. In hand-pointer mode, Y also moves the pointer to an item or switch. The manual’s inventory instructions (printed page 19) describe moving items between hand, champion slots, and backpack with the hand pointer. See the Japanese retail manual, control table and inventory instructions.

A-button attack remains unbound

The manual documents A as an attack in movement mode, but the authentic retail input-to-combat route is still unknown. In a Ymir 0.4.1 --debug probe, the Japanese retail ControlPad profile mapped J to A and loaded the same hash-verified gameplay savestate for the no-input and A-input runs. The high-WRAM comparison showed queue count zero in both captures. The read cursor advanced from 0 to 1 and a stale queue-storage word changed from event 56 (EV_SAVELOAD) to event 29 (EV_DYNAMIC), but a zero-count queue makes those records insufficient to identify a live event or attribute it to A. Context 10’s candidate item pairs matched the timed no-input control, and the captured view had no visible enemy; this probe does not establish an attack effect. Screenshots and source hashes are in nexus-a-button-debug-20261025; raw WRAM is kept outside Git on the external disk.

Static analysis of the authentic DM.BIN confirms combat cases at 0x0197FC and a case-0 branch to the champion-attack routine at 0x01986A. The call setup begins earlier at 0x0197DE; the disassembly report had previously mislabeled that address as the switch entry. Direct SH-2 literal and pointer scans find no input-to-combat reference, and the event-name table has no EV_ATTACK entry. These scans cannot exclude indirect dispatch. Do not route A to the host combat model until a live-enemy Ymir trace joins controller input, the retail dispatcher, and the resulting enemy/party state changes.

A Ymir --debug run on the authentic Japanese retail disc independently confirmed L/R leader changes: the configured L input selected the fourth party member and R returned to the first. The before/after game captures are in nexus-leader-cycle-debug-20261025. Firestaff routes its existing Tab “cycle champion” input through the loaded Nexus party order, matching the manual’s leader-change control. The captures establish the retail behavior, but do not identify the guest RAM leader field. The retail PLRD roster has no live/dead field, so Firestaff does not treat its zero-initialized runtime alive member as proof that a selected champion is dead. Leader cycling accepts a roster-backed party member with positive current health, and skips members whose runtime health is zero. This keeps the authentic start roster selectable without inventing liveness data.

These documented controls define the retail interaction contract. Firestaff implements the Z mode toggle and logical pointer movement in the captured viewport. Inventory/magic panels and pointer targets remain unimplemented; they must use Nexus-owned data and proven hit regions rather than DM1 panels or guessed coordinates.

Firestaff keyboard routing

The Nexus host keeps W/S for forward/backward and uses A/D to turn left/right, matching the authenticated Ymir ControlPad capture. Left/right arrow keys remain available for strafing through the shared M11 action map; Q/E and Home/End also turn. DM1 retains its own A/D strafe bindings. The Nexus-specific A/D mapping is evidence-based: Ymir mapped those keys to the Saturn D-pad, and the retail D-pad turns in movement mode.

The retail game tick accepts only the six basic movement commands (forward/backward, turn left/right, and strafe left/right) against the authenticated DGN grid. In the loaded dungeon, Z toggles a host hand-pointer mode. W/A/S/D and the arrow keys move its logical position across the authentic NEXUS_HIT_FULL_GAME_SCREEN rectangle parsed from DM.BIN; simultaneous directions allow diagonal movement. Firestaff clips its lower edge to the 320×200 source framebuffer. This lets the visible hand cursor move from the viewport over the Nexus HUD. The W/A/S/D mapping matches the captured retail profile’s D-pad bindings. Mouse motion positions the hand pointer directly across the same screen area. The hand sprite is sourced from the hash-verified retail ITEM.IBS image 65 and palette 6, joined against Ymir --debug VDP1 texture capture. Mouse movement and the six keyboard movement commands remain available with pointer mode off. The authentic DM.BIN movement-pad rectangle is also wired as a six-cell desktop movement surface: the upper row maps to turn left, forward, and turn right; the lower row maps to strafe left, backward, and strafe right. This host mapping uses the retail rectangle but does not claim to reproduce the unresolved callback’s cell semantics. Clicks elsewhere and hand-pointer clicks remain inert. A/B/Y/C actions remain inert until their retail consumers are traced. Tab cycles to the next party leader and Shift+Tab cycles to the previous party leader in Firestaff’s desktop controls. The reverse direction is a host keyboard convenience; it does not claim that the retail L/R events or an identified guest RAM field have been reproduced. Item use, inventory, spells, combat, sensors, doors, and level transitions remain fail-closed.

In a loaded Nexus dungeon, Space toggles Firestaff’s host pause. Ymir evidence records that the retail Start button displayed the PAUSE overlay; whether retail gameplay resumes on a second press remains unverified. Firestaff’s host pause freezes the session tick and host audio until Space is pressed again. This does not reproduce the retail PAUSE graphic or menu.

With pointer mode off, left-click within the authentic Nexus movement-pad rectangle parsed from DM.BIN to send the corresponding desktop movement command: the upper row maps to turn left, forward, and turn right; the lower row maps to strafe left, backward, and strafe right. This host mapping uses a retail rectangle but does not claim to reproduce Saturn ShuttleMouse or the retail callback’s unresolved cell semantics. Every Firestaff pointer-button entry point uses that same rectangle and six-cell mapping; clicks elsewhere do nothing. With pointer mode on, mouse motion moves the logical hand pointer across the viewport and HUD. Mouse clicks remain inert while the callback’s HUD-region action semantics are unresolved.

scripts/analyze_nexus_mouse_event_crossrefs.py inventories direct SH-2 MOV.L @(disp,PC),Rn references in the hash-verified retail DM.BIN. In the hash-pinned Japanese retail image, none of the 60 event-name strings has a direct literal-pointer reference. The image does reference the HUD hit-rectangle subtable beginning at file offset 0x38040, and yam\\mouse.c appears in a separate source-path reference. The string scan alone cannot resolve indirect tables or generated pointers. The callback trace below follows one path beyond those string references, but it still does not bind individual hit regions to game commands.

The analyzer now also verifies one retail registration and dispatch chain. SH-2 instructions at DM.BIN:0x16588 load a callback at runtime address 0x060264a8, a companion table at 0x0604850c, and the hit rectangles at 0x06048040 (DM.BIN:0x38040), then call the setup routine at 0x06034ad0. That routine stores the supplied callback pointer in a global slot; the paired dispatcher checks its active flag and makes an indirect call through that slot. A second verified path at DM.BIN:0x164a8 reads fields at object offsets 100 and 104. When the first field is 6, submode 0 queues numeric event 13 and submode 2 queues numeric event 44 to 0x06024288; submode 1 does not queue either event. The retail event-name pointer table maps ID 13 to EV_EXIT_INV and ID 44 to EV_INV_EQUIP. The event-44 dispatch target and slot-pair access/write path are verified below, while its held-item UI effects and Firestaff state mapping remain unverified. The analyzer checks the branch targets, event values, queue target, and name pointers against the hash-verified Japanese retail DM.BIN.

The same retail image contains an eight-entry action-rectangle table at file offset 0x3850c. Each 12-byte record stores (x1, y1, x2, y2, event, slot); the eight authentic records all use event 44 and slot arguments 0 through 7. The SH-2 hit scanner at file offset 0x24ed6 compares pointer coordinates against those bounds, reads the event and slot fields, and queues them to 0x06024288. This binds the rectangles to EV_INV_EQUIP with a slot argument. The verified consumer at file offset 0x21c84 has special branches only for event IDs 38, 39, 40, 49, 52, 56, and 57. IDs 13 and 44 branch at 0x21cce to the generic diagnostic at 0x21d98, which resolves the event name and emits bad event data. This rules out an inventory mutation in this queue consumer; it does not rule out a separate consumer elsewhere in the retail runtime. The fallback calls DM.BIN:0x141b4, which bounds-checks the event ID and indexes the authentic name-pointer table at runtime address 0x0604adc4. It returns a name string; it does not dispatch an event handler. The analyzer now verifies this helper’s instructions and table base in the pinned image. The callback’s event-44 producer, the event-17 producer behind a separate global-slot gate, and the dispatcher share the same bounded queue: eight 12-byte records at runtime 0x060797b0, count at 0x06079814, and read cursor at 0x06079810; the dequeue helper is 0x060242d6. Only the count records starting at that cursor are live (the ring has eight slots); remaining storage can retain stale event IDs. The later queue loop is not necessarily the only consumer; event-action semantics must be followed from each caller’s event context. An even-offset scan of the pinned image finds no raw CMP/EQ #44,R0 opcode candidate. The analyzer labels this as an opcode-pattern scan only: it cannot distinguish data from code or exclude register comparisons, jump tables, or indirect event dispatch. An early main event dispatcher at file offset 0x260 uses a relative jump table. The event-44 case reaches 0x8c0, loads the slot argument from stack offset 56, and calls the verified handler at runtime address 0x06036e58. That handler passes the context index through a resolver that uses base 0x0607fba0 and stride 0x13c. For ordinary slots 0–6, the helper accesses two 16-bit words at context + 0x110 + 4*slot, stages and clears the source pair, checks item metadata through the 40-byte records at 0x06064610, and writes the staged pair to the selected destination on the compatible path. The old destination pair is staged through the same held-item helper, so the path supports a source-to-hand and hand-to-slot transaction; whether that appears as pickup, placement, or swap depends on the active UI state. Slot 7 uses a separate path. The handler also updates context fields using masks 0x1000 and 0x0200. The checker verifies the SH-2 branch and helper-call sites, table literals, pair reads, source clearing, destination writes and displaced pair staging against the hash-pinned retail DM.BIN.

The first pair word is an item-definition ordinal; 0xffff is the empty marker. There is a partial fit with Firestaff’s ITEM.IBS declaration indices, but not a lossless mapping. The context index is not joined to a champion, Firestaff’s champion model has no field for the opaque second 16-bit word, and the retail PLRD item pairs do not establish the inventory-panel layout. The hash-pinned Japanese RLOWFIX.BIN (f2686bf3d6b971c5eaa613b2619b7e1bb7958a8045876296a83509f137be18b0) contains 20 PLRD rows with ten item pairs each: 64 pairs have an item ordinal, 136 are empty, and all 200 second words are zero. A read-only comparison of four authentic Ymir captures found that context records 0–3 duplicate each other and match PLRD row 2’s first seven pairs, but differ at slot 7; empty context 4 matches four PLRD rows. These ambiguous matches do not establish a unique context-to-champion mapping or the auxiliary word’s meaning for live items. The candidate relation and capture hashes are recorded in nexus-v1-inventory-button-debug-20261025. The helper code stages the displaced pair through global UI state, but the runtime-visible result still needs a controlled Ymir before/after capture. The analyzer reproduces the DM.BIN instruction checks and PLRD pair summary. This path is separate from the later 0x21c84 generic diagnostic loop. The separate mouse-motion poller filters for event 46 before it calls the hit-region scanner; it does not consume event 44 as a second pointer action. Event 44 has a hash-verified source-side slot-pair path, but its runtime held-item effects and Firestaff state mapping are not verified. Production inventory and equipment clicks remain disabled until those joins are captured.

For a controlled Ymir run, save a baseline and post-action high-WRAM dump from the same retail savestate with Debug > Dump all memory, then compare them with scripts/analyze_nexus_inventory_wram_pair.py. The tool checks that both wram-hi.bin inputs are exactly 1 MiB, prints the raw eight-record event queue, and reports item-pair changes for an explicitly selected context range. For example, use --context-start 0 --context-count 11 to include the indices observed in the existing captures. Its output is a byte-level delta only; it does not identify a context as a champion or establish that a pointer click caused a change. Keep each Ymir profile’s dump directory separate so a stale snapshot from another run cannot be mistaken for the post-action capture.

Mouse and remaining input work

Nexus has startup pointer handling, full-game-screen mouse movement, keyboard movement, and the authentic retail cursor sprite joined from the captured viewport data and ITEM.IBS source. The keyboard supports forward/backward movement, turning, strafing, party leader cycling (Tab), pointer mode, and pointer movement. The mouse supports the six-cell desktop movement pad and direct pointer positioning across the game screen. Inventory, attack, spell, and item-use clicks remain inert until their retail callback consumers are established. The existing logical click-route helpers require pre-resolved targets and do not establish how viewport pixels map to Nexus actions. The orange retail cursor and D-pad movement are captured, while desktop mouse movement in Firestaff is a host control behavior rather than a claim about Saturn ShuttleMouse.

Next work must identify the retail context-to-champion relationship and the opaque item-pair auxiliary word, then trace whether the event-39 selection commits a retail inventory mutation and how the relevant item maps to the authentic Nexus champion/inventory model. Bind pointer actions only after those joins are proven. Keep unsupported actions inert. The attempted ShuttleMouse click and its unmatched WRAM snapshots are preserved in parity-evidence/verification/nexus-keyboard-mouse-retail-input-20261025/; they do not prove an action.

A later isolated Ymir probe used the authentic slot-1 state with ControlPad on port 1 and ShuttleMouse on port 2. XTEST core-pointer motion and the ShuttleMouse port’s relative arrow-key bindings produced no visible movement of a clearly identifiable retail hand pointer in the Xvfb captures. The setup and captures are recorded in nexus-shuttle-mouse-xvfb-20261025. The XTEST result was explained by a Ymir 0.4.1 frontend gap: SDL global mouse ID 0 entered relative-capture mode and returned before Ymir mapped its motion or buttons to the emulated ShuttleMouse. Ymir PR #963 was built and run under --debug on the authentic Nexus disc. In a supplemental devlog run using the same hash-verified state and peripheral setup, SDL global mouse ID 0 motion and button edges passed with imguiCapture=false and produced nonzero Shuttle Mouse frame input. This confirms delivery to Ymir’s peripheral layer; it does not establish a retail action. In the separate paired-dump trial, neither absolute nor relative host motion visibly moved the retail cursor/selection, one occupied-icon click left the screen unchanged, and before/after WRAM dumps show no event 44, live queue change, or item-pair deltas across contexts 0–15. The full setup and hash-verified captures are recorded in nexus-shuttle-mouse-ymir-pr963-input-routing-20261025. This rules out a missing Ymir peripheral report for the supplemental input trace, but it does not show that the retail event-44 handler rejected a correctly targeted click because the cursor never moved visibly. Firestaff’s desktop pointer actions still need to follow proven Nexus state changes before enabling equipment or other actions.

A separate port-2 trial investigated the earlier Xvfb probe, which showed no identifiable hand-pointer movement because Ymir’s frontend did not route SDL global mouse ID 0 to the emulated ShuttleMouse. Ymir PR #963 now builds successfully and passed an isolated --debug runtime probe with the authentic Japanese retail disc and hash-verified Saturn IPL. Ymir visibly bound global mouse ID 0 to ShuttleMouse port 2 while a ControlPad was on port 1, confirming the host-to-peripheral connection. The new game-view captures do not establish reliable retail pointer movement or a mouse action, so Nexus ShuttleMouse gameplay semantics and Firestaff mouse-action parity remain unverified. Build limitations and captures are recorded in nexus-shuttle-mouse-ymir-pr963-20261025. Firestaff’s desktop mouse actions still need to follow proven Nexus state changes before enabling equipment or other pointer actions.