1 /* Nitfol - z-machine interpreter using Glk for output.
2 Copyright (C) 1999 Evin Robertson
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
18 The author can be reached at nitfol@deja.com
23 #include <stdlib.h> /* For NULL, rand, srand */
24 #include <time.h> /* For time() */
25 #include <ctype.h> /* for isspace, isgraph, etc. */
27 #include <libchimara/glk.h>
28 #define GLK_EOF ((glsi32) -1)
30 #define NITFOL_MAJOR 0
31 #define NITFOL_MINOR 5
33 /* Change these next few typedefs depending on your compiler */
35 typedef unsigned char zbyte;
37 #error "Can't find an 8-bit integer type"
43 typedef unsigned short zword;
45 typedef unsigned int zword;
47 #error "Can't find a 16-bit integer type"
50 #if INT_MAX==0x7fffffff
51 typedef unsigned int offset;
52 #elif LONG_MAX==0x7fffffff
53 typedef unsigned long offset;
55 #error "Can't find a 32-bit integer type"
59 #define FAST_TWOS16SHORT
65 #if INT_MAX==0x7fffffff
68 #elif LONG_MAX==0x7fffffff
72 #error "Can't find a 32-bit integer type"
77 #if INT_MAX==0x7fffffff
78 typedef unsigned int zword;
79 typedef unsigned int offset;
80 #elif LONG_MAX==0x7fffffff
81 typedef unsigned long zword;
82 typedef unsigned long offset;
84 #error "Can't find a 32-bit integer type"
102 #define MAX(a, b) (a > b ? a : b)
105 #define MIN(a, b) (a < b ? a : b)
114 #define PASTE(a, b) a##b
115 #define XPASTE(a, b) PASTE(a, b)
118 #if defined(__cplusplus) || defined(USE_INLINE)
119 #define N_INLINE inline
120 #elif defined(INLINE)
121 #define N_INLINE INLINE
122 #elif defined(__GNUC__)
123 #define N_INLINE __inline__
130 #ifdef ZVERSION_GRAHAM_9
133 #define ZWORD_MAX 0x7fffffffL
134 #define ZWORD_MASK 0xffffffffL
135 #define ZWORD_WRAP 0x100000000L
136 #define ZWORD_TOPBITMASK 0x80000000L
141 #define ZWORD_MAX 0x7fff
142 #define ZWORD_MASK 0xffff
143 #define ZWORD_WRAP 0x10000L
144 #define ZWORD_TOPBITMASK 0x8000
149 #ifdef FAST_TWOS16SHORT
151 #define ARITHMASK(n) (n)
152 #define is_neg(a) ((short) (a) < 0)
153 #define neg(a) (-((short) (a)))
157 #define ARITHMASK(n) ((n) & ZWORD_MASK)
158 #define is_neg(a) ((a) > ZWORD_MAX)
159 #define neg(a) ((ZWORD_WRAP - (a)) & ZWORD_MASK)
166 #define is_greaterthan(a, b) (((short) (a)) > ((short) (b)))
167 #define is_lessthan(a, b) (((short) (a)) < ((short) (b)))
171 #define is_greaterthan(a, b) (((b) - (a)) & ZWORD_TOPBITMASK)
172 #define is_lessthan(a, b) (((a) - (b)) & ZWORD_TOPBITMASK)
179 #define LOBYTE(p) z_memory[p]
180 #define LOBYTEcopy(d, s) z_memory[d] = LOBYTE(s)
181 #define LOBYTEwrite(p, n) z_memory[p] = (n)
182 #define LOWORD(p) MSBdecodeZ(z_memory + (p))
183 #define LOWORDcopy(d, s) BYTEcopyZ(z_memory + (d), z_memory + (s))
184 #define LOWORDwrite(p, n) MSBencodeZ(z_memory + (p), n)
186 /* If you have a segmented memory model or need to implement virtual memory,
187 you can change the next three lines, and the corresponding three in the
189 #define HIBYTE(p) z_memory[p]
190 #define HIWORD(p) MSBdecodeZ(z_memory + (p))
191 #define HISTRWORD(p) HIWORD(p)
195 /* FIXME: these tests may not work on 16 bit machines */
197 #define LOBYTE(p) ((p) >= ZWORD_WRAP ? z_range_error(p) : \
199 #define LOBYTEcopy(a, b) ((void) \
200 ((a) >= dynamic_size ? z_range_error(a) : \
201 (z_memory[a] = LOBYTE(b))))
202 #define LOBYTEwrite(p, n) ((void) \
203 ((p) >= dynamic_size ? z_range_error(p) : \
204 (z_memory[p] = (n))))
205 #define LOWORD(p) ((p) + ZWORD_SIZE > ZWORD_WRAP ? z_range_error(p) : \
206 MSBdecodeZ(z_memory + (p)))
207 #define LOWORDcopy(d, s) ((void) \
208 ((d) + ZWORD_SIZE > dynamic_size ? z_range_error(d) : \
209 BYTEcopyZ(z_memory + (d), z_memory + (s))))
210 #define LOWORDwrite(p, n) ((void) \
211 ((p) + ZWORD_SIZE > dynamic_size ? z_range_error(p) : \
212 MSBencodeZ(z_memory + (p), n)))
214 #define HIBYTE(p) ((p) >= game_size ? z_range_error(p) : z_memory[p])
215 #define HIWORD(p) ((p) + ZWORD_SIZE > total_size ? z_range_error(p) : \
216 MSBdecodeZ(z_memory + (p)))
217 #define HISTRWORD(p) HIWORD(p)
220 #endif /* not FAST */
224 /* Probably your system has more efficient ways of reading/writing MSB values,
225 so go ahead and plop it in here if you crave that extra bit of speed */
227 #define MSBdecode1(v) ((v)[0])
228 #define MSBdecode2(v) ((((zword) (v)[0]) << 8) | (v)[1])
229 #define MSBdecode3(v) ((((offset) (v)[0]) << 16) | (((offset) (v)[1]) << 8) \
231 #define MSBdecode4(v) ((((offset) (v)[0]) << 24) | (((offset) (v)[1]) << 16) \
232 | (((offset) (v)[2]) << 8) | (v)[3])
234 #define MSBencode1(v, n) ((v)[0] = (char) (n))
235 #define MSBencode2(v, n) (((v)[0] = (char) ((n) >> 8)), ((v)[1] = (char) (n)))
236 #define MSBencode3(v, n) (((v)[0] = (char) ((n) >> 16)), \
237 ((v)[1] = (char) ((n) >> 8)), \
238 ((v)[2] = (char) (n)))
239 #define MSBencode4(v, n) (((v)[0] = (char) ((n) >> 24)), \
240 ((v)[1] = (char) ((n) >> 16)), \
241 ((v)[2] = (char) ((n) >> 8)), \
242 ((v)[3] = (char) (n)))
244 #define BYTEcopy1(d, s) ((d)[0] = (s)[0])
245 #define BYTEcopy2(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1])
246 #define BYTEcopy3(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1], (d)[2] = (s)[2])
247 #define BYTEcopy4(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1], \
248 (d)[2] = (s)[2], (d)[3] = (s)[3])
251 #define MSBdecodeZ(v) XPASTE(MSBdecode, ZWORD_SIZE)(v)
252 #define MSBencodeZ(v, n) XPASTE(MSBencode, ZWORD_SIZE)(v, n)
253 #define BYTEcopyZ(d, s) XPASTE(BYTEcopy, ZWORD_SIZE)(d, s)
257 #define UNPACKR(paddr) (paddr * granularity + rstart)
258 #define UNPACKS(paddr) (paddr * granularity + sstart)
260 #define PACKR(addr) ((addr - rstart) / granularity)
261 #define PACKS(addr) ((addr - sstart) / granularity)
263 /* Byte offsets into the header */
264 #define HD_ZVERSION 0x00
265 #define HD_FLAGS1 0x01
266 #define HD_RELNUM 0x02
267 #define HD_HIMEM 0x04
268 #define HD_INITPC 0x06
270 #define HD_OBJTABLE 0x0a
271 #define HD_GLOBVAR 0x0c
272 #define HD_STATMEM 0x0e
273 #define HD_FLAGS2 0x10
274 #define HD_SERNUM 0x12
275 #define HD_ABBREV 0x18
276 #define HD_LENGTH 0x1a
277 #define HD_CHECKSUM 0x1c
278 #define HD_TERPNUM 0x1e
279 #define HD_TERPVER 0x1f
280 #define HD_SCR_HEIGHT 0x20
281 #define HD_SCR_WIDTH 0x21
282 #define HD_SCR_WUNIT 0x22
283 #define HD_SCR_HUNIT 0x24
284 #define HD_FNT_WIDTH 0x26
285 #define HD_FNT_HEIGHT 0x27
286 #define HD_RTN_OFFSET 0x28
287 #define HD_STR_OFFSET 0x2a
288 #define HD_DEF_BACK 0x2c
289 #define HD_DEF_FORE 0x2d
290 #define HD_TERM_CHAR 0x2e
291 #define HD_STR3_WIDTH 0x30
292 #define HD_STD_REV 0x32
293 #define HD_ALPHABET 0x34
294 #define HD_HEADER_EXT 0x36
295 #define HD_USERID 0x38
296 #define HD_INFORMVER 0x3c
299 enum zversions { v1 = 1, v2, v3, v4, v5, v6, v7, v8, vM };
300 enum opcodeinfoflags { opNONE = 0, opSTORES = 1, opBRANCHES = 2, opJUMPS = 4,
305 int minversion, maxversion;
306 int minargs, maxargs;
312 typedef enum { OBJ_GET_INFO, OBJ_RECEIVE, OBJ_MOVE } watchinfo;
315 #include "portfunc.h" /* For miscellaneous string functions, etc. */
317 #include "linkevil.h"
331 #include <libchimara/gi_blorb.h>
332 #include "no_graph.h"
333 #include "no_blorb.h"
343 #include "tokenise.h"
350 #include "op_table.h"
357 strid_t startup_findfile(void);
359 strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
360 glui32 contents_id, glui32 interp_id,
363 void intd_filehandle_make(strid_t savefile);
365 glui32 intd_get_size(void);
367 strid_t startup_open(const char *name);