1 /*
2 File
3 */
4
5 #include "file.h"
6
7 #include "config.h"
8 #include "console.h"
9 #include "head.h"
10 #include "interp.h"
11 #include "jump.h"
12 #include "os.h"
13 #include "page.h"
14 #include "pc.h"
15 #include "mem.h"
16 #include "shared.h"
17 #include "stack.h"
18 #include "stop.h"
19 #include "support.h"
20 #include "var.h"
21 #include "wio.h"
22
23 #define COOKIE "IDFZ" /* Cookie to indicate new compressed save file */
24
25 bool game_saved = 1;
26
filename(void)27 static char *filename(void)
28 {
29 static char name[257];
30 getline((byte *) "Filename: ", name, sizeof(name) - 1);
31 return name;
32 }
33
put_word(filep save_file,word number)34 static bool put_word(filep save_file, word number)
35 {
36 byte c[2];
37 wr_word_ptr(c, number);
38 return os_write(c, sizeof(byte), 2, save_file) != 2;
39 }
40
ld_word(filep save_file,word * number)41 static bool ld_word(filep save_file, word *number)
42 {
43 byte c[2];
44 int res = os_read(c, sizeof(byte), 2, save_file);
45 *number = rd_word_ptr(c);
46 return res != 2;
47 }
48
save_byte(byte b,filep file)49 static bool save_byte(byte b, filep file)
50 {
51 return os_write(&b, sizeof(byte), 1, file) != 1;
52 }
53
save_block(word page,filep file)54 static bool save_block(word page, filep file)
55 {
56 int i = 0;
57 bool err = 0;
58 byte *p = pg_fetch(page);
59
60 hd_flip(page, p);
61 while(i < BLOCK_SIZE && !err)
62 {
63 err = save_byte(p[i], file);
64 if(p[i++] == 0 && !err)
65 {
66 int c = 1;
67 while(i < BLOCK_SIZE && c < 256 && p[i] == 0) { ++c; ++i; }
68 err = save_byte(c - 1, file);
69 }
70 }
71 hd_flip(page, p);
72 return err;
73 }
74
save_game(void)75 void save_game(void)
76 {
77 filep save_file;
78 bool err = 0;
79 int i;
80 char *name;
81
82 game_saved = 0;
83 name = filename();
84 os_patch_save(name);
85 if((save_file = os_open_write(name)) == (filep) 0)
86 {
87 if(!hd_plus())
88 ret_value(0);
89 else
90 store((word) 0);
91 return;
92 }
93 err = os_write(COOKIE, 1, sizeof(COOKIE), save_file) != sizeof(COOKIE);
94 for(i = 0; i < hd_save_blocks() && !err; ++i)
95 err = save_block(i, save_file);
96
97 /* Save the Stack, Stack Pointers & Program Counter */
98
99 err = err || put_word(save_file, stk_encode_stk());
100 err = err || put_word(save_file, stk_encode_var());
101 for(i = STACK_SIZE - stk_encode_stk(); i < STACK_SIZE && !err; ++i)
102 err = put_word(save_file, stk_get_abs(i));
103 err = err || put_word(save_file, pc_page());
104 err = err || put_word(save_file, pc_offset());
105
106 err = err || os_close(save_file);
107 game_saved = !err;
108 if(!hd_plus())
109 {
110 ret_value(!err);
111 }
112 else
113 {
114 store(!err);
115 }
116 }
117
find_cookie(filep file)118 static bool find_cookie(filep file)
119 {
120 char b[sizeof(COOKIE)];
121 if(os_read(b, 1, sizeof(COOKIE), file) == sizeof(COOKIE)
122 && os_strcmp(b, COOKIE) == 0)
123 {
124 return 1;
125 }
126 else
127 {
128 os_seek_fore(file, 0L);
129 return 0;
130 }
131 }
132
load_byte(filep file,byte * b)133 static bool load_byte(filep file, byte *b)
134 {
135 return os_read(b, sizeof(byte), 1, file) != 1;
136 }
137
load_block(word page,filep file)138 static bool load_block(word page, filep file)
139 {
140 bool err = 0;
141 byte *p = pg_fetch(page);
142 int i = 0;
143 while(i < BLOCK_SIZE && !err)
144 {
145 err = load_byte(file, &p[i]);
146 if(!err && p[i++] == 0)
147 {
148 byte c;
149 err = load_byte(file, &c) || i + c > 512;
150 if(!err)
151 {
152 os_mset((char *) &p[i], c, 0);
153 i += c;
154 }
155 }
156 }
157 if(!err)
158 hd_flip(page, p);
159 return err;
160 }
161
restore_game(void)162 void restore_game(void)
163 {
164 filep save_file;
165 bool err;
166 word i;
167 word temp;
168 word blocks = hd_save_blocks();
169 int high = hd_height();
170 int wide = hd_width();
171 char *name;
172
173 game_saved = 0;
174 name = filename();
175 os_patch_save(name);
176 if((save_file = os_open_read(name)) == (filep) 0)
177 {
178 if(!hd_plus())
179 ret_value(0);
180 else
181 store((word) 0);
182 return;
183 }
184 err = !find_cookie(save_file);
185 for(i = 0; i < blocks && !err; ++i)
186 err = load_block(i, save_file);
187 hd_set_size(high, wide);
188
189 err = err || ld_word(save_file, &temp);
190 stk_decode_stk(temp);
191 err = err || ld_word(save_file, &temp);
192 stk_decode_var(temp);
193 for(i = STACK_SIZE - stk_encode_stk(); i < STACK_SIZE && !err; ++i)
194 {
195 err = ld_word(save_file, &temp);
196 stk_set_abs(i, temp);
197 }
198 {
199 word page, offset;
200 err = err || ld_word(save_file, &page);
201 err = err || ld_word(save_file, &offset);
202 set_pc(page, offset);
203 }
204 /* Should be at EOF now, or have the GAME: cookie */
205 if(!err)
206 {
207 char test[5];
208 int found = os_read(test, sizeof(char), 5, save_file);
209 switch(found)
210 {
211 case 0:
212 break; /* EOF */
213 case 5:
214 if(test[0] == 'G'
215 && test[1] == 'A'
216 && test[2] == 'M'
217 && test[3] == 'E'
218 && test[4] == ':')
219 #if 0
220 /* This would stop users renaming the story file ... bad */
221 #endif
222 break; /* Cookie */
223 default:
224 err = 1;
225 }
226 }
227
228 err = os_close(save_file) || err;
229
230
231 game_saved = !err;
232 if(!err)
233 {
234 init_interpreter(0);
235 if(!hd_plus())
236 ret_value(1);
237 else
238 store(2);
239 }
240 else
241 {
242 display((byte *) "Wrong Game or Version ...\n");
243 quit();
244 }
245 }
246
247
248 /*
249 ** Scripting Routines and Variables.
250 */
251
252 static filep script_file = (filep) 0;
253
init_script(void)254 void init_script(void)
255 {
256 extern bool script_on;
257
258 script_on = 0;
259 }
260
open_script(void)261 bool open_script(void)
262 {
263 script_file = os_open_append(filename());
264 return script_file != 0;
265 }
266
close_script(void)267 void close_script(void)
268 {
269 extern filep script_file;
270
271 if(script_file)
272 {
273 if(os_close(script_file))
274 display((byte *) "Cannot Close Script File\n");
275 script_file = 0;
276 }
277 }
278
script_char(word c)279 void script_char(word c)
280 {
281 extern filep script_file;
282 extern bool disable_script;
283 extern bool script_on;
284
285 if(1 || !hd_plus())
286 {
287 if(script_on && !hd_get_script())
288 {
289 script_on = 0;
290 hd_set_script(0);
291 close_script();
292 return;
293 }
294 if(!script_on && hd_get_script())
295 {
296 script_on = 1;
297 if(open_script())
298 hd_set_script(1);
299 else
300 script_on = 0;
301 }
302 }
303
304 if(script_on && script_file && !disable_script && kind(c) == 0)
305 {
306 byte b = c;
307 os_write(&b, sizeof(b), 1, script_file);
308 }
309 }
310
311
312