diff xrogue/save.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xrogue/save.c	Tue Apr 21 08:55:20 2015 -0400
@@ -0,0 +1,304 @@
+/*
+    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 <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
+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 = 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 */
+
+    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));
+    } while (savef == NULL);
+
+    msg("");
+    /*
+     * write out encrpyted file
+     */
+    if (save_file(savef) == FALSE) {
+        fclose(savef);
+        msg("Cannot create save file.");
+        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(savef)
+register FILE *savef;
+{
+    int slines = LINES;
+    int scols = COLS;
+    int 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);
+}
+
+restore(file, envp)
+register char *file;
+char **envp;
+{
+    register int 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 = open(file, O_RDONLY)) < 0)
+    {
+        perror(file);
+        return(-1);
+    }
+
+    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");
+        close(inf);
+        return(FALSE);
+    }
+
+    close(inf);
+
+    if (!wizard)
+        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(1);
+}
+
+#define ENCWBSIZ        1024
+
+/*
+ * perform an encrypted write
+ */
+
+long
+encwrite(start, size, outf)
+register char *start;
+register unsigned long size;
+register 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(start, size, inf)
+register char *start;
+register unsigned long size;
+int 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 = read(inf,&start[total_read],rd_siz);
+        if(rd_siz==-1 || 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;
+}
+