Xenon 2

How it works · write-up

Final shop and campaign restart

xenondoc/FINAL_SHOP_VALIDATION_20261005.MD · 6 KB · updated 2026-10-06

The earlier full campaigns stopped too early. $1178C is the final-message selection byte, written before ShopScreen_InitAndOpen begins. It is not an end-of-recording signal, and stays nonzero after Level 1 reloads. This correction does not change any combat, navigation, collection or purchase tactic.

Original game logic

ReVa /mydumpat0 contains the shared shop code used by all levels:

  • $7D56 clears the byte for ordinary shops; $7D6C sets it for the Level 5 ending.
  • $10520, ShopScreen_InitAndOpen, checks it at $10652 and $10670. The ending skips Sell/Buy and shows the three messages beginning at $10864, $1087F and $108A6.
  • $10798..$107C6 prints those messages, separated by calls to $10912. $10912, ShopPanel_IdleWaitWhileDrawing, waits a counter, not a fire edge. The third message asks whether the game was good enough for the viewer.
  • $107C6..$10842 closes the shop and finishes the timed ending.
  • $7E78..$7EAA advances the level, wraps 6 to 1, increments the campaign-loop counter at $E18, and loads the next arena.
  • The subsequent GET READY interstitial waits for fire using instruction $0011. This is the fire acknowledgement observed in the recording; no purchase or menu movement is required in the final shop itself.

The C session formerly gave the completion byte priority over every lifecycle branch, permanently suppressing that fire acknowledgement and subsequent play. It now acknowledges captured fire prompts first, remains passive during the timed final shop, and resumes normal gameplay once the player returns to Level 1. No ABI fields or per-frame host control calls were added.

The native validator latches the Level 5 ending, records shop-entry and restart milestones, and stops only at playable Level 1 outside the shop/fire prompt. Timed ending text uses a bounded ending wait rather than the ordinary idle-menu stall threshold. Explicit shorter probe flags retain their existing behavior.

Visible resident-C continuation

Source checkpoint:

E:/xenon_runs/ffmpeg-full-hd-highfps-20261005-r581-1.validation/checkpoints/f49973-periodic.sav

Both Release Hatari and the Python replay DLL were rebuilt through xenon_tools/hatari_dev.ps1. The following run used resident C control, a visible Sprite Stream window, normal speed, HD sprites, HIGH FPS, 1280x800 sprite recording, QSV H.264/AAC MP4, and checkpoint requests every 150 frames:

python xenon_tools\validate_campaign.py native-run ffmpeg-final-shop-20261005-r582 --output-root E:/xenon_runs --resume E:/xenon_runs/ffmpeg-full-hd-highfps-20261005-r581-1.validation/checkpoints/f49973-periodic.sav --build-type Release --build-directory out/build/codex-validate --port 6945 --memory-trace off --record-format mp4 --record-encoder qsv --record-quality 18 --ffmpeg-path C:/Users/matej/AppData/Local/Microsoft/WinGet/Links/ffmpeg.exe --sprite-scale 4 --hd-sprites --high-fps --checkpoint-interval 150

Artifacts are in ffmpeg-final-shop-20261005-r582.validation:

  • Canonical recording
  • Original MP4
  • HD/high-FPS sprite MP4
  • Run result, video audit, shop audit
Event Canonical frame
Loaded checkpoint 49973
First captured frame 49975
Final shop selected/opened 49983
Shop finished; Level 1 loading began 51040
GET READY waiting for fire 51327
C pilot emitted Fire (0x80) 51328
Fire wait cleared 51329
Playable Level 1 returned 51352
Last recorded frame 51358

There are 1384 continuous canonical records, zero shield damage, zero lost lives, zero stalls and no cleanup errors. Both shop messages and the final Level 1 playfield were inspected in the two videos. The final shop makes no transactions: cash remains 6400 and equipment remains unchanged throughout it. Hatari is left visible and paused after recording, with manual input released to the user.

Both MP4s fully decode with H.264 video and nonsilent mono AAC at 44100 Hz. The sprite video has 2657 continuous VBL-indexed frames, 1280x800, 44.256 seconds; the original has 2661 frames, 640x400, 44.322 seconds. Each audio track matches its own video duration (original drift 19 microseconds). Their different capture boundaries mean the decoded audio hashes are not identical.

An existing renderer limitation is visible after the shop closes: Sprite Stream temporarily retains the shop backdrop during part of the Level 1 loading screen, where the original recording displays loading text. The shop dialogue and the returned gameplay are recorded in both; use the original video for the complete authentic intervening loading screen. No renderer changes were made in this fix.

Validation: python -m unittest test_native_campaign test_native_session from xenon_tools passes all 26 tests. Tests cover early ending selection, an active shop, loading without a player, fire waits, the sticky flag in Level 1, bounded ending stalls and resuming C gameplay. Re-observing the finalized capture with the current monitor confirms completion at 51352 with no incidents.

This is a continuation from the latest checkpoint, not a new uninterrupted campaign. Earlier campaign survival and gameplay comparisons remain useful; their endpoint should be described as spaceship defeat/final-shop entry.