Mercurial > hg > early-roguelike
diff arogue7/save.c @ 125:adfa37e67084
Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Fri, 08 May 2015 15:24:40 -0400 |
parents | |
children | b786053d2f37 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arogue7/save.c Fri May 08 15:24:40 2015 -0400 @@ -0,0 +1,302 @@ +/* + * save.c - save and restore routines + * + * Advanced Rogue + * Copyright (C) 1984, 1985, 1986 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. + */ + +/* + * save and restore routines + * + */ + +#include "curses.h" +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <signal.h> +#include "rogue.h" +#include <fcntl.h> +#include <errno.h> +#include "mach_dep.h" +#ifdef PC7300 +#include "sys/window.h" +extern struct uwdata wdata; +#endif + +#if u370 || uts +#define ENCREAD(b,n,fd) read(fd,b,n) +#define ENCWRITE(b,n,fd) write(fd,b,n) +#endif +#ifndef ENCREAD +#define ENCREAD encread +#define ENCWRITE encwrite +#endif + +typedef struct stat STAT; + +extern char version[], encstr[]; +/* extern bool _endwin; */ +extern int errno; + +STAT sbuf; + +bool +save_game() +{ + register int savefd; + register int c; + char buf[LINELEN]; + + /* + * get file name + */ + mpos = 0; + if (file_name[0] != '\0') + { + msg("Save file (%s)? ", file_name); + do + { + c = readchar(); + if (c == ESCAPE) 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; + } + } + + do + { + msg("File name: "); + mpos = 0; + buf[0] = '\0'; + if (get_str(buf, msgw) == QUIT) + { + msg(""); + return FALSE; + } + strcpy(file_name, buf); +gotfile: + if ((savefd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC,0666)) < 0) + msg(strerror(errno)); /* fake perror() */ + } while (savefd < 0); + + /* + * write out encrpyted file (after a stat) + */ + if (save_file(savefd) == FALSE) { + msg("Cannot create save file."); + unlink(file_name); + return(FALSE); + } + else return(TRUE); +} + +/* + * automatically save a file. This is used if a HUP signal is + * recieved + */ +void +auto_save(sig) +int sig; +{ + register int savefd; + register int i; + + for (i = 0; i < NSIG; i++) + signal(i, SIG_IGN); + if (file_name[0] != '\0' && + pstats.s_hpt > 0 && + (savefd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC, 0600)) >= 0) + save_file(savefd); + endwin(); +#ifdef PC7300 + endhardwin(); +#endif + exit(1); +} + +/* + * write the saved game on the file + */ +bool +save_file(savefd) +register int savefd; +{ + register unsigned num_to_write, num_written; + FILE *savef; + int ret; + + wmove(cw, lines-1, 0); + draw(cw); + lseek(savefd, 0L, 0); + fstat(savefd, &sbuf); + num_to_write = strlen(version) + 1; + num_written = ENCWRITE(version, num_to_write, savefd); + sprintf(prbuf,"%d x %d\n", LINES, COLS); + ENCWRITE(prbuf,80,savefd); + savef = (FILE *) fdopen(savefd,"wb"); + ret = rs_save_file(savef); + fclose(savef); + if (num_to_write == num_written && ret == 0) return(TRUE); + else return(FALSE); +} + +restore(file, envp) +register char *file; +char **envp; +{ + register int inf; + extern char **environ; + char buf[LINELEN]; + STAT sbuf2; + int oldcol, oldline; /* Old number of columns and lines */ + + if (strcmp(file, "-r") == 0) + file = file_name; + if ((inf = open(file, 0)) < 0) + { + 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; + } + + /* + * Get the lines and columns from the previous game + */ + + ENCREAD(buf, 80, inf); + sscanf(buf, "%d x %d\n", &oldline, &oldcol); + fstat(inf, &sbuf2); + fflush(stdout); + + initscr(); + + if (COLS < oldcol || LINES < oldline) { + endwin(); + printf("Cannot restart the game on a smaller screen.\n"); + return FALSE; + } + + setup(); + /* + * Set up windows + */ + 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,1); + keypad(msgw,1); + + if (rs_restore_file(inf) != 0) + { + printf("Cannot restore file\n"); + close(inf); + return(FALSE); + } + + cols = COLS; + lines = LINES; + if (cols > 85) cols = 85; + if (lines > 24) lines = 24; + + mpos = 0; + mvwprintw(msgw, 0, 0, "%s: %s", file, ctime(&sbuf2.st_mtime)); + + /* + * defeat multiple restarting from the same place + */ + if (!wizard && md_unlink_open_file(file, inf) < 0) { + printf("Cannot unlink file\n"); + return FALSE; + } + + environ = envp; + strcpy(file_name, file); + setup(); + clearok(curscr, TRUE); + touchwin(cw); + srand(getpid()); + playit(); + /*NOTREACHED*/ + return(0); +} + +#define ENCWBSIZ 1024 +/* + * perform an encrypted write + */ +encwrite(start, size, outf) +register char *start; +register unsigned size; +register int outf; +{ + register char *ep; + register int i = 0; + int num_written = 0; + auto char buf[ENCWBSIZ]; + + ep = encstr; + + while (size--) + { + buf[i++] = *start++ ^ *ep++ ; + if (*ep == '\0') + ep = encstr; + + if (i == ENCWBSIZ || size == 0) { + if (write(outf, buf, (unsigned)i) < i) + return(num_written); + else { + num_written += i; + i = 0; + } + } + } + return(num_written); +} + +/* + * perform an encrypted read + */ +encread(start, size, inf) +register char *start; +register unsigned size; +register int inf; +{ + register char *ep; + register int read_size; + + if ((read_size = read(inf, start, size)) == -1 || read_size == 0) + return read_size; + + ep = encstr; + + size = read_size; + while (size--) + { + *start++ ^= *ep++; + if (*ep == '\0') + ep = encstr; + } + return read_size; +}