Entry 40
The event engine: our own instruction set, the official scripts loaded without loss, the interpreter checked against the game
Documented in The event interpreter, Event scripts, How the game is put together.
Filescrates/piney-eventtools/test_event_vm.pytools/evscript.pydocs/engine/event-vm.mddocs/engine/events.md
18 decoded the story's scripts and 24 read them on every volume. To see the desktop as a new game sees it, the scripts have to run: they deliver the first mails, lock the desktop's other icons until those are read, and post the board and news.
The user also asked that the scripts could later be replaced by our own clean-room ones. So the engine is built in three layers, and the official bytecode is only one way in. A helper agent built it; I re-ran its checks. The reference is the event interpreter page.
Layers
ir: our own instruction set. A script is its open conditions and blocks of (tags, conditions, instructions).- It has 169 instructions, 40 conditions and 10 tags, each an enum variant with named fields (evscript.py's names).
- It has no opcode numbers and no offsets.
textprints and parses a readable form, and the two round-trip exactly. This is the format a clean-room script set would be written in. A made-up script runs through the whole engine intests/clean_room.rs.
official: the adapter for the game's scripts. It findsExecute,CheckOpen,eventTbland the message tables through the code, with no symbols, on all four volumes, and maps opcodes per volume.- Every script on every disc goes bytecode to IR to identical bytecode: 192, 196, 199 and 206 scripts.
- All 192 Infection events round-trip through the text form, with 2,369 messages.
- The scripts and messages are the game's content. They are read from
the disc at run time.
examples/exportwrites their text form only underwork/.
vm: the interpreter. It isCheckOpen,SetCurrentOpen,ExecuteandeventSubat levels 0-2, andccThEvent's passes by phase.- Instructions that span frames keep the game's own frame counts.
- Every effect goes through a
Hosttrait of named, typed calls: messages, mail, modes, sound, the field's cameras and characters. ALogHostrecords them. - The saved state is the shared
SaveData. The ccSaveData functions the scripts call (AddItemwith its category sort,DelItem,AddSkill,AddFriendship,SetGateList,SetAreaBan) are ported. - The rest of
ccEventisEventMng, with its offsets documented.
Checked
tools/test_event_vm.py runs the game's own event and save code in eemu,
and tests/vm.rs compares the Rust against the fixture it writes. The
fixture holds numbers only; I grepped it and it has no script text. All
match:
- Bookkeeping.
ccEventFlagSetfor every script from the boot save and three random saves: 768 runs, every save byte and the event-manager registers. - Starting events.
ccStartEventon every volume, andccStartThEvent's 63-to-62 rule. - Conditions. 1,536
CheckOpenwalks, and each of 2,059 conditions in 8 random worlds. - Playing. 576
eventSubruns, and every block played at level 2: 2,616 blocks over 169,146 frames, matching frame counts, saves and registers. - A new game reaching the desktop. 152 frames under the game's own
ccThEvent. The phase matches every frame, every call outside the event code matches in kind and frame, and three save snapshots match.
Deliberate mistakes planted in the Rust are caught.
What a new game does, as the checks show it. At boot ccStartEvent(1, 0) marks event 0 done. When the desktop's phase-0 pass runs, event 1's
block 0:
- plays from frame 2 to frame 59;
- locks every desktop operation but the mailer;
- delivers mails 4, 5 and 320;
- posts board thread 62's first seven messages and news 0-3 and 37.
Trying a locked icon replays a message (block 1). Reading mails 4 and 5 releases the locks, posts 53 more board messages (not the 57 18 counted), and closes the event.
On integration:
- the crate's tests pass;
test_event_vm.pyandtest_evscript.pyare OK;- clippy and fmt are clean.
The agent also corrected seven instruction descriptions in evscript.py,
such as wait, which waits count + 1 frames.
- The later volumes' own semantics. The VM runs Infection's rules for every dialect, including the changed cases on the events page and the order their event task walks story events. - Story areas. The table of story areas' gate words and servers is not loaded from the executable yet; the host supplies it. -
piros_colour. Its frame shape is inferred; it needs Piros present. - The field side of the Host. Markers, distances and entries come from whoever ports the field game.