Repository navigation
Port: autosave a dungeon floor as its load event entered it - #123
Merged
Merged
Conversation
carrdylan52
marked this pull request as draft
October 19, 2026 00:55
The dungeon autosave was written from the live game on the first frame the player had control on a floor. Loading it runs the floor load event (1010) again, which replays the floor's arrival events from the saved flags. In the Channel Pump Room (Underground Channel floor 4) the scene before Linda sets flag 103 and then sets the boss loose, and control only returns once the fight has started. The autosave therefore held flag 103 with no boss, so loading it dropped Max into an empty arena where nothing ever happens (TheMoonPeople#113). DungeonFloorInit, empty in retail, is called by every dungeon's floor load event once the floor is chosen and before any of the floor's own events. Its port override now records the whole save document as the floor's entry state: the save data, the header and a copy of every town's Georama layout. The layouts live beside the save data, found by the address of the live town records, so a copy of the save data alone would have written and then loaded empty towns. The dungeon autosave writes the entry state when the player gets control, taking only a new counter, so loading replays the floor's arrival scenes as entering it from the floor list does. The entry state is dropped on the floor's first controllable frame whether or not it was written. A floor whose first controllable frame passes with autosave off is therefore not autosaved when autosave is turned on later, since the entry state would undo what the player had done there since. A floor reached without DungeonFloorInit is not autosaved; town autosaves are unchanged.
carrdylan52
force-pushed
the
pr/autosave-floor-entry
branch
from
October 19, 2026 01:45
90f0ef2 to
da61698
Compare
carrdylan52
marked this pull request as ready for review
October 19, 2026 01:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #113.
Before
The dungeon autosave was written from the live game on the first frame the player had control on a floor. Loading a dungeon save goes through the floor load event (1010), which builds the floor and runs its arrival events again from the saved flags. In the Channel Pump Room (Underground Channel floor 4), the scene before Linda sets flag 103 and then sets the boss loose, and control only comes back once the fight has started. The autosave therefore held flag 103 with no boss, and loading it put Max in an empty arena where nothing ever happens.
After
A dungeon autosave is the game as the floor's load event entered the floor, before any of the floor's own events. Loading it reruns the floor load event from that captured state, as entering the floor from the floor list does, so the pump room autosave starts Linda's scene and the fight. Every town's Georama layout is kept in the autosave, including towns with more parts than retail's records hold.
Trade-offs:
DNG_FLOOR_INITcall is not autosaved. Town autosaves are unchanged and still write the game as it stands.How
DungeonFloorInitis empty in retail. Every dungeon's 1010 calls it throughDNG_FLOOR_INITonce the floor is chosen and before the floor's events. Its port override (port/src/dng_event.cpp) callsSaveSlotRecordFloorEntry.SaveSlotRecordFloorEntry(port/src/memcard.cpp) builds a completeSaveDocumentright then, with the sameBuildDocumentthat the save screen uses: the retail image, header and metadata, plus an owned copy of each town's layout. The layouts are stored beside the save data and looked up by the address of the liveCEditDatarecords. A copy ofCSaveDataalone would therefore have found no layouts, then written empty towns, and loading the autosave would have wiped the live Georama.dng_tree_flagis cleared at capture time.SaveSlotWriteAutosave(LOOP_DUNGEON)writes that document. It only gives it the next unique counter. It refuses to write if the entry state belongs to a different stage or floor than the game is on. Nothing else read when saving lives outside the document.SaveJsonWritetakes play time, progress, location (map, dungeon, floor) and unlock bits from the image, and the only other global, the floor-listdng_tree_flag, is forced to 0.AutosaveFloor(port/src/mainloop.cpp) now checks for the floor's first controllable frame before it checks the autosave setting. On that frame it writes the entry state if autosave is enabled, then drops it in either case. Entering a game loop also drops it.docs/PC.mddescribes what the dungeon autosave keeps and what it loses.Tests
DungeonAutosaveKeepsTheStateTheFloorWasEnteredWith: flags and money changed after entry are not in the autosave. A town autosave still writes the live state.DungeonAutosaveNeedsAnEntryStateOfTheCurrentFloor: no write without an entry state, or for another floor, or for the same floor number in another dungeon.DungeonAutosaveRoundTripsTheTownsLayouts(new): two towns with 340 parts each (retail holds 300), plus houses, a placement log and a river grid. The test changes the live layouts after floor entry, writes the dungeon autosave, reads it back and loads it, and checks that every part, house, log entry and grid cell comes back in the live store. A town autosave and a save-screen save of the loaded game keep the same layouts.ArrivalAutosaveWaitsForControlAndEnabledConfigurationThenRunsOnce: the floor is not written after its first controllable frame passes with autosave off. This is checked separately for capture mode,PortAutosaveand thegame.autosavesetting, each turned back on afterwards.CSaveData.darkchronicle_testson Windows x64 Release, withEeKernelThreads.RotateInsidePumpWithNothingReadyDoesNotSwitchexcluded because it aborts the process on master too: 1840 tests, 1764 passed. Master: 1837 tests, 1762 passed. The 28 failures shared with master are GPU, file-system, audio and environment tests.GeoramaParts.PaintedFencesMatchRetailRecursionfailed in one full run on each build and passes when run on its own on both, so it is flaky on master.--jumpand loads a save file into the game before jumping. Loading a save with four built towns (64, 42, 61 and 69 parts) and jumping to Underground Channel floor 2 wrote a dungeon autosave whose five towns are identical to the source save's. The PR's first revision, run the same way, wrote five empty towns.