static int save_restore( const char *file_name, int flag ) { FILE *tfp = NULL; #if defined BUFFER_FILES char tfpbuffer[BUFSIZ]; #endif int scripting_flag = 0, status = 0; #if !defined(USE_QUETZAL) zword_t zw; int little_endian = 0; /* Find out if we are big-endian */ zw = 0x0001; if ( *( zbyte_t * ) & zw ) { /* We are little-endian, like an Intel 80x86 chip. */ little_endian = 1; } #endif /* Open the save file and disable scripting */ if ( flag == GAME_SAVE || flag == GAME_RESTORE ) { if ( ( tfp = fopen( file_name, ( flag == GAME_SAVE ) ? "wb" : "rb" ) ) == NULL ) { output_line( "Cannot open SAVE file" ); return ( 1 ); } #if defined BUFFER_FILES setbuf( tfp, tfpbuffer ); #endif scripting_flag = get_word( H_FLAGS ) & SCRIPTING_FLAG; set_word( H_FLAGS, get_word( H_FLAGS ) & ( ~SCRIPTING_FLAG ) ); } #if defined(USE_QUETZAL) if ( flag == GAME_SAVE ) { status = !save_quetzal( tfp, gfp ); } else if ( flag == GAME_RESTORE ) { status = !restore_quetzal( tfp, gfp ); } else { #endif /* defined(USE_QUETZAL) */ /* Push PC, FP, version and store SP in special location */ stack[--sp] = ( zword_t ) ( pc / PAGE_SIZE ); stack[--sp] = ( zword_t ) ( pc % PAGE_SIZE ); stack[--sp] = fp; stack[--sp] = h_version; stack[0] = sp; /* Save or restore stack */ #if !defined(USE_QUETZAL) if ( flag == GAME_SAVE ) { if ( little_endian ) swap_bytes( stack, sizeof ( stack ) ); if ( status == 0 && fwrite( stack, sizeof ( stack ), 1, tfp ) != 1 ) status = 1; if ( little_endian ) swap_bytes( stack, sizeof ( stack ) ); } else if ( flag == GAME_RESTORE ) { if ( little_endian ) swap_bytes( stack, sizeof ( stack ) ); if ( status == 0 && fread( stack, sizeof ( stack ), 1, tfp ) != 1 ) status = 1; if ( little_endian ) swap_bytes( stack, sizeof ( stack ) ); } else #endif /* !defined(USE_QUETZAL) */ { if ( flag == UNDO_SAVE ) { memmove( undo_stack, stack, sizeof ( stack ) ); } else /* if (flag == UNDO_RESTORE) */ { memmove( stack, undo_stack, sizeof ( stack ) ); } } /* Restore SP, check version, restore FP and PC */ sp = stack[0]; if ( stack[sp++] != h_version ) { fatal( "save_restore(): Wrong game or version" ); } fp = stack[sp++]; pc = stack[sp++]; pc += ( unsigned long ) stack[sp++] * PAGE_SIZE; /* Save or restore writeable game data area */ #if !defined(USE_QUETZAL) if ( flag == GAME_SAVE ) { if ( status == 0 && fwrite( datap, h_restart_size, 1, tfp ) != 1 ) status = 1; } else if ( flag == GAME_RESTORE ) { if ( status == 0 && fread( datap, h_restart_size, 1, tfp ) != 1 ) status = 1; } else #endif /* !defined(USE_QUETZAL) */ { if ( flag == UNDO_SAVE ) { memmove( undo_datap, datap, h_restart_size ); } else /* if (flag == UNDO_RESTORE) */ { memmove( datap, undo_datap, h_restart_size ); } } #if defined(USE_QUETZAL) } #endif /* defined(USE_QUETZAL) */ /* Close the save file and restore scripting */ if ( flag == GAME_SAVE ) { fclose( tfp ); if ( scripting_flag ) { set_word( H_FLAGS, get_word( H_FLAGS ) | SCRIPTING_FLAG ); } } else if ( flag == GAME_RESTORE ) { fclose( tfp ); restart_screen( ); restart_interp( scripting_flag ); } /* Handle read or write errors */ if ( status ) { if ( flag == GAME_SAVE ) { output_line( "Write to SAVE file failed" ); remove( file_name ); } else { fatal( "save_restore(): Read from SAVE file failed" ); } } return ( status ); } /* save_restore */
void z_restore (void) { FILE *gfp; zword success = 0; if (zargc != 0) { /* Get the file name */ /* Open auxilary file */ if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == NULL) goto finished; /* Load auxilary file */ success = fread (zmp + zargs[0], 1, zargs[1], gfp); /* Close auxilary file */ fclose (gfp); } else { long pc; zword release; zword addr; int i; /* Open game file */ if ((gfp = frotzopenprompt(FILE_RESTORE)) == NULL) goto finished; if (f_setup.save_quetzal) { success = restore_quetzal (gfp, story_fp, blorb_ofs); } else { /* Load game file */ release = (unsigned) fgetc (gfp) << 8; release |= fgetc (gfp); (void) fgetc (gfp); (void) fgetc (gfp); /* Check the release number */ if (release == h_release) { pc = (long) fgetc (gfp) << 16; pc |= (unsigned) fgetc (gfp) << 8; pc |= fgetc (gfp); SET_PC (pc); sp = stack + (fgetc (gfp) << 8); sp += fgetc (gfp); fp = stack + (fgetc (gfp) << 8); fp += fgetc (gfp); for (i = (int) (sp - stack); i < STACK_SIZE; i++) { stack[i] = (unsigned) fgetc (gfp) << 8; stack[i] |= fgetc (gfp); } fseek (story_fp, blorb_ofs, SEEK_SET); for (addr = 0; addr < h_dynamic_size; addr++) { int skip = fgetc (gfp); for (i = 0; i < skip; i++) zmp[addr++] = fgetc (story_fp); zmp[addr] = fgetc (gfp); (void) fgetc (story_fp); } /* Check for errors */ if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size) success = -1; else /* Success */ success = 2; } else print_string ("Invalid save file\n"); } if ((short) success >= 0) { /* Close game file */ fclose (gfp); if ((short) success > 0) { zbyte old_screen_rows; zbyte old_screen_cols; /* In V3, reset the upper window. */ if (h_version == V3) split_window (0); LOW_BYTE (H_SCREEN_ROWS, old_screen_rows); LOW_BYTE (H_SCREEN_COLS, old_screen_cols); /* Reload cached header fields. */ restart_header (); /* * Since QUETZAL files may be saved on many different machines, * the screen sizes may vary a lot. Erasing the status window * seems to cover up most of the resulting badness. */ if (h_version > V3 && h_version != V6 && (h_screen_rows != old_screen_rows || h_screen_cols != old_screen_cols)) erase_window (1); } } else os_fatal ("Error reading save file"); } finished: if (h_version <= V3) branch (success); else store (success); }/* z_restore */