Pokered Save Editor 2: a test suite, and the save-corruption bug it caught
An automated QtTest/CTest suite goes in — and immediately turns up an off-by-one that was clobbering a byte on every save.
A comprehensive automated test suite now covers
Pokered Save Editor 2,
built on QtTest and
CTest. It exercises the
save-file engine, the game database, and the randomiser. To make the UI’s logic
testable in the first place, that logic was extracted into a standalone appcore
library, so the models can now be unit-tested rather than only clicked through by
hand.
The bug it caught on day one
The headline find was a save-corruption bug. The checksum for the second bank of PC boxes was being written one byte early — which also overwrote the last data byte of Box 6 on every save of a progressed file:
// savefiletoolset.cpp — recalcChecksums()
- data[0x5A4B] = getChecksum(0x4000, 0x1A4B); // wrong: clobbers Box 6's last byte
+ data[0x5A4C] = getChecksum(0x4000, 0x1A4C); // correct address + range
The corrected address matches the original game’s own sBank2AllBoxesChecksum
location in the pret/pokered disassembly, which is
the project’s oracle for anything save-format related. With the fix in, a real save
round-trips byte-for-byte:
$ ctest --output-on-failure -R roundtrip
1/1 Test #1: tst_roundtrip .................... Passed
100% tests passed, 0 tests failed out of 1
This is exactly the class of bug that’s almost impossible to spot by eye and trivial for a round-trip test to catch — and it’s the kind this editor cares about most, since its core promise is to change only the bytes an edit requires.
A crash, and the randomiser
A second find was a crash in the Day Care teardown when the Day Care was empty, from an unconditional cleanup of a pointer that could be null:
- pokemon->deleteLater();
+ if (pokemon != nullptr) pokemon->deleteLater();
The randomiser also reached the point of running end to end with coverage for its current scope — invariants checked across repeated runs, plus byte fidelity on the results. Features that aren’t built yet, like map and Hall of Fame randomisation, are explicitly held back with re-enable notes rather than left half-wired.
References
- Pokered Save Editor 2 repository · documentation site
- pret/pokered — the Gen 1 disassembly used as the save-format oracle
- QtTest · CTest