diff options
Diffstat (limited to 'apps/plugins/zxbox/snapshot.c')
-rw-r--r-- | apps/plugins/zxbox/snapshot.c | 727 |
1 files changed, 727 insertions, 0 deletions
diff --git a/apps/plugins/zxbox/snapshot.c b/apps/plugins/zxbox/snapshot.c new file mode 100644 index 0000000000..e1a3552382 --- /dev/null +++ b/apps/plugins/zxbox/snapshot.c | |||
@@ -0,0 +1,727 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996-1998 Szeredi Miklos | ||
3 | * Email: mszeredi@inf.bme.hu | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. See the file COPYING. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include "misc.h" | ||
22 | #include "helpers.h" | ||
23 | #include "spperif.h" | ||
24 | #include "z80.h" | ||
25 | |||
26 | #include "snapshot.h" | ||
27 | #include "compr.h" | ||
28 | #include "interf.h" | ||
29 | |||
30 | #include "spconf.h" | ||
31 | |||
32 | #include "interf.h" | ||
33 | |||
34 | #include <stdio.h> | ||
35 | #include <stdlib.h> | ||
36 | /*#include <errno.h>*/ | ||
37 | /*#include "string.h"*/ | ||
38 | #include <sys/types.h> | ||
39 | |||
40 | #define COMPRESS_SAVE 1 | ||
41 | |||
42 | static char quick_snap_file[MAXFILENAME]; | ||
43 | static int qsnap_created = 0; | ||
44 | typedef struct { | ||
45 | int isfile; | ||
46 | /*FILE *fp;*/ | ||
47 | int fd; | ||
48 | |||
49 | unsigned len; | ||
50 | byte *at; | ||
51 | } SNFILE; | ||
52 | |||
53 | |||
54 | #define sngetc(snfp) ((snfp)->isfile ? getc((snfp)->fd) : snmgetc(snfp)) | ||
55 | |||
56 | static int snmgetc(SNFILE *snfp) | ||
57 | { | ||
58 | if(!snfp->len) return EOF; | ||
59 | snfp->len--; | ||
60 | return *snfp->at++; | ||
61 | } | ||
62 | |||
63 | static int snread(void *ptr, int size, SNFILE *snfp) | ||
64 | { | ||
65 | int i; | ||
66 | byte *dest; | ||
67 | |||
68 | if(snfp->isfile) /*return (int) fread(ptr, 1, (size_t) size, snfp->fp);*/ | ||
69 | return (int) rb->read( snfp->fd,ptr, (size_t) size); | ||
70 | |||
71 | dest = (byte *) ptr; | ||
72 | for(i = 0; snfp->len && size; i++, snfp->len--, size--) | ||
73 | *dest++ = *snfp->at++; | ||
74 | |||
75 | return i; | ||
76 | } | ||
77 | |||
78 | |||
79 | |||
80 | /* These structures are taken from 'spconv' by Henk de Groot */ | ||
81 | |||
82 | struct sna_s { | ||
83 | byte i; | ||
84 | byte lbk; | ||
85 | byte hbk; | ||
86 | byte ebk; | ||
87 | byte dbk; | ||
88 | byte cbk; | ||
89 | byte bbk; | ||
90 | byte fbk; | ||
91 | byte abk; | ||
92 | byte l; | ||
93 | byte h; | ||
94 | byte e; | ||
95 | byte d; | ||
96 | byte c; | ||
97 | byte b; | ||
98 | byte iyl; | ||
99 | byte iyh; | ||
100 | byte ixl; | ||
101 | byte ixh; | ||
102 | byte iff2; | ||
103 | byte r; | ||
104 | byte f; | ||
105 | byte a; | ||
106 | byte spl; | ||
107 | byte sph; | ||
108 | byte im; | ||
109 | byte border; | ||
110 | }; | ||
111 | |||
112 | #define sna_size 27 /* sizeof(struct sna_s)=27 */ | ||
113 | |||
114 | |||
115 | struct z80_1_s { | ||
116 | byte a; /*00*/ | ||
117 | byte f; /*01*/ | ||
118 | byte c; /*02*/ | ||
119 | byte b; /*03*/ | ||
120 | byte l; /*04*/ | ||
121 | byte h; /*05*/ | ||
122 | byte pcl; /*06*/ | ||
123 | byte pch; /*07*/ | ||
124 | byte spl; /*08*/ | ||
125 | byte sph; /*09*/ | ||
126 | byte i; /*0A*/ | ||
127 | byte r; /*0B*/ | ||
128 | byte data; /*0C*/ | ||
129 | byte e; /*0D*/ | ||
130 | byte d; /*0E*/ | ||
131 | byte cbk; /*0F*/ | ||
132 | byte bbk; /*10*/ | ||
133 | byte ebk; /*11*/ | ||
134 | byte dbk; /*12*/ | ||
135 | byte lbk; /*13*/ | ||
136 | byte hbk; /*14*/ | ||
137 | byte abk; /*15*/ | ||
138 | byte fbk; /*16*/ | ||
139 | byte iyl; /*17*/ | ||
140 | byte iyh; /*18*/ | ||
141 | byte ixl; /*19*/ | ||
142 | byte ixh; /*1A*/ | ||
143 | byte iff1; /*1B*/ | ||
144 | byte iff2; /*1C*/ | ||
145 | byte im; /*1D*/ | ||
146 | }; | ||
147 | |||
148 | #define z80_145_size 0x1e /* length of z80 V1.45 header */ | ||
149 | |||
150 | |||
151 | struct z80_2_s { | ||
152 | /* Extended 2.01 and 3.0 header, flagged with PC=0 */ | ||
153 | byte h2_len_l; /*1E*/ | ||
154 | byte h2_len_h; /*1F*/ | ||
155 | byte n_pcl; /*20*/ | ||
156 | byte n_pch; /*21*/ | ||
157 | byte hardware; /*22*/ | ||
158 | byte samram; /*23*/ | ||
159 | byte if1_paged; /*24*/ | ||
160 | byte r_ldir_emu; /*25*/ | ||
161 | byte last_out; /*26*/ | ||
162 | byte sound_reg[16]; /*27*/ | ||
163 | |||
164 | /* Continues with extended 3.0 header, but this part is not used anyway */ | ||
165 | }; | ||
166 | |||
167 | #define z80_201_ext_size 23 /* length of extended z80 V2.01 header */ | ||
168 | #define z80_300_ext_size 54 /* length of extended z80 V3.0 header */ | ||
169 | |||
170 | |||
171 | struct z80_page_s { | ||
172 | byte blklen_l; /*00*/ | ||
173 | byte blklen_h; /*01*/ | ||
174 | byte page_num; /*02*/ | ||
175 | }; | ||
176 | |||
177 | #define z80_pg_size 3 /* sizeof(struct z80_page_s)=3 */ | ||
178 | |||
179 | |||
180 | /*static FILE *savfp;*/ | ||
181 | static int savfd; | ||
182 | static int memptr; | ||
183 | |||
184 | int compr_read_byte(void) | ||
185 | { | ||
186 | if(memptr < 0x10000) return z80_proc.mem[memptr++]; | ||
187 | else return -1; | ||
188 | } | ||
189 | |||
190 | void compr_put_byte(int i) | ||
191 | { | ||
192 | putc(i, savfd); | ||
193 | } | ||
194 | |||
195 | |||
196 | #define STORE_NORMAL_REGS(head) \ | ||
197 | head.f = RF; /* F reg */ \ | ||
198 | head.a = RA; /* A reg */ \ | ||
199 | head.b = RB; /* B reg */ \ | ||
200 | head.c = RC; /* C reg */ \ | ||
201 | head.d = RD; /* D reg */ \ | ||
202 | head.e = RE; /* E reg */ \ | ||
203 | head.h = RH; /* H reg */ \ | ||
204 | head.l = RL; /* L reg */ \ | ||
205 | head.fbk = FBK; /* F' reg */ \ | ||
206 | head.abk = ABK; /* A' reg */ \ | ||
207 | head.bbk = BBK; /* B' reg */ \ | ||
208 | head.cbk = CBK; /* C' reg */ \ | ||
209 | head.dbk = DBK; /* D' reg */ \ | ||
210 | head.ebk = EBK; /* E' reg */ \ | ||
211 | head.hbk = HBK; /* H' reg */ \ | ||
212 | head.lbk = LBK; /* L' reg */ \ | ||
213 | head.iyh = YH; /* IY reg */ \ | ||
214 | head.iyl = YL; \ | ||
215 | head.ixh = XH; /* IX reg */ \ | ||
216 | head.ixl = XL | ||
217 | |||
218 | |||
219 | #define LOAD_NORMAL_REGS(head) \ | ||
220 | RF = head.f; /* F reg */ \ | ||
221 | RA = head.a; /* A reg */ \ | ||
222 | RB = head.b; /* B reg */ \ | ||
223 | RC = head.c; /* C reg */ \ | ||
224 | RD = head.d; /* D reg */ \ | ||
225 | RE = head.e; /* E reg */ \ | ||
226 | RH = head.h; /* H reg */ \ | ||
227 | RL = head.l; /* L reg */ \ | ||
228 | FBK = head.fbk; /* F' reg */ \ | ||
229 | ABK = head.abk; /* A' reg */ \ | ||
230 | BBK = head.bbk; /* B' reg */ \ | ||
231 | CBK = head.cbk; /* C' reg */ \ | ||
232 | DBK = head.dbk; /* D' reg */ \ | ||
233 | EBK = head.ebk; /* E' reg */ \ | ||
234 | HBK = head.hbk; /* H' reg */ \ | ||
235 | LBK = head.lbk; /* L' reg */ \ | ||
236 | YH = head.iyh; /* IY reg */ \ | ||
237 | YL = head.iyl; \ | ||
238 | XH = head.ixh; /* IX reg */ \ | ||
239 | XL = head.ixl | ||
240 | |||
241 | |||
242 | static void snsh_z80_save(int fd) | ||
243 | { | ||
244 | struct z80_1_s z80; | ||
245 | |||
246 | int to_comp = COMPRESS_SAVE; | ||
247 | |||
248 | STORE_NORMAL_REGS(z80); | ||
249 | |||
250 | z80.i = RI; /* I reg */ | ||
251 | z80.r = RR; /* R reg */ | ||
252 | |||
253 | z80.sph = SPH; /* SP reg */ | ||
254 | z80.spl = SPL; | ||
255 | z80.pch = PCH; /* PC reg */ | ||
256 | z80.pcl = PCL; | ||
257 | |||
258 | z80.iff1 = z80_proc.iff1; /* iff1 */ | ||
259 | z80.iff2 = z80_proc.iff2; /* iff2 */ | ||
260 | |||
261 | z80.im = (z80_proc.it_mode & 0x03) | 0x60; | ||
262 | /* | ||
263 | Bit 0-1: Interrupt mode (0, 1 or 2) | ||
264 | Bit 2 : 1=Issue 2 emulation | ||
265 | Bit 3 : 1=Double interrupt frequency | ||
266 | Bit 4-5: 1=High video synchronisation | ||
267 | 3=Low video synchronisation | ||
268 | 0,2=Normal | ||
269 | Bit 6-7: 0=Cursor/Protek/AGF joystick | ||
270 | 1=Kempston joystick | ||
271 | 2=Sinclair 1 joystick | ||
272 | 3=Sinclair 2 joystick | ||
273 | */ | ||
274 | |||
275 | z80.data = ((RR >> 7) & 0x01) | | ||
276 | ((z80_proc.ula_outport & 0x07) << 1) | | ||
277 | (to_comp ? 0x20 : 0); | ||
278 | /* | ||
279 | Bit 0 : Bit 7 of the R-register | ||
280 | Bit 1-3: Border colour | ||
281 | Bit 4 : 1=Basic SamRom switched in | ||
282 | Bit 5 : 1=Block of data is compressed | ||
283 | Bit 6-7: No meaning | ||
284 | */ | ||
285 | |||
286 | |||
287 | /*fwrite(&z80, z80_145_size, 1, fp);*/ | ||
288 | rb->write(fd,&z80,z80_145_size); | ||
289 | |||
290 | if(!to_comp) | ||
291 | /*fwrite(z80_proc.mem + 0x4000, 0xC000, 1, fp);*/ | ||
292 | rb->write(fd,z80_proc.mem + 0x4000,0xC000); | ||
293 | else { | ||
294 | memptr = 0x4000; | ||
295 | savfd = fd; | ||
296 | compr(); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | |||
301 | |||
302 | static void snsh_sna_save(int fd) | ||
303 | { | ||
304 | struct sna_s sna; | ||
305 | byte saves1, saves2; | ||
306 | |||
307 | STORE_NORMAL_REGS(sna); | ||
308 | |||
309 | sna.i = RI; /* I reg */ | ||
310 | sna.r = RR; /* R reg */ | ||
311 | |||
312 | sna.border = z80_proc.ula_outport & 0x07; | ||
313 | |||
314 | SP -= 2; | ||
315 | |||
316 | sna.sph = SPH; /* SP reg */ | ||
317 | sna.spl = SPL; | ||
318 | |||
319 | saves1 = z80_proc.mem[SP]; | ||
320 | saves2 = z80_proc.mem[(dbyte)(SP+1)]; | ||
321 | if(SP >= 0x4000) { | ||
322 | z80_proc.mem[SP] = PCL; | ||
323 | if(SP < 0xFFFF) z80_proc.mem[SP+1] = PCH; | ||
324 | } | ||
325 | |||
326 | sna.iff2 = z80_proc.iff2 ? 0xff : 0x00; /* iff2 */ | ||
327 | |||
328 | sna.im = z80_proc.it_mode & 0x03; | ||
329 | |||
330 | /*fwrite(&sna, sna_size, 1, fp); | ||
331 | fwrite(z80_proc.mem + 0x4000, 0xC000, 1, fp);*/ | ||
332 | rb->write(fd,&sna, sna_size); | ||
333 | rb->write(fd,z80_proc.mem + 0x4000, 0xC000); | ||
334 | |||
335 | if(SP > 0x4000) { | ||
336 | z80_proc.mem[SP] = saves1; | ||
337 | if(SP < 0xFFFF) z80_proc.mem[SP+1] = saves2; | ||
338 | } | ||
339 | |||
340 | SP += 2; | ||
341 | } | ||
342 | |||
343 | #define GET_DATA(c) { \ | ||
344 | if(!datalen) break; \ | ||
345 | c = sngetc(fp); \ | ||
346 | if(c == EOF) break; \ | ||
347 | if(datalen > 0) datalen--; \ | ||
348 | } | ||
349 | |||
350 | |||
351 | static void read_compressed_data(SNFILE *fp, byte *start, unsigned size, | ||
352 | long datalen) | ||
353 | { | ||
354 | int j; | ||
355 | int times, last_ed, ch; | ||
356 | byte *p, *end; | ||
357 | |||
358 | p = start; | ||
359 | end = start+size; | ||
360 | last_ed = 0; | ||
361 | while(p < end) { | ||
362 | GET_DATA(ch); | ||
363 | if(ch != 0xED) { | ||
364 | last_ed = 0; | ||
365 | *p++ = ch; | ||
366 | } | ||
367 | else { | ||
368 | if(last_ed) { | ||
369 | last_ed = 0; | ||
370 | p--; | ||
371 | GET_DATA(times); | ||
372 | if(times == 0) break; | ||
373 | |||
374 | GET_DATA(ch); | ||
375 | if(p + times > end) { | ||
376 | put_msg("Warning: Repeat parameter too large in snapshot"); | ||
377 | times = (int) ((long) end - (long) p); | ||
378 | } | ||
379 | for(j = 0; j < times; j++) *p++ = ch; | ||
380 | } | ||
381 | else { | ||
382 | last_ed = 1; | ||
383 | *p++ = 0xED; | ||
384 | } | ||
385 | } | ||
386 | } | ||
387 | |||
388 | if(datalen < 0) { | ||
389 | if(sngetc(fp) != 0 || sngetc(fp) != 0xED || | ||
390 | sngetc(fp) != 0xED || sngetc(fp) != 0) | ||
391 | put_msg("Warning: Illegal ending of snapshot"); | ||
392 | } | ||
393 | |||
394 | if(datalen > 0) { | ||
395 | while(datalen) { | ||
396 | if(sngetc(fp) == EOF) break; | ||
397 | datalen--; | ||
398 | } | ||
399 | put_msg("Warning: Page too long in snapshot"); | ||
400 | } | ||
401 | |||
402 | if(p < end) put_msg("Warning: Page too short in snapshot"); | ||
403 | } | ||
404 | |||
405 | static int read_header(void *p, int size, SNFILE *fp) | ||
406 | { | ||
407 | int res; | ||
408 | |||
409 | res = snread(p, size, fp); | ||
410 | if(res != size) { | ||
411 | put_msg("Error, End Of File in snapshot header"); | ||
412 | return 0; | ||
413 | } | ||
414 | return 1; | ||
415 | } | ||
416 | |||
417 | static int read_z80_page(SNFILE *fp) | ||
418 | { | ||
419 | struct z80_page_s page; | ||
420 | unsigned datalen; | ||
421 | unsigned pos = 0; | ||
422 | int validpage; | ||
423 | |||
424 | int res; | ||
425 | |||
426 | res = snread(&page, z80_pg_size, fp); | ||
427 | if(res == 0) return 0; | ||
428 | if(res != z80_pg_size) { | ||
429 | put_msg("Error, End Of File in page header"); | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | datalen = (page.blklen_h << 8) | page.blklen_l; | ||
434 | |||
435 | validpage = 1; | ||
436 | switch(page.page_num) { | ||
437 | case 4: | ||
438 | pos = 0x8000; | ||
439 | break; | ||
440 | |||
441 | case 5: | ||
442 | pos = 0xC000; | ||
443 | break; | ||
444 | |||
445 | case 8: | ||
446 | pos = 0x4000; | ||
447 | break; | ||
448 | |||
449 | default: | ||
450 | validpage = 0; | ||
451 | while(datalen) { | ||
452 | if(sngetc(fp) == EOF) { | ||
453 | put_msg("Warning: Page too short in snapshot"); | ||
454 | break; | ||
455 | } | ||
456 | datalen--; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | if(validpage) read_compressed_data(fp, z80_proc.mem+pos, 0x4000, | ||
461 | (long) datalen); | ||
462 | return 1; | ||
463 | } | ||
464 | |||
465 | |||
466 | static void snsh_z80_load(SNFILE *fp) | ||
467 | { | ||
468 | struct z80_1_s z80; | ||
469 | |||
470 | if(!read_header(&z80, z80_145_size, fp)) return; | ||
471 | if(z80.pch == 0 && z80.pcl == 0) { | ||
472 | struct z80_2_s z80_2; | ||
473 | int ext_size, rem; | ||
474 | if(!read_header(&z80_2, 2, fp)) return; | ||
475 | ext_size = z80_2.h2_len_l | (z80_2.h2_len_h << 8); | ||
476 | if(ext_size < z80_201_ext_size) { | ||
477 | put_msg("Error in Z80 header"); | ||
478 | return; | ||
479 | } | ||
480 | if(!read_header(&z80_2.n_pcl, z80_201_ext_size, fp)) return; | ||
481 | rem = ext_size - z80_201_ext_size; | ||
482 | for(; rem; rem--) sngetc(fp); | ||
483 | |||
484 | if(z80_2.hardware >= 3 && (ext_size == z80_201_ext_size || | ||
485 | z80_2.hardware >= 4)) { | ||
486 | put_msg("Can't load non 48k snapshot"); | ||
487 | return; | ||
488 | } | ||
489 | if(z80_2.if1_paged) { | ||
490 | put_msg("Can't load snapshot: IF1 roma paged in"); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | PCH = z80_2.n_pch; | ||
495 | PCL = z80_2.n_pcl; | ||
496 | |||
497 | while(read_z80_page(fp)); | ||
498 | } | ||
499 | else { | ||
500 | if(z80.data == 0xFF) z80.data = 1; | ||
501 | if(z80.data & 0x20) | ||
502 | read_compressed_data(fp, z80_proc.mem + 0x4000, 0xC000, -1); | ||
503 | else { | ||
504 | if(snread(z80_proc.mem + 0x4000, 0xC000, fp) != 0xC000) | ||
505 | put_msg("Warning: Snapshot file too short (z80)"); | ||
506 | else if(sngetc(fp) != EOF) | ||
507 | put_msg("Warning: Snapshot file too long"); | ||
508 | } | ||
509 | |||
510 | PCH = z80.pch; | ||
511 | PCL = z80.pcl; | ||
512 | } | ||
513 | |||
514 | |||
515 | LOAD_NORMAL_REGS(z80); | ||
516 | |||
517 | RI = z80.i; /* I reg */ | ||
518 | RR = (z80.r & 0x7F) | ((z80.data & 0x01) << 7); /* R reg */ | ||
519 | |||
520 | SPH = z80.sph; /* SP reg */ | ||
521 | SPL = z80.spl; | ||
522 | |||
523 | z80_proc.ula_outport = (z80_proc.ula_outport & ~(0x07)) | | ||
524 | ((z80.data >> 1) & 0x07); | ||
525 | |||
526 | /* | ||
527 | Bit 0 : Bit 7 of the R-register | ||
528 | Bit 1-3: Border colour | ||
529 | Bit 4 : 1=Basic SamRom switched in | ||
530 | Bit 5 : 1=Block of data is compressed | ||
531 | Bit 6-7: No meaning | ||
532 | */ | ||
533 | |||
534 | z80_proc.iff1 = z80.iff1 ? 1 : 0; | ||
535 | z80_proc.iff2 = z80.iff2 ? 1 : 0; | ||
536 | |||
537 | z80_proc.it_mode = z80.im & 0x03; | ||
538 | |||
539 | /* | ||
540 | Bit 0-1: Interrupt mode (0, 1 or 2) | ||
541 | Bit 2 : 1=Issue 2 emulation | ||
542 | Bit 3 : 1=Double interrupt frequency | ||
543 | Bit 4-5: 1=High video synchronisation | ||
544 | 3=Low video synchronisation | ||
545 | 0,2=Normal | ||
546 | Bit 6-7: 0=Cursor/Protek/AGF joystick | ||
547 | 1=Kempston joystick | ||
548 | 2=Sinclair 1 joystick | ||
549 | 3=Sinclair 2 joystick | ||
550 | */ | ||
551 | |||
552 | z80_proc.haltstate = 0; | ||
553 | |||
554 | sp_init_screen_mark(); | ||
555 | } | ||
556 | |||
557 | static void snsh_sna_load(SNFILE *fp) | ||
558 | { | ||
559 | struct sna_s sna; | ||
560 | |||
561 | if(!read_header(&sna, sna_size, fp)) return; | ||
562 | |||
563 | if(snread(z80_proc.mem+0x4000, 0xC000, fp) != 0xC000) | ||
564 | put_msg("Warning: Snapshot file too short (sna)"); | ||
565 | else if(sngetc(fp) != EOF) | ||
566 | put_msg("Warning: Snapshot file too long"); | ||
567 | |||
568 | LOAD_NORMAL_REGS(sna); | ||
569 | |||
570 | RI = sna.i; /* I reg */ | ||
571 | RR = sna.r; /* R reg */ | ||
572 | |||
573 | z80_proc.ula_outport = (z80_proc.ula_outport & ~(0x07)) | | ||
574 | (sna.border & 0x07); | ||
575 | |||
576 | SPH = sna.sph; /* SP reg */ | ||
577 | SPL = sna.spl; | ||
578 | |||
579 | PCL = z80_proc.mem[SP]; | ||
580 | if(SP >= 0x4000) z80_proc.mem[SP] = 0; | ||
581 | SP++; | ||
582 | PCH = z80_proc.mem[SP]; | ||
583 | if(SP >= 0x4000) z80_proc.mem[SP] = 0; | ||
584 | SP++; | ||
585 | |||
586 | z80_proc.iff1 = z80_proc.iff2 = sna.iff2 ? 1 : 0; | ||
587 | z80_proc.it_mode = sna.im & 0x03; | ||
588 | |||
589 | z80_proc.haltstate = 0; | ||
590 | |||
591 | sp_init_screen_mark(); | ||
592 | } | ||
593 | /* | ||
594 | static void cleanup_qsnap(void) | ||
595 | { | ||
596 | if(qsnap_created) rb->remove(quick_snap_file); | ||
597 | } | ||
598 | */ | ||
599 | static void save_snapshot_file_type(char *name, int type) | ||
600 | { | ||
601 | /*FILE *snsh;*/ | ||
602 | int snsh; | ||
603 | snsh = rb->open(name, O_WRONLY); | ||
604 | if(snsh < 0) { | ||
605 | snsh = rb->creat(name, O_WRONLY); | ||
606 | /* sprintf(msgbuf, "Could not open snapshot file `%s', %s", | ||
607 | name, strerror(errno));*/ | ||
608 | if(snsh < 0) { | ||
609 | put_msg("Could not create snapshot file"); | ||
610 | return; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | if(type == SN_SNA) snsh_sna_save(snsh); | ||
615 | else if(type == SN_Z80) snsh_z80_save(snsh); | ||
616 | |||
617 | rb->close(snsh); | ||
618 | } | ||
619 | |||
620 | void save_snapshot_file(char *name) | ||
621 | { | ||
622 | int type; | ||
623 | |||
624 | rb->strncpy(filenamebuf, name, MAXFILENAME-10); | ||
625 | filenamebuf[MAXFILENAME-10] = '\0'; | ||
626 | |||
627 | type = SN_Z80; | ||
628 | if(check_ext(filenamebuf, "z80")) type = SN_Z80; | ||
629 | else if(check_ext(filenamebuf, "sna")) type = SN_SNA; | ||
630 | else { | ||
631 | add_extension(filenamebuf, "z80"); | ||
632 | type = SN_Z80; | ||
633 | } | ||
634 | |||
635 | save_snapshot_file_type(filenamebuf, type); | ||
636 | |||
637 | /* sprintf(msgbuf, "Saved snapshot to file %s", filenamebuf); | ||
638 | put_msg(msgbuf);*/ | ||
639 | } | ||
640 | |||
641 | void save_quick_snapshot(void) | ||
642 | { | ||
643 | /* if(!qsnap_created) { | ||
644 | if(tmpnam(quick_snap_file) == NULL) { | ||
645 | put_msg("Could not create temporary file for quick snapshot"); | ||
646 | return; | ||
647 | } | ||
648 | qsnap_created = 1; | ||
649 | atexit(cleanup_qsnap); | ||
650 | } | ||
651 | save_snapshot_file_type(quick_snap_file, SN_Z80);*/ | ||
652 | } | ||
653 | |||
654 | void save_snapshot(void) | ||
655 | { | ||
656 | char name[MAXFILENAME]; | ||
657 | name[0]='/'; | ||
658 | name[1]='\0'; | ||
659 | put_msg("Enter name of snapshot file to save:"); | ||
660 | if (!rb->kbd_input((char*)&name, sizeof name)) | ||
661 | save_snapshot_file(&name[0]); | ||
662 | } | ||
663 | |||
664 | |||
665 | void load_snapshot_file_type(char *name, int type) | ||
666 | { | ||
667 | int filetype = FT_SNAPSHOT; | ||
668 | /*FILE *snsh;*/ | ||
669 | int snsh; | ||
670 | SNFILE snfil; | ||
671 | |||
672 | rb->strncpy(filenamebuf, name, MAXFILENAME-10); | ||
673 | filenamebuf[MAXFILENAME-10] = '\0'; | ||
674 | |||
675 | spcf_find_file_type(filenamebuf, &filetype, &type); | ||
676 | if(type < 0) type = SN_Z80; | ||
677 | |||
678 | snsh = rb->open(filenamebuf, O_RDONLY); | ||
679 | if(snsh < 0) { | ||
680 | #ifndef USE_GRAY | ||
681 | rb->splash(HZ,true, "Could not open snapshot file `%s'",filenamebuf); | ||
682 | #endif | ||
683 | return; | ||
684 | } | ||
685 | |||
686 | snfil.isfile = 1; | ||
687 | snfil.fd = snsh; | ||
688 | |||
689 | if(type == SN_SNA) snsh_sna_load(&snfil); | ||
690 | else if(type == SN_Z80) snsh_z80_load(&snfil); | ||
691 | |||
692 | rb->close(snsh); | ||
693 | } | ||
694 | |||
695 | void snsh_z80_load_intern(byte *p, unsigned len) | ||
696 | { | ||
697 | SNFILE snfil; | ||
698 | |||
699 | snfil.isfile = 0; | ||
700 | snfil.at = p; | ||
701 | snfil.len = len; | ||
702 | |||
703 | snsh_z80_load(&snfil); | ||
704 | } | ||
705 | |||
706 | void load_quick_snapshot(void) | ||
707 | { | ||
708 | if(!qsnap_created) { | ||
709 | put_msg("No quick snapshot saved yet"); | ||
710 | return; | ||
711 | } | ||
712 | load_snapshot_file_type(quick_snap_file, SN_Z80); | ||
713 | } | ||
714 | |||
715 | |||
716 | void load_snapshot(void) | ||
717 | { | ||
718 | char *name; | ||
719 | |||
720 | put_msg("Enter name of snapshot file to load:"); | ||
721 | |||
722 | name = spif_get_filename(); | ||
723 | if(name == NULL) return; | ||
724 | |||
725 | load_snapshot_file_type(name, -1); | ||
726 | } | ||
727 | |||