The Creation of Zebra - Z Machine Interpreter

Contents
Resources Used
Emulating the Text System
Emulating the Memory System
Emulating the Stack
Emulating the Object Table
Emulating the Dictionary
Emulating the IO System
Emulating the CPU


Resources Used

  • The Z-Machine Standards Document - Graham Nelson
  • Frotz Source Code - Stefan Jokisch
  • Emulating the Z-Text System

    Emulation of the Z-Text system was the first part I tackled, and it might have been just as well. Decoding the 5-bit Z-Character language was quite finicky for a youngling like me. However, after many hours of wrangling with endians (yes, the Z-machine is a big-endian machine) and bit shifting, ANDs and ORs, and all that, I finally finished it. Thanks to The Z-Machine Standards, most of the information I needed to make it work was readily on hand.

    After copping a bit of criticism for using pointers instead of std::vector, I decided to try and overhaul it to use vectors instead. Long story made short, it didn't work very well, so I threw the addled version, and kept the first one.

    Emulating the Memory System

    Emulating the memory system was quite an easy part. I only had to deal with read/write range and sanity checks, and more endianizing. Again, the Z-Machine Standards gave me all the information I needed.

    Emulating the Stack

    Another easy part, that took me fifteen minutes to write. Just a simple stack :)

    Emulating the Object Table

    The object table is one of the more tricky parts of the Z-Machine, due to its heavy use of tables, and lots of bit-manipulation. With exception of the CPU, this is probably one of the components which took me the longest to complete.

    Emulating the Dictionary

    The dictionary was reasonable, not too hard, yet still tricky. One of the most frustrating points of the development of this module was when a nasty and seemingly harmless "warning" reared its ugly head and became a runtime error. After a few posts on cplusplus.com and extensive use of online compilers (haha) I (finally) found the problem:

    	// this code will return a variable, but the caller will never recieve it
    	int f(){
    		vector[zword] a(10);
    		if(rand()&1){
    			// odd integer
    			return 777;	// this will never reach the caller!
    		}else{
    			return 666;	// this will never reach the caller!
    		}
    		// we should return a NULL even though the program will never
    		// execute this line during runtime.
    		// It appears that all compilers flag this as a warning
    		// But in this case, it's an error!
    	}
    		
    apart from this mishap, however, things went relatively smoothly

    Emulating the IO System

    Quite easy, mainly harnessing the usage of the cstdlib IO and the VT100 terminal control codes

    Emulating the CPU