320c5e6ce5
assetLocaleGetString rewinds and linearly scans/re-decompresses the whole locale file from byte 0 on every single call, with no caching - a text-heavy screen can easily make 10+ of these in a row (e.g. opening the game menu), and on PSP the containing archive is already fully resident in RAM, so the repeated cost is pure CPU (decompression + scanning), not I/O. Adds a fixed 128-entry move-to-front LRU cache keyed by (messageId, pluralCount), capped at 64/256 bytes per key/value (~40KB total) so the cost stays bounded no matter how large the game's script ends up being, rather than caching the whole locale file's text. The cache is a lazily-allocated pointer on assetlocalefile_t, not embedded inline - that struct lives inside the assetloaderoutput_t union shared by every asset type, and all ASSET_ENTRY_COUNT_MAX asset slots carry that union directly, so embedding it would have sized every slot up by ~40KB regardless of what asset type occupies it. Also fixes a bug this surfaced in test_assetlocale.c's own fixture: locale_teardown zeroed the locale struct directly instead of going through assetLocaleDispose, which would have leaked the new cache allocation across tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>