Commit Graph

180 Commits

Author SHA1 Message Date
bryanthaboi 76aab74bf1 potentially CLOSES #758 2026-08-03 17:08:42 -04:00
bryanthaboi b831076839 CLOSES #592 2026-08-03 16:38:07 -04:00
Andrew Barnes 4a00f2335c Fix launcher save-slot panel overlap 2026-08-03 16:18:35 -04:00
bryanthaboi f89977a8e7 Merge pull request #747 from johnjohto/fix-fly-animation-702
Play the full Fly departure and landing animation (#702)
2026-08-03 16:11:40 -04:00
Adrian Castro 59b55a8f37 fix(ios): support mod index networking and text input dismissal 2026-08-03 20:43:27 +02:00
johnjohto f19f4e9341 Play the full Fly departure and landing animation (#702) 2026-08-03 13:11:40 -04:00
bryanthaboi 0f7261dd92 CLOSES #623, CLOSES #624, CLOSES #636, CLOSES #637, CLOSES #639, CLOSES #650, CLOSES #697, CLOSES #704, CLOSES #722 2026-08-03 13:05:57 -04:00
bryanthaboi 5c041ea857 snip for scroll 2026-08-03 12:39:36 -04:00
bryanthaboi a0ab949399 Merge pull request #738 from johnjohto/fix-yellow-route18-gate-trade
Wire up Yellow's Route 18 gate trade cook (#651)
2026-08-03 12:00:09 -04:00
bryanthaboi 30ed68ae22 Merge pull request #736 from johnjohto/fix-flavor-talk-double-text
Show only one branch of the gated flavor talks (#719)
2026-08-03 11:59:36 -04:00
bryanthaboi f2aa376304 Merge pull request #733 from johnjohto/fix-fuchsia-exhibit-pokedex
Show the exhibited species' Pokédex entries in Fuchsia City (#646)
2026-08-03 11:58:43 -04:00
johnjohto 4dfbc5a828 Wire up Yellow's Route 18 gate trade cook (#651) 2026-08-03 11:52:48 -04:00
bryanthaboi f0f5bc7551 big ui moment 2026-08-03 11:50:49 -04:00
johnjohto f002db2929 Show only one branch of the gated flavor talks (#719) 2026-08-03 11:22:40 -04:00
johnjohto c5791574f5 Show the exhibited species' Pokédex entries in Fuchsia City (#646) 2026-08-03 11:01:39 -04:00
Adrian Castro 01f68d4038 fix(ios): consolidate mobile integration changes 2026-08-03 11:09:30 +02:00
Shane McGovern 175bff4b29 Match the original faint sound sequence per side (#709)
pokered plays no 'pitched-down faint cry': the player mon's faint is its
ordinary species cry (RemoveFaintedPlayerMon -> PlayCry) with no
Faint_Fall, and the enemy faint plays no species cry at all -- trainer
battles get SFX_FAINT_FALL then SFX_FAINT_THUD, wild battles go straight
to the victory music (FaintEnemyPokemon core.asm:732-796).

The port played the species cry AND Faint_Fall on every faint, so a
fainted enemy sounded its full battle cry and a fainted player mon got
the fall whistle the hardware never plays.

BattleState.onFaint now:
- player: Sound.playCry only
- enemy trainer: Faint_Fall then Faint_Thud (after the slide)
- enemy wild: no faint sfx (victory music already queued)

Adds tests/parity_faint_cry_bug709.lua asserting the per-side sequence.

Fixes #709
2026-08-03 01:55:52 +01:00
bryanthaboi 5348ba1c65 Merge pull request #690 from spiritsnails/fix/faithful-ratio-mobile 2026-08-02 17:58:41 -04:00
Shane McGovern 5e41c74682 Add tile aliases for LOBBY table blocks 45 and 49
The Celadon Diner uses three LOBBY table blocks that share tile 0x37 on
their flat surfaces. Only block 29 had the 0x37->0x5a BROWN alias; blocks
45 and 49 showed raw tile 0x37 in ROOF (blue-gray), creating a blue
square on the second/third tables with the Advanced Colors preset.

Add alias entries for blocks 45 (cells 13/14) and 49 (cells 1/2).

Fixes #689
2026-08-02 21:20:28 +01:00
spiritsnails 02ad846dfa fix: FAITHFUL RATIO works on Android and iOS
apply() returned false on its first line for mobile, so the option did
nothing there. A phone has no window to resize, so the lock caps the
render scale instead: the largest whole multiple of 160x144 the display
holds, centred, black around it.

Two parts beyond that. The scale is read off the display rather than from
the desktop's 1X-4X ladder, which named a different fraction of every
device and left the useful levels off the list; mobile shows ON or OFF.
And the world pass, which expands to cover the whole display so letterbox
becomes more map, is now sized against the locked viewport, so the lock
reaches the overworld instead of showing more of it.

Pixel perfect throughout, whole multiples only. Desktop and OFF are
unchanged. Renames the row to FAITHFUL RATIO on both platforms; the saved
key stays faithfulRes so existing settings carry over.
2026-08-02 12:44:38 -06:00
bryanthaboi fa886899fc Merge pull request #653 from jherediagu/fix/oak-intro-name-confirmation 2026-08-02 13:11:51 -04:00
bryanthaboi 164c555bb4 Merge pull request #669 from jherediagu/fix/battle-messages-use-rom-text 2026-08-02 13:10:15 -04:00
bryanthaboi e5926893a9 Merge pull request #670 from ShaneMcGovernIE/fix/oak-starter-jingle-668 2026-08-02 13:07:38 -04:00
bryanthaboi dbcaf705c2 Merge pull request #672 from ShaneMcGovernIE/fix/faint-animation-671 2026-08-02 13:05:23 -04:00
spiritsnails 3ddf70888e test: ui_layout_option runs ROM-free
The row assertions called Data:load(), which needs data/generated/. The
T1/T2 tier runs without a ROM in CI, so the suite died on the import
rather than failing an assertion. Use T.fixtures.load() like the other
engine suites do.

Verified by moving data/generated aside and re-running: 20/20 with no
imported data present.
2026-08-02 10:54:04 -06:00
spiritsnails fe7dcf33ec feat: UI LAYOUT option, centered by default
Edge docking and zoom-linked UI scaling shipped as unconditional
behaviour. Both are departures from how the port composed the screen, so
they become a setting instead: UI LAYOUT = CENTERED (the default) or
DYNAMIC.

CENTERED is a fixed letterbox. Elements stay where they were drawn in the
160x144 canvas, and the UI does not follow the survey zoom, so screen
furniture neither moves nor resizes under the player. That is what the
pre-anchoring builds did. DYNAMIC is the current behaviour, unchanged.

Both halves matter together: gating only the anchoring would stop the
dialogue box moving but leave it resizing with the zoom, which is the same
complaint in a different form.

Gated at Renderer:setUIAnchor and Renderer:uiScale rather than at each
caller, so one switch covers the dialogue box, its YES/NO, the START menu
and anything anchored later, and no caller knows the option exists.
Game.dynamicUI answers true only for an explicit "dynamic", so a save
written before this keeps the layout it already had.

Independent of it, deliberately: BATTLE SIZE still works under either mode
(uiFill overrides the scale later, in endFrame), and a battle still holds
its own prompts inside its screen under DYNAMIC.

Also includes the Oak intro fix (previously #674): the speech fills white
over the UI canvas while its dialogue box docks to the window edge, so
under DYNAMIC black showed between the two. letterboxWhite closes it, and
the shrink beat's replica box rides the same anchor as the real box it
stands in for.
2026-08-02 10:47:27 -06:00
Shane McGovern 733450bf86 Fix faint slide starting partway down (#671)
The faint slide was shortened from 30 to Timing.FAINT_SLIDE (14) frames
in the timing-parity pass, but fxFaintOffset still computed the offset
with a stale (30 - frames) * 2.  With frames starting at 14 the sprite
teleported 32px down on the first frame and only slid the remaining
28px, cutting the animation short.

SlideDownFaintedMonPic drops the pic one 8px row per 2-frame step, so
the offset advances Timing.FAINT_SLIDE_STEP (4px) per frame at 1x and
covers the full 56px PIC_HEIGHT over the 14-frame budget.
2026-08-02 16:34:02 +01:00
Shane McGovern 1dae9622e1 Play the jingle when Oak hands over the starter (#668)
The starter balls' scripts showed the received-mon text but never played
the sound_get_key_item fanfare that the text carries in the original
(scripts/OaksLab.asm OaksLabReceivedMonText / OaksLabRivalReceivedMonText).
Add play_sound Get_Key_Item before each received text, mirroring the
Yellow starter port.
2026-08-02 16:21:49 +01:00
Juan Heredia da0fa5c9ad Use the ROM's own battle text instead of paraphrasing it 2026-08-02 17:09:08 +02:00
bryanthaboi cb26367f46 Merge pull request #655 from spiritsnails/fix/warden-yesno-645 2026-08-02 08:26:05 -04:00
bryanthaboi 31dc89c0d7 Merge pull request #652 from spiritsnails/fix/enemy-sendout-early-sprite 2026-08-02 08:24:32 -04:00
bryanthaboi 35b3fa6d9c CLOSES #455, CLOSES #487, CLOSES #501, CLOSES #540, CLOSES #585, CLOSES #591, CLOSES #593, CLOSES #595, CLOSES #597, CLOSES #599, CLOSES #600, CLOSES #606, CLOSES #607, CLOSES #610, CLOSES #613, CLOSES #616, CLOSES #620, CLOSES #626, CLOSES #632, CLOSES #633, CLOSES #647 2026-08-02 08:19:28 -04:00
spiritsnails 9934e4d765 fix: Warden's House gibberish line offers YES/NO
WardensHouseWardenText prints Gibberish1, calls YesNoChoice, and answers
with Gibberish2 on yes / Gibberish3 on no (scripts/WardensHouse.asm). The
port printed the question and ended the script. Both reply strings were
already extracted and unused, so this is script wiring only.

The branch targets become labels: they were hand-numbered absolute rows,
already mis-pointed once (#535), and any insert meant renumbering jumps
that had no way to announce they were stale.

Also fixes the parity suite's show_text instrumentation, which stopped
forwarding arguments at `subs` and so dropped the extraOpts carrying
Commands.ask's choice callback -- silently turning every ask under test
back into a plain show_text.
2026-08-02 00:34:46 -06:00
Juan Heredia b6a397460e fix: Play Oak's name confirmation lines 2026-08-02 08:18:33 +02:00
spiritsnails 2b75c07571 fix: enemy mon appears before its send-out animation
The trainer intro was the only enemy send-out path that never set
enemySendingOut, so the front sprite drew at full size the moment the
trainer pic walked off, held through "X sent out Y!", and the grow-in
then played over a mon that had already arrived. Set it with the pic
teardown and clear it with startGrowIn, matching the mid-battle
replacement and the player's own send-out.

Also repairs two parity suites that could not load at all: their game
stubs lacked input.isDown, which battle text has read every frame since
typing started honouring PrintLetterDelay. intro_chrome additionally
pressed A inside PromptText's ProtectedDelay3 hold, which ignores the
button for TEXT_PRE_ADVANCE frames.
2026-08-01 23:55:23 -06:00
bryanthaboi ebbc55c4d0 Merge pull request #586 from andimiller/surfing-pikachu-fix
feat(yellow): port SurfingPikachu behaviour
2026-08-02 00:58:32 -04:00
spiritsnails 46bd0f6709 fix: battle screens keep their composition when they open a menu or prompt
BATTLE SIZE "fixed" draws the battle as a discrete letterbox rather than
filling the window, and BATTLE BG "world" composes it over the live map.
Everything the battle then opens broke out of that composition, because
each piece of the frame's geometry was read off a fact about THIS FRAME
instead of about the battle:

* Renderer:uiScale follows the survey zoom only while a world is behind
  the UI, gated on worldActive -- this frame's world pass.  PartyMenu and
  ListMenu are opaque, so pushing one makes StateStack:visibleBase skip
  the map, no world pass runs, and the menu loses the step-down and blits
  a whole integer scale larger than the battle it just covered.  Held
  with uiWorldHold, the same whole-stack rule uiFill and the battle dim
  already use.  ("fill" hid this: it overrides the scale outright.)

* Game:draw started the frame at visibleBase, so that same opaque menu
  cut the overworld -- and the world pass with it -- out of the frame
  entirely, collapsing a "world" backdrop to endFrame's flat black clear.
  A world-bg battle now keeps the frame starting from underneath itself
  (drawBaseInStack).  Only the START of the draw moves; the clear stays
  keyed to the real visibleBase, so the menu still gets its opaque canvas
  and draws exactly as before.

* worldZones was keyed to that same clear base, so it came out nil for a
  frame whose world pass HAD run -- dropping endFrame's world blit onto
  the UI zone list instead, smearing the party menu's own HP-bar palettes
  across a world-canvas-sized image.  Keyed to whether the map drew.

* endFrame's letterbox clear read letterboxWhite off visibleBase alone,
  so an opaque menu over a BG "white" battle flipped its surround to
  black the same way.  Same whole-stack hold.

* ChoiceBox bottom-anchored unconditionally, docking it to the WINDOW
  edge.  That is only right when it rides the dialogue box beneath it,
  which is anchored there too; TextBox now passes the anchor and nothing
  else does, so the battle's switch offer and the shop/PC confirms stay
  over the screen that pushed them.

* TextBox anchors likewise: a battle is a self-contained SCREEN, not the
  window, and pokered prints its text box in the same 160x144 tilemap as
  the HUD.  The caught-mon nickname prompt was landing a whole letterbox
  below the blanked battle field it is printed on.  BattleState.holdsUI-
  Anchors holds setUIAnchor off while a battle is in the stack; the
  overworld's own dialogue box still docks to the screen edge.
2026-08-01 22:55:58 -06:00
spiritsnails 2b92562538 fix: yes/no box popping up after the question text closes, not over it
several places (Commands.ask, the give-a-nickname prompt, PC box release/
change confirms, start menu save/quit) pushed a bare ChoiceBox after the
preceding text box already popped on an A press, instead of riding
TextBox's opts.choice like the rest of the engine. the YES/NO box now
comes up while the question is still on screen, matching the original.
2026-08-01 21:36:30 -06:00
bryanthaboi f205464aa4 Merge pull request #627 from spiritsnails/parity-fixes 2026-08-01 21:18:52 -04:00
spiritsnails b820d3917c fixing failed tests/harnesses 2026-08-01 19:13:03 -06:00
spiritsnails 4cb132199c Fix ADVANCED palette pack using Gen 2 per-species palettes instead of Gen 1's
pokered-gbc's palettes.asm carries two species->palette tables gated on
GEN_2_GRAPHICS; data/palettes_gbc.lua had imported the per-species Gen 2
table, shaded for Gen 2 sprite art this port doesn't use, instead of Gen
1's own assignments. Bulbasaur wore PAL_BULBASAUR's red-orange, Squirtle
wore PAL_SQUIRTLE's shell brown on his head. Palette values are unchanged;
only which palette each species points at is corrected.
2026-08-01 16:04:22 -06:00
spiritsnails aedc63c40d Port timing/parity fixes, seamless battle transitions, faithful-res lock, and zoom-aware UI anchoring
Ports from a downstream fork, hand-surgered hunk-by-hunk to exclude the
fork's randomizer/pokescript work and to skip a FixedStep jitter-tolerance
attempt that never fixed the stutter it targeted.

- src/core/Timing.lua: hardware-accurate frame-delay catalog ported from
  pret/pokered, feeding BattleState:waitNext, EffectRegistry's miss/crit
  beats, TextBox/ChoiceBox scroll and prompt holds, and the battle
  silhouette slide/shake/blink/faint timings.
- Seamless battle transitions: Renderer:drawBattleWipe replaces the old
  160x144-only cascade with one wipe drawn over the whole surface at any
  zoom or window size; BattleTransition's per-style frame lengths are
  corrected against pokered-c's derivation; Transition.battleReturn adds
  the post-battle GBFadeInFromWhite the port never had.
- BATTLE SIZE / BATTLE BG options (BattleState:wantsFillScale/bgMode,
  Game.fillScaleInStack/worldBgBattleDim): battle surface can fill the
  window instead of the fixed integer letterbox, and the area around it
  can show white/black/the dimmed overworld instead of only white.
- src/core/FaithfulRes.lua: locks the window to an exact 160x144 multiple.
- Zoom-aware UI anchoring: Renderer:uiScale steps the UI down with survey
  zoom (gated to worldActive so the title/intro never shrink);
  Renderer:setUIAnchor lets TextBox, ChoiceBox, and an opted-in Menu
  (the START menu) pin themselves to a screen edge instead of the
  zoomed-out letterbox.
2026-08-01 15:52:34 -06:00
Shane McGovern d951fe8fc5 Fix Viridian old man tutorial dialog in Yellow (#617) 2026-08-01 22:38:09 +01:00
Andi Miller 6fb5aa08ff Merge branch 'dev' into surfing-pikachu-fix 2026-08-01 21:02:06 +01:00
bryanthaboi 9f072285a6 Merge pull request #611 from ShaneMcGovernIE/fix/oak-last-ball-601 2026-08-01 16:00:52 -04:00
Shane McGovern 0dd187fe30 Fix wrong dialogue on Prof. Oak's leftover ball (#601)
After the player picks a starter and the rival takes his, every ball on
the lab table fell through to 'Those are POKé BALLs' instead of the
leftover-mon line.  Port the pokered OaksLabSelectedPokeBallScript ->
OaksLabLastMonScript beat: with EVENT_GOT_STARTER set, Oak turns to face
the player and reads 'That's PROF.OAK's last Pokémon!'.  The ROM's
'#MON' ligature is spelled out as Pokémon.

The renumbering also drops the table's nine out-of-range 'jump 21'
rows (run-time 'end' idioms) for explicit "end" targets, so the
script now validates cleanly.

Tests: T2 suite drives the ball talk table through a ScriptRunner-
compatible executor (leftover text, pre-escort text, pre-pick offer)
plus a T3 driver that talks to the leftover ball in a real game.
2026-08-01 20:55:31 +01:00
bryanthaboi 6bb2e078c0 Scrub mod manifest strings to valid UTF-8
A manifest whose name, version, description, or category carries invalid
UTF-8 (a BOM, Latin-1 bytes) crashed the launcher's MODS panel, since
love.graphics.printf raises on invalid UTF-8. Manifest.validate now drops
invalid bytes and a leading BOM from those strings, in place so the
badge's raw.category read agrees.
2026-08-01 14:22:30 -04:00
bryanthaboi d26d63ed38 Merge pull request #588 from techmore/fix/prof-oaks-pc-flow 2026-08-01 12:58:03 -04:00
bryanthaboi 2009df3dd1 CLOSES #575, CLOSES #578, CLOSES #584, CLOSES #589 2026-08-01 12:56:13 -04:00
techmore f0f3e9634b fix: restore PROF. OAK's PC intro, jingle timing and closing link
CLOSES #576

The launcher skipped oaks_pc.asm's whole session -- the access text and
the 'Want to get your #DEX rated?' YES/NO -- and played the Pokedex_Rating
jingle the moment the entry was picked, before any text printed.  Now the
access text types out, the YES/NO pops, and only once the completion line
and the rating tier have printed does the jingle sound (DisplayDexRating
-> PlayPokedexRatingSfx, auto.wait hands the box to the A/B path), then
the 'Closed link to PROF.OAK's PC.' tail closes the session.
2026-08-01 11:01:19 -04:00