RomArchive sniffs magic, probes platform mount capability (zip/7z,
cached), unwraps first accepted-size ROM (prefer known SHA-1). Wired
into startData, filedropped game-tab zip routing, chooseRom picker
exts, FileBrowser rom filter (hidden when capability probe fails).
The prompt a mode shows (Choose a POKéMON., Move to where?...) was kept on the party menu for the rest of the session. PartyMenu.show now clears it, like the menu's other per-open state, so a prompt is resolved once per opening.
The CONTEST MOVES page printed the contest effect's description as the contest moves pack has it. It now goes through SummaryData.contestEffectDescription, as Emerald's summary does, resolved once per effect while the summary is open.
The party menu's prompts (Do what with {STR_VAR_1}?, Choose a POKéMON., Move to where?...) printed the rse/party pack's copies, plain English strings that also dropped the POKéMON's name from Do what with {STR_VAR_1}?. They now read the script cache by their PartyMenuPromptTexts slot, with the selected POKéMON's name as STR_VAR_1, the pack's copy as the fallback; a prompt is resolved once for the menu or mode that shows it.
Data.drawActions looked each action's text up in the script cache on every frame. It now draws the texts the party menu resolves once for each action list (action_texts, exposed as PartyMenu._actionTextsFor), as Emerald's and FireRed's menus already do.
The Ruby/Sapphire party menu printed its actions from the rse/menus
pack's cursor options, plain English strings the extractor copied from
sPokemonMenuActions, and a field move's English label, so a translation
mod's SUMMARY, SWITCH, ITEM and the others never showed. The actions now
read the script cache by the labels sPokemonMenuActions points at
(pokeruby/src/pokemon_menu.c:126), with the pack's copy as the fallback,
and a field move prints its move's name, as the cart does; Emerald's
party menu does the same since gen1recomp#2678.
The Ruby/Sapphire Easy Chat editor, mail composer and reader, Dewford
trendy phrase editor and trainer card printed each word's cart text
(EasyChatText.rawWord) and the pickers each group's and word's raw
name, and the TV and the Dewford line naming the new trend got the raw
words too, so a translation mod's Easy Chat vocabulary never showed
there. They now print EasyChatText.word and groupName, as the other
game3 screens do, each screen keeping a word it resolves until it opens
again; the comparisons the scripts rely on (changed phrases, the
Mystery Event words, the trend's comparison) keep the raw text.
Gabby and Ty's last quote is printed from the cart's bytes, so a
translated word the cart's charset cannot hold (a Japanese one on a US
cart) keeps the cart's word there instead of printing "????".
The Ruby/Sapphire shop, decoration menus, move relearner and contest
paintings printed the cart strings their extractors copied into their
packs (textBytes, keyed by the strings' pokeruby labels), so a
translation never reached them. The script cache holds the same strings
under the same labels, where a mod's text overrides land: these screens
now read it there, with the pack's copy as the fallback, the way
Emerald's screens do (RomText.irOr). The shop, the decoration menus and
the move relearner keep each text they resolve until the screen opens
again, the painting its caption once it is built.
A hall painting's caption names the trainer, then the POKéMON, as the
US cart does; the European carts name the POKéMON first, their
possessive row starting with a space (" von ", " de ", " di ",
pokeruby/src/contest_painting.c:234), and so does the caption now
when the row does.
The native Ruby/Sapphire Pokédex printed the entry's two description
pages from the entries pack, and its labels (?????POKéMON, CRY OF,
REGISTRATION COMPLETE...) and search screen from the chrome packs'
English copies, so a translation never reached them: the Emerald path's
Strings() lookup does not cover the native one, and the search screen's
labels are Emerald's (gText_Dex*), which Ruby and Sapphire's cache does
not have.
The entries pack now keeps the pret label of each description pointer
(DexDescription_Treecko_1 and _2; each edition words its entries in its
own way under the same labels), and the Ruby/Sapphire Pokédex pack the
DexText_ label of each search title and description (DexText_ABC...);
the pack's version moves to 1 and the entries are ready on Ruby and
Sapphire only with their labels, so a cache imported without them is
imported again. The screen reads them from the script cache by those
labels, its own labels by their gDexText_* labels and the category
through Strings(), as Emerald's does, with the pack's copy as the
fallback.
The category is followed by what the unknown-category string has after
its question marks, as only the English cart does
(pokeruby/src/pokedex.c:4228): " POKéMON" in English, "ポケモン" in
Japanese, nothing in the European strings ("?????", "POKéMON ?????"),
whose carts print the category alone.
The Japanese size comparison row is a suffix ("の おおきさくらべ"), so
the screen prints the player's name before it.
The runtime expanded Ruby and Sapphire's {EVIL_TEAM}, {GOOD_LEADER},
{VERSION}, {RIVAL} and {KUN} (and the other version-dependent names)
from text/placeholders.lua, the values the extractor reads from the US
cart, so a translation never reached them: the team leaders stayed MAXIE
and ARCHIE, the rival MAY or BRENDAN, the version RUBY or SAPPHIRE, and
the Japanese honorific empty. Each value is a cart string the script
cache also holds under its pokeruby label (gExpandedPlaceholder_Maxie,
_May, _Ruby, _Kun...); the placeholders now read it from there, with the
extract's value as the fallback, the way Emerald's do.
The labels are defined once, in text_placeholders_extract.lua
(rsSymbols, the evil and good teams swapped by edition), and both the
Ruby/Sapphire import and the message box read them from there.
- Add normalizePad() and aliases in GamepadMap for triggers and sticks
- Automatically load custom mappings from SDL_GAMECONTROLLERCONFIG and gamecontrollerdb.txt
- Add support for left and right analog sticks, triggers (L2/R2), stick clicks (LS/RS), and extra SDL buttons (Guide, Touchpad, Paddles)
- Route analog stick axis thresholds into discrete directional press/release events for seamless in-game and menu navigation
- Support rebinding buttons, thumbstick directions, triggers, and stick clicks in the CONTROLS menu (BindingsMenu) with clear abbreviated labels (LS-UP, RS-DN, L2, R2, etc.)
- Integrate stick axis event dispatch across Gen1, Gen2, and Gen3 game loops
- Add comprehensive test suite in tests/engine/sdl_controller_support_test.lua covering all axes, buttons, holds, rebinding, and multi-generation routing