/*
* save and restore routines
*
* @(#)save.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* All rights reserved.
*
* Based on "Rogue: Exploring the Dungeons of Doom"
* Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include "rogue.h"
#include "rogue.ext"
EXTCHAR version[];
bool dosave(void);
void save_file(FILE *savef);
typedef struct stat STAT;
STAT sbuf;
/*
* ignore:
* Ignore ALL signals possible
*/
void
ignore(void)
{
md_ignoreallsignals();
}
/*
* save_game:
* Save the current game
*/
bool
save_game(void)
{
reg FILE *savef;
reg int c;
char buf[LINLEN];
mpos = 0;
if (file_name[0] != '\0') {
if (use_savedir)
msg("Save game? (y/n) ");
else
msg("Save file (%s)? ", file_name);
do {
c = wgetch(cw);
if(c == ESCAPE) {
msg("");
return FALSE;
}
} while (c != 'n' && c != 'y');
mpos = 0;
if (c == 'y')
goto gotfile;
}
if (use_savedir) {
msg("");
return FALSE;
}
msg("File name: ");
mpos = 0;
buf[0] = '\0';
if (get_str(buf, cw) == QUIT) {
msg("");
return FALSE;
}
msg("");
strcpy(file_name, buf);
gotfile:
c = dosave(); /* try to save this game */
if (c == FALSE)
msg("Could not save game to file %s", file_name);
return c;
}
/*
* auto_save:
* Automatically save a game
*/
void
auto_save(int a)
{
dosave(); /* save this game */
byebye(1); /* so long for now */
}
/*
* game_err:
* When an error occurs. Set error flag and save game.
*/
void
game_err(int a)
{
int ok;
ok = dosave(); /* try to save this game */
clear();
refresh();
endwin();
printf("\nInternal error !!!\n\nYour game was ");
if (ok)
printf("saved.");
else
printf("NOT saveable.");
fflush(stdout);
#ifdef SIGIOT
signal(SIGIOT, SIG_DFL); /* allow core dump signal */
#endif
abort(); /* cause core dump */
byebye(3);
}
/*
* dosave:
* Save the game. UID/GID no longer get reset here.
*/
bool
dosave(void)
{
FILE *savef;
ignore();
umask(022);
if (file_name[0] != '\0') {
if ((savef = fopen(file_name,"w")) != NULL)
{
save_file(savef);
return TRUE;
}
}
return FALSE;
}
/*
* save_file:
* Do the actual save of this game to a file
*/
void
save_file(FILE *savef)
{
int slines = LINES;
int scols = COLS;
#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
_djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
#endif
encwrite(version,strlen(version)+1,savef);
encwrite(&slines,sizeof(slines),savef);
encwrite(&scols,sizeof(scols),savef);
msg("");
rs_save_file(savef);
fclose(savef);
md_onsignal_exit();
wclear(cw);
draw(cw);
}
/*
* restore:
* Restore a saved game from a file
*/
bool
restore(char *file, char **envp)
{
register int pid;
int ret_status;
#ifndef _AIX
extern char **environ;
#endif
#ifdef __DJGPP__ /* st_ino w/ DJGPP under WinXP broken */
_djstat_flags |= _STAT_INODE; /* so turn off computing it for now */
#endif
FILE *inf;
char buf[LINLEN];
STAT sbuf2;
int slines, scols;
if ((inf = fopen(file, "r")) == NULL) {
if (use_savedir && errno == ENOENT)
return TRUE;
else {
printf("Cannot read save game %s\n",file);
return FALSE;
}
}
encread(buf, strlen(version) + 1, inf);
if (strcmp(buf, version) != 0) {
printf("Sorry, saved game version is out of date.\n");
return FALSE;
}
stat(file, &sbuf2);
encread(&slines,sizeof(slines),inf);
encread(&scols,sizeof(scols),inf);
/*
* we do not close the file so that we will have a hold of the
* inode for as long as possible
*/
#ifdef __INTERIX
setenv("TERM","interix");
#endif
initscr();
if (slines > LINES)
{
endwin();
printf("Sorry, original game was played on a screen with %d lines.\n",slines);
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
return(FALSE);
}
if (scols > COLS)
{
endwin();
printf("Sorry, original game was played on a screen with %d columns.\n", scols);
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
return(FALSE);
}
cw = newwin(LINES, COLS, 0, 0);
mw = newwin(LINES, COLS, 0, 0);
hw = newwin(LINES, COLS, 0, 0);
keypad(cw, 1);
mpos = 0;
mvwprintw(cw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime));
/* defeat multiple restarting from the same place */
if (!wizard)
{
if (sbuf2.st_nlink != 1)
{
endwin();
printf("Cannot restore from a linked file\n");
return FALSE;
}
}
if (rs_restore_file(inf) == FALSE)
{
endwin();
printf("Cannot restore file\n");
return(FALSE);
}
#if defined(__CYGWIN__) || defined(__DJGPP__)
fclose(inf);
#endif
if (!wizard)
{
if (md_unlink_open_file(file, inf) < 0)
{
endwin();
printf("Cannot unlink file\n");
return FALSE;
}
}
if (him->s_hpt <= 0) {
endwin();
printf("This character is already dead.\n");
return FALSE;
}
environ = envp;
strcpy(file_name, file);
setup();
restscr(cw);
md_srandom(md_random_seed());
playit();
}