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