diff arogue5/save.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children a98834ce7e04
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue5/save.c	Thu Aug 09 22:58:48 2012 +0000
@@ -0,0 +1,289 @@
+/*
+ * save and restore routines
+ *
+ * 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 <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include "rogue.h"
+
+typedef struct stat STAT;
+
+extern char version[], encstr[];
+/* extern bool _endwin; */
+
+STAT sbuf;
+
+bool
+save_game()
+{
+    register FILE *savef;
+    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, cw) == QUIT)
+	{
+	    msg("");
+	    return FALSE;
+	}
+        msg("");
+	strcpy(file_name, buf);
+gotfile:
+	if ((savef = fopen(file_name, "w")) == NULL)
+	    msg(strerror(errno));	/* fake perror() */
+    } while (savef == NULL);
+
+    /*
+     * write out encrpyted file (after a stat)
+     * The fwrite is to force allocation of the buffer before the write
+     */
+    if (save_file(savef) != 0) {
+	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(int sig)
+{
+    register FILE *savef;
+    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, "w")) != NULL)
+	save_file(savef);
+    exit(1);
+}
+
+/*
+ * write the saved game on the file
+ */
+bool
+save_file(savef)
+register FILE *savef;
+{
+    int ret;
+    int slines = LINES;
+    int scols  = COLS;
+
+    wmove(cw, LINES-1, 0);
+    draw(cw);
+    fwrite("junk", 1, 5, savef);
+    fseek(savef, 0L, 0);
+    /* _endwin = TRUE; */
+    fstat(fileno(savef), &sbuf);
+
+    encwrite(version,strlen(version)+1,savef);
+    sprintf(prbuf,"%d x %d\n", LINES, COLS);
+    encwrite(prbuf,80,savef);
+
+    msg("");
+    ret = rs_save_file(savef);
+
+    fclose(savef);
+ 
+    return(ret);
+}
+
+restore(file, envp)
+register char *file;
+char **envp;
+{
+    register int inf;
+#ifndef _AIX
+    extern char **environ;
+#endif
+    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, O_RDONLY)) < 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);
+
+    /*
+     * Set the new terminal and make sure we aren't going to a smaller screen.
+     */
+
+    initscr();
+   
+    if (COLS < oldcol || LINES < oldline) {
+        endwin();
+	printf("\nCannot restart the game on a smaller screen.\n");
+	return FALSE;
+    }
+
+    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);
+
+    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("\nCannot restore from a linked file\n");
+	    return FALSE;
+	}
+    }
+
+    if (rs_restore_file(inf) != 0)
+    {
+        endwin();
+        printf("\nCannot restore file\n");
+        return(FALSE);
+    }
+
+    if (!wizard)
+    {
+	if (unlink(file) < 0) {
+            close(inf); /* only close if system insists */
+            if (unlink(file) < 0) {
+                endwin();
+	        printf("\nCannot unlink file\n");
+	        return FALSE;
+            }
+	}
+    }
+
+    environ = envp;
+    strcpy(file_name, file);
+    setup();
+    clearok(curscr, TRUE);
+    touchwin(cw);
+    srand(getpid());
+    playit();
+    /*NOTREACHED*/ 
+    return(FALSE);
+}
+
+/*
+ * perform an encrypted write
+ */
+encwrite(start, size, outf)
+register char *start;
+register unsigned size;
+register FILE *outf;
+{
+    register char *ep;
+    register num_written = 0;
+
+    ep = encstr;
+
+    while (size--)
+    {
+	if (putc(*start++ ^ *ep++, outf) == EOF && ferror(outf))
+	    return(num_written);
+	num_written++;
+	if (*ep == '\0')
+	    ep = encstr;
+    }
+    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;
+}