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 #define GLK_EOF ((glsi32) -1)
29 #define NITFOL_MAJOR 0
30 #define NITFOL_MINOR 5
32 /* Change these next few typedefs depending on your compiler */
34 typedef uint8_t zbyte;
37 typedef uint16_t zword;
38 typedef uint32_t offset;
41 #define FAST_TWOS16SHORT
47 typedef int32_t zword;
48 typedef int32_t offset;
50 typedef uint32_t zword; /* Needs to be >= real zword */
51 typedef uint32_t offset;
67 #define MAX(a, b) (a > b ? a : b)
70 #define MIN(a, b) (a < b ? a : b)
79 #define PASTE(a, b) a##b
80 #define XPASTE(a, b) PASTE(a, b)
83 #if defined(__cplusplus) || defined(USE_INLINE)
84 #define N_INLINE inline
86 #define N_INLINE INLINE
87 #elif defined(__GNUC__)
88 #define N_INLINE __inline__
95 #ifdef ZVERSION_GRAHAM_9
98 #define ZWORD_MAX 0x7fffffffL
99 #define ZWORD_MASK 0xffffffffL
100 #define ZWORD_WRAP 0x100000000L
101 #define ZWORD_TOPBITMASK 0x80000000L
106 #define ZWORD_MAX 0x7fff
107 #define ZWORD_MASK 0xffff
108 #define ZWORD_WRAP 0x10000L
109 #define ZWORD_TOPBITMASK 0x8000
114 #ifdef FAST_TWOS16SHORT
116 #define ARITHMASK(n) (n)
117 #define is_neg(a) ((short) (a) < 0)
118 #define neg(a) (-((short) (a)))
122 #define ARITHMASK(n) ((n) & ZWORD_MASK)
123 #define is_neg(a) ((a) > ZWORD_MAX)
124 #define neg(a) ((ZWORD_WRAP - (a)) & ZWORD_MASK)
131 #define is_greaterthan(a, b) (((short) (a)) > ((short) (b)))
132 #define is_lessthan(a, b) (((short) (a)) < ((short) (b)))
136 #define is_greaterthan(a, b) (((b) - (a)) & ZWORD_TOPBITMASK)
137 #define is_lessthan(a, b) (((a) - (b)) & ZWORD_TOPBITMASK)
144 #define LOBYTE(p) z_memory[p]
145 #define LOBYTEcopy(d, s) z_memory[d] = LOBYTE(s)
146 #define LOBYTEwrite(p, n) z_memory[p] = (n)
147 #define LOWORD(p) MSBdecodeZ(z_memory + (p))
148 #define LOWORDcopy(d, s) BYTEcopyZ(z_memory + (d), z_memory + (s))
149 #define LOWORDwrite(p, n) MSBencodeZ(z_memory + (p), n)
151 /* If you have a segmented memory model or need to implement virtual memory,
152 you can change the next three lines, and the corresponding three in the
154 #define HIBYTE(p) z_memory[p]
155 #define HIWORD(p) MSBdecodeZ(z_memory + (p))
156 #define HISTRWORD(p) HIWORD(p)
160 /* FIXME: these tests may not work on 16 bit machines */
162 #define LOBYTE(p) ((p) >= ZWORD_WRAP ? z_range_error(p) : \
164 #define LOBYTEcopy(a, b) ((void) \
165 ((a) >= dynamic_size ? z_range_error(a) : \
166 (z_memory[a] = LOBYTE(b))))
167 #define LOBYTEwrite(p, n) ((void) \
168 ((p) >= dynamic_size ? z_range_error(p) : \
169 (z_memory[p] = (n))))
170 #define LOWORD(p) ((p) + ZWORD_SIZE > ZWORD_WRAP ? z_range_error(p) : \
171 MSBdecodeZ(z_memory + (p)))
172 #define LOWORDcopy(d, s) ((void) \
173 ((d) + ZWORD_SIZE > dynamic_size ? z_range_error(d) : \
174 BYTEcopyZ(z_memory + (d), z_memory + (s))))
175 #define LOWORDwrite(p, n) ((void) \
176 ((p) + ZWORD_SIZE > dynamic_size ? z_range_error(p) : \
177 MSBencodeZ(z_memory + (p), n)))
179 #define HIBYTE(p) ((p) >= game_size ? z_range_error(p) : z_memory[p])
180 #define HIWORD(p) ((p) + ZWORD_SIZE > total_size ? z_range_error(p) : \
181 MSBdecodeZ(z_memory + (p)))
182 #define HISTRWORD(p) HIWORD(p)
185 #endif /* not FAST */
189 /* Probably your system has more efficient ways of reading/writing MSB values,
190 so go ahead and plop it in here if you crave that extra bit of speed */
192 #define MSBdecode1(v) ((v)[0])
193 #define MSBdecode2(v) ((((zword) (v)[0]) << 8) | (v)[1])
194 #define MSBdecode3(v) ((((offset) (v)[0]) << 16) | (((offset) (v)[1]) << 8) \
196 #define MSBdecode4(v) ((((offset) (v)[0]) << 24) | (((offset) (v)[1]) << 16) \
197 | (((offset) (v)[2]) << 8) | (v)[3])
199 #define MSBencode1(v, n) ((v)[0] = (char) (n))
200 #define MSBencode2(v, n) (((v)[0] = (char) ((n) >> 8)), ((v)[1] = (char) (n)))
201 #define MSBencode3(v, n) (((v)[0] = (char) ((n) >> 16)), \
202 ((v)[1] = (char) ((n) >> 8)), \
203 ((v)[2] = (char) (n)))
204 #define MSBencode4(v, n) (((v)[0] = (char) ((n) >> 24)), \
205 ((v)[1] = (char) ((n) >> 16)), \
206 ((v)[2] = (char) ((n) >> 8)), \
207 ((v)[3] = (char) (n)))
209 #define BYTEcopy1(d, s) ((d)[0] = (s)[0])
210 #define BYTEcopy2(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1])
211 #define BYTEcopy3(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1], (d)[2] = (s)[2])
212 #define BYTEcopy4(d, s) ((d)[0] = (s)[0], (d)[1] = (s)[1], \
213 (d)[2] = (s)[2], (d)[3] = (s)[3])
216 #define MSBdecodeZ(v) XPASTE(MSBdecode, ZWORD_SIZE)(v)
217 #define MSBencodeZ(v, n) XPASTE(MSBencode, ZWORD_SIZE)(v, n)
218 #define BYTEcopyZ(d, s) XPASTE(BYTEcopy, ZWORD_SIZE)(d, s)
222 #define UNPACKR(paddr) (paddr * granularity + rstart)
223 #define UNPACKS(paddr) (paddr * granularity + sstart)
225 #define PACKR(addr) ((addr - rstart) / granularity)
226 #define PACKS(addr) ((addr - sstart) / granularity)
228 /* Byte offsets into the header */
229 #define HD_ZVERSION 0x00
230 #define HD_FLAGS1 0x01
231 #define HD_RELNUM 0x02
232 #define HD_HIMEM 0x04
233 #define HD_INITPC 0x06
235 #define HD_OBJTABLE 0x0a
236 #define HD_GLOBVAR 0x0c
237 #define HD_STATMEM 0x0e
238 #define HD_FLAGS2 0x10
239 #define HD_SERNUM 0x12
240 #define HD_ABBREV 0x18
241 #define HD_LENGTH 0x1a
242 #define HD_CHECKSUM 0x1c
243 #define HD_TERPNUM 0x1e
244 #define HD_TERPVER 0x1f
245 #define HD_SCR_HEIGHT 0x20
246 #define HD_SCR_WIDTH 0x21
247 #define HD_SCR_WUNIT 0x22
248 #define HD_SCR_HUNIT 0x24
249 #define HD_FNT_WIDTH 0x26
250 #define HD_FNT_HEIGHT 0x27
251 #define HD_RTN_OFFSET 0x28
252 #define HD_STR_OFFSET 0x2a
253 #define HD_DEF_BACK 0x2c
254 #define HD_DEF_FORE 0x2d
255 #define HD_TERM_CHAR 0x2e
256 #define HD_STR3_WIDTH 0x30
257 #define HD_STD_REV 0x32
258 #define HD_ALPHABET 0x34
259 #define HD_HEADER_EXT 0x36
260 #define HD_USERID 0x38
261 #define HD_INFORMVER 0x3c
264 enum zversions { v1 = 1, v2, v3, v4, v5, v6, v7, v8, vM };
265 enum opcodeinfoflags { opNONE = 0, opSTORES = 1, opBRANCHES = 2, opJUMPS = 4,
270 int minversion, maxversion;
271 int minargs, maxargs;
277 typedef enum { OBJ_GET_INFO, OBJ_RECEIVE, OBJ_MOVE } watchinfo;
280 #include "portfunc.h" /* For miscellaneous string functions, etc. */
282 #include "linkevil.h"
296 #include "gi_blorb.h"
297 #include "no_graph.h"
298 #include "no_blorb.h"
308 #include "tokenise.h"
315 #include "op_table.h"
322 strid_t startup_findfile(void);
324 strid_t intd_filehandle_open(strid_t savefile, glui32 operating_id,
325 glui32 contents_id, glui32 interp_id,
328 void intd_filehandle_make(strid_t savefile);
330 glui32 intd_get_size(void);
332 strid_t startup_open(const char *name);