Features
Player
- Make save files more portable
112289cc58- Save files now remember where their quest was actually found: when the recorded quest path is stale and the fallback search locates the quest elsewhere, the corrected location is stored the next time the game saves, so the search isn't needed again.
- The qst search can now find a quest by file name anywhere under the quests directory, not just by dropping leading folders from the recorded path.
- Save files now always record quest paths relative to the quests directory when the .qst file is in that folder; and it's stored with forward slashes. This should help keep .sav files working even when moved between different installations and platforms.
- Find a save file's quest by its contents when the path fails
3386fefa9aSave files now record a fingerprint of their quest file. If the recorded path no longer resolves - even after searching by file name - the quest directory is searched for a file with the same contents, so the quest can be found even after being renamed. A content match is preferred over a file name match, since a different quest file could share the name.
ZScript
- Dispatch switch statements without walking a compare ladder
3ebe18df63Speeds up scripts built around large switch statements. Quests must be recompiled to benefit.
After recompiling, a switch-heavy benchmark ran about 24% faster interpreted; the JITs already dispatched switches well, so they see little change.
Bug Fixes
Player
- Find the quest for a save file made on a different computer
f5cebcd5e5Save files record the path of their quest file as it was when the save was created. If that was an absolute path from another computer - such as a Windows path in a save file opened on a Mac - the player failed to load the quest even when it was sitting in the quest directory: the foreign path was mistaken for a relative one, and the fallback search never looked in the quest directory at all. Absolute paths from either platform are now recognized everywhere, and the search tries each path suffix in the quest directory too.
Bug present since the quest-path fallback search was added, prior to the initial repo commit (429df347a1).
ZScript
- lweapon scripts lifting themselves not stopping the engine loop
0b8c59253fWhen an lweapon script called Hero->LiftWeapon() on itself, the script engine was meant to report a "self remove" so the engine stops processing the now-lifted weapon that frame. Instead it returned a meaningless value (the early-return code was reset before being returned), so the weapon kept animating after being removed from the weapon list. With the JIT the signal was dropped entirely and the script also kept running past the call, diverging from the interpreter. Now both stop the script at the call and the engine skips the rest of that weapon's frame, as intended.
Bug introduced when script access to lifting was added in 2.55-alpha-114 (530f7c6898).
Refactors
ZScript
- Cache script object lookups instead of walking a map
30974734aaSpeeds up scripts that make heavy use of objects - classes, arrays, and other script-created values.
An object-heavy benchmark ran 39% faster with the JIT and 7% faster interpreted.
- Dispatch interpreter commands through a single switch
32735ccc41Speeds up all scripts on platforms where the JIT is unavailable, or when it is disabled.
Script-heavy benchmarks ran 13-17% faster interpreted; JIT performance is unchanged.
- Resolve switch/class/stack registers on the fast path
fd5aac89b7Speeds up scripts that lean on switch statements and class method calls.
A benchmark heavy in both ran 10-12% faster, interpreted and with the JIT.
- Resolve D registers inline at register access sites
6fc4cd93adSpeeds up something every script does constantly: reading and writing local variables.
Script-heavy benchmarks ran 4-8% faster interpreted; JIT performance is unchanged.
- Inline script stack reads and writes
34e5265650Speeds up scripts that call functions frequently.
Script-heavy interpreter benchmarks ran about 3% faster.
- Inline the interpreter's comparison checks
2065e65832Speeds up scripts with lots of conditionals - if statements, loops, and comparisons.
Comparison-heavy interpreted scripts ran about 4% faster.
- Screen rare interpreter loop-exit checks behind one branch
c6fa3ea74dSpeeds up every script when running interpreted.
Script-heavy benchmarks ran 4-5% faster.
- Fast-path plain array element access in the pod opcodes
988b3e9d22Speeds up scripts that read and write arrays heavily.
An array-heavy benchmark ran about 8% faster under the JIT and about 1% faster interpreted.
- Resolve script debug checks inline on engine entry
eaf13045dfScript-heavy benchmarks ran about 3% faster, both interpreted and with the JIT.
- Compile class member reads and writes in the JITs
4685ecd825Speeds up scripts that use classes, when running under the JIT.
A class-heavy benchmark ran about 30% faster under the JIT, native and web alike.
Tests
- Let web replay runs preload host files into the page
f731d29a7eReplays for quests that read from their "Files" directory (like the ZC-emu NES emulator loading a ROM) could not run on the web build: the files exist only on the host filesystem, outside what the page can reach. ZC_WEB_PRELOAD_FILES ("src:dest,...") now copies local files into the page's in-memory filesystem after the replay engine starts, before the quest's scripts run.