Implement native opening scenes, battle foundation and overworld movement
Checks / web (push) Canceled after 0s

This commit is contained in:
Sébastien QUEROL committed 2026-09-23 16:09:22 +02:00
1 parent 8b80d05ca2
commit c08d250cf6
39 files changed
+10727 -1524

No files matched your search

+25 -13
View File
@@ -2,7 +2,7 @@
## Reproducible reference
The private `.reference/pokecrystal` checkout is pinned to `7a7881d0d62e0ddbd82dcf10e7116807487ac651`. With RGBDS 1.0.3, its `crystal11` build is byte-identical to the supplied English US/Europe revision 1.1 ROM. `npm run check:reference` verifies the files, commit and every address in `src/game/rom/profile.ts` against generated symbols.
The private `.reference/pokecrystal` checkout is pinned to `7a7881d0d62e0ddbd82dcf10e7116807487ac651`. With RGBDS 1.0.3, its `crystal11` build is byte-identical to the supplied English US/Europe revision 1.1 ROM. `npm run check:reference` verifies the files and commit. It checks every ROM and RAM address in `src/game/rom/profile.ts` against generated symbols, event constants against `constants/event_flags.asm`, and map-group bounds against `data/maps/maps.asm`.
To recreate the private reference:
@@ -21,23 +21,31 @@ The reference checkout, rebuilt ROM, extracted graphics, saves and gameplay scre
These paths refer to the pinned [PRET source](https://github.com/pret/pokecrystal/tree/7a7881d0d62e0ddbd82dcf10e7116807487ac651).
| Native module | PRET reference | Evidence and limits |
| -------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `game/rom/lz.ts` | `home/decompress.asm` | All LZ command types have unit vectors; six tilesets match original ASM execution byte-for-byte. |
| `game/rom/assets.ts` maps/events | `data/maps/maps.asm`, `data/maps/attributes.asm`, `macros/scripts/maps.asm` | Six-map dimensions, events, destinations, navigation and return warps checked with the actual ROM. Connections are decoded but traversal is disabled. |
| Tiles/palettes | `home/map.asm`, `engine/gfx/color.asm`, `engine/tilesets/mapgroup_roofs.asm` | Graphics match rebuilt reference bytes. Day/night palettes and roofs supported; terrain animation/dynamic tiles and other special palettes pending. |
| Sprites/rendering | `data/sprites/sprites.asm`, `data/sprites/facings.asm` | Chris/Kris and standard NPC graphics/facings decoded. Dynamic Pokémon icons and room decorations pending. |
| `game/world/world.ts` | `engine/overworld/player_movement.asm`, `data/collision/collision_permissions.asm` | Walking, walls, visible objects and ordinary local warps. Not complete frame-by-frame parity; forced movement, ledges and surfing are refused. |
| Event interpreter | `macros/scripts/events.asm`, `engine/overworld/scripting.asm`, `engine/events/std_scripts.asm` | Bounded calls/jumps/conditions, flags, initial sprite variables and basic text interactions. Unknown commands abort; no assembly fallback. |
| Text interpreter | `macros/scripts/text.asm`, `constants/charmap.asm` | Literal/far text, line/paragraph controls and player substitution. Dynamic RAM/ASM text is unsupported. |
| Native module | PRET reference | Evidence and limits |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `game/rom/lz.ts` | `home/decompress.asm` | All LZ command types have unit vectors; six tilesets match original ASM execution byte-for-byte. |
| `game/rom/assets.ts` maps/events | `data/maps/maps.asm`, `data/maps/attributes.asm`, `data/maps/scenes.asm`, `data/maps/landmarks.asm`, `macros/scripts/maps.asm` | Any map header in the ROM's 26 groups decodes; only the six ported maps can be entered. Location names, scene-variable owners and connection offsets come from the ROM. |
| Tiles/palettes | `home/map.asm`, `engine/gfx/color.asm`, `engine/tilesets/mapgroup_roofs.asm` | Graphics match rebuilt reference bytes. Connected maps draw beyond the edges with the current tileset, like the original strips. Terrain animation and other special palettes pending. |
| Sprites/rendering | `data/sprites/sprites.asm`, `data/sprites/facings.asm`, `data/sprites/emotes.asm` | Chris/Kris, standard NPCs, emote bubbles and jump shadows decoded. Walking frames follow `SetFacingStepAction`. Dynamic Pokémon icons and room decorations pending. |
| `game/world/world.ts` | `engine/overworld/events.asm`, `player_movement.asm`, `warp_connection.asm`, `data/collision/collision_permissions.asm` | 30 Hz overworld ticks, 8-tick walks, 16-tick ledge jumps, directional mats, animated door/stair exits, connection coordinates, events, scenes and callbacks. Surfing and NPC roaming remain absent; turn timing still needs comparison. |
| Event interpreter | `macros/scripts/events.asm`, `engine/overworld/scripting.asm`, `engine/events/std_scripts.asm` | Resumable; yields text, choices, movement, emotes and pauses. Scenes, phone contacts, string buffers and object commands. Unknown commands and specials abort without committing. |
| Movement interpreter | `macros/scripts/movement.asm`, `engine/overworld/movement.asm`, `engine/overworld/map_objects.asm` | Turns, steps, slides, jumps (two tiles with the original arc), sleeps, facing locks, visibility and emotes. `follow` moves the follower into the leader's previous square. |
| Specials | `data/events/special_pointers.asm`, `engine/rtc/timeset.asm`, `engine/overworld/decorations.asm` | Selected by routine address from the ROM table: `SetDayOfWeek`, initial DST flags, `RestartMapMusic` (no audio yet) and the empty-room decoration toggles. |
| `game/rom/pokemon.ts` | `data/pokemon/base_stats`, `evos_attacks.asm`, `data/moves/moves.asm`, `data/items/attributes.asm`, `engine/gfx/load_pics.asm` | Species, move and item names, base data, learnsets, move PP, item pockets, growth-rate exp and front pictures (`FixPicBank`, `PadFrontpic`). Starter pictures match rebuilt bytes. |
| `game/party` | `engine/pokemon/move_mon.asm`, `engine/pokemon/caught_data.asm`, `engine/items/items.asm` | `GeneratePartyMonStats` for script gifts: DVs, `FillMoves`, PP, exp, `CalcMonStatC`, happiness and caught data. `PutItemInPocket`, key items and `TossItem`. PC boxes, TMs and HMs are refused. |
| Text interpreter | `macros/scripts/text.asm`, `constants/charmap.asm`, `home/text.asm` | Literal/far text, RAM names and string buffers from native state, numbers of dots, and sound or pause cues (consumed). `text_asm` and other RAM reads are refused. |
Supported event opcodes are explicit in the interpreter switch. Audio commands and delays consume their operands, but sound sequencing and presentation timing are pending; those opcodes do not imply complete audiovisual behavior.
Supported event opcodes are explicit in the interpreter switch. Audio commands consume their operands, but sound sequencing is pending; those opcodes do not imply complete audiovisual behavior. `pause` holds the current text or waits the original number of overworld ticks.
Scripts run on a private draft. The world presents each yielded effect, then resumes the script with the player's answer or when the animation ends. The draft is committed only when the script ends. A save made during a scene returns the committed state, and coordinate events rewind to the source of the triggering walk or two-tile jump. Saves during movement also retain the source tile until arrival events run, including across map connections. A failed scene restores the positions it had changed. As in `LoadMapObjects`, map objects spawn when the map loads. Later flag changes do not remove objects already shown; only `appear` and `disappear` do.
The opening scenes currently run end to end from the ROM: Mom's Pokégear, weekday and DST scene, the teacher at the west edge, the rival at the lab window, Elm's introduction with its yes/no loop, the lab's exit guard, the starter choice with `pokepic`, `givepoke` and the nickname prompt, Elm's directions and the aide's Potion through the ROM's own `GiveItemScript`. `callasm` accepts only explicitly empty routines or native translations; battle whiteout hooks are present but await full flow validation. The naming screen is a native text field limited to the characters the original offers.
## Actual emulator comparison
`tests/reference-parity.spec.ts` loads the user's ROM into the reference emulator and places a small original test trampoline in emulated WRAM. It calls the ROM's `FarDecompress` routine at `$0b40`, then sets a return sentinel. Every output byte is compared with the native decoder for six supported map tilesets. This executes the original routine rather than comparing two copies of our code.
That establishes decompression parity for those inputs. It does not prove complete gameplay, rendering, battles, audio, timing or physical-device parity. Extend controlled comparisons as each subsystem is translated.
The same suite compares 400 damage cases and 400 type-effectiveness cases per browser against the original battle routines. Battle unit tests cover win, escape, loss, experience, level-up and move-learning flows. This establishes parity only for the compared routines and inputs. It does not prove complete gameplay, rendering, battles, audio, timing or physical-device parity. Extend controlled comparisons as each subsystem is translated.
## Validation
@@ -55,6 +63,10 @@ User-ROM tests skip when the file is absent, including public CI. Synthetic test
Native production is `dist/`; the optional reference output is `dist-reference/`. Release checks reject emulator dependencies, binary game files and embedded binary assets in the native output. Source review is still required when adding assets or data.
## Save schema
Native saves are version 3. Version 2 added scene values by owning map, phone contacts, the weekday offset and DST flag, and positions of objects that scripts moved on the current map. Version 3 adds the player ID, party, bag, Pokédex seen/caught sets and money. Early version-3 backups without money receive the original starting balance; explicitly invalid balances are rejected. Restores recompute each Pokémon's stats from its DVs and reject any mismatch, and check every item against its ROM pocket. Older saves migrate with new-game defaults; a missing player ID is drawn as a new game draws it. Objects are restored from the save on continue, and only the TILES callback runs, as in `MapSetupScript_Continue`.
## Next slice
Expand automatic scenes/callbacks and native party/inventory models to implement the opening through starter selection. Add the first battle loop with Route 29 and the Mystery Egg quest. Keep this story milestone separate from exploration saves until initialization and migration are defined.
Validate the existing battle core and UI together, including win, escape, whiteout and save/reload through the browser. Encounter tables and ledge movement are present, but Route 29 stays disabled until its scripts, catching tutorial, fruit tree and item interactions are supported and tested. Then continue to Cherrygrove. Add party, bag and Pokégear menus over the native models. Heal-machine and other specials stay refused until translated.