- On Android, allow game audio to mix with external audio by default instead of demanding exclusive audio focus and freezing when focus changes.
- Add an 'AUDIO MODE' option across Gen 1, Gen 2, and Gen 3 options menus and Launcher Settings:
- BOTH: Game BGM and SFX mix with external media.
- EXT ONLY: In-game BGM is muted while SFX remains active, mixing with external media.
- GAME ONLY: Requests exclusive audio focus (AUDIOFOCUS_GAIN), pausing background media.
- Guard Gen 3 waitse/waitfanfare audio script waits with timeouts and Audio._suspended checks so script execution never blocks indefinitely when audio is paused or interrupted.
- Expose setAudioMixWithSystem / love.audio.setMixWithSystem via JNI / C++ to dynamically toggle Android audio focus behavior based on user setting.
- Add unit test suite in tests/engine/audio_focus_mode_test.lua.
* Add native Black and White battle sprite importer and shared provider
* Reduce Gen 5 import scheduling and duplicate atlas work
* Play long Gen 5 idle animations from independent part tracks
* Skip part tracks when a late frame cannot be composed
* Fix importer picker lifecycle, Xbox formats, and CI coverage
* Fix Linux Gen 5 test discovery and picker regression checks
* Preserve original Gen 5 sprite resolution in provider API 2
* Trim importer comments and documentation
FireRed/LeafGreen's, Ruby/Sapphire's and Emerald's Pokédex pages print a species' height in feet and inches and its weight in pounds, converted from the cart's decimetres and hectograms; the localized carts print metres and kilograms. A mod can now give a Gen 3 species its metric height and weight the way it can on Red/Blue and Gold/Silver: the Gen 3 dexEntry schema takes heightM and weightKg, and a patch carries them into the dex table Pokemon.dexEntry reads.
src/core/game3/pokedex_units.lua tells whether a species has them, without loading the dex table itself, and formats them with one decimal and a comma before Strings("m") and Strings("kg"). FireRed/LeafGreen's entry page uses them for a seen or caught species, resolved once per species and caught state rather than on every draw; Ruby/Sapphire's and Emerald's entry pages use them for a caught species, each aligning the digits as its imperial weight does (two spaces per missing digit on Ruby/Sapphire's native page, as the cart's metric printer shifts the number by a digit's width, pokeruby src/pokedex.c:4300; {UNK_SPACER} on Emerald's), and keep the cart's unknown rows for a seen one.
The #DEX page prints the US cart's height in feet and inches, with the foot and inch tiles, and its weight in pounds; the localized carts print metres and kilograms ("TAI ???m", "PDS ???kg"). A mod can now give a species its metric height and weight the way it can on Red/Blue: mod.content.pokemon:patch(id, { dexEntry = { heightM = ..., weightKg = ... } }). src/core/gen2/PokedexText.lua copies them onto the #DEX entry beside the cart's own values, and the page then prints them with one decimal and a comma, right-aligned before the "m" and "kg" labels, "???" until the species is caught; the printout draws the same body, and the plain page drawn without the cache's dex sheet prints the metric values as it prints the imperial ones. The Gen 2 pokemon schema declares the dexEntry fields the #DEX page reads.
The Pokédex resolves the "m" and "kg" labels when it opens (PokedexMenu.new) rather than on every frame.
The Pokédex page prints a species' dexEntry.heightM and weightKg when it carries them ("GR. %.1fm", "GEW. %.1fkg"), the way the localized carts print metres and kilograms. An entry seen but not caught printed nothing there, where the imperial fields print their question marks (engine/menus/pokedex.asm:449-450) and the localized carts their own mask ("GR. ???m", "GEW ???kg"). It now prints "GR. ???m" and "GEW. ???kg", which a translation mod words like the two formats.
The entry page resolves both masks when it opens (DexEntryMenu.new) rather than on every frame; the printer's one-off render still looks them up itself.
A secret base is named after its owner: the owner's name, then the row the US carts append ("'s BASE"): Emerald's gText_ApostropheSBase, which Ruby and Sapphire's text aliases point at their gOtherText_PlayersBase. SB.name fills the STR_VAR_1 of Emerald's European rows, but Ruby and Sapphire's European rows name the owner with the player placeholder ("BASIS v. {PLAYER}", "BASE DE {PLAYER}"), which the German cart fills with the owner's name (pokeruby/src/secret_base.c:642, de_sub_8073174), and the TV's map name appended the row after the owner's name. With a translation mod, a base was named "MAYBASE DE " followed by the player's own name.
SB.nameWith fills either placeholder with the owner, or appends the row where it has none; the secret base's name and the TV's map name both use it.
The registry lists draw every registered base's name on every frame, so the rendered row is kept per row text, label and catalog state, and naming another owner only fills it.
The starter selection labels a starter with its category's first 11
characters (pokeruby/src/starter_choose.c:522), but cut the string at 11
bytes. An English category fits, but a translated one can be written in
multi-byte UTF-8: a Japanese category, three bytes a character, was cut
in the middle of its fourth character, and an accented letter can be cut
the same way. The label now keeps 11 characters (FrlgFont.truncate).
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 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.