Skip to content

Save which cartridge bank is selected in the machine state - #49

Merged
Tom1975 merged 1 commit into
Tom1975:masterfrom
rtissera:cartridge-bank-state
Sep 19, 2026
Merged

Tom1975 merged 1 commit into
Tom1975:masterfrom
rtissera:cartridge-bank-state

Conversation

@rtissera

Copy link
Copy Markdown
Contributor

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 CART chunk gains a third U32 holding the selected bank index. It is restored through Memory::SwitchBank, so the mapping is redone rather than the field simply assigned.

Older states still load. They are 8 bytes long, ReadCartridge returns 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 before LoadSnapshotNow, which resets and repopulates the components, so the change would not survive anyway.

Test

CprLoader.CarriesTheSelectedCartridgeBlock builds 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 six CprLoader tests green.

The two failures are pre-existing on master and unrelated to this change, which touches only MachineState.cpp/.h and TestCprLoader.cpp:

  • GateArray.Clocks — in AmstradCoreTests, a different binary.
  • unitTests (Not Run) — the aggregate add_test at UnitTests/CMakeLists.txt:128 uses WORKING_DIRECTORY <bindir>/$<CONFIG>, which does not exist on single-config Makefile generators. It duplicates what gtest_discover_tests registers.

Branched on 97d1453.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HnVjbxoLEetx7Kgu68pUwy

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.
@Tom1975
Tom1975 merged commit 559bfe2 into Tom1975:master Sep 19, 2026
3 checks passed
@rtissera
rtissera deleted the cartridge-bank-state branch September 19, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants