Open Route 42 to Mahogany, the Lake of Rage, the Rocket Hideout and Pryce (#32)

Route 42, Mt. Mortar, Mahogany Town, Route 43 and its gates, the Lake of
Rage and its houses, the Rocket Hideout and Route 44 are open. The story
plays through the toll, the red Gyarados, Lance, the hideout and Pryce's
GLACIERBADGE, which starts the Radio Tower takeover.

The fishing guru measures Magikarp (CheckMagikarpLength,
MagikarpHouseSign, FindPartyMonThatSpecies); the record is saved.
takemoney now leaves a short account at zero as TakeMoney does, and
setmapscene/setscene on a map without scenes consume the byte instead of
refusing. The playthrough's path search slides on ice and the run gains
five stages to Pryce.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
kawaandClaude Opus 5.5 committed 2026-10-13 13:35:58 +02:00
1 parent 62fe4bf664
commit 061ca4d59d
11 files changed
+578 -43

No files matched your search

+3 -2
View File
@@ -51,6 +51,7 @@ These paths refer to the pinned [PRET source](https://github.com/pret/pokecrysta
| `game/world/roam-mons.ts` | `engine/overworld/wildmons.asm` (`InitRoamMons`, `CheckEncounterRoamMon`, `UpdateRoamMons`, `JumpRoamMons`), `data/wild/roammon_maps.asm` | Raikou and Entei roam from `InitRoamMons`; Suicune's slot is kept but not started. `UpdateRoamMons` runs on connections, door and pit warps and after one wild battle in sixteen; `JumpRoamMons` on Fly, Teleport and Continue. A roaming beast can take a grass encounter, and the battle writes its HP back or clears the slot. |
| Bug-Catching Contest | `engine/events/bug_contest/*.asm`, `maps/Route35NationalParkGate.asm`, `maps/Route36NationalParkGate.asm`, `engine/menus/start_menu.asm` | Registration, Park Balls, contestant selection, the timer on the game clock, out of balls, QUIT, judging from `BugContestantPointers` with ties to the earlier entry, prizes and `CheckPartyFullAfterContest`. The contest state saves. The status box is a text page above the start menu. No sound. |
| `game/scripts/cianwood.ts`, Routes 38–41, Olivine and Cianwood | `engine/events/shuckle.asm` (`GiveShuckle`, `ReturnShuckie`), `engine/pokemon/bills_pc_top.asm` (`CheckCurPartyMonFainted`), `engine/pokemon/caught_data.asm` (`SetGiftPartyMonCaughtData`), `engine/events/poke_seer.asm`, `engine/events/print_photo.asm`, `engine/printer/printer.asm` (`PrintPartymon`, `CheckPrinterStatus`), `engine/printer/printer_serial.asm`, `engine/events/specials.asm` (`PlaySlowCry`) | Shuckie is a level 15 party-only gift with MANIA's OT, ID 518, nickname, a Berry and `LANDMARK_GIFT` caught data; it sets `ENGINE_GOT_SHUCKIE_TODAY`. `ReturnShuckie` returns all five codes; `CheckCurPartyMonFainted` looks at the rest of the party, and Mania answers `SHUCKIE_FAINTED` with his happiness speech, as the original does. `PokeSeer` follows `ReadCaughtData`, including the missing `cp [hl]` that compares only the OT ID's high byte, `GetCaughtLocation`'s event and gift landmarks, `GetCaughtLevel`'s ??? that leaves `wSeerCaughtLevel` unchanged, and `SeerAdvice`'s inclusive thresholds. `wSeerCaughtLevel` lives in the "Miscellaneous WRAM 1" union: the port keeps the Seer's own last value until a load, while in the original other users of those bytes may change it. `PhotoStudio` has no printer to talk to: the handshake reads $ff, so `CheckPrinterStatus` reports `PRINTER_ERROR_2`, and `SendScreenToPrinter` retries until B sets `hPrinter`. The port shows "Printer Error 2" with "Press B to Cancel" on one page, then the no-photo text; the print page behind the box and its alternation with "CHECKING LINK" are not drawn. `PlaySlowCry` is audio. The story maps run on ported script commands; `tests/olivine-cianwood.test.ts` and six playthrough stages cover them. |
| `game/scripts/lake-of-rage.ts`, Route 42 to Mahogany, the Lake of Rage, the Rocket Hideout and Pryce | `engine/events/magikarp.asm` (`CheckMagikarpLength`, `CalcMagikarpLength`, `PrintMagikarpLength`, `MagikarpHouseSign`), `engine/menus/intro_menu.asm` (`InitializeMagikarpHouse`), `engine/pokemon/search_party.asm` (`FindThatSpecies`), `engine/overworld/scripting.asm` (`DoScene`), `engine/events/money.asm` (`TakeMoney`) | The Magikarp is measured from its own DVs and OT ID with the battle code's `CalcMagikarpLength` (whose `.BCLessThanDE` compares only the high byte). A longer one, compared feet then inches, becomes the record with the Magikarp's OT name as holder; the record starts at 3′6″ by RALPH and is saved as `magikarpRecord`. `FindThatSpecies` reads `wPartySpecies`, where an Egg is EGG, so an Egg is never found. `setmapscene`/`setscene` on a map without a scene variable (Route 43, the Lake of Rage): `GetMapSceneID` leaves `de` alone and `DoScene` still writes the byte through it when it is nonzero. At the Route 43 gate `de` is `EventFlagAction`'s byte offset of `EVENT_CLEARED_ROCKET_HIDEOUT` (4), the MBC3 RAM-enable register, so nothing changes. After the Red Gyarados, `de` is whatever `closetext` left; the port consumes the byte and changes nothing, and that write was not checked in an emulator. `TakeMoney` leaves a short account at zero, so the Route 43 Rockets take all of a smaller balance. The Rocket Hideout's cameras, traps, passwords, executives and Electrodes and Pryce's ice floor run on ported primitives; `PlayCurMonCry` is audio. `tests/mahogany.test.ts` and five playthrough stages cover them. |
| `game/scripts/slot-machine.ts`, `game/scripts/card-flip.ts` | `engine/games/slot_machine.asm`, `engine/games/card_flip.asm`, `engine/gfx/cgb_layouts.asm` | Both on a realtime tile screen (two frames per tick, buffered buttons). Slots: reel strips, spin rates and scrolling, bias tables with the lucky machine and seven streak, reel 3's Golem and Chansey replay with their sprites, payouts. Card Flip: deck, 12×11 board, cursor sprites and `ChooseCard_HandleJoypad`, paytable. Tilemaps, all 48 cursor positions, selected reel states and whole Golem/Chansey/Egg sequences are checked against the ROM (`tests/reference-game-corner.spec.ts`, which runs `CardFlip_UpdateCursorOAM`, `Slots_UpdateReelPositionAndOAM`/`.SpinReel` and the sprite-animation engine's own Golem/Chansey/Egg routines): the cursor, the reel symbols and the three creatures each anchor an OAM-relative pixel pair 8 (x) and 16 (y) beyond the screen's, as `cursorSprites` reads; `depixel`'s own two arguments end up swapped by `_InitSpriteAnimStruct` (confirmed against the reference emulator), so Golem/Chansey/Egg's X and Y bases were swapped to match, and Golem's own OAM table X-flips its right half. `PlaySpriteAnimations` is compared frame by frame over a three-Golem run and a Chansey round with two eggs (shadow OAM, `wSlotsDelay` and `hSCY`): frames last 8 ticks (the first draw plus 7 decrements); Golem's frames 3 and 4 flip the whole OAM set (offsets become −8−offset); a sprite removed by `DeinitializeSprite` is still drawn that tick, because `UpdateAnimFrame` runs after the animation function; the Golem's roll toggles `hSCY` by ±2, which the tile screen shows with the space tiles `_SlotMachine` filled the BG map with. The rows scrolled in use palette 0, since the attribute map beyond row 18 is not reproduced. No sound. |
| 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. |
@@ -597,8 +598,8 @@ frames) and the boops (120 frames). The two "……" rings last 12 ticks each,
an estimate from `Sfx_Call`'s notes; no sound is played.
Interpreter additions: `random` (`Script_random`'s rejection of draws past
the largest multiple), `givemoney`, `takemoney` (unchanged when short, like
`TakeMoney`), `checkmoney` (`HAVE_MORE`/`HAVE_AMOUNT`/`HAVE_LESS`) and
the largest multiple), `givemoney`, `takemoney` (an account that is short is left at
zero, like `TakeMoney`), `checkmoney` (`HAVE_MORE`/`HAVE_AMOUNT`/`HAVE_LESS`) and
`getmoney` on `YOUR_MONEY` or `MOMS_MONEY`, `getcurlandmarkname` and
`getlandmarkname` (`GetLandmarkName`; `<BSP>` prints as a space). The money
and landmark macros put the account or landmark before the string buffer.