Entry 182

"No executable at run time: each volume's main data in piney-data"

Filescrates/piney-game/src/story.rstools/main_data.pycrates/piney-data/src/exe.rscrates/piney-data/src/iso.rscrates/piney-data/src/main_data/inf.bincrates/piney-event/src/official/mod.rscrates/piney-fieldui/src/tables.rscrates/piney-game/src/main.rsplans/volumes.md

An inventory of what the port read from SLUS_202.67 at run time found three kinds of reader, 27 files in all:

  • readers that read a table once;
  • readers that decode a function's instructions;
  • readers that keep the whole image and follow pointers into it while the game runs.

The last kind is the most common: the world's NPC rows, the talk menus, the battle's spawn tables and the story's announcements. The save also stores pointers into the executable (the new game's name lists, the characters' messages). Turning all of them into typed tables at once is days of work; phase 1 of plans/volumes.md did it the short way.

The main data. tools/main_data.py writes, per volume, the spans of main the port reads to crates/piney-data/src/main_data/<volume>.bin:

  • main's data, from the font ef12x20 (the first thing after the code the port uses) to the end of the section's bytes, with the .bss past it reading zero. The later volumes do not name the font; its bytes are Infection's, found once by content: Mutation 0x307a00, Outbreak 0x2ff180, Quarantine 0x1f3100.
  • the three function bodies the port decodes rather than transcribes: ccCheckVoiceGrp, ccParticle::Setup and ccGetItemIcon. The third was found by the check below, not by the survey.

That is 542-558 KB a volume. Image::main(volume) builds the image from it, and every Image::elf(&iso.read_path("SLUS_202.67")?)? became Image::main(iso.volume()?), including in the tests and examples that only needed the data. The three ELF_PATH constants are gone. main_data_is_the_executables compares every span with the executable, byte for byte.

The rest. Two readers still reached the executable some other way:

  • The field UI's tutorial messages used the event loader's own table finder. They now come from the generated scripts (official::events, parsed once a run).
  • story::read and the announcements read the word tables and eventAreaInfo a second time, at Infection's addresses. They now take them from AreaTables (story::from_tables); story_areas_match_the_game still agrees with the game's GetWordParamFromEvCode on all 126.

The check. The game calls iso::deny_executable() at start; from then on a read of SLUS_* fails with "the port does not read the boot executable". Every mode was shot under it: the power-on game, the desktop, Mac Anu, Dun Loireag, area 14's field and dungeon, and story starts 3, 4, 11 and 14. The first run failed in the field menus on ccGetItemIcon's jump targets, which is how the third body was found; after that, none failed.

Still unknown

The readers still use Infection's addresses into the generated bytes; for the other volumes each becomes a typed table (phase 2). A reader that swallows its error (.ok()?) would not show in the smoke runs; the console font's is one, and it drew.