File Coverage

blib/lib/Language/Zcode.pm
Criterion Covered Total %
statement 6 6 100.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 8 8 100.0


line stmt bran cond sub pod time code
1             package Language::Zcode;
2            
3 1     1   1427 use strict;
  1         3  
  1         42  
4 1     1   6 use warnings;
  1         2  
  1         108  
5            
6             our $VERSION = 0.8;
7            
8             # No code here, just docs.
9            
10             =head1 NAME
11            
12             Language::Zcode - Play with Z-code and the Z-machine
13            
14             =head1 SYNOPSIS
15            
16             Translate a Z-code file into Perl. The following (if piped to a file) will
17             create an executable which will will execute just as if you ran zork1.z3 under
18             a Z-code interpreter. Note: the executable will not be standalone; it will use
19             Language::Zcode::Runtime::* modules. Creating a downloadable single-file
20             executable is a TODO.
21            
22             use Language::Zcode::Parser; # parse Z-file
23             use Language::Zcode::Translator; # language-specific output routines
24            
25             my $Zfile = "zork1.z3";
26             my $Parser = new Language::Zcode::Parser "Perl";
27             $Parser->read_memory($Zfile);
28             $Parser->parse_header();
29            
30             my $T = new Language::Zcode::Translator "Perl";
31             print $T->program_start();
32             for my $rtn ($Parser->find_subs($Zfile)) {
33             $rtn->parse();
34             print $T->routine_start($rtn->address, $rtn->locals);
35             print $T->translate_command($_) for $rtn->commands;
36             print $T->routine_end();
37             }
38             print $T->write_memory();
39             print $T->program_end();
40            
41             Create a Z-machine...
42            
43             Nothing here yet.
44            
45             Parse a Quetzal save file.
46            
47             Nothing here yet.
48            
49             =head1 DESCRIPTION
50            
51             Z-code is the machine language for the Z-machine, the virtual machine
52             that the Infocom text adventure games (among others) run on.
53             Language::Zcode provides tools to parse story files written in Z-code, and to
54             translate ("compile") them to executables in other languages (such as Perl).
55            
56             This module does not contain a Z-machine interpreter: you can't run a
57             Z-machine file without translating it to some other language first. Pick up
58             Michael Edmonson's Games::Rezrov if you want to B Zork, rather than
59             translate it to Perl. (I stole almost all of Games::Rezrov to start this
60             module.)
61            
62             =head2 Parsing
63            
64             Language::Zcode should be able to handle almost any story file, except
65             for fancy stuff like Unicode. Parsing will let you look at a story
66             file's commands and strings, like the (ca. 1992) txd program. Looking
67             at objects (like infodump does) is a bit harder, but doable
68             using the API. Grammar/action tables are totally not supported.
69            
70             =head2 Translating to Perl
71            
72             The "compiled" Perl executables basically support early-to-mid-80's Infocom
73             technology. That is:
74            
75             =over 4
76            
77             =item *
78            
79             All v3 opcodes are implemented, some better than others.
80            
81             =item *
82            
83             Some v4 and v5 opcodes are implemented.
84            
85             =item *
86            
87             Only the Dumb and Win32 Console I/O systems are implemented.
88            
89             =back
90            
91             This means (although I haven't tested exhaustively) that you should be able to
92             play most Infocom games, if you're lucky enough to have the story files.
93             Most modern (late Infocom, Inform) games won't work. I hope to have
94             support for those in the next version.
95            
96             =head2 Translating to PIR
97            
98             PIR is also known as Parrot Intermediate Representation or IMCC.
99             Language::Zcode is only doing this as a proof of concept. A few v3 opcodes
100             are implemented, badly. See L.
101            
102             =head2 Translating to XML
103            
104             Barely even a proof of concept. A static file, rather than an executable.
105             But with some good XSL work (by someone who actually knows XSL), you could have
106             a very pretty display of the game's commands and strings. Further XML
107             TODOs left to the imagination.
108            
109             =head1 TODO
110            
111             (Only includes TODOs within the current set of supported commands.)
112            
113             =over 4
114            
115             =item *
116            
117             print_char should do ZSCII, not ASCII.
118            
119             =item *
120            
121             output stream 3
122            
123             =back
124            
125             See Todo for far more information.
126            
127             =head1 BUGS
128            
129             =over 4
130            
131             =item *
132            
133             Stream 2 isn't buffered (word-wrapped) correctly.
134            
135             =item *
136            
137             Language::Zcode can't read a Windows command input file (input stream
138             1) when it's running on Unix. It gets a \r\n instead of a \n.
139            
140             =item *
141            
142             sending "y\n" to get_key in dumb-terminal mode leaves a \n on STDIN,
143             so the next get_key (which just does read(STDIN, $z, 1) reads the \n even
144             if you don't type anything!
145            
146             =item *
147            
148             $SIG{INT} should call cleanup. See rezrov.
149            
150             =item *
151            
152             It's legal (but "bad practice" and confuses txd) to jump into a subroutine.
153             I don't care for now. I might in later versions. But, for example, if you
154             do allow jumping into subroutines, then you can't (easily) translate
155             Z-machine routines into Perl subs; the latter tend to get fussy about
156             goto's breaking scope.
157            
158             =item *
159            
160             All pops & pulls ought to crash on stack underflow. We'll just return
161             an undef, which will probably turn into 0. Problem is that fixing this
162             while still using a normal Perl array for the stack is Hard, because
163             pop @stack happens in so many places where we don't want to have a big
164             do {die unless @stack; pop @stack}
165            
166             =item *
167            
168             For safety, Z_machine() should take
169             first_instruction_address - 2*num_locals - 1, or it might break on
170             Infocom z3's whose Mains have local variables.
171            
172             =item *
173            
174             PlotzMemory::set_word_at doesn't & 0xff the high byte. (storew DOES do it)
175             Also need to "unsigned_word-ify" some more constructs to make sure
176             we're safe.
177            
178             =item *
179            
180             split_window in v3 (only) should erase the screen, and
181             restart/restore shouldn't clear screen
182            
183             =back
184            
185             =head1 HISTORY
186            
187             It all started with Dan Sugalski's suggestion that Parrot could
188             run Z-code natively. He subtly hinted at this idea as early as 12/2001
189             (http://www.nntp.perl.org/group/perl.perl6.internals/6875) and dedicated
190             a whole slide to it in a 2002 RubyConf presentation.
191            
192             Dan's idea was to make the Parrot VM think it's a Z-machine, running
193             the Z-code opcodes instead of the regular Parrot ones. Or,
194             as he put it, "parrot -b:zmachine zork.dat". Whoa! Why do it? Because
195             it proves how powerful Parrot is. "Plus, it's really cool."
196            
197             Given that I had no clue at all how to do this, I got some advice from
198             the Parrot mailing list, and it was suggested that I:
199            
200             =over 4
201            
202             =item 1
203            
204             Write a program that translates ("compiles") Z-code to Perl.
205            
206             =item 2
207            
208             Compile Z-code to PIR, writing new Parrot opcodes for Z-machine opcodes.
209             The PIR and C could just be translations of the Perl code from step 1.
210            
211             =item 3
212            
213             Convince Parrot to read Z-code directly, and then execute the Z Parrot opcodes
214             that I'd written in step 2.
215            
216             =item 4
217            
218             ...
219            
220             =item 5
221            
222             Profit!
223            
224             =back
225            
226             Language::Zcode v0.8 is step 1, and later versions will do part of step 2.
227             Given how long it took to get this far, I'm not all that confident about step
228             5, but we'll see.
229            
230             See Changes for version information.
231            
232             =head1 AUTHOR
233            
234             Amir Karger
235            
236             =head1 LICENSE
237            
238             Copyright (c) 2004 Amir Karger. All rights reserved.
239            
240             This program is free software; you can redistribute it and/or modify it under
241             the same terms as Perl itself.
242            
243             =head1 SEE ALSO
244            
245             =over 4
246            
247             =item *
248            
249             L - A Perl Z-code interpreter by Michael Edmonson (which I
250             stole from. A lot. As in, pretty much all of the I/O, and many of the opcode
251             translations. But I keep trying to convince myself that Language::Zcode has
252             some independent value.)
253            
254             =item *
255            
256             www.ifarchive.org - everything Interactive Fiction-y
257            
258             =item *
259            
260             www.inform-fiction.org - Inform, a coding language that compiles to Z-code.
261             Get the Z-code spec here (or at ifarchive.org).
262            
263             =back
264            
265             =cut
266            
267             1;