Commit Graph
245 Commits
Author SHA1 Message Date
YourWishesandClaude Sonnet 5 fed04b66b8 Persist and resume in-progress cutscene via save slot; add species stub
Save slots now track the currently-active cutscene file (defaulting to a
new placeholder new_game.jsonc intro) so loading a save resumes it;
cutsceneSystemStartCutsceneWith persists this on every cutscene start, and
a cutsceneSystemLoad ordering bug (loadedFile stamped after starting) is
fixed so the persisted path is always correct. Also adds a
battlefighterspecies_t/battlespeciesid_t stub for upcoming species data.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-22 18:44:45 -05:00
YourWishesandClaude Sonnet 5 a4ca718070 Add shared battleFighterParse/Serialize, use it everywhere a fighter is (de)serialized
Replaces three independently hand-rolled battlefighter_t JSON readers/
writers (party.jsonc roster loading, BATTLE_START enemy definitions, and
the v1 save-file party member format) with one generic pair in
battlefighter.c: battleFighterParse(fighter, obj) and its inverse
battleFighterSerialize(fighter, doc). Covers team/controller/status
(optional, default ally/player/normal), the 7 base stats (required),
current health/mp (optional, default to max), and an optional abilities
name array.

- party.c: partyInit now parses each roster member via battleFighterParse
  directly, dropping the old partyParseStats/partyParseStatField.
- cutscenebattlestart.c/.h: cutscenebattlestartenemy_t now embeds a full
  battlefighter_t, parsed once at Load time; Start just copies it into the
  enemy pool instead of re-initializing. battletest.jsonc's enemies are
  now flat (dropped the "stats" wrapper) to match.
- saveslotver1.c/.h: rewritten in place to use the shared parser/
  serializer, changing the v1 on-disk field names/shape (no migration -
  acceptable pre-release, documented in saveslotver1.h).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-22 14:20:45 -05:00
YourWishesandClaude Sonnet 5 8dbd3e1dd2 Key-based party roster, show party member names in battle UI
- party.jsonc's "members" is now a key/value object (e.g. "hero",
  "companion") instead of an array - partyInit seeds party_t.keys
  alongside members, and partyGetMemberIndexByKey/partyGetMemberKey do the
  lookups. Cutscene items (PARTY_ADD_MEMBER/PARTY_REMOVE_MEMBER/
  PARTY_HEAL_MEMBER) now take a "key" JSON field, resolved to a roster
  index at load time, instead of a raw index.
- Battle UI shows who's acting: uibattlemenu.c draws the current fighter's
  party key above the action menu, and uibattlehud.c draws each ally
  fighter's key as an extra line above their HP/MP.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-21 22:38:04 -05:00
YourWishesandClaude Sonnet 5 7a9a2b9832 Add order-based party roster, back-navigation in battle selection, fix win-state cutscene leak
- Battle selection menu can now go back a fighter to re-decide their move,
  and battle win/loss no longer leaks the round's remaining queued move
  cutscenes into the ending state (cutsceneSystemDiscardQueued).
- Party roster is now driven by party.jsonc: every defined member always
  exists (partyInit), while party->order alone determines who's currently
  active - partyAddMember/partyRemoveMember (and their cutscene items) now
  activate/deactivate an existing roster member by index instead of
  creating/destroying one, with removal compacting order to stay packed.
- New PARTY_ADD_MEMBER/PARTY_REMOVE_MEMBER/PARTY_HEAL_MEMBER/PARTY_HEAL_ALL
  cutscene items.
- saveSlotInit/partyInit now return errorret_t and take their target
  struct directly (saveslot_t*/party_t*) instead of implicitly operating
  on SAVE.slot; saveSlotReadJSON resets through saveSlotInit rather than
  duplicating the reset logic.
- Test coverage: stub the JSON asset loader in save test fixtures so
  partyInit's real party.jsonc load runs against an in-memory doc instead
  of hanging with no asset system initialized.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-21 22:27:46 -05:00
YourWishesandClaude Sonnet 5 7aeffac9fc Add battle fighter damage/heal cutscene items, wire up battle results
BATTLE_FIGHTER_DAMAGE/BATTLE_FIGHTER_HEAL let a move's own cutscene
apply damage/healing to "target" or "user", resolved from
BATTLE_FIGHTER_POS_TARGET/USER sentinels against the current action by
battleStateExecutingInit. fire/slash now call BATTLE_FIGHTER_DAMAGE on
their target.

BATTLE_POST_MOVE checks fighter health after each move and sets
BATTLE.result (now a real field, previously commented out) to
win/loss, transitioning into BATTLE_STATE_WON/LOST; fleeing sets
BATTLE_RESULT_FLED. All three end states now show a textbox before
moving on to BATTLE_STATE_ENDING.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-20 21:14:00 -05:00
YourWishesandClaude Sonnet 5 37e7e95ace Resolve moves into per-move cutscenes during battle execution
Each queued action now resolves to its move's cutscene
(cutscenes/battle/moves/<name>.jsonc), spliced into the executing state
with a BATTLE_POST_MOVE checkpoint after each one. Fighter turn order is
tracked via fighterOrder/fighterOrderCount, and resolved actions/pending
counts are cleared so fighters aren't skipped in later rounds. Also fixes
a BATTLE_WAIT_SELECTION deadlock and adds an optional "blocking" flag to
MODAL cutscene items.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-20 17:49:06 -05:00
YourWishesandClaude Sonnet 5 e3f56c4d12 Drive battle rounds through cutscene items, fix render/init bugs
Adds BATTLE_START, BATTLE_SET_STATE and BATTLE_WAIT_SELECTION cutscene
items so a battle's state transitions (opening -> pre-round -> selection
-> executing) are chained through the running cutscene, with
cutsceneSystemInsertItemsNext/InsertItems splitting "splice" from
"splice and advance immediately". Adds battlestateselection's
get-current-fighter/player-attack/player-flee API backing the battle UI,
and battleMoveGetIdByName for JSON-authored ability lookups.

Fixes: off-by-one in battleMoveInit that let the first-defined move
alias BATTLE_MOVE_ID_NULL; a segfault in scenebattle.c from rendering
unfilled (NULL) fighter slots; stale battleGetCurrentFighter/
battlePlayerAttack/battlePlayerFlee references in the battle UI.

Adds assertions across the battle/scene/UI code for fighter-index
bounds and non-null invariants. Updates battletest.jsonc for the new
BATTLE_START item schema.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-20 13:32:52 -05:00
YourWishes d8273a225c Battle changes, first pass. 2026-09-19 22:30:01 -05:00
YourWishesandClaude Sonnet 5 c1c8174b27 Use CUTSCENE/INSERT item names as full asset paths directly
cutsceneCutsceneResolve/cutsceneInsertResolveAndSplice no longer inject
a "cutscenes/%s.jsonc" prefix/suffix around an item's "name" field -
matching cutsceneSystemLoad, which already takes a full path. Fixes a
latent double-prefix bug in initial.jsonc's CUTSCENE reference (also had
a "jsonsc" typo) that this change would otherwise have exposed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-19 21:38:09 -05:00
YourWishesandClaude Sonnet 5 4b29bf7a30 Wire story flags into the save slot and add cutscene controls
Implements storyInit/storyGetFlagByName/storyGetFlagValue/etc, moves flag
storage into saveslot_t (persisted keyed by name so save files survive
flag reordering), and adds STORY_SET_FLAG/STORY_WAIT_FLAG cutscene items.
Also removes the now-superseded storyflag.c/h stub.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-19 20:39:53 -05:00
YourWishes 6f1bbe4f2f First pass story flags 2026-09-19 10:45:06 -05:00
YourWishesandClaude Sonnet 5 5910110b95 Rework CUTSCENE_ITEM_TYPE_INSERT to splice into the running scene's item array
Replaces the separate insert buffer/scene and insertStack return-frame
mechanism with cutsceneAppend/cutsceneAppendNext, so an inserted
cutscene's items become part of the running scene's own array instead
of a jump-and-return. Moves the loaded-items buffer/scene from file-scope
globals into cutscenesystem_t, and extracts shared start-cutscene setup
into cutsceneSystemPrepare.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-17 22:26:36 -05:00
YourWishesandClaude Sonnet 5 74a4290be4 Add optional cutscene field to move schema
Lets a move reference a cutscene to play when used, resolved by name
the same way a CUTSCENE item's "name" field is. Still just a schema
placeholder - no loader consumes moves.jsonc yet.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-14 12:10:06 -05:00
YourWishesandClaude Sonnet 5 3ce892f846 Move items.jsonc under items/, add starter battle/moves.jsonc
Groups item data under assets/items/ to match the cutscenes/ folder
convention, updating itemInit()'s asset path accordingly. Also adds
assets/battle/moves.jsonc as a starting point for move data - there's
no JSON loader consuming it yet (battleability_t is still just a bare
enum), so its field shape is a placeholder rather than a contract.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-14 12:00:46 -05:00
YourWishesandClaude Sonnet 5 109ddc9e1e Switch item definitions to a JSON-driven runtime registry
Replaces the build-time item.json/tools.item.py code generator with a
single item_t ITEM registry populated at runtime by parsing
assets/items.jsonc, so items/types can grow without a rebuild. Adds
itemGetDefById/itemGetTypeById/itemGetIdByName/itemTypeGetOrCreate,
updates inventory/backpack to size off the new *_DEF_COUNT_MAX caps
and look up types dynamically, and reorders engine init so rpgInit
(which loads items) runs before uiInit (which needs the item type
count to size the backpack's tabs).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-13 11:36:50 -05:00
YourWishesandClaude Sonnet 5 0566166af4 Persist party across saves and flag/warn on corrupt save slots
Party moves off a global singleton onto each save slot, letting
START_BATTLE pick specific active-order members to bring into a fight,
and round-trips through save/load via saveslotver1. A corrupt slot load
now flags the cache and shows a red "Corrupted Save" warning in the
select-save UI instead of silently resetting.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-10 14:19:03 -05:00
YourWishesandClaude Sonnet 5 efd760fb2e Store chunk tile data as a dense minified grid instead of per-tile objects
Cuts the six overworld chunk JSON files from 146KB to 10KB by replacing
{"pos":[x,y,z],"type":t,"tile":u} entries with a fixed 256-slot array
(index x + y*16, value null or [type, z]) and dropping pretty-printing.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-09 15:28:22 -05:00
YourWishesandClaude Sonnet 5 9688e88a7c Load raw chunk JSON at runtime instead of baked DCF/DMF
Experimental: skip the offline tools/asset/chunk bake step entirely.
The chunk asset loader now parses the same JSON schema tools/asset/chunk
already consumed (tiles/meshes/entities/areas) directly at load time,
generating the terrain mesh in C instead of reading pre-baked .dcf/.dmf
bytes. The raw assetsraw/maps/*/chunks/*.json files are now the shipped
source directly under assets/, replacing the old baked chunk/mesh/model
output.

Also drops MAP_CHUNK_LOAD_CONCURRENCY to 1 for now, per PSP hardware
testing (8 crashed, 4 untested further - 1 is the known-safe value).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-09 14:05:19 -05:00
YourWishes db42bca44b Reintroduce multiple maps: per-map chunk directories + map_t name/mapSetMap
Move chunk assets from a single flat assetsraw/chunks (and assets/chunks)
into per-map assetsraw/maps/<map>/chunks (assets/maps/<map>/chunks), so
terrain mesh/model output no longer collides across maps sharing chunk
coordinates. map_t gains a name[MAP_NAME_MAX] field plus mapSetMap()/
mapIsLoaded() (checks name[0] == '\0') in place of the old bool loaded
flag; mapInit() now just resets state and mapSetMap() does the chunk
grid load. Updated the chunk asset tool and the map editor's dev
server/client to match.
2026-09-07 21:28:07 -05:00
YourWishesandClaude Sonnet 5 845a395ff1 Fix New Game falling through into the Quit confirm dialog
The SAVE_DEVICE_FOUND/SAVE_LOAD_ALL_SLOTS block had been moved to the
end of the file (after QUIT/QUIT_GAME) without moving the LOADED
marker with it. MARKER items always auto-advance to whatever follows
them in the array, so reaching LOADED after a successful save-load fell
straight through into the QUIT block's confirm dialog instead of
completing the cutscene. LOADED now sits after SAVE_LOAD_ALL_SLOTS as
the true last item, so it falls off the end and fires
uiMainMenuOpenSelectSave again as intended.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-06 11:52:48 -05:00
YourWishesandClaude Sonnet 5 f63653c307 Wire main menu Options/Quit through the cutscene, fix locale crashes
Options and Quit now route through main_menu.jsonc markers the same
way New Game does, with a new QUIT_GAME cutscene item type ending the
process directly once quit is confirmed via MODAL_OPTIONS_MARKERS
(whose "message" field is now optional, defaulting to "" like "title").

Fixes two crashes surfaced along the way:
- uiModalLocalize asserted on an empty locale key instead of treating
  it as "nothing to show" - hit as soon as a modal omitted a title or
  message.
- assetLocaleGetString's new empty-message-ID guard broke the PO
  format's own header-read convention (messageId "") used internally
  by assetLocaleLoaderAsync, crashing on every boot. Extracted the
  shared lookup into assetLocaleGetStringLookup and added a dedicated
  assetLocaleGetHeader for that internal read, leaving
  assetLocaleGetString's validation untouched for every real caller.

Also replaced every raw assetLocaleGetString/WithVA call across the UI
with the locale/localemanager.h helpers (adding localeManagerGetString
for the plain, non-formatting case), so app code no longer bypasses
them.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-06 11:47:34 -05:00
YourWishesandClaude Sonnet 5 6ccaedd48f Load cutscenes directly from JSONC at runtime, fix asset bundling staleness
Cutscenes now parse their authored .jsonc straight into the runtime
cutsceneitem_t/pool representation via yyjson, instead of going through a
separate Python-compiled DCTS binary format - removes the whole
build/compile step and the byte-format contract between the Python
encoder and the C decoder, at the cost of a (still tiny, one-time)
parse per cutscene load.

Also fixes dusk.dsk going stale after a build: the old custom_command
depended on a CMake-configure-time file glob, which only re-detects
added/removed assets on the next configure and could miss edits
entirely. tools.asset.pack now always runs and decides for itself
(via a small manifest) whether anything actually needs repacking, so
asset changes are never missed regardless of add/edit/remove.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-05 12:05:23 -05:00
YourWishesandClaude Sonnet 5 707856fcf2 Run one persistent cutscene for the whole main menu, not just start-game
Previously the main menu UI opened directly with no cutscene, and only
pressing "Start Game" spun up a brand new cutscene
(main_menu_start_game.jsonc) for the save-device check/load-slots flow.
Now a single cutscene (main_menu.jsonc) starts the moment the main menu
scene becomes active, sitting idle (new CUTSCENE_ITEM_TYPE_IDLE item -
no existing item type blocked forever with no side effect) while the
menu is shown, so it can own menu-wide state going forward.

Pressing "Start Game" now jumps the already-running cutscene to a
NEW_GAME marker via cutsceneGoTo instead of starting a second cutscene -
this already-existing mechanism needed no engine changes. Both retry
options (no device / load error) also now jump straight back to
NEW_GAME instead of RESTARTing the whole cutscene, since RESTART would
otherwise strand the player on the idle block. sceneMainMenuStartGame
also handles the case where the cutscene already ran to completion once
(e.g. backing out of the save picker and pressing Start Game again) by
restarting it landing straight on NEW_GAME, avoiding a crash from
jumping a marker with no cutscene running.

Built and verified on Linux (boots/idles without crashing, cutscene
tests pass), PSP, GameCube and Wii (Docker).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-04 18:18:49 -05:00
YourWishes fe2ef92ef3 Testing audio cutscene controls 2026-09-02 18:49:12 -05:00
YourWishesandClaude Sonnet 5 f8f8a80a21 Add MP3 audio stream support with hardware/software decoder backends
New ASSET_LOADER_TYPE_MP3 (hand-rolled MPEG-1/2/2.5 Layer III header
parser - no third-party dependency needed just for metadata, since PSP's
hardware path doesn't need one at all) plus a shared audiostreammp3.c
stream layer mirroring audiostreampcm.c's shape. Generalized the stream
dispatch (hoisted sampleRate/channels onto audiostream_t, added
audioStreamGetTotalFrames()/Seek()/Read()) so all three platform audio
backends keep working unchanged, just calling the generic names instead
of PCM-specific ones.

Two decoder backends behind one interface: PSP uses the real sceMp3
hardware decoder (firmware-offloaded, lazily initialized on first use);
Linux and Dolphin share one minimp3-based software decoder (public
domain, vendored via CMake FetchContent) - libogc's own MP3Player wraps
libmad (GPL) and drives its own output pipeline, not a fit for the
ansnd-based architecture already in place, so skipped in favor of the
shared minimp3 path.

Fixed three real bugs found via hardware/runtime testing along the way:
- LAME's Xing header counts its own placeholder frame in the declared
  total, which made playback stall permanently one frame short of the
  declared end (looked like "never loops") - fixed by subtracting it.
- sceMp3Decode() can return more PCM than one MPEG frame's worth in a
  single call (PSP's pcmBuf is provisioned for 2x), overflowing the
  shared per-frame decode buffer with no bound check - very intermittent
  corruption/clicking on real hardware. Widened the buffer to the real
  worst case and added an assertion.
- sceMp3ResetPlayPosition()'s exact internal reset semantics aren't
  documented precisely enough to trust for looping - occasionally
  disagreed with the fresh stream position fed right after, clicking at
  the loop boundary about 1 in 3-4 loops. Rewind now fully tears down and
  recreates the decoder instead, the same path already proven correct at
  first Init. Also widened the PSP ring buffer to absorb that now-heavier
  operation, capping each top-up call's own work so the bigger buffer
  doesn't turn into one long blocking decode burst instead.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-01 08:21:30 -05:00
YourWishes d37109f5f7 Fixed PSP trying to load entirely into memory 2026-08-31 19:07:51 -05:00
YourWishes 51f262efa0 Wire keyboard into save naming, add fatal error overlay, cutscene keyboard item
- uimainmenu: removed the temporary keyboard test entry now that the
  keyboard has a real caller.
- uiselectsave: picking an empty save slot now opens the keyboard to
  name it (localized title "Enter game save file name"), writes the
  named slot to disk (mirroring the existing delete-confirm write
  pattern), and on a write failure opens the new fatal error overlay.
- uikeyboardopen_t gains a title override (NULL keeps the default
  "ENTER YOUR TEXT").
- New ui/overlay/uifatalerror: a minimal fullscreen, non-dismissible
  overlay (message + QUIT button, back disabled) for unrecoverable
  errors - a nicer alternative to a raw assert crash. Draws above
  everything else in the UI element list.
- New CUTSCENE_ITEM_TYPE_KEYBOARD cutscene item: opens the keyboard
  with an embedded uikeyboardopen_t, blocks the cutscene until it
  closes, then caches the entered text via a new general-purpose
  cutscenesystem_t.textCache (CUTSCENE_TEXT_CACHE_MAX, with get/set
  accessors) mirroring the existing entity/area/text-mini id caching
  pattern.
2026-08-28 08:29:07 -05:00
YourWishesandClaude Sonnet 5 e630827b34 Add runtime-loaded cutscene files, convert initial/main menu to use them
New ASSET_LOADER_TYPE_CUTSCENE (assetcutsceneloader.c) reads a versioned
binary .cts format decoded into a heap-allocated cutsceneitem_t array + a
string/data pool, both sized to the file's actual content rather than a
fixed capacity, so the shared assetloaderoutput_t union doesn't bloat for
every asset slot regardless of type. Authoring pipeline mirrors the chunk
asset pattern: assetsraw/cutscenes/*.jsonc (JSON plus // and /* */
comments) -> tools/asset/cutscene -> assets/cutscenes/*.cts.

cutsceneSystemSetOnComplete() lets the caller arm a native callback that
fires when a cutscene finishes normally, so a file (which can't store a
function pointer) can end plainly and still hand off to native code -
cutsceneRestart() preserves it across a retry loop rather than clearing it,
since a restart is the same logical run trying again.

The initial and main-menu start-game cutscenes are now loaded from files
instead of compiled in via the CUTSCENE(...) macro.

Fixed a real bug found while converting these: the sync loader read the
file's total size from assetfile_t.size to locate the trailing pool
region, but assetFileDispose() (called at the end of the async phase)
zeroes that whole struct first, so the size was always 0 and the pool
offset computation underflowed into an out-of-bounds read - intermittent
depending on heap layout. Fixed by saving the size before disposal; also
fixed the read-completeness assert being checked after that same zeroing
(a no-op 0 == 0 check).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-25 09:51:26 -05:00
YourWishesandClaude Sonnet 5 1a199f6ce3 Add declarative cutscene items for save checks and marker-based modals
CUTSCENE_SAVE_DEVICE_CHECK and CUTSCENE_SAVE_LOAD_ALL_SLOTS wrap the
existing device-lookup/slot-load calls and jump straight to a
success/failure marker, and CUTSCENE_MODAL_OPTIONS_ONE/TWO do the same
for one/two-option modals, removing the need for a hand-written
goTo-only callback per use. Main menu's "Start Game" now runs a
cutscene (mirroring the initial scene's save-check flow) that loads all
slots before opening the load-game picker, retrying on error; the
initial scene's own device check is migrated onto the same items.
Backing out of the main menu now returns to the initial scene.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-23 20:29:57 -05:00
YourWishesandClaude Sonnet 5 cb28d2b611 Add save slot picker (uiselectsave/uisaveslot), fix focus stack reentrancy
uiselectsave is a Save/Load/Delete slot picker built on save/save.h's
SAVE_SLOT_COUNT: a scrolling list of framed uisaveslot_t rows (slot
number + file name, or an "Empty Slot" placeholder), navigated via the
same uimenu_t/focus-stack convention as every other menu. Load and
Delete modes add a trailing action row (switch to delete / cancel)
fixed below the scrollable area. Selecting a slot in Delete mode routes
through uiConfirmOpen before actually blanking the slot via
saveSlotInit + saveDeviceSlotWrite. uiScrollingEnsureVisible in
uiscrolling.c is now a real implementation instead of the earlier
placeholder.

Main menu collapses New Game/Load Game into a single Start Game entry
that opens uiselectsave in Load mode; backing out reopens the main
menu via uiselectsave's result callback.

Also fixes a real reentrancy bug in uiFocusPop: it invoked the popped
item's closed callback before decrementing UI_FOCUS.count, so a push
triggered from within that callback (e.g. reopening the main menu once
select-save reports no result) landed one slot past the true stack top
and got silently dropped, stranding the new item outside navigation.
Count is now decremented first.

Adds a uikeyboard placeholder widget, registered in uielementlist with
no behavior yet.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-21 14:16:39 -05:00
YourWishesandClaude Sonnet 5 27b6ddf5cb Rebuild uiconfirm on top of uimodal, add quit confirmation
uiconfirm no longer duplicates its own backdrop/frame/text/menu drawing
- it now just opens the shared uimodal_t with a Confirm/Cancel option
pair and translates the result back to a bool. uimodal itself gains an
optional title (NULL skips the title row entirely) so a title-less
confirm dialog doesn't reserve blank space.

Main menu's Quit option now opens a confirm dialog instead of exiting
immediately.

Drops es_MX.po/jp_JP.po locale files.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-20 22:41:06 -05:00
YourWishesandClaude Sonnet 5 475c865e33 Move uimodal to ui/widget, make main menu its own scene
uimodal.c/.h now live in ui/widget alongside the other widgets rather
than ui/frame. The main menu now has a real scene (scene/mainmenu)
whose init just calls the new uiMainMenuOpen(), replacing the
SCENE.current-polling uiMainMenuUpdate with an explicit open call like
uiGameMenuOpen/uiBackpackOpen. Also renames the ui.main_menu.* locale
keys to main_menu.* and groups them under a Main Menu Scene heading in
en_US.po, alongside the existing Initial Scene keys.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-20 19:18:50 -05:00
YourWishesandClaude Sonnet 5 0b4ba062bb Translate and word-wrap cutscene modal text
uiModalOpen now resolves title/message/option strings as locale
message IDs first, falling back to the literal string if no match is
found, and word-wraps the result to stay within the screen's scan
width via the new shared textWrap helper. sceneinitial.c's no-device
modal now uses locale keys instead of hardcoded English strings.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-20 18:53:47 -05:00
YourWishes 45331c2a60 First pass of save 2026-08-14 14:19:44 -05:00
YourWishesandClaude Sonnet 5 6c8e4d5cbd Route remaining hardcoded UI strings through the locale system
Main menu buttons, the confirm dialog, battle menu/HUD text, backpack
tab labels, the loading/autosave indicators, and the settings tab
placeholders were all raw English literals bypassing translation.
Loads each through assetLocaleGetString like the rest of the UI, adding
new Init hooks for uibattlehud/uiautosave/uiloading where none existed,
and adds the corresponding message ids to en_US/es_MX/jp_JP.po.

Also widens the settings placeholder buffers to 64 bytes - the es_MX
and jp_JP translations overflowed the previous 32-byte size.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-10 09:12:57 -05:00
YourWishesandClaude Sonnet 5 e008fb108a Embed default font as a hard-coded bitmap instead of loading it as an asset
Moves FONT_DEFAULT and its init/dispose into their own font.h/font.c,
and rebuilds it from a static glyph bit array + a runtime-generated
texture/tileset rather than loading ui/minogram.png/.dtf through the
asset system. The engine now always has a usable font to render with,
even if asset loading fails. The now-unused minogram assets are removed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-04 22:37:22 -05:00
YourWishesandClaude Sonnet 5 7357b4a5df Localize remaining hardcoded UI strings and persist language preference
Replaces the last hardcoded English strings (initial-scene modals, game
menu save status messages) with locale-loaded text, adds a shared
LOCALE_LIST so the settings dropdown and locale manager stay in sync,
and persists the chosen language into savemeta_t across all platforms.
Also fixes two message buffers that were too small for their longest
translations.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-04 21:39:24 -05:00
YourWishes 7a03ef8eaf Re-enable save system, fix header/version stamping, handle missing media
- Fixed the actual reason saving never worked on any platform: saveWrite()
  never stamped file->header/file->version before serializing, so every
  written save file had a zeroed magic header and failed its own
  validation on the next load. Confirmed via a manual write/load round
  trip that this alone fully explains "saving doesn't work."
- Re-enabled saveInit()/saveDispose() in engine.c (previously commented out
  under "Temporarily disable save code").
- Added SAVE.available + saveIsAvailable(), refreshed by every real
  save/load/delete attempt. saveInit() no longer treats an unreachable
  save medium as fatal to booting - it logs and continues, since a missing
  memory card/stick shouldn't prevent playing.
- Hardened PSP's saveInitPSP() to actually detect a missing memory stick
  (sceIoGetstat on ms0:/) instead of assuming success, and fixed
  single-level sceIoMkdir to build the full PSP/SAVEDATA directory chain.
- Added busy-retry (CARD_ERROR_BUSY) and a not-mounted guard to Dolphin's
  live savestreamdolphin.c path, extending the same handling already
  backported into savedolphin.c.
- Added a "Save" entry to the game menu wired to saveWrite(0), showing a
  clear message on success, on failure, and when saveIsAvailable() is false.
2026-08-04 08:30:24 -05:00
YourWishes 4b0388a0e1 Chunk streaming concurrency, entity slot fix, and map-data-driven spawns
- Allow 2 chunks to be mid-load concurrently instead of 1 (MAP_CHUNK_LOAD_CONCURRENCY).
- Fix entitySetChunk silently losing track of an entity when its target chunk's
  entity slots are full - it now stays detached (and retries later) instead of
  claiming a chunk that never actually registered it.
- DCF format bumped to v5: chunks can now declare entity spawns (global/NPC via
  the existing entityglobal registry, or one-shot item pickups) and map area
  triggers, resolved via a new callback-ID registry (mapareagloballist.h)
  mirroring the entity one. rpg.c's hardcoded TEST entity/item/area spawns are
  gone - chunk_0_0_0.json now carries that data instead. The player is still
  bootstrapped in code since it isn't map-authored content.
2026-08-04 07:37:48 -05:00
YourWishes ca02ee0352 Add camera shake 2026-07-11 11:02:09 -05:00
YourWishes b693ea4102 Starting item and battle stuff 2026-07-08 10:05:21 -05:00
YourWishes a73f55beb0 Battle stuff
Build Dusk / build-linux (push) Successful in 7m5s
Build Dusk / build-psp (push) Successful in 1m33s
Build Dusk / build-knulli (push) Successful in 4m0s
Build Dusk / build-gamecube (push) Successful in 3m31s
Build Dusk / build-gamecube-iso (push) Successful in 3m39s
Build Dusk / build-wii (push) Successful in 3m5s
Build Dusk / build-wii-iso (push) Successful in 3m25s
2026-07-08 07:55:15 -05:00
YourWishes 0bd2491ab7 Dropdown test. 2026-07-07 15:18:33 -05:00
YourWishes 38c5080f9f Collapsing more ui settings code 2026-07-07 14:36:19 -05:00
YourWishes fae191d8fe Settings improvements 2026-07-07 14:00:37 -05:00
YourWishes d83a953e2d First pass of language 2026-07-07 11:14:02 -05:00
YourWishes a292f1992b Change to use the Z tile system 2026-07-04 08:40:53 -05:00
YourWishes 7b98e40ccf Cutscene tests 2026-07-02 11:18:36 -05:00
YourWishes 172dc5d37b Tile Z is now hypotenused to 1 rather than stretching to have Z of 1. 2026-07-01 16:27:59 -05:00
YourWishes 874c6258ab New ramp types
Build Dusk / run-tests (push) Failing after 5m33s
Build Dusk / build-linux (push) Successful in 5m3s
Build Dusk / build-psp (push) Successful in 1m17s
Build Dusk / build-knulli (push) Successful in 4m45s
Build Dusk / build-gamecube (push) Successful in 3m49s
Build Dusk / build-gamecube-iso (push) Successful in 3m50s
Build Dusk / build-wii (push) Successful in 3m29s
Build Dusk / build-wii-iso (push) Successful in 4m4s
2026-07-01 16:05:02 -05:00