/*
save.c - save and restore routines
XRogue: Expeditions into the Dungeons of Doom
Copyright (C) 1991 Robert Pietkivitch
All rights reserved.
Based on "Advanced Rogue"
Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include "rogue.h"
#include "mach_dep.h"
extern char version[];
extern unsigned char encstr[];
extern int big_endian;
bool rs_write_int(FILE *savef, int c);
bool rs_read_int(FILE *inf, int *i);
bool rs_save_file(FILE *savef);
bool rs_restore_file(FILE *inf);
int md_unlink(char *file);
bool save_file(FILE *savef);
bool
save_game(void)
{
register FILE *savef;
register int c;
char buf[LINELEN];
/*
* get file name
*/
mpos = 0;
if (file_name[0] != '\0')
{
if (use_savedir)
msg("Save game? ");
else
msg("Save file (%s)? ", file_name);
do
{
c = wgetch(cw);
if (c == ESC) return(0);
} while (c != 'n' && c != 'N' && c != 'y' && c != 'Y');
mpos = 0;
if (c == 'y' || c == 'Y')
{
msg("File name: %s", file_name);
goto gotfile;
}
}
else
goto gotfile; /* must save to file restored from */
if (use_savedir) {
msg("");
return FALSE;
}
do
{
msg("File name: ");
mpos = 0;
buf[0] = '\0';
if (get_str(buf, msgw) == QUIT)
{
msg("");
return FALSE;
}
strcpy(file_name, buf);
gotfile:
if ((savef = fopen(file_name, "wb")) == NULL) {
msg(strerror(errno));
if (use_savedir)
return FALSE;
}
} while (savef == NULL);
msg("");
/*
* write out encrpyted file
*/
if (save_file(savef) == FALSE) {
fclose(savef);
msg("Cannot create save file.");
md_unlink(file_name);
return(FALSE);
}
fclose(savef);
return(TRUE);
}
/*
* automatically save a file. This is used if a HUP signal is recieved
*/
void
auto_save(int sig)
{
register FILE *savef = NULL;
register int i;
NOOP(sig);
for (i = 0; i < NSIG; i++)
signal(i, SIG_IGN);
if (file_name[0] != '\0' &&
pstats.s_hpt > 0 &&
((savef = fopen(file_name, "wb")) != NULL))
save_file(savef);
fclose(savef);
exit_game(EXIT_ENDWIN);
}
/*
* write the saved game on the file
*/
bool
save_file(FILE *savef)
{
int slines = LINES;
int scols = COLS;
bool ret = FALSE;
int endian = 0x01020304;
big_endian = ( *((char *)&endian) == 0x01 );
wmove(cw, LINES-1, 0);
draw(cw);
encwrite(version,strlen(version)+1,savef);
rs_write_int(savef,slines);
rs_write_int(savef,scols);
ret = rs_save_file(savef);
return(ret);
}
bool
restore(char *file, char *envp[])
{
FILE *inf;
extern char **environ;
char buf[LINELEN];
int endian = 0x01020304;
big_endian = ( *((char *)&endian) == 0x01 );
if (strcmp(file, "-r") == 0)
file = file_name;
if ((inf = fopen(file, "r")) == NULL)
{
if (use_savedir && errno == ENOENT)
{
/* No game in progress, so one will be started. */
return TRUE;
}
perror(file);
return FALSE;
}
fflush(stdout);
encread(buf, strlen(version) + 1, inf);
if (strcmp(buf, version) != 0)
{
printf("Sorry, saved game is out of date.\n");
return FALSE;
}
fflush(stdout);
rs_read_int(inf,&lines);
rs_read_int(inf,&cols);
initscr();
if (lines > LINES)
{
endwin();
printf("Sorry, original game was played on a screen with %d lines.\n",lines);
printf("Current screen only has %d lines. Unable to restore game\n",LINES);
return(FALSE);
}
if (cols > COLS)
{
endwin();
printf("Sorry, original game was played on a screen with %d columns.\n",cols);
printf("Current screen only has %d columns. Unable to restore game\n",COLS);
return(FALSE);
}
typeahead(-1);
setup();
cw = newwin(LINES, COLS, 0, 0);
mw = newwin(LINES, COLS, 0, 0);
hw = newwin(LINES, COLS, 0, 0);
msgw = newwin(4, cols, 0, 0);
keypad(cw, TRUE);
keypad(hw, TRUE);
if (rs_restore_file(inf) == FALSE)
{
endwin();
printf("Cannot restore file\n");
fclose(inf);
return(FALSE);
}
fclose(inf);
if (!wizard)
md_unlink(file);
mpos = 0;
environ = envp;
strcpy(file_name, file);
clearok(curscr, TRUE);
touchwin(cw);
wrefresh(cw);
msg("Welcome back! --More-- ");
wait_for(' ');
msg("");
playit();
/*NOTREACHED*/
return FALSE;
}
#define ENCWBSIZ 1024
/*
* perform an encrypted write
*/
long
encwrite(char *start, unsigned long size, FILE *outf)
{
register unsigned char *ep;
register int i = 0;
unsigned long num_written = 0;
char buf[ENCWBSIZ];
int ret;
ep = encstr;
while (size--)
{
buf[i++] = *start++ ^ *ep++;
if (*ep == '\0')
ep = encstr;
if (i == ENCWBSIZ || size == 0)
{
ret = (unsigned int) fwrite(buf, 1, i, outf);
if (ret > 0)
num_written += ret;
if (ret < i)
return(num_written);
i = 0;
}
}
return(num_written);
}
#define ENCRBSIZ 32768
/*
* perform an encrypted read
*/
long
encread(char *start, unsigned long size, FILE *inf)
{
register unsigned char *ep;
register int rd_siz;
register unsigned long total_read;
total_read = 0;
while (total_read < size) {
rd_siz = ENCRBSIZ;
rd_siz = ((size-total_read) > ENCRBSIZ) ? ENCRBSIZ : (size-total_read);
rd_siz = fread(&start[total_read], 1, rd_siz, inf);
if(rd_siz==0)
break;
total_read += rd_siz;
}
ep = encstr;
size = total_read;
while (size--)
{
*start++ ^= *ep++;
if (*ep == '\0')
ep = encstr;
}
return total_read;
}