Commit Graph

1572 Commits

Author SHA1 Message Date
bryanthaboi acdcbd8d4d bazinga 2026-09-13 01:06:04 -04:00
1jamie 65badd1a4b fix(game3): fix learn-move show and pump for both battle and party contexts
Two contexts call LearnMove.begin with different pushMsg semantics:
- Battle (Ui.push): single-arg, ignores callback -> pump() must poll
  Ui.dialogPending() to wait for the player to dismiss the message
- Party menu / rare candy (PartyMenu.showMessage): honours the callback,
  calling it when the player presses A -> finish() must fire inline

Fix: set _pending='done' for the pump() path (battle) AND restore the
say() callback for the direct path (party menu). A guard on _pending
prevents double-finish. pump() now checks Ui.dialogPending() before
acting on 'done' so the 'X learned Y!' message stays visible until
the player dismisses it in both contexts.
2026-09-11 17:02:16 -05:00
1jamie dc9d5c74c7 fix(game3): fix level-up move learn soft lock when mon has free move slots
LearnMove.begin's free-slot path called say(text, cb) expecting pushMsg
to invoke the callback once the message is dismissed. The battle UI's
hooks.pushMsg is Ui.push which only accepts (text) and silently drops
the callback, so finish(ok) was never called, LearnMove._active stayed
true forever → soft lock (reported as Charmander learning Ember).

Fix: set _pending="done" + _pendingResult before say() so pump() can
complete the sequence on the next update tick once the dialog drains,
matching how the 4-move full path already uses _pending="delete".
The say() callback is still wired so contexts whose pushMsg does honour
it (party_menu TM flow) finish inline as before.
2026-09-11 16:50:56 -05:00
1jamie 0ec555b25b feat(android): update application ID for development and add FireRed manifest support
- Change application ID to 'com.theboisclub.pokemonred.dev' for development builds.
- Introduce FireRed manifest handling in build scripts and ensure its validation during packaging.
- Update various scripts to include FireRed resources in the build process.
- fixed a lot of the cachefs extraction to work on android
2026-09-11 10:41:37 -05:00
1jamie b06d8bc99c feat(game3): battle animation VM rendering architecture, full ROM extraction, evolution scene, and UI refinements 2026-09-10 20:12:29 -05:00
1jamie 0c55d1d32f feat(game3): align battle flow, transitions, and animations 1:1 with pret pokefirered
- Add spinning rotation to Pokeball throw animations
- Align enemy trainer send-out sequence and concurrent slide-out
- Fix battle intro terrain parking to prevent initial frame position snapping
- Initiate battle BGM immediately on transition start matching retail FRLG
- Extract authentic red dialogue prompt down-arrow from ROM
- Split battle terrain background wallpaper from transparent platform ovals
- Fix faint, exp, and shift-switch sequencing order
2026-09-10 13:05:01 -05:00
1jamie 6874e3705b feat(game3): extract ROM trainers, line-of-sight sight check, dialogues, and battle rewards
- Add full 743 trainer ROM extraction from gTrainers with 4-tier party struct support
- Account for flat IV scaling math ((rawIv * 31) / 255) and enforce 0 EVs for trainer Pokémon
- Decompose 32-bit AI script flags for runtime execution
- Implement backwards-search fallback for boss dialogue disconnect (0x1, 0x3, 0x9)
- Implement TrainerSight line-of-sight raycast with elevation & ledge masking and spinning trainer turn hooks
- Support pre-battle intro dialogue, encounter music, and in-battle defeat quotes
- Implement authentic prize money calculation and reward triggering
- Fix move name resolution for table-wrapped party moves in battle UI and party menus
2026-09-09 18:19:45 -05:00
1jamie 4f1877daae fix(game3): fix surf blob animation/palette, cut effects, and tree canopy path collision 2026-09-09 17:13:41 -05:00
1jamie 2426e519b2 bit of fixes for door transition and stub placeholders for field moves 2026-09-09 16:37:01 -05:00
1jamie ce0edb6994 fix(host): close iOS branch in HostShell.restart 2026-09-09 15:06:15 -05:00
1jamie 342e80b963 fix(game3): safely resolve harborVar in space.lua to prevent nil table index on new game 2026-09-09 15:02:51 -05:00
1jamie 1c173a6377 feat(game3): make extraction and runtime 100% self-contained and ROM-derived
- Implement pure ROM extraction for Trainer Card backgrounds and badges
- Connect TrainerCardExtract to RomExtractorGen3 and CacheContract
- Update TrainerCard, FrlgFont, Chrome, PcChrome, PokedexChrome, and SummaryChrome to route exclusively through CacheFs
- Remove all legacy fallback paths to src/import/gba/chrome and hardcoded pret directories
- Add standalone procedural fallbacks for field effects and Pokecenter heal
2026-09-09 14:56:34 -05:00
1jamie 432c8bb4d7 feat(game3): pure ROM extractor for FRLG text fonts, widths, and dialogue chrome 2026-09-09 14:42:27 -05:00
1jamie dcb18bd34e fix(launcher): balance GBA cart sizing and margins in game panel 2026-09-09 14:20:09 -05:00
1jamie c860065e4a feat(launcher): configure GBA cart shape and FireRed label art for launcher 2026-09-09 14:18:26 -05:00
1jamie 52ad498b8b feat(game3): self-contained ROM-derived FireRed extraction & cache contract alignment
- Align CacheContract firered overrides with pure ROM extraction
- Fix door animation extraction tile sizes, palettes, and strides
- Update storage chrome, pokedex, summary, and battle chrome extractors
- Ensure 100% self-contained ROM extraction without external dependencies
2026-09-09 14:14:40 -05:00
bryanthaboi 8aa6e3d4b9 ...bug fixes 2026-09-09 12:23:55 -04:00
bryanthaboi a0f9d73aa2 linux arm64 builder: bullseye apt sources from snapshot.debian.org
bullseye hit EOL on 2026-08-31; deb.debian.org now serves an expired
bullseye-security InRelease and its pool already 404s, while
archive.debian.org has only the main suite (whose libc6 is older than the
one baked into the debian:bullseye image). Pin both suites to the
2026-08-31 snapshot so the image builds again and stays reproducible.
2026-09-09 10:38:11 -04:00
bryanthaboi ab10687ba6 sync save deletion 2026-09-09 09:46:27 -04:00
bryanthaboi ca8a32746b CLOSES #2166 and other stuff, including documentation updates for better understandability and helpfulness 2026-09-09 09:32:09 -04:00
bryanthaboi a6a85a3244 Merge pull request #2229 from HighDrexler/proposal/mod-job-asset-io 2026-09-09 07:49:49 -04:00
bryanthaboi 558cf082a1 Merge pull request #2221 from BountyHunterKanden/input-key-gamepad-wheel-hooks 2026-09-09 07:48:46 -04:00
bryanthaboi dbb13861d3 Merge pull request #2213 from AverageConsumer/codex/secondary-touch-motion 2026-09-09 07:47:54 -04:00
bryanthaboi debbca330a Merge pull request #2207 from wild1walker/claude/gen2-cart-save-scope 2026-09-09 07:46:50 -04:00
bryanthaboi 2e24febaca CLOSES #2199, CLOSES #2200, CLOSES #2203, CLOSES #2204, CLOSES #2205, CLOSES #2206, CLOSES #2212, CLOSES #2214, CLOSES #2218, CLOSES #2219, CLOSES #2223, CLOSES #2224, CLOSES #2225, CLOSES #2226 2026-09-09 07:32:12 -04:00
bryanthaboi 60df2fbb65 CLOSES #2230, CLOSES #2232 2026-09-09 06:05:00 -04:00
HighDrexler 0bd2b2040c mods: allow bounded asset I/O in background jobs 2026-09-07 21:12:32 -04:00
HighDrexler 2641279051 docs: mock proposal for mod.job asset preprocessing 2026-09-07 20:49:09 -04:00
BountyHunterKanden 975dc40d41 Add input.key, input.gamepad, and input.wheel hooks (RFC 0020)
Kanto Companion's Edit Mode can't run during battle -- there's no way
to stop a D-pad press from also driving the battle menu, so the only
option today is pausing the game outright. This adds the same input
precedence a mod had before the sandbox changes: vanilla is the whole
existing callback body, and the hook fires before any of it runs.
input.wheel stays a plain observer like input.pointer, since nothing
depends on suppressing it.
2026-09-06 12:24:08 -05:00
AverageConsumer 25ced236da Forward touch movement on the Android secondary screen 2026-09-05 23:13:16 +02:00
Claude 5920402de4 Gen 2: a cart saves into its own scope, not the base game's
A cart's saves are keyed by cart id, not by version.  SaveData resolves
every path through activeScopeKey, which answers cart_<id> while one is
active, and the launcher lists, creates and selects a cart's slots from
the cartSlots registry (RomImporter._refreshSlots / _selectSlot /
_newSlot).

src/core/gen2/Save.lua asked in the version's name alone.  saveNames
built saves/<version>/<slot>.lua or save_<suffix>.lua from the version in
both branches and never consulted the active cart, so a cart on Gold,
Silver or Crystal read and wrote the BASE GAME's playthrough.  Gen 1 was
unaffected because it saves through SaveData itself, which is already
cart-scoped -- so this only showed on a Gen 2 cart.

It was worse than sharing one file.  Save.save opens by asking
activeSlot(version) and, on nil, calling createSlot + setActiveSlot in
the version's name, so the first save inside a cart registered a slot in
the base game's registry and made it active: the cart's playthrough
appeared in the launcher's list for the base version, and the player's
own save there was what the cart then overwrote.

Both sites now resolve the cart scope the way SaveData does, and the
names they build are SaveData's own -- slotDir's saves/cart_<id>/ and
legacyNames' save_cart_<id>.lua -- so the in-game save layer and the
launcher land on one file again.

tests/gen2_save_test.lua covers the cart's flat name, its slot name, the
slot going into the cart's registry rather than the base game's, the
cart's scope winning over a base slot, and the base game keeping its own
once the cart is cleared.  Four of them fail on the unpatched module.

Reported as "when I select Wild Crystal to launch it loads my save from
regular Crystal".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 18:36:17 +00:00
bryanthaboi fdd1d61ea6 yellow residuals 2026-09-05 09:03:47 -04:00
bryanthaboi 4420f14cbd CLOSES #2185, CLOSES #2188, CLOSES #2189, CLOSES #2190, CLOSES #2191, CLOSES #2192, CLOSES #2193, CLOSES #2194, CLOSES #2195, CLOSES #2196, CLOSES #2197 2026-09-05 08:55:59 -04:00
bryanthaboi 469ba593a6 textbox fix for intro fade out 2026-09-04 10:48:56 -04:00
bryanthaboi 1863af2bac gsc: the battle HUD frame fades with the rest of the screen 2026-09-04 10:45:08 -04:00
bryanthaboi 9ae53ac81f gsc: intro palette rotations, music fade and player icon, CLOSES #2171 2026-09-04 10:45:07 -04:00
bryanthaboi e6e3459dbe yellow: Bill's house Pikachu timing, collision and spawn cell, CLOSES #2165 2026-09-04 10:45:02 -04:00
bryanthaboi e9cf07ef47 gsc: map-load white hold measured on hardware, CLOSES #2141 2026-09-04 10:45:02 -04:00
bryanthaboi aa997eeb51 online fixerino 2026-09-04 09:56:35 -04:00
bryanthaboi 8d62d80f1c yellow: a parked Pikachu blocks the player in every follow-disabled scene 2026-09-04 09:41:20 -04:00
bryanthaboi f30ecb484e Merge branch 'dev' of https://github.com/bryanthaboi/gen1recomp into dev 2026-09-04 09:34:16 -04:00
bryanthaboi 16d684297e battle: status moves print the cart's refusal lines 2026-09-04 09:25:34 -04:00
bryanthaboi 77f8c0ca7e battle: a refused status effect keeps its animation cancelled 2026-09-04 09:20:36 -04:00
bryanthaboi 7f1336a830 CLOSES #2114, CLOSES #2115, CLOSES #2116, CLOSES #2117, CLOSES #2118, CLOSES #2124, CLOSES #2125, CLOSES #2126, CLOSES #2148, CLOSES #2149, CLOSES #2150, CLOSES #2151, CLOSES #2152, CLOSES #2153, CLOSES #2155, CLOSES #2156, CLOSES #2158, CLOSES #2159, CLOSES #2161, CLOSES #2162, CLOSES #2163, CLOSES #2164, CLOSES #2170, CLOSES #2173, CLOSES #2174, CLOSES #2175, CLOSES #2176, CLOSES #2178, CLOSES #2179, CLOSES #2180, CLOSES #2181, CLOSES #2182 2026-09-04 09:15:16 -04:00
bryanthaboi ff2ea95eb9 Merge pull request #2160 from thibautbus/fix/gen2-move-learn-and-item-effect-strings 2026-09-03 16:51:27 -04:00
bryanthaboi bf39f7a3da Merge pull request #2154 from 1Jamie/android-fixes 2026-09-03 16:51:10 -04:00
1jamie 3cce66d497 Implement Android image export functionality and enhance save data management. Added exportImageToGallery method for saving images to the public Pictures directory on Android. Updated Printer and SaveData modules to support this feature, ensuring proper slot resolution and user feedback. Improved touch handling in the launcher to prevent unintended actions after exiting games. 2026-09-03 13:17:59 -05:00
thibautbus fa4e96e879 Route Battle Tower Menu messages through Strings()
BattleTowerMenu:drawPanel() shows self.message via Chrome.printWrapped
directly, with no Strings() lookup of its own -- same shape as
Game2:say()/TextBox.new(), which also expect their caller to have
already resolved the text. Every assignment to self.message in this
file used the raw Strings.source() return value (an identity/harvest
marker, not a lookup) instead: the level-picker prompt, the "quit your
challenge?" confirmation, the level-cap refusal, and the Uber-clause
refusal (which additionally called Lua's own string.format() on the
untranslated source instead of Strings(UBER_TEXT, name)). The YES/NO
confirmation labels and the CANCEL row label had the identical bug one
level down: declared with Strings.source() but printed via
Chrome.print() with no Strings() call around them either. The whole
Battle Tower level-picker menu, including its yes/no prompt, stayed in
English regardless of any translation catalog a mod supplied.

Found via a systematic trace of every TextBox.new() (143) and
Chrome.print()/Chrome.printWrapped() call site in the engine back to
its text source, cross-checked against the real tools/modkit.py
harvester and an independent review of the branch. That same review
also flagged src/world/OverworldController.lua:3314
(Strings.source("%s's PC"):format(playerName)) as the same bug shape,
and an earlier revision of this branch "fixed" it to
Strings("%s's PC", playerName) -- but that call site is not a bug:
openPC() deliberately builds every PC row's label from a stable
English Strings.source() value first, so the ui.pc.items mod hook can
match/reorder rows by their vanilla English text, and only translates
via a second translatedLabels[playerPcLabel] pass after the hook has
run (openPC()'s own comment: "Hooks identify the vanilla rows by their
English source labels. Delay localization until after ui.pc.items has
inspected/reordered/replaced them"). Translating playerPcLabel early
broke that contract -- confirmed by tests/engine/rby_translation_runtime_test.lua,
which already covered this exact case and failed with
"ui.pc.items sees the stable player-PC source label (got PC DE RED,
want RED's PC)" once that change landed. Reverted; the label was
already being translated correctly by the existing second pass, which
this branch never needed to touch.

A second independent review round, after the fixes above, found one
more real gap in the same family: ItemEffects.lua's VITAMIN_LABEL
table (folded into the previous commit once found), and confirmed
everything else on the branch clean.

Verified with tools/modkit.py's harvest_engine_strings that all seven
BattleTowerMenu.lua literals are still discovered from their
Strings.source() declarations, luajit tests/run_gen2.lua: 144/145 (the
one unrelated pre-existing failure noted in the previous commit), and
luajit tests/run_engine.lua: 533/533 (including the PC-label
regression test above, now passing).
2026-09-03 19:11:36 +02:00
thibautbus 9401445c0f Route Gen 2 move-learning and item-effect text through Strings()
learnMoveOn (Game2.lua) built every move-learning message -- level-up
learn, TM/HM teach, the "trying to learn X, forget a move?" flow, "stop
learning?", the HM-can't-be-forgotten refusal, "which move should be
forgotten?", and the "1, 2 and... forgot X, learned Y!" replace result
-- with a bare string literal or a direct :format() call, bypassing
Strings() entirely (src/core/Strings.lua). Game2:say()/TextBox.new()
show whatever text they're handed with no lookup of their own, so this
meant the entire move-learning UI stayed in English no matter what
translation catalog a mod supplied -- confirmed against a real
gen1recomp-translation-mods build, which has translated overrides for
several of these keys that could never apply because the literal never
reached the catalog. Same bug for the TM/HM teach refusals ("X can't
learn Y!"/"X already knows Y!").

src/core/gen2/ItemEffects.lua had the same bug across its whole family:
every item-usage message (Potion/heal, status cure, Revive, Rare Candy,
Vitamin, PP restore/PP Up, "no effect"/"can't use on an EGG"/"can't use
on this #MON") was either a bare table constant or built with :format()
directly, none of it routed through Strings(). Its constants are now
wrapped in Strings.source() at declaration (so a mod's catalog harvest
still finds them, per the pattern already documented in Strings.lua)
and looked up through Strings() at each use site. The Vitamin success
message's own VITAMIN_LABEL table (HEALTH/ATTACK/DEFENSE/SPEED/SPECIAL)
gets the same two-part fix -- each entry wrapped in Strings.source() at
declaration, and Strings(VITAMIN_LABEL[stat]) at the one use site --
matching the identical stat-name tables in MoveEffects.lua/TrainerAI.lua/
gen2/Effects.lua/ContestMenu.lua/SummaryMenu.lua, which all already do
this; without it a Vitamin's stat name would stay in English mid-sentence
even inside an otherwise fully translated message. Two more call sites
read ItemEffects.TEXT_NO_EFFECT raw outside that file and needed the
same fix: PartyMenu.lua's Softboiled-no-target refusal, and
BattleState.lua's X-item-reused-with-no-effect and
BitterBerry-when-not-confused refusals -- both battle-side messages
where every neighboring self.message assignment already correctly
wraps in Strings(), which is what made these two stand out as missed.

None of this changes vanilla (no mod loaded) output: Strings.get() is
an identity function with no catalog active, so every message renders
byte-identical to before. Verified with the headless Gen 2 suite
(luajit tests/run_gen2.lua): 144/145, the one failure
(gen2_fishing_time_test.lua) reproduces identically on dev before this
change and is unrelated (fishing time-group logic); the full engine
suite (luajit tests/run_engine.lua) is 533/533.
2026-09-03 19:11:23 +02:00
bryanthaboi d6cf840e02 test fix 2026-09-03 08:51:37 -04:00