Port the Pokégear, phone calls and Mom's bank
Checks / web (push) Canceled after 0s

POKéGEAR in the start menu runs the clock, Town Map and phone cards with
the original joypad rules. Calls to Elm and Mom run their callee scripts,
with the out-of-area and out-of-hours cases and HangUp's corrected timing.
Mom saves a quarter of trainer prizes once asked, talking to her at home
opens BankOfMom (GET, SAVE, CHANGE and the DST checks) with its digit
amount box, and MomTriesToBuySomething buys items and dolls with her
savings. Saves gain Mom's money, her next item and its trigger balance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sébastien QUEROLandClaude Opus 5.5 committed 2026-10-01 11:38:22 +02:00
1 parent 3456aa4e11
commit 209778cabe
29 files changed
+2726 -47

No files matched your search

+7 -1
View File
@@ -34,7 +34,7 @@ flowchart LR
| `src/reference`, `src/emulator` | Original-game reference, excluded from the native build |
| `reference/public` | Licensed emulator files for the reference build only |
`GameRuntime` is a lifecycle interface, not an emulator contract. Native state is validated JSON, schema version 3. It holds the map, position, facing, name/avatar, player ID and in-game tile count; event and engine flags and sprite variables; scene values, phone contacts, a queued special call, the rival's name, the game clock's minute offset, the weekday offset and DST flag, whether the introduction is still pending; positions of objects that scripts moved; and the party, bag, Pokédex sets, money, registered item and room decoration slots. Older saves without decorations migrate to the original bed and Town Map poster. Decoration imports validate slot categories, ownership and unique doll placement. Early version-3 backups without a money field migrate to the starting balance. It contains no graphics, music, dialogue, GB memory or ROM bytes. Versions 1 and 2 migrate with new-game defaults. Party Pokémon are validated by recomputing their stats from the ROM. The backup envelope retains the historical `coreId` field; native backups use it for their runtime/schema ID.
`GameRuntime` is a lifecycle interface, not an emulator contract. Native state is validated JSON, schema version 3. It holds the map, position, facing, name/avatar, player ID and in-game tile count; event and engine flags and sprite variables; scene values, phone contacts, a queued special call, the rival's name, the game clock's minute offset, the weekday offset and DST flag, whether the introduction is still pending; positions of objects that scripts moved; and the party, bag, Pokédex sets, money, Mom's savings, registered item and room decoration slots. Older saves without decorations migrate to the original bed and Town Map poster. Decoration imports validate slot categories, ownership and unique doll placement. Early version-3 backups without a money field migrate to the starting balance. It contains no graphics, music, dialogue, GB memory or ROM bytes. Versions 1 and 2 migrate with new-game defaults. Party Pokémon are validated by recomputing their stats from the ROM. The backup envelope retains the historical `coreId` field; native backups use it for their runtime/schema ID.
Saves made during an unfinished walk or jump retain its source tile and completed step count, so loading cannot skip a landing event or map transition. Directional mats wait for exit input; doors, stairs and caves force an animated downward step after arrival.
@@ -81,6 +81,12 @@ boxes and the PC's items. A `memscript` effect queues Bill's call (like
`LoadMemScript`); the world keeps it in memory only and runs it before scene
scripts.
The wall/poster Town Map is a ROM-backed canvas presented by a script effect.
`scripts/pokegear.ts` runs the Pokégear inside the start menu run: each card
is a `pokegear` effect answered with a button, and a phone call runs the
callee's ROM script in the event interpreter on the same draft. The world
keeps the card on screen (`world.pokegear`) during the call's texts.
`scripts/mom.ts` runs `BankOfMom` as a special; its amount box is a
`mombank` effect answered with buttons in the same way.
`TilesetAnimator` translates the ROM animation command tables, advancing two
video frames per overworld tick. It owns mutable graphics separately from the
+93 -1
View File
@@ -33,6 +33,7 @@ These paths refer to the pinned [PRET source](https://github.com/pret/pokecrysta
| 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), room decoration toggles, `PokemonCenterPC` and `PlayersHousePC` (Bill's, the player's and Oak's PCs), the Town Map, `HealParty`, `HealMachineAnim` (presentation only), `CheckPokerus` and the `StubbedTrainerRankings_Healings` stub. |
| `game/scripts/pc.ts` | `engine/events/pokecenter_pc.asm`, `engine/pokemon/bills_pc_top.asm`, `engine/pokemon/bills_pc.asm`, `engine/events/prof_oaks_pc.asm`, `engine/events/std_collision.asm` | The Pokémon Center and house PCs: Bill's PC (deposit, withdraw, release, change and name boxes, MOVE PKMN W/O MAIL, stats), item storage, the empty mail box and Oak's rating. Menu strings and texts come from the ROM; lists are native. Printing is not ported. |
| `game/scripts/start-menu.ts` | `engine/menus/start_menu.asm`, `engine/pokemon/mon_menu.asm`, `mon_submenu.asm`, `party_menu.asm`, `switchpartymons.asm`, `engine/items/pack.asm`, `engine/items/item_effects.asm` | The start menu, the party menu with the Pokémon submenu (STATS, SWITCH, MOVE, ITEM) and the pack (USE, GIVE, TOSS) with the field item effects listed below, including Rare Candy, stones and vitamins. Menu strings, prompts and texts come from the ROM; screens are native. Field moves from the menu (checked by the world), Softboiled and Milk Drink, SEL and the Select button (`SelectMenu`). MAIL and the other field items give a notice. |
| `game/scripts/pokegear.ts` | `engine/pokegear/pokegear.asm`, `engine/phone/phone.asm`, `engine/phone/scripts/mom.asm`, `elm.asm`, `engine/rtc/print_hours_mins.asm` | `PokeGear` with each card's joypad handling: the clock (`Pokegear_UpdateClock`, `PrintHoursMins`), the map card's landmark cursor (`TownMap_InitCursorAndPlayerIconPositions`, `TownMap_GetKantoLandmarkLimits`), the phone list (`PokegearPhone_UpdateDisplayList`, `GetCallerClassAndName`, `PokegearPhoneContactSubmenu`, `CheckCanDeletePhoneNumber`) and calls (`MakePhoneCallFromPokegear`, `CheckPhoneContactTimeOfDay`, `GetMapPhoneService`, `HangUp`). Callee scripts run in the event interpreter on the start menu's draft. Screens are native; the radio's stations are not ported. |
| `game/scripts/evolution.ts` | `engine/pokemon/evolve.asm`, `engine/pokemon/learn.asm`, `engine/movie/evolution_animation.asm`, `engine/pokemon/party_menu.asm` | `EvolveAfterBattle`/`EvolvePokemon` over the raw evolution bytes, the evolution texts and a timed, B-stoppable picture sequence, `UpdateSpeciesNameIfNotNicknamed`, `CalcMonStats` and the HP rise, `LearnLevelMoves`, `LearnMove`/`ForgetMove` outside battle and `PlacePartyMonEvoStoneCompatibility`. |
| `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, evolution lists, learnsets, move PP, item pockets, growth-rate exp and front pictures (`FixPicBank`, `PadFrontpic`). Starter pictures match rebuilt bytes; all 251 evolution lists match the pinned source. |
| `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`. `SendMonIntoBox`, `SendGetMonIntoFromBox` (deposit and withdraw), `RestorePPOfDepositedPokemon` and `CalcLevel` for the PC's boxes and item storage. TMs and HMs are refused. |
@@ -88,7 +89,7 @@ Native production is `dist/`; the optional reference output is `dist-reference/`
## 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`.
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, and later Mom's savings (`momsMoney`, migrated by absence to 0). 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`.
## Scripted trainer battle foundation
@@ -437,3 +438,94 @@ left its slot; `tests/pc.test.ts` moves Pokémon party to box, box to party,
within the party and within a full box, and refuses the last Pokémon and a
full destination. Browser tests register the Bicycle and ride it with
Select from the keyboard and the on-screen button.
### The Pokégear, phone calls and Mom's savings
`PokeGear` runs from the start menu as a generator (`Pokegear`) that yields
each card as a `pokegear` effect and is answered with the button pressed, so
the original's joypad rules (`PokegearClock_Joypad`,
`PokegearMap_ContinueMap`, `PokegearPhone_Joypad`, `PokegearRadio_Joypad`
and the contact submenu's loop) stay in the rules layer. The world routes A,
B, the directions, Start and Select to it and refreshes the clock card from
the game clock every tick, as `Pokegear_UpdateClock` runs every frame.
Texts, menu strings, caller names and the AM/PM strings come from the ROM
(`POKEGEAR` profile table, verified by `check:reference`). The map header's
palette byte's high nybble is decoded as `GetMapPhoneService`.
A call runs the callee script from `PhoneContacts` (or
`PhoneOutOfAreaScript`/`PhoneScript_JustTalkToThem`) in the event
interpreter with the world's script host, on the start menu's draft; its
state is adopted when it ends. The callee's last text waits for A or B, as
`PokegearPhone_FinishPhoneCall` does, then `HangUp` shows "Click!" (20
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
`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.
`WinTrainerBattle.give_money` now splits the reward: the reward is added
four times, to Mom for as many quarters as `wMomSavingMoney`'s mask says
(SOME|HALF counts as four) unless `.CheckMaxedOutMomMoney` finds her
account full, and to the wallet otherwise; the text is `SentSomeToMomText`,
`SentHalfToMomText` or `SentAllToMomText`. Only `ENGINE_MOM_SAVING_MONEY`
(the SOME bit) is reachable: nothing in the ROM sets the HALF and ALL bits.
After a trainer battle, `Script_reloadmapafterbattle` calls
`MomTriesToBuySomething` (see Mom's bank below).
Tests: `tests/pokegear.test.ts` (local ROM) covers the cards and their
switching, the live clock, the map cursor's wrapping, phone scrolling over
ten slots, the contact submenu, Elm's call, "Just go talk to that person!",
Mom's lecture and balance call with commits after the menu closes, no
service and the save migration. `tests/trainer-battle.test.ts` and
`tests/trainer-world.test.ts` cover Mom's quarter, her full account and the
purchase refusal. A browser test drives the cards and a call to Elm from the
keyboard and the on-screen D-pad.
### Mom's bank and her purchases
`BankOfMom` (`scripts/mom.ts`) follows the ROM's jumptable: the yes/no
questions and the GET/SAVE/CHANGE/CANCEL menu (strings from
`BankOfMom_MenuHeader`) are ordinary effects, and the deposit/withdraw box is
a `mombank` effect answered with the button pressed, like the Pokégear's
cards, so `Mom_WithdrawDepositMenuJoypad`'s rules stay in the rules layer.
`DigitQuantities` is read from the ROM. Texts, strings and the routine come
from the `MOM` profile table, verified by `check:reference`. Refusal texts
end in `prompt` and the routine returns to the same jumptable entry, which
prints its question again and resets the amount; natively the refusal is a
page before the next box. The last text is left for the script's
`waitbutton`.
`DSTChecks` reads `hHours` from the game clock. `SetClockForward` and
`SetClockBack` move `wStartHour` with a carry into `wStartDay`; the native
clock keeps `minuteOffset` within ±720 minutes, so `shiftClockHour` wraps it
and moves `weekdayOffset` the other way, which keeps the weekday and the
daily reset day unchanged.
`MomTriesToBuySomething` runs at `Script_reloadmapafterbattle` after a
trainer battle. `CheckBalance_MomItem2` compares her savings with the next
MomItems_2 trigger; failing that, `.check_have_2300` adds ¥2300 to
`wMomItemTriggerBalance` while it is below her savings, and only an exact
match buys a `RandomRange(5)` MomItems_1 entry (and steps once more). The
trigger balance keeps those increments even when nothing is bought, as in
the original. `Mom_GiveItemOrDoll` puts an item in the PC (a full PC cancels
the purchase after the steps) or sets the doll's decoration event. The ROM's
`.Script` memscript runs `.ASMFunction` (the cost and `wWhichMomItem`) and
then `Script_ReceivePhoneCall` with `Mom_GetScriptPointer`'s item or doll
script. Natively `.ASMFunction`'s changes are made when the call is queued
and the queued script is `Script_ReceivePhoneCall` itself with that caller
script; the call starts at the next `PlayerEvents`, so nothing can observe
the difference. `wMapReentryScriptQueueFlag`'s early return is the world's
rule that keeps an already queued script.
Tests: `tests/mom.test.ts` (local ROM; the clock shift runs without it)
covers the first visit, declining, deposits and withdrawals with each
refusal, the digit cursor and step limits, B and zero-amount cancels,
CHANGE, the Daylight Saving Time branches and the near-midnight refusal.
`tests/trainer-world.test.ts` covers a MomItems_2 purchase and its call, an
exact ¥2300 step, a step without a purchase, a doll, a full PC and the save
migration. A browser test deposits through the keyboard and the on-screen
buttons and checks the backup.
+25 -3
View File
@@ -190,11 +190,31 @@ The numbered sections below keep their full scope. Each one opens with a checkli
- Bill's PC's MOVE PKMN W/O MAIL: refused while a party Pokémon holds MAIL, then "Each time you move a POKéMON, data will be saved. OK?". Choose the party or a box, a Pokémon (MOVE, STATS, CANCEL), then a box and the position to insert before. The party keeps its last Pokémon and its last healthy one, a different full box or party has "no room", a Pokémon moved down its own list lands one place earlier (`.CheckTrivialMove`), a boxed Pokémon joining the party gets its stats with full HP and no status (`CalcBufferMonStats`), and one entering a box gets its PP restored. The original's left/right box switching is presented as a list of boxes; after "no room" the box is chosen again rather than the position.
- Save format 3 gained `registeredItem`, migrated by absence to none.
## Implemented: the Pokégear, phone calls and Mom's savings
- POKéGEAR in the start menu runs `PokeGear` and returns to the start menu. The clock card shows the weekday (`GearTodayText`) and `PrintHoursMins`'s 12-hour time with the ROM's AM and PM, follows the game clock while open, and exits on A, B, Start or Select. Left and right change cards in the original order, skipping the cards the player lacks (the map card from the Guide Gent, the phone card from Mom).
- The map card draws the ROM's Johto or Kanto Town Map with the player's landmark (a special landmark uses the backup map's, as `TownMap_InitCursorAndPlayerIconPositions` does) and a cursor that up and down step through the region's landmarks with wrapping; Kanto's routes need the Hall of Fame. The cursor keeps its place while the Pokégear stays open. The landmark name comes from the ROM.
- The phone card lists `wPhoneList`'s ten slots four at a time, with `GetCallerClassAndName` (non-trainer names, or a trainer's name over its class) and dashes for empty slots, and the signal bars from the map header's phone service nybble. A on a contact opens CALL/CANCEL, or CALL/DELETE/CANCEL for numbers `CheckCanDeletePhoneNumber` allows (never Mom or Elm). Deleting asks first.
- Calls follow `PokegearPhone_MakePhoneCall` and `MakePhoneCallFromPokegear`: "You're out of the service area." without service; otherwise two "……" rings, then `PhoneOutOfAreaScript` outside the callee's hours, `PhoneScript_JustTalkToThem` on the callee's map, or the callee script from `PhoneContacts`. The script runs on the start menu's draft, so its changes commit with the menu. The call ends with `HangUp`'s "Click!" and boops. Elm's and Mom's callee scripts run; trainer contacts are not reachable yet.
- Mom's savings: `wMomsMoney` is saved as `momsMoney` (migrated by absence to 0). The interpreter gained `givemoney`, `takemoney`, `checkmoney` and `getmoney` for both accounts, `getcurlandmarkname`, `getlandmarkname` and `random`. After the catching lesson, calling Mom runs her lecture, which sets `ENGINE_MOM_SAVING_MONEY` on a yes; later calls report where the player is and her balance. While she saves, a won trainer battle sends a quarter of the prize to her (`WinTrainerBattle.give_money`, "Sent some to MOM!"), unless her account is full.
- `HangUp` now shows "Click!" for its 20 frames and the boops' "……" for the remaining 120, instead of "Click!" for twice the whole duration.
- Not ported: the radio card (it is only obtainable in Goldenrod; it gives a notice); trainer callee scripts; random incoming calls; ringtones, music and the original card graphics.
## Implemented: Mom's bank and her purchases
- Talking to Mom after the Mystery Egg runs `BankOfMom`. The first time she offers to save money (`MomLeavingText1`–`3`); until New Bark Town's flypoint callback clears `EVENT_FIRST_TIME_BANKING_WITH_MOM` she only cheers the player on. Later visits ask "Or is this about your money?": GET, SAVE, CHANGE or CANCEL.
- GET and SAVE open `Mom_ContinueMenuSetup`'s box (SAVED, HELD, then WITHDRAW or DEPOSIT and a six-digit amount with a blinking digit). `Mom_WithdrawDepositMenuJoypad`: left and right move the digit cursor (starting on the last digit, stopping at both ends), up and down add or take the digit's `DigitQuantities` step through `GiveMoney`/`TakeMoney`'s ¥999999 and zero limits, A confirms and B cancels. A zero amount cancels. Refusals ("You don't have that much.", "You can't save that much.", "You haven't saved that much.", "You can't take that much.") return to a fresh box. CHANGE starts or stops her savings.
- Declining the money question runs `DSTChecks`: switch Daylight Saving Time on or off, moving the clock an hour, unless that would change the day (within an hour of midnight), when Mom has lost the Pokégear's booklet.
- `wMomSavingMoney` stays two engine flags: nothing in the ROM sets the half and all bits.
- After a won trainer battle with phone service, `MomTriesToBuySomething` buys MomItems_2's next item once her savings reach its trigger, or a random MomItems_1 item when `wMomItemTriggerBalance`'s ¥2300 steps land exactly on her savings. Items go to the PC (nothing happens when it is full), dolls to the room's decorations, and her call follows ("I bought it with your money. Sorry!").
- Save format 3 gained `momItem` and `momItemTriggerBalance` (`wWhichMomItem`, `wMomItemTriggerBalance`), migrated by absence to 0 and ¥2300.
- The amount box has no key repeat: like the other native menus, a held direction counts once.
## Native battles: current state
The battle core, ROM tables, encounter hooks, battle UI and whiteout hooks are present. Unit tests cover wins, escape, loss, experience, move learning and capture; reference tests compare damage, type effectiveness, stat calculation and experience curves. Browser tests drive a test-only wild encounter through the real UI: victory with level-up and move learning, escape, whiteout, catching with a nickname, keyboard and on-screen D-pad menu navigation, mid-battle backup restore, rollback of unsupported effects, switching through the party menu and a Potion from the Items pocket. Real Route 29 encounters now use the ROM's encounter tables. Only the special Kurt and Park balls remain unported among battle items.
This is still not a complete new game. The Pokégear, Pokédex and trainer card screens, story progression beyond Route 30 and Mr. Pokémon's house, and audio remain unfinished. The start menu opens the party menu and the pack, and Select uses the registered item, such as the Bicycle; the PCs store Pokémon, items and decorations. Surfing and terrain animation now have native implementations; later maps remain gated. Save slots, a Johto/Kanto atlas, Pokédex records, online Link, friends and real-world steps come later.
This is still not a complete new game. The Pokégear's radio, the Pokédex and trainer card screens, Mom's bank, story progression beyond Route 30 and Mr. Pokémon's house, and audio remain unfinished. The start menu opens the party menu and the pack, and Select uses the registered item, such as the Bicycle; the PCs store Pokémon, items and decorations. Surfing and terrain animation now have native implementations; later maps remain gated. Save slots, a Johto/Kanto atlas, Pokédex records, online Link, friends and real-world steps come later.
## 1. Complete the overworld foundation
@@ -272,7 +292,7 @@ Introduce native player, party, Pokémon, inventory, money and quest models. Rea
Expand script calls, choices, scene state, inventory commands and native special handlers. Translate routines reached through assembly calls into explicit native services; never fall back to emulator execution in the shipping game.
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle, and Pokémon evolve. Field moves from the menu, SEL/Select and MOVE PKMN W/O MAIL run too. Next: the Pokégear, then the trainer card and options.
Meeting Mom, Elm's introduction, the starter, the aide's Potion, Route 29, Cherrygrove, Route 30's trainers, Mr. Pokémon's house, the Cherrygrove rival battle, the return to Elm, capture, the catching tutorial, the PC, the introduction's naming and clock screens, and switching and healing items in battle run now. The opening milestone is complete within the recorded acceptance boundaries. The start menu, party menu and pack now run outside battle, and Pokémon evolve. Field moves from the menu, SEL/Select and MOVE PKMN W/O MAIL run too, and the Pokégear's clock, map and phone cards, with calls to Mom and Elm, Mom's bank at home and her purchases. Next: the trainer card and options.
Complete and validate the native battle engine: deterministic randomness, stats, move selection, accuracy/critical checks, damage, status, turn order, switching, fainting, experience, capture and rewards. Compare controlled seeds and states with the original, including integer rounding and overflow behavior.
@@ -305,7 +325,9 @@ Acceptance: main-game/postgame playthroughs, representative optional content, ba
- [x] Touch battle commands, move list, PKMN party menu, PACK (Items and Balls pockets) and naming fields
- [x] Start menu, party menu and pack outside battle (switching, moves, held items, healing and PP items, tossing, the Bicycle)
- [x] Bill's PC: MOVE PKMN W/O MAIL between the party and every box
- [ ] Pokégear, Pokédex, trainer card and options screens
- [x] Pokégear clock, map and phone cards (the radio card waits for its stations)
- [x] Mom's bank: the amount box with its digit cursor, on keyboard, D-pad and on-screen buttons
- [ ] Pokédex, trainer card and options screens
- [ ] Scalable text, configurable controls and fuller accessibility
- [ ] Save slots with migration, atomic writes and import previews
- [ ] Installable web app with offline app shell, safe updates and quota handling
+92 -1
View File
@@ -1,6 +1,6 @@
# Recovered Claude session
Latest continuation: see **Field moves, SEL and moving Pokémon: 2026-09-30**
Latest continuation: see **Mom's bank and her purchases: 2026-10-01**
at the end of this file. Earlier sections are historical snapshots.
Recovered on 2026-09-23 from the local Claude Code transcript
@@ -795,3 +795,94 @@ physical-device run.
Next: the Pokégear (clock, map, phone and radio cards), then the trainer
card and options; later the Fly map and Teleport/Dig warps (they need
script commands after a warp).
## The Pokégear, phone calls and Mom's savings: 2026-10-01
Resumed with "Continue the plan" after `3456aa4`, taking the recorded next
item (the Pokégear).
- `src/game/scripts/pokegear.ts` (`Pokegear`): POKéGEAR in the start menu
runs the clock, map and phone cards with the original joypad rules,
yielding a `pokegear` effect per card answered with a button name. The
world routes A/B/directions/Start/Select to it, keeps `world.pokegear` on
screen during call texts and refreshes the clock every tick. The radio
card (Goldenrod only) gives a notice.
- Calls: no-service text, two "……" rings, out-of-hours or same-map scripts,
otherwise the callee script from `PhoneContacts` in `ScriptRun` on the
start menu's draft (adopted with `Object.assign` when it ends), then
`HangUp`. Elm's and Mom's callee scripts run; Mom's lecture after the Dude
sets `ENGINE_MOM_SAVING_MONEY`.
- Interpreter: `random`, `givemoney`/`takemoney`/`checkmoney`/`getmoney`
for both accounts, `getcurlandmarkname`, `getlandmarkname` (operand order
checked against the macros), `ScriptHost.phoneService`, `landmarkName`.
`HangUp` is now "Click!" 10 ticks, then "……" 60 ticks (it was "Click!" for
140 ticks, double the original's 140 frames); two `mr-pokemon` assertions
were updated.
- Mom's savings: `momsMoney` in `ScriptState` and saves (migrated by absence
to 0). Battles take `mom: { saving, money }` and return `momMoney`;
`WinTrainerBattle.give_money` sends a quarter while she saves some.
`MomTriesToBuySomething` refuses once her balance reaches ¥900 (not
reachable in the open area).
- Map headers decode `phoneService`. New `POKEGEAR` profile table and OW
constants (landmark limits, card/Mom engine flags, money results), all
verified by `check:reference`.
- UI: `#pokegear` panel (card labels, clock, Town Map canvas with the
cursor frame, phone list with ▶/▷ and the submenu); the textbox is the
native dialogue, hidden on the map card; the minimap hides while it is
open. `drawTownMap` takes an optional card (region, player, cursor).
Checks: 381 unit tests with the local ROM (131 passed, 250 skipped without
it; new `tests/pokegear.test.ts`, plus Mom tests in `trainer-battle` and
`trainer-world`); 113 Chromium/WebKit browser tests passed, 19 skipped
intentionally (a new Pokégear flow in both browsers); native and reference
builds; reference, vendor and release checks; `git diff --check`. No
emulator comparison of the Pokégear; no CI or physical-device run. Not
committed.
Next: `BankOfMom` (talking to Mom after the Egg still refuses with special
34), then Mom's purchases (`MomTriesToBuySomething`, `wWhichMomItem`,
`wMomItemTriggerBalance`), the trainer card and options; later the Fly map
and Teleport/Dig warps.
## Mom's bank and her purchases: 2026-10-01
Resumed with "Continue the plan" on top of the uncommitted Pokégear
increment above (still not committed), taking the recorded next items.
- `src/game/scripts/mom.ts` (`bankOfMom`): `BankOfMom` as a special. First
visit: `MomLeavingText1`–`3` and the saving question; later: "Or is this
about your money?", then GET/SAVE/CHANGE/CANCEL from
`BankOfMom_MenuHeader`. The amount box is a `mombank` effect answered
with button names (the world routes A, B and directions to it like the
Pokégear, via `buttonChoice`). `DigitQuantities` is read from the ROM;
`GiveMoney`/`TakeMoney` limits, cursor 0–5 starting on 5, zero or B
cancels, refusals return to a fresh box. Declining runs `DSTChecks`
(near-midnight booklet refusal; `shiftClockHour` wraps `minuteOffset`
into ±720 and moves `weekdayOffset` the other way).
- `MomTriesToBuySomething` is ported (it had to be: deposits make the ¥900
trigger reachable at once, and it refused after every trainer win):
MomItems_2 triggers, the ¥2300 `wMomItemTriggerBalance` steps with the
exact-match `RandomRange(5)` MomItems_1 purchase, PC items (full PC
cancels), doll decoration events, and the call through the existing
`memscript` path (`Script_ReceivePhoneCall` with
`Mom_GetScriptPointer`'s item or doll script). `.ASMFunction`'s cost and
`wWhichMomItem` are applied when the call is queued. `randomRange` is
shared with `Script_random`.
- Saves gained `momItem` (0–10) and `momItemTriggerBalance`, migrated by
absence to 0 and ¥2300.
- New `MOM` profile table and extra `POKEGEAR` entries (MomItems lists,
item/doll scripts), verified by `check:reference`.
- UI: the amount box in the dialogue choice (`.mom-bank`, a blinking digit
that respects reduced motion) with ◀ ▼ ▲ ▶, OK and CANCEL buttons.
Checked visually at desktop and 390px widths.
Checks: 398 unit tests with the local ROM (132 passed, 266 skipped without
it; new `tests/mom.test.ts`, purchase tests replace the refusal test in
`tests/trainer-world.test.ts`); 115 Chromium/WebKit browser tests passed,
19 skipped intentionally (new deposit flow in both browsers); native and
reference builds; reference, vendor and release checks; `git diff --check`.
No emulator comparison of the bank or purchases; no CI or physical-device
run. Not committed.
Next: the trainer card and options; later the Fly map and Teleport/Dig
warps.