Save which cartridge bank is selected in the machine state - #49
Merged
Merged
Conversation
A cartridge larger than 512 KB is several banks, and the running program picks one by reading page 0 at &3FFE/&3FFD/&3FFF. That selection is machine state rather than media: the ROM is identical whichever bank is active, and nothing else in the state records which one the program was using. Loading a state taken on a bank other than the one currently mapped therefore resumed on the wrong bank. The CART chunk gains a third U32 holding the selected bank index, restored through Memory::SwitchBank so the mapping is redone rather than the field just assigned. States written before this field are 8 bytes long and still load; the new ReadCartridge returns early and the machine keeps the bank it has. The restore is done by a chunk handler in the load loop, not by DescribesThisMachine. That function is documented as checking the chunks "before touching it, so a state meant for another machine is refused instead of half applied", and it runs before LoadSnapshotNow, which resets and repopulates the components -- so it is both the wrong place to mutate the machine and too early for the change to survive. UnitTests/TestCprLoader.cpp covers it: a three-block cartridge with a distinct marker byte in each, switch to the second bank, save, switch away, load, and confirm the second bank's marker is mapped again.
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.
A cartridge larger than 512 KB is several banks, and the running program picks one by reading page 0 at
&3FFE/&3FFD/&3FFF. That selection is machine state rather than media: the ROM is identical whichever bank is active, and nothing else in the state records which one the program was using. A state taken while the program was on the second bank therefore resumed on whatever bank happened to be mapped.The
CARTchunk gains a third U32 holding the selected bank index. It is restored throughMemory::SwitchBank, so the mapping is redone rather than the field simply assigned.Older states still load. They are 8 bytes long,
ReadCartridgereturns early, and the machine keeps the bank it has.Where the restore happens
In a chunk handler in the load loop, not in
DescribesThisMachine. I had it in the latter first, which was wrong twice over: that function is documented as checking the chunks "before touching it, so a state meant for another machine is refused instead of half applied", so mutating the machine there can half-apply a state that is then rejected; and it runs beforeLoadSnapshotNow, which resets and repopulates the components, so the change would not survive anyway.Test
CprLoader.CarriesTheSelectedCartridgeBlockbuilds a three-block cartridge with a distinct marker byte in each block, switches to the second bank, saves the state, switches away, loads, and checks the second bank's marker is mapped again.Test suite
Full suite on this branch, Linux, Release,
-DGENERATE_UNITTESTS=ON: 299 of 301 passed, all sixCprLoadertests green.The two failures are pre-existing on master and unrelated to this change, which touches only
MachineState.cpp/.handTestCprLoader.cpp:GateArray.Clocks— inAmstradCoreTests, a different binary.unitTests(Not Run) — the aggregateadd_testatUnitTests/CMakeLists.txt:128usesWORKING_DIRECTORY <bindir>/$<CONFIG>, which does not exist on single-config Makefile generators. It duplicates whatgtest_discover_testsregisters.Branched on 97d1453.
🤖 Generated with Claude Code
https://claude.ai/code/session_01HnVjbxoLEetx7Kgu68pUwy