1 /*
2 Head
3 */
4
5 #include "head.h"
6
7 #include "infocom.h"
8 #include "mem.h"
9 #include "os.h"
10 #include "page.h"
11 #include "shared.h"
12 #include "stop.h"
13 #include "support.h"
14 #include "wio.h"
15
16 static filep game_file;
17
18 /* Interpreter numbers */
19
20 #define XZIP 0
21 #define DEC_20 1
22 #define APPLE_2E 2
23 #define MACINTOSH 3
24 #define AMIGA 4
25 #define ATARI_ST 5
26 #define IBM_MSDOS 6
27 #define COMMODORE_128 7
28 #define C64 8
29 #define APPLE_2C 9
30 #define APPLE_2GS 10
31 #define TANDY_COLOR 11
32
33 #ifndef INTERPRETER
34 #define INTERPRETER APPLE_2E
35 #endif
36
37 /* Script flags */
38
39 #define SCRIPT_MODE_ON 0x0001
40 #define USE_NON_PROP_FONT 0x0002
41 #define SCRIPT_ERROR 0x0400
42
43 /* Mode flags (change with version) */
44
45 #define mode3_status 0x02 /* What sort of status line */
46 #define mode3_tandy 0x08 /* Set for tandy interpreters */
47 #define mode3_non_status 0x10 /* Set if can't do status line */
48 #define mode3_can_split 0x20 /* Set if can split screen */
49 #define mode3_non_fixed 0x40 /* Set if using non-fixed-space fonts */
50
51 #define set_mode3 (mode3_status | mode3_can_split | mode3_non_fixed)
52 #define clr_mode3 (mode3_non_status)
53
54 #define mode4_can_colour 0x01 /* Colour available */
55 #define mode4_can_picture 0x02 /* Always on V4, If pictures on V6 */
56 #define mode4_can_bold 0x04 /* Bold available */
57 #define mode4_can_emph 0x08 /* Can do underline */
58 #define mode4_can_fixed 0x10 /* Can do fixed width */
59 #define mode4_can_sound 0x20 /* Sound effects */
60 #define mode4_can_timed 0x80 /* Can do timed inputs */
61
62 #define set_mode4 (mode4_can_colour | mode4_can_bold | mode4_can_emph | mode4_can_fixed)
63 #define clr_mode4 (mode4_can_sound | mode4_can_timed)
64
65 /* Offsets into the header, all are 1 byte in extent unless specified */
66
67 #define z_code_version 0 /* Game's Z-CODE Version Number */
68 #define mode_bits 1 /* Status Bar display indicator */
69 #define release 2 /* 2 bytes for game release number */
70 #define resident_bytes 4 /* 2 bytes giving resident bytes */
71 #define start 6 /* 2 bytes, offset to game start */
72 #define vocab 8 /* 2 bytes, offset to vocabulary */
73 #define object_list 10 /* 2 bytes, offset to objects */
74 #define globals 12 /* 2 bytes, offset to globals */
75 #define save_bytes 14 /* 2 bytes, length to save to disk */
76 #define script_status 16 /* 2 bytes, printing modes */
77 #define serial_no 18 /* 6 bytes, serial number */
78 #define common_word 24 /* 2 bytes, offset to common words */
79 #define verify_length 26 /* 2 bytes, total game file size */
80 #define verify_checksum 28 /* 2 bytes, checksum for verify */
81 #define interpreter_number 30 /* 1 byte, set by interpreter */
82 #define interpreter_version 31 /* 1 byte, letter set by interpreter */
83 #define screen_height 32 /* 1 byte, set by interpreter */
84 #define screen_width 33 /* 1 byte, set by interpreter */
85 #define left 34 /* 1 byte, set by interpreter */
86 #define right 35 /* 1 byte, set by interpreter */
87 #define top 36 /* 1 byte, set by interpreter */
88 #define bottom 37 /* 1 byte, set by interpreter */
89 #define unknown1 38 /* 1 unknown, set by interpreter */
90 #define unknown2 39 /* 1 unknown, set by interpreter */
91 #define code_offset 40 /* 1 word, code offset in longs (>V5)*/
92 #define text_offset 42 /* 1 word, code offset in longs (>V5)*/
93 #define default_back 44 /* 1 byte, default paper set by interpreter */
94 #define default_fore 45 /* 1 byte, default ink set by interpreter */
95 #define unknown5 46 /* 1 unknown, set in data file */
96 #define padding2 48 /* 6 blanks */
97 #define unknown6 54 /* 2 unknowns */
98 #define padding3 56 /* 8 blanks */
99
100 /* For a total of 64 bytes of header */
101
hd_open(char * filename)102 int hd_open(char *filename)
103 {
104 game_file = os_wild_read(filename);
105 return game_file != 0;
106 }
107
hd_close(void)108 void hd_close(void)
109 {
110 os_close(game_file);
111 }
112
hd_load(word block,word num_blocks,byte * ptr)113 void hd_load(word block, word num_blocks, byte *ptr)
114 {
115 int wide = hd_width();
116 int high = hd_height();
117 long_word offset = ((long_word) block) << BLOCK_SHIFT;
118 if(os_seek_fore(game_file, offset) < 0)
119 {
120 display((byte *) "Failed to Seek required Blocks\n");
121 quit();
122 }
123 /* Need the -1 since we may want a final (incomplete) block */
124 else if(os_read(ptr, BLOCK_SIZE, num_blocks, game_file) < num_blocks - 1)
125 {
126 display((byte *) "Failed to Read required Blocks\n");
127 quit();
128 }
129 hd_set_size(high, wide);
130 }
131
hd_flip(word page,byte * block)132 void hd_flip(word page, byte *block)
133 {
134 #if 0
135 int i;
136 byte b[BLOCK_SIZE];
137 hd_load(page, 1, b);
138 for(i = 0; i < BLOCK_SIZE; ++i)
139 block[i] ^= b[i];
140 #else
141 byte b[BLOCK_SIZE];
142 word *s = (void *) b;
143 word *d = (void *) block;
144 int c = BLOCK_SIZE / (2 * sizeof(*s));
145 hd_load(page, 1, b);
146 do { *d ^= *s; *++d ^= *++s; ++d; ++s; } while(--c);
147 #endif
148 }
149
hd_no_colour(void)150 void hd_no_colour(void)
151 {
152 if(hd_plus())
153 base_ptr[mode_bits] &= ~mode4_can_sound;
154 }
155
hd_init(void)156 void hd_init(void)
157 {
158 base_ptr[interpreter_number] = INTERPRETER;
159 base_ptr[interpreter_version] = 'A';
160 if(hd_plus())
161 base_ptr[mode_bits] = (base_ptr[mode_bits] | set_mode4) & ~clr_mode4;
162 else
163 base_ptr[mode_bits] = (base_ptr[mode_bits] | set_mode3) & ~clr_mode3;
164 if(hd_five())
165 {
166 base_ptr[left] = 0;
167 base_ptr[top] = 0;
168 base_ptr[unknown1] = 1;
169 base_ptr[unknown2] = 1;
170 base_ptr[default_back] = 9;
171 base_ptr[default_fore] = 2;
172 }
173 }
174
hd_set_size(int high,int wide)175 void hd_set_size(int high, int wide)
176 {
177 base_ptr[screen_width] = wide;
178 base_ptr[screen_height] = high - 1;
179 base_ptr[right] = wide;
180 base_ptr[bottom] = high - 1;
181 }
182
hd_width(void)183 int hd_width(void)
184 {
185 return base_ptr[screen_width];
186 }
187
hd_height(void)188 int hd_height(void)
189 {
190 return (int) base_ptr[screen_height] + 1;
191 }
192
hd_version(void)193 version hd_version(void)
194 {
195 return base_ptr[z_code_version];
196 }
197
198 /*
199 hd_resident_blocks could actually use save_bytes rather than
200 resident_bytes -- Graham calls these
201
202 dynamic memory (can be changed)
203 <-- split defined by $0e, so save_bytes
204 static memory (assumed resident)
205 <-- split defined by $04, so resident_bytes
206 high_memory (used for code and strings)
207
208 Doing so would mean that pg_delta packed pages less often
209 */
210
hd_resident_blocks(void)211 word hd_resident_blocks(void)
212 {
213 #if 0
214 return pg_blocks(rd_word_ptr(base_ptr + resident_bytes));
215 #else
216 return pg_blocks(rd_word_ptr(base_ptr + save_bytes));
217 #endif
218 }
219
hd_verify(void)220 word hd_verify(void)
221 {
222 return rd_word_ptr(base_ptr + verify_length);
223 }
224
hd_save_blocks(void)225 word hd_save_blocks(void)
226 {
227 return pg_blocks(rd_word_ptr(base_ptr + save_bytes));
228 }
229
hd_start(void)230 word hd_start(void)
231 {
232 return rd_word_ptr(base_ptr + start);
233 }
234
hd_mode(void)235 byte hd_mode(void)
236 {
237 return base_ptr[mode_bits];
238 }
239
hd_set_screen(void)240 void hd_set_screen(void)
241 {
242 wr_word_ptr(base_ptr + mode_bits, rd_word_ptr(base_ptr + mode_bits) | SCREEN_MODES);
243 }
244
hd_check(void)245 word hd_check(void)
246 {
247 return rd_word_ptr(base_ptr + verify_checksum);
248 }
249
hd_script(void)250 static word hd_script(void)
251 {
252 return rd_word_ptr(base_ptr + script_status);
253 }
254
hd_set_script(int on)255 void hd_set_script(int on)
256 {
257 if(on)
258 wr_word_ptr(base_ptr + script_status, rd_word_ptr(base_ptr + script_status) | SCRIPT_MODE_ON);
259 else
260 wr_word_ptr(base_ptr + script_status, rd_word_ptr(base_ptr + script_status) & ~ SCRIPT_MODE_ON);
261 }
262
hd_set_fixed(int on)263 void hd_set_fixed(int on)
264 {
265 if(on)
266 wr_word_ptr(base_ptr + script_status, rd_word_ptr(base_ptr + script_status) | USE_NON_PROP_FONT);
267 else
268 wr_word_ptr(base_ptr + script_status, rd_word_ptr(base_ptr + script_status) & ~USE_NON_PROP_FONT);
269 }
270
hd_get_script(void)271 bool hd_get_script(void)
272 {
273 return (hd_script() & SCRIPT_MODE_ON) != 0;
274 }
275
hd_get_fixed(void)276 bool hd_get_fixed(void)
277 {
278 return (hd_script() & USE_NON_PROP_FONT) != 0;
279 }
280
hd_err_script(void)281 void hd_err_script(void)
282 {
283 wr_word_ptr(base_ptr + script_status, SCRIPT_ERROR);
284 }
285
hd_object(void)286 word hd_object(void)
287 {
288 return rd_word_ptr(base_ptr + object_list);
289 }
290
hd_global(void)291 word hd_global(void)
292 {
293 return rd_word_ptr(base_ptr + globals);
294 }
295
hd_common(void)296 word hd_common(void)
297 {
298 return rd_word_ptr(base_ptr + common_word);
299 }
300
hd_vocab(void)301 word hd_vocab(void)
302 {
303 return rd_word_ptr(base_ptr + vocab);
304 }
305
hd_plus(void)306 int hd_plus(void)
307 {
308 return hd_version() >= VERSION_4;
309 }
310
hd_five(void)311 int hd_five(void)
312 {
313 return hd_version() >= VERSION_5;
314 }
315
hd_offset(word w)316 static word hd_offset(word w)
317 {
318 switch(hd_version())
319 {
320 case VERSION_6:
321 case VERSION_7:
322 return rd_word_ptr(base_ptr + w);
323 default:
324 return 0;
325 }
326 }
327
hd_code_offset(void)328 word hd_code_offset(void)
329 { return hd_offset(code_offset); }
330
hd_text_offset(void)331 word hd_text_offset(void)
332 { return hd_offset(text_offset); }
333
hd_request_status(void)334 void hd_request_status(void)
335 {
336 /* Set the header bit asking for a redraw? */
337 }
338