-
Notifications
You must be signed in to change notification settings - Fork 1
kmill/zmach
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
zmach is a (semi-functional) Javascript-targeting Z-machine emulator. It only implements version 5 of the machine (i.e., z5 files when they are named correctly). The technique is to decompile the bytecode dynamically, recompiling it as Javascript, using an emscripten-inspired relooper algorithm to generate (mostly) switch-less code. The main idea behind this is that by converting full Z-machine routines into Javascript functions, with arguments and local variables becoming actual Javascript arguments and local variables, the Javascript engine's JIT is given a chance to optimize the code. This is in contrast to emulators which maintain a separate call stack from Javascript's native call stack. One difficulty with this is that the Z-machine has blocking I/O instructions (for instance, 'aread' for user input), which browser Javascript has no support for. The interesting thing about this particular emulator is its use of the Javascript call stack despite this difficulty --- the relooper is there partly to show that this technique gives it access to full Z-machine routines. To handle blocking I/O, it implements a method to reify the call stack as Javascript objects only when this is needed, at the expense of wrapping function bodies in a try-catch block and storing an integer into a local variable before call sites. In other words, it takes the idea of using continuations to implement cooperative multitasking, but simulates continuations using try-catch blocks. When resuming a continuation, instead of trying to resume the actual functions which were paused, the emulator calls specially compiled functions which pick up at exactly where a routine last paused. As far as I know, this is a novel technique. There is a 2007 paper[1] I later came across with a similar exception-based technique, but it uses the same function when resuming a continuation, complicating control flow. In principle, this stack reification technique should also allow saving a game in Quetzal, but this has not yet been implemented. The emstripten-inspired relooper is a more streamlined version of their algorithm. (However, I've implemented the algorithm inefficiently.) At some point I plan on writing about how this works. The motivation behind this project was to have an excuse to understand the relooper, and to attempt the context resumption described above. The full emulator might never be finished. However, it does seem to be able to play Zork I and other games without errors now. To try it out: 1. run "node convert_zcode.js $storyfile.z5", which produces "$storyfile.z5.js" (or use your favorite technique for doing base64 encoding. Just call "loadData('base64', '$your-base64-string')" in the browser.) 2. edit zmach.html to load '$storyfile.z5.js' 3. open zmach.html [1] Loitsch, Florian. Exceptional Continuations in Javascript. Proceedings of the 2007 Workshop on Scheme and Functional Programming. http://www.schemeworkshop.org/2007/procPaper4.pdf
About
A z-machine interpreter which does dynamic recompilation to javascript
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published