Home | History | Annotate | Line # | Download | only in adventure
save.c revision 1.11.6.2
      1  1.11.6.2      yamt /*	$NetBSD: save.c,v 1.11.6.2 2014/05/22 11:36:21 yamt Exp $	*/
      2       1.2       cgd 
      3       1.1       jtc /*-
      4       1.1       jtc  * Copyright (c) 1991, 1993
      5       1.1       jtc  *	The Regents of the University of California.  All rights reserved.
      6       1.1       jtc  *
      7       1.1       jtc  * The game adventure was originally written in Fortran by Will Crowther
      8       1.1       jtc  * and Don Woods.  It was later translated to C and enhanced by Jim
      9       1.1       jtc  * Gillogly.  This code is derived from software contributed to Berkeley
     10       1.1       jtc  * by Jim Gillogly at The Rand Corporation.
     11       1.1       jtc  *
     12       1.1       jtc  * Redistribution and use in source and binary forms, with or without
     13       1.1       jtc  * modification, are permitted provided that the following conditions
     14       1.1       jtc  * are met:
     15       1.1       jtc  * 1. Redistributions of source code must retain the above copyright
     16       1.1       jtc  *    notice, this list of conditions and the following disclaimer.
     17       1.1       jtc  * 2. Redistributions in binary form must reproduce the above copyright
     18       1.1       jtc  *    notice, this list of conditions and the following disclaimer in the
     19       1.1       jtc  *    documentation and/or other materials provided with the distribution.
     20       1.8       agc  * 3. Neither the name of the University nor the names of its contributors
     21       1.1       jtc  *    may be used to endorse or promote products derived from this software
     22       1.1       jtc  *    without specific prior written permission.
     23       1.1       jtc  *
     24       1.1       jtc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25       1.1       jtc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26       1.1       jtc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27       1.1       jtc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28       1.1       jtc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29       1.1       jtc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30       1.1       jtc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31       1.1       jtc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32       1.1       jtc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33       1.1       jtc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34       1.1       jtc  * SUCH DAMAGE.
     35       1.1       jtc  */
     36       1.1       jtc 
     37       1.3  christos #include <sys/cdefs.h>
     38       1.1       jtc #ifndef lint
     39       1.2       cgd #if 0
     40       1.1       jtc static char sccsid[] = "@(#)save.c	8.1 (Berkeley) 5/31/93";
     41       1.2       cgd #else
     42  1.11.6.2      yamt __RCSID("$NetBSD: save.c,v 1.11.6.2 2014/05/22 11:36:21 yamt Exp $");
     43       1.2       cgd #endif
     44       1.4     lukem #endif				/* not lint */
     45       1.1       jtc 
     46  1.11.6.1      yamt #include <sys/types.h>
     47  1.11.6.1      yamt #include <sys/time.h>
     48  1.11.6.1      yamt #include <stdbool.h>
     49       1.1       jtc #include <stdio.h>
     50       1.3  christos #include <stdlib.h>
     51  1.11.6.1      yamt #include <err.h>
     52  1.11.6.1      yamt #include <assert.h>
     53  1.11.6.1      yamt 
     54       1.1       jtc #include "hdr.h"
     55       1.3  christos #include "extern.h"
     56       1.1       jtc 
     57  1.11.6.1      yamt struct savefile {
     58  1.11.6.1      yamt 	FILE *f;
     59  1.11.6.1      yamt 	const char *name;
     60  1.11.6.1      yamt 	bool warned;
     61  1.11.6.2      yamt 	size_t bintextpos;
     62  1.11.6.1      yamt 	uint32_t key;
     63  1.11.6.1      yamt 	struct crcstate crc;
     64  1.11.6.1      yamt 	unsigned char pad[8];
     65  1.11.6.1      yamt 	unsigned padpos;
     66  1.11.6.1      yamt };
     67  1.11.6.1      yamt 
     68  1.11.6.1      yamt #define BINTEXT_WIDTH 60
     69  1.11.6.1      yamt #define FORMAT_VERSION 2
     70  1.11.6.1      yamt #define FORMAT_VERSION_NOSUM 1
     71  1.11.6.1      yamt static const char header[] = "Adventure save file\n";
     72  1.11.6.1      yamt 
     73  1.11.6.1      yamt ////////////////////////////////////////////////////////////
     74  1.11.6.1      yamt // base16 output encoding
     75  1.11.6.1      yamt 
     76  1.11.6.1      yamt /*
     77  1.11.6.1      yamt  * Map 16 plain values into 90 coded values and back.
     78  1.11.6.1      yamt  */
     79  1.11.6.1      yamt 
     80  1.11.6.1      yamt static const char coding[90] =
     81  1.11.6.1      yamt 	"Db.GOyT]7a6zpF(c*5H9oK~0[WVAg&kR)ml,2^q-1Y3v+"
     82  1.11.6.1      yamt 	"X/=JirZL$C>_N?:}B{dfnsxU<@MQ%8|P!4h`ESt;euwIj"
     83  1.11.6.1      yamt ;
     84  1.11.6.1      yamt 
     85  1.11.6.1      yamt static int
     86  1.11.6.1      yamt readletter(char letter, unsigned char *ret)
     87  1.11.6.1      yamt {
     88  1.11.6.1      yamt 	const char *s;
     89  1.11.6.1      yamt 
     90  1.11.6.1      yamt 	s = strchr(coding, letter);
     91  1.11.6.1      yamt 	if (s == NULL) {
     92  1.11.6.1      yamt 		return 1;
     93  1.11.6.1      yamt 	}
     94  1.11.6.1      yamt 	*ret = (s - coding) % 16;
     95  1.11.6.1      yamt 	return 0;
     96  1.11.6.1      yamt }
     97  1.11.6.1      yamt 
     98  1.11.6.1      yamt static char
     99  1.11.6.1      yamt writeletter(unsigned char nibble)
    100  1.11.6.1      yamt {
    101  1.11.6.1      yamt 	unsigned code;
    102  1.11.6.1      yamt 
    103  1.11.6.1      yamt 	assert(nibble < 16);
    104  1.11.6.1      yamt 	do {
    105  1.11.6.1      yamt 		code = (16 * (random() % 6)) + nibble;
    106  1.11.6.1      yamt 	} while (code >= 90);
    107  1.11.6.1      yamt 	return coding[code];
    108  1.11.6.1      yamt }
    109  1.11.6.1      yamt 
    110  1.11.6.1      yamt ////////////////////////////////////////////////////////////
    111  1.11.6.1      yamt // savefile
    112  1.11.6.1      yamt 
    113  1.11.6.1      yamt /*
    114  1.11.6.1      yamt  * Open a savefile.
    115  1.11.6.1      yamt  */
    116  1.11.6.1      yamt static struct savefile *
    117  1.11.6.1      yamt savefile_open(const char *name, bool forwrite)
    118  1.11.6.1      yamt {
    119  1.11.6.1      yamt 	struct savefile *sf;
    120  1.11.6.1      yamt 
    121  1.11.6.1      yamt 	sf = malloc(sizeof(*sf));
    122  1.11.6.1      yamt 	if (sf == NULL) {
    123  1.11.6.1      yamt 		return NULL;
    124  1.11.6.1      yamt 	}
    125  1.11.6.1      yamt 	sf->f = fopen(name, forwrite ? "w" : "r");
    126  1.11.6.1      yamt 	if (sf->f == NULL) {
    127  1.11.6.1      yamt 		free(sf);
    128  1.11.6.1      yamt 		fprintf(stderr,
    129  1.11.6.1      yamt 		    "Hmm.  The name \"%s\" appears to be magically blocked.\n",
    130  1.11.6.1      yamt 		    name);
    131  1.11.6.1      yamt 		return NULL;
    132  1.11.6.1      yamt 	}
    133  1.11.6.1      yamt 	sf->name = name;
    134  1.11.6.1      yamt 	sf->warned = false;
    135  1.11.6.1      yamt 	sf->bintextpos = 0;
    136  1.11.6.1      yamt 	sf->key = 0;
    137  1.11.6.1      yamt 	crc_start(&sf->crc);
    138  1.11.6.1      yamt 	memset(sf->pad, 0, sizeof(sf->pad));
    139  1.11.6.1      yamt 	sf->padpos = 0;
    140  1.11.6.1      yamt 	return sf;
    141  1.11.6.1      yamt }
    142  1.11.6.1      yamt 
    143  1.11.6.1      yamt /*
    144  1.11.6.1      yamt  * Raw read.
    145  1.11.6.1      yamt  */
    146  1.11.6.1      yamt static int
    147  1.11.6.1      yamt savefile_rawread(struct savefile *sf, void *data, size_t len)
    148  1.11.6.1      yamt {
    149  1.11.6.1      yamt 	size_t result;
    150  1.11.6.1      yamt 
    151  1.11.6.1      yamt 	result = fread(data, 1, len, sf->f);
    152  1.11.6.1      yamt 	if (result != len || ferror(sf->f)) {
    153  1.11.6.1      yamt 		fprintf(stderr, "Oops: error reading %s.\n", sf->name);
    154  1.11.6.1      yamt 		sf->warned = true;
    155  1.11.6.1      yamt 		return 1;
    156  1.11.6.1      yamt 	}
    157  1.11.6.1      yamt 	return 0;
    158  1.11.6.1      yamt }
    159  1.11.6.1      yamt 
    160  1.11.6.1      yamt /*
    161  1.11.6.1      yamt  * Raw write.
    162  1.11.6.1      yamt  */
    163  1.11.6.1      yamt static int
    164  1.11.6.1      yamt savefile_rawwrite(struct savefile *sf, const void *data, size_t len)
    165  1.11.6.1      yamt {
    166  1.11.6.1      yamt 	size_t result;
    167  1.11.6.1      yamt 
    168  1.11.6.1      yamt 	result = fwrite(data, 1, len, sf->f);
    169  1.11.6.1      yamt 	if (result != len || ferror(sf->f)) {
    170  1.11.6.1      yamt 		fprintf(stderr, "Oops: error writing %s.\n", sf->name);
    171  1.11.6.1      yamt 		sf->warned = true;
    172  1.11.6.1      yamt 		return 1;
    173  1.11.6.1      yamt 	}
    174  1.11.6.1      yamt 	return 0;
    175  1.11.6.1      yamt }
    176  1.11.6.1      yamt 
    177  1.11.6.1      yamt /*
    178  1.11.6.1      yamt  * Close a savefile.
    179  1.11.6.1      yamt  */
    180  1.11.6.1      yamt static int
    181  1.11.6.1      yamt savefile_close(struct savefile *sf)
    182  1.11.6.1      yamt {
    183  1.11.6.1      yamt 	int ret;
    184  1.11.6.1      yamt 
    185  1.11.6.1      yamt 	if (sf->bintextpos > 0) {
    186  1.11.6.1      yamt 		savefile_rawwrite(sf, "\n", 1);
    187  1.11.6.1      yamt 	}
    188  1.11.6.1      yamt 
    189  1.11.6.1      yamt 	ret = 0;
    190  1.11.6.1      yamt 	if (fclose(sf->f)) {
    191  1.11.6.1      yamt 		if (!sf->warned) {
    192  1.11.6.1      yamt 			fprintf(stderr, "Oops: error on %s.\n", sf->name);
    193  1.11.6.1      yamt 		}
    194  1.11.6.1      yamt 		ret = 1;
    195  1.11.6.1      yamt 	}
    196  1.11.6.1      yamt 	free(sf);
    197  1.11.6.1      yamt 	return ret;
    198  1.11.6.1      yamt }
    199  1.11.6.1      yamt 
    200  1.11.6.1      yamt /*
    201  1.11.6.1      yamt  * Read encoded binary data, discarding any whitespace that appears.
    202  1.11.6.1      yamt  */
    203  1.11.6.1      yamt static int
    204  1.11.6.1      yamt savefile_bintextread(struct savefile *sf, void *data, size_t len)
    205  1.11.6.1      yamt {
    206  1.11.6.1      yamt 	size_t pos;
    207  1.11.6.1      yamt 	unsigned char *udata;
    208  1.11.6.1      yamt 	int ch;
    209  1.11.6.1      yamt 
    210  1.11.6.1      yamt 	udata = data;
    211  1.11.6.1      yamt 	pos = 0;
    212  1.11.6.1      yamt 	while (pos < len) {
    213  1.11.6.1      yamt 		ch = fgetc(sf->f);
    214  1.11.6.1      yamt 		if (ch == EOF || ferror(sf->f)) {
    215  1.11.6.1      yamt 			fprintf(stderr, "Oops: error reading %s.\n", sf->name);
    216  1.11.6.1      yamt 			sf->warned = true;
    217  1.11.6.1      yamt 			return 1;
    218  1.11.6.1      yamt 		}
    219  1.11.6.1      yamt 		if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
    220  1.11.6.1      yamt 			continue;
    221  1.11.6.1      yamt 		}
    222  1.11.6.1      yamt 		udata[pos++] = ch;
    223  1.11.6.1      yamt 	}
    224  1.11.6.1      yamt 	return 0;
    225  1.11.6.1      yamt }
    226  1.11.6.1      yamt 
    227  1.11.6.1      yamt /*
    228  1.11.6.1      yamt  * Read binary data, decoding from text using readletter().
    229  1.11.6.1      yamt  */
    230  1.11.6.1      yamt static int
    231  1.11.6.1      yamt savefile_binread(struct savefile *sf, void *data, size_t len)
    232  1.11.6.1      yamt {
    233  1.11.6.1      yamt 	unsigned char buf[64];
    234  1.11.6.1      yamt 	unsigned char *udata;
    235  1.11.6.1      yamt 	unsigned char val1, val2;
    236  1.11.6.1      yamt 	size_t pos, amt, i;
    237  1.11.6.1      yamt 
    238  1.11.6.1      yamt 	udata = data;
    239  1.11.6.1      yamt 	pos = 0;
    240  1.11.6.1      yamt 	while (pos < len) {
    241  1.11.6.1      yamt 		amt = len - pos;
    242  1.11.6.1      yamt 		if (amt > sizeof(buf) / 2) {
    243  1.11.6.1      yamt 			amt = sizeof(buf) / 2;
    244  1.11.6.1      yamt 		}
    245  1.11.6.1      yamt 		if (savefile_bintextread(sf, buf, amt*2)) {
    246  1.11.6.1      yamt 			return 1;
    247  1.11.6.1      yamt 		}
    248  1.11.6.1      yamt 		for (i=0; i<amt; i++) {
    249  1.11.6.1      yamt 			if (readletter(buf[i*2], &val1)) {
    250  1.11.6.1      yamt 				return 1;
    251  1.11.6.1      yamt 			}
    252  1.11.6.1      yamt 			if (readletter(buf[i*2 + 1], &val2)) {
    253  1.11.6.1      yamt 				return 1;
    254  1.11.6.1      yamt 			}
    255  1.11.6.1      yamt 			udata[pos++] = val1 * 16 + val2;
    256  1.11.6.1      yamt 		}
    257  1.11.6.1      yamt 	}
    258  1.11.6.1      yamt 	return 0;
    259  1.11.6.1      yamt }
    260  1.11.6.1      yamt 
    261  1.11.6.1      yamt /*
    262  1.11.6.1      yamt  * Write encoded binary data, inserting newlines to get a neatly
    263  1.11.6.1      yamt  * formatted block.
    264  1.11.6.1      yamt  */
    265  1.11.6.1      yamt static int
    266  1.11.6.1      yamt savefile_bintextwrite(struct savefile *sf, const void *data, size_t len)
    267  1.11.6.1      yamt {
    268  1.11.6.1      yamt 	size_t pos, amt;
    269  1.11.6.1      yamt 	const unsigned char *udata;
    270  1.11.6.1      yamt 
    271  1.11.6.1      yamt 	udata = data;
    272  1.11.6.1      yamt 	pos = 0;
    273  1.11.6.1      yamt 	while (pos < len) {
    274  1.11.6.1      yamt 		amt = BINTEXT_WIDTH - sf->bintextpos;
    275  1.11.6.1      yamt 		if (amt > len - pos) {
    276  1.11.6.1      yamt 			amt = len - pos;
    277  1.11.6.1      yamt 		}
    278  1.11.6.1      yamt 		if (savefile_rawwrite(sf, udata + pos, amt)) {
    279  1.11.6.1      yamt 			return 1;
    280  1.11.6.1      yamt 		}
    281  1.11.6.1      yamt 		pos += amt;
    282  1.11.6.1      yamt 		sf->bintextpos += amt;
    283  1.11.6.1      yamt 		if (sf->bintextpos >= BINTEXT_WIDTH) {
    284  1.11.6.1      yamt 			savefile_rawwrite(sf, "\n", 1);
    285  1.11.6.1      yamt 			sf->bintextpos = 0;
    286  1.11.6.1      yamt 		}
    287  1.11.6.1      yamt 	}
    288  1.11.6.1      yamt 	return 0;
    289  1.11.6.1      yamt }
    290  1.11.6.1      yamt 
    291  1.11.6.1      yamt /*
    292  1.11.6.1      yamt  * Write binary data, encoding as text using writeletter().
    293  1.11.6.1      yamt  */
    294  1.11.6.1      yamt static int
    295  1.11.6.1      yamt savefile_binwrite(struct savefile *sf, const void *data, size_t len)
    296  1.11.6.1      yamt {
    297  1.11.6.1      yamt 	unsigned char buf[64];
    298  1.11.6.1      yamt 	const unsigned char *udata;
    299  1.11.6.1      yamt 	size_t pos, bpos;
    300  1.11.6.1      yamt 	unsigned char byte;
    301  1.11.6.1      yamt 
    302  1.11.6.1      yamt 	udata = data;
    303  1.11.6.1      yamt 	pos = 0;
    304  1.11.6.1      yamt 	bpos = 0;
    305  1.11.6.1      yamt 	while (pos < len) {
    306  1.11.6.1      yamt 		byte = udata[pos++];
    307  1.11.6.1      yamt 		buf[bpos++] = writeletter(byte >> 4);
    308  1.11.6.1      yamt 		buf[bpos++] = writeletter(byte & 0xf);
    309  1.11.6.1      yamt 		if (bpos >= sizeof(buf)) {
    310  1.11.6.1      yamt 			if (savefile_bintextwrite(sf, buf, bpos)) {
    311  1.11.6.1      yamt 				return 1;
    312  1.11.6.1      yamt 			}
    313  1.11.6.1      yamt 			bpos = 0;
    314  1.11.6.1      yamt 		}
    315  1.11.6.1      yamt 	}
    316  1.11.6.1      yamt 	if (savefile_bintextwrite(sf, buf, bpos)) {
    317  1.11.6.1      yamt 		return 1;
    318  1.11.6.1      yamt 	}
    319  1.11.6.1      yamt 	return 0;
    320  1.11.6.1      yamt }
    321  1.11.6.1      yamt 
    322  1.11.6.1      yamt /*
    323  1.11.6.1      yamt  * Lightweight "encryption" for save files. This is not meant to
    324  1.11.6.1      yamt  * be secure and wouldn't be even if we didn't write the decrypt
    325  1.11.6.1      yamt  * key to the beginning of the save file; it's just meant to be
    326  1.11.6.1      yamt  * enough to discourage casual cheating.
    327  1.11.6.1      yamt  */
    328  1.11.6.1      yamt 
    329  1.11.6.1      yamt /*
    330  1.11.6.1      yamt  * Make cheesy hash of buf[0..buflen]. Note: buf and outhash may overlap.
    331  1.11.6.1      yamt  */
    332  1.11.6.1      yamt static void
    333  1.11.6.1      yamt hash(const void *data, size_t datalen, unsigned char *out, size_t outlen)
    334  1.11.6.1      yamt {
    335  1.11.6.1      yamt 	const unsigned char *udata;
    336  1.11.6.1      yamt 	size_t i;
    337  1.11.6.1      yamt 	uint64_t val;
    338  1.11.6.1      yamt 	const unsigned char *uval;
    339  1.11.6.1      yamt 	size_t valpos;
    340  1.11.6.1      yamt 
    341  1.11.6.1      yamt 	udata = data;
    342  1.11.6.1      yamt 	val = 0;
    343  1.11.6.1      yamt 	for (i=0; i<datalen; i++) {
    344  1.11.6.1      yamt 		val = val ^ 0xbadc0ffee;
    345  1.11.6.1      yamt 		val = (val << 4) | (val >> 60);
    346  1.11.6.2      yamt 		val += udata[i] ^ 0xbeefU;
    347  1.11.6.1      yamt 	}
    348  1.11.6.1      yamt 
    349  1.11.6.1      yamt 	uval = (unsigned char *)&val;
    350  1.11.6.1      yamt 	valpos = 0;
    351  1.11.6.1      yamt 	for (i=0; i<outlen; i++) {
    352  1.11.6.1      yamt 		out[i] = uval[valpos++];
    353  1.11.6.1      yamt 		if (valpos >= sizeof(val)) {
    354  1.11.6.1      yamt 			valpos = 0;
    355  1.11.6.1      yamt 		}
    356  1.11.6.1      yamt 	}
    357  1.11.6.1      yamt }
    358  1.11.6.1      yamt 
    359  1.11.6.1      yamt /*
    360  1.11.6.1      yamt  * Set the "encryption" key.
    361  1.11.6.1      yamt  */
    362  1.11.6.1      yamt static void
    363  1.11.6.1      yamt savefile_key(struct savefile *sf, uint32_t key)
    364  1.11.6.1      yamt {
    365  1.11.6.1      yamt 	sf->key = 0;
    366  1.11.6.1      yamt 	crc_start(&sf->crc);
    367  1.11.6.1      yamt 	hash(&sf->key, sizeof(sf->key), sf->pad, sizeof(sf->pad));
    368  1.11.6.1      yamt 	sf->padpos = 0;
    369  1.11.6.1      yamt }
    370  1.11.6.1      yamt 
    371  1.11.6.1      yamt /*
    372  1.11.6.1      yamt  * Get an "encryption" pad byte. This forms a stream "cipher" that we
    373  1.11.6.1      yamt  * xor with the plaintext save data.
    374  1.11.6.1      yamt  */
    375  1.11.6.1      yamt static unsigned char
    376  1.11.6.1      yamt savefile_getpad(struct savefile *sf)
    377  1.11.6.1      yamt {
    378  1.11.6.1      yamt 	unsigned char ret;
    379  1.11.6.1      yamt 
    380  1.11.6.1      yamt 	ret = sf->pad[sf->padpos++];
    381  1.11.6.1      yamt 	if (sf->padpos >= sizeof(sf->pad)) {
    382  1.11.6.1      yamt 		hash(sf->pad, sizeof(sf->pad), sf->pad, sizeof(sf->pad));
    383  1.11.6.1      yamt 		sf->padpos = 0;
    384  1.11.6.1      yamt 	}
    385  1.11.6.1      yamt 	return ret;
    386  1.11.6.1      yamt }
    387  1.11.6.1      yamt 
    388  1.11.6.1      yamt /*
    389  1.11.6.1      yamt  * Read "encrypted" data.
    390  1.11.6.1      yamt  */
    391  1.11.6.1      yamt static int
    392  1.11.6.1      yamt savefile_cread(struct savefile *sf, void *data, size_t len)
    393  1.11.6.1      yamt {
    394  1.11.6.1      yamt 	char buf[64];
    395  1.11.6.1      yamt 	unsigned char *udata;
    396  1.11.6.1      yamt 	size_t pos, amt, i;
    397  1.11.6.1      yamt 	unsigned char ch;
    398  1.11.6.1      yamt 
    399  1.11.6.1      yamt 	udata = data;
    400  1.11.6.1      yamt 	pos = 0;
    401  1.11.6.1      yamt 	while (pos < len) {
    402  1.11.6.1      yamt 		amt = len - pos;
    403  1.11.6.1      yamt 		if (amt > sizeof(buf)) {
    404  1.11.6.1      yamt 			amt = sizeof(buf);
    405  1.11.6.1      yamt 		}
    406  1.11.6.1      yamt 		if (savefile_binread(sf, buf, amt)) {
    407  1.11.6.1      yamt 			return 1;
    408  1.11.6.1      yamt 		}
    409  1.11.6.1      yamt 		for (i=0; i<amt; i++) {
    410  1.11.6.1      yamt 			ch = buf[i];
    411  1.11.6.1      yamt 			ch ^= savefile_getpad(sf);
    412  1.11.6.1      yamt 			udata[pos + i] = ch;
    413  1.11.6.1      yamt 		}
    414  1.11.6.1      yamt 		pos += amt;
    415  1.11.6.1      yamt 	}
    416  1.11.6.1      yamt 	crc_add(&sf->crc, data, len);
    417  1.11.6.1      yamt 	return 0;
    418  1.11.6.1      yamt }
    419  1.11.6.1      yamt 
    420  1.11.6.1      yamt /*
    421  1.11.6.1      yamt  * Write "encrypted" data.
    422  1.11.6.1      yamt  */
    423  1.11.6.1      yamt static int
    424  1.11.6.1      yamt savefile_cwrite(struct savefile *sf, const void *data, size_t len)
    425  1.11.6.1      yamt {
    426  1.11.6.1      yamt 	char buf[64];
    427  1.11.6.1      yamt 	const unsigned char *udata;
    428  1.11.6.1      yamt 	size_t pos, amt, i;
    429  1.11.6.1      yamt 	unsigned char ch;
    430  1.11.6.1      yamt 
    431  1.11.6.1      yamt 	udata = data;
    432  1.11.6.1      yamt 	pos = 0;
    433  1.11.6.1      yamt 	while (pos < len) {
    434  1.11.6.1      yamt 		amt = len - pos;
    435  1.11.6.1      yamt 		if (amt > sizeof(buf)) {
    436  1.11.6.1      yamt 			amt = sizeof(buf);
    437  1.11.6.1      yamt 		}
    438  1.11.6.1      yamt 		for (i=0; i<amt; i++) {
    439  1.11.6.1      yamt 			ch = udata[pos + i];
    440  1.11.6.1      yamt 			ch ^= savefile_getpad(sf);
    441  1.11.6.1      yamt 			buf[i] = ch;
    442  1.11.6.1      yamt 		}
    443  1.11.6.1      yamt 		if (savefile_binwrite(sf, buf, amt)) {
    444  1.11.6.1      yamt 			return 1;
    445  1.11.6.1      yamt 		}
    446  1.11.6.1      yamt 		pos += amt;
    447  1.11.6.1      yamt 	}
    448  1.11.6.1      yamt 	crc_add(&sf->crc, data, len);
    449  1.11.6.1      yamt 	return 0;
    450  1.11.6.1      yamt }
    451  1.11.6.1      yamt 
    452  1.11.6.1      yamt ////////////////////////////////////////////////////////////
    453  1.11.6.1      yamt // compat for old save files
    454  1.11.6.1      yamt 
    455  1.11.6.1      yamt struct compat_saveinfo {
    456       1.4     lukem 	void   *address;
    457  1.11.6.2      yamt 	size_t  width;
    458       1.1       jtc };
    459       1.1       jtc 
    460  1.11.6.1      yamt static const struct compat_saveinfo compat_savearray[] =
    461       1.1       jtc {
    462       1.4     lukem 	{&abbnum, sizeof(abbnum)},
    463       1.4     lukem 	{&attack, sizeof(attack)},
    464       1.4     lukem 	{&blklin, sizeof(blklin)},
    465       1.4     lukem 	{&bonus, sizeof(bonus)},
    466       1.4     lukem 	{&chloc, sizeof(chloc)},
    467       1.4     lukem 	{&chloc2, sizeof(chloc2)},
    468       1.4     lukem 	{&clock1, sizeof(clock1)},
    469       1.4     lukem 	{&clock2, sizeof(clock2)},
    470       1.4     lukem 	{&closed, sizeof(closed)},
    471      1.11  dholland 	{&isclosing, sizeof(isclosing)},
    472      1.11  dholland 	{&daltloc, sizeof(daltloc)},
    473       1.4     lukem 	{&demo, sizeof(demo)},
    474       1.4     lukem 	{&detail, sizeof(detail)},
    475       1.4     lukem 	{&dflag, sizeof(dflag)},
    476       1.4     lukem 	{&dkill, sizeof(dkill)},
    477       1.4     lukem 	{&dtotal, sizeof(dtotal)},
    478       1.4     lukem 	{&foobar, sizeof(foobar)},
    479       1.4     lukem 	{&gaveup, sizeof(gaveup)},
    480      1.11  dholland 	{&holding, sizeof(holding)},
    481       1.4     lukem 	{&iwest, sizeof(iwest)},
    482       1.4     lukem 	{&k, sizeof(k)},
    483       1.4     lukem 	{&k2, sizeof(k2)},
    484       1.4     lukem 	{&knfloc, sizeof(knfloc)},
    485       1.4     lukem 	{&kq, sizeof(kq)},
    486      1.11  dholland 	{&latency, sizeof(latency)},
    487       1.4     lukem 	{&limit, sizeof(limit)},
    488       1.4     lukem 	{&lmwarn, sizeof(lmwarn)},
    489       1.4     lukem 	{&loc, sizeof(loc)},
    490       1.4     lukem 	{&maxdie, sizeof(maxdie)},
    491      1.11  dholland 	{&maxscore, sizeof(maxscore)},
    492       1.4     lukem 	{&newloc, sizeof(newloc)},
    493       1.4     lukem 	{&numdie, sizeof(numdie)},
    494       1.4     lukem 	{&obj, sizeof(obj)},
    495      1.11  dholland 	{&oldloc2, sizeof(oldloc2)},
    496       1.4     lukem 	{&oldloc, sizeof(oldloc)},
    497       1.4     lukem 	{&panic, sizeof(panic)},
    498       1.6   hubertf 	{&saveday, sizeof(saveday)},
    499       1.4     lukem 	{&savet, sizeof(savet)},
    500      1.11  dholland 	{&scoring, sizeof(scoring)},
    501       1.4     lukem 	{&spk, sizeof(spk)},
    502       1.4     lukem 	{&stick, sizeof(stick)},
    503       1.4     lukem 	{&tally, sizeof(tally)},
    504       1.4     lukem 	{&tally2, sizeof(tally2)},
    505       1.4     lukem 	{&tkk, sizeof(tkk)},
    506       1.4     lukem 	{&turns, sizeof(turns)},
    507       1.4     lukem 	{&verb, sizeof(verb)},
    508       1.4     lukem 	{&wd1, sizeof(wd1)},
    509       1.4     lukem 	{&wd2, sizeof(wd2)},
    510      1.11  dholland 	{&wasdark, sizeof(wasdark)},
    511       1.4     lukem 	{&yea, sizeof(yea)},
    512       1.4     lukem 	{atloc, sizeof(atloc)},
    513       1.4     lukem 	{dloc, sizeof(dloc)},
    514       1.4     lukem 	{dseen, sizeof(dseen)},
    515       1.4     lukem 	{fixed, sizeof(fixed)},
    516       1.4     lukem 	{hinted, sizeof(hinted)},
    517       1.4     lukem 	{links, sizeof(links)},
    518       1.4     lukem 	{odloc, sizeof(odloc)},
    519       1.4     lukem 	{place, sizeof(place)},
    520       1.4     lukem 	{prop, sizeof(prop)},
    521       1.4     lukem 	{tk, sizeof(tk)},
    522       1.1       jtc 
    523       1.4     lukem 	{NULL, 0}
    524       1.1       jtc };
    525       1.1       jtc 
    526  1.11.6.1      yamt static int
    527  1.11.6.1      yamt compat_restore(const char *infile)
    528       1.1       jtc {
    529       1.4     lukem 	FILE   *in;
    530  1.11.6.1      yamt 	const struct compat_saveinfo *p;
    531       1.4     lukem 	char   *s;
    532       1.4     lukem 	long    sum, cksum = 0;
    533  1.11.6.2      yamt 	size_t  i;
    534  1.11.6.1      yamt 	struct crcstate crc;
    535       1.4     lukem 
    536       1.4     lukem 	if ((in = fopen(infile, "rb")) == NULL) {
    537       1.4     lukem 		fprintf(stderr,
    538       1.4     lukem 		    "Hmm.  The file \"%s\" appears to be magically blocked.\n",
    539       1.4     lukem 		    infile);
    540       1.4     lukem 		return 1;
    541       1.1       jtc 	}
    542       1.4     lukem 	fread(&sum, sizeof(sum), 1, in);	/* Get the seed */
    543       1.1       jtc 	srandom((int) sum);
    544  1.11.6.1      yamt 	for (p = compat_savearray; p->address != NULL; p++) {
    545       1.1       jtc 		fread(p->address, p->width, 1, in);
    546       1.1       jtc 		for (s = p->address, i = 0; i < p->width; i++, s++)
    547       1.4     lukem 			*s = (*s ^ random()) & 0xFF;	/* Lightly decrypt */
    548       1.1       jtc 	}
    549       1.1       jtc 	fclose(in);
    550       1.1       jtc 
    551  1.11.6.1      yamt 	crc_start(&crc);		/* See if she cheated */
    552  1.11.6.1      yamt 	for (p = compat_savearray; p->address != NULL; p++)
    553  1.11.6.1      yamt 		crc_add(&crc, p->address, p->width);
    554  1.11.6.1      yamt 	cksum = crc_get(&crc);
    555       1.4     lukem 	if (sum != cksum)	/* Tsk tsk */
    556       1.4     lukem 		return 2;	/* Altered the file */
    557       1.1       jtc 	/* We successfully restored, so this really was a save file */
    558  1.11.6.1      yamt 
    559  1.11.6.1      yamt 	/*
    560  1.11.6.1      yamt 	 * The above code loads these from disk even though they're
    561  1.11.6.1      yamt 	 * pointers. Null them out and hope we don't crash on them
    562  1.11.6.1      yamt 	 * later; that's better than having them be garbage.
    563  1.11.6.1      yamt 	 */
    564  1.11.6.1      yamt 	tkk = NULL;
    565  1.11.6.1      yamt 	wd1 = NULL;
    566  1.11.6.1      yamt 	wd2 = NULL;
    567  1.11.6.1      yamt 
    568  1.11.6.1      yamt 	return 0;
    569  1.11.6.1      yamt }
    570  1.11.6.1      yamt 
    571  1.11.6.1      yamt ////////////////////////////////////////////////////////////
    572  1.11.6.1      yamt // save + restore
    573  1.11.6.1      yamt 
    574  1.11.6.1      yamt static int *const save_ints[] = {
    575  1.11.6.1      yamt 	&abbnum,
    576  1.11.6.1      yamt 	&attack,
    577  1.11.6.1      yamt 	&blklin,
    578  1.11.6.1      yamt 	&bonus,
    579  1.11.6.1      yamt 	&chloc,
    580  1.11.6.1      yamt 	&chloc2,
    581  1.11.6.1      yamt 	&clock1,
    582  1.11.6.1      yamt 	&clock2,
    583  1.11.6.1      yamt 	&closed,
    584  1.11.6.1      yamt 	&isclosing,
    585  1.11.6.1      yamt 	&daltloc,
    586  1.11.6.1      yamt 	&demo,
    587  1.11.6.1      yamt 	&detail,
    588  1.11.6.1      yamt 	&dflag,
    589  1.11.6.1      yamt 	&dkill,
    590  1.11.6.1      yamt 	&dtotal,
    591  1.11.6.1      yamt 	&foobar,
    592  1.11.6.1      yamt 	&gaveup,
    593  1.11.6.1      yamt 	&holding,
    594  1.11.6.1      yamt 	&iwest,
    595  1.11.6.1      yamt 	&k,
    596  1.11.6.1      yamt 	&k2,
    597  1.11.6.1      yamt 	&knfloc,
    598  1.11.6.1      yamt 	&kq,
    599  1.11.6.1      yamt 	&latency,
    600  1.11.6.1      yamt 	&limit,
    601  1.11.6.1      yamt 	&lmwarn,
    602  1.11.6.1      yamt 	&loc,
    603  1.11.6.1      yamt 	&maxdie,
    604  1.11.6.1      yamt 	&maxscore,
    605  1.11.6.1      yamt 	&newloc,
    606  1.11.6.1      yamt 	&numdie,
    607  1.11.6.1      yamt 	&obj,
    608  1.11.6.1      yamt 	&oldloc2,
    609  1.11.6.1      yamt 	&oldloc,
    610  1.11.6.1      yamt 	&panic,
    611  1.11.6.1      yamt 	&saveday,
    612  1.11.6.1      yamt 	&savet,
    613  1.11.6.1      yamt 	&scoring,
    614  1.11.6.1      yamt 	&spk,
    615  1.11.6.1      yamt 	&stick,
    616  1.11.6.1      yamt 	&tally,
    617  1.11.6.1      yamt 	&tally2,
    618  1.11.6.1      yamt 	&turns,
    619  1.11.6.1      yamt 	&verb,
    620  1.11.6.1      yamt 	&wasdark,
    621  1.11.6.1      yamt 	&yea,
    622  1.11.6.1      yamt };
    623  1.11.6.1      yamt static const unsigned num_save_ints = __arraycount(save_ints);
    624  1.11.6.1      yamt 
    625  1.11.6.1      yamt #define INTARRAY(sym) { sym, __arraycount(sym) }
    626  1.11.6.1      yamt 
    627  1.11.6.1      yamt static const struct {
    628  1.11.6.1      yamt 	int *ptr;
    629  1.11.6.1      yamt 	unsigned num;
    630  1.11.6.1      yamt } save_intarrays[] = {
    631  1.11.6.1      yamt 	INTARRAY(atloc),
    632  1.11.6.1      yamt 	INTARRAY(dseen),
    633  1.11.6.1      yamt 	INTARRAY(dloc),
    634  1.11.6.1      yamt 	INTARRAY(odloc),
    635  1.11.6.1      yamt 	INTARRAY(fixed),
    636  1.11.6.1      yamt 	INTARRAY(hinted),
    637  1.11.6.1      yamt 	INTARRAY(links),
    638  1.11.6.1      yamt 	INTARRAY(place),
    639  1.11.6.1      yamt 	INTARRAY(prop),
    640  1.11.6.1      yamt 	INTARRAY(tk),
    641  1.11.6.1      yamt };
    642  1.11.6.1      yamt static const unsigned num_save_intarrays = __arraycount(save_intarrays);
    643  1.11.6.1      yamt 
    644  1.11.6.1      yamt #undef INTARRAY
    645  1.11.6.1      yamt 
    646  1.11.6.1      yamt #if 0
    647  1.11.6.1      yamt static const struct {
    648  1.11.6.1      yamt 	void *ptr;
    649  1.11.6.1      yamt 	size_t len;
    650  1.11.6.1      yamt } save_blobs[] = {
    651  1.11.6.1      yamt 	{ &wd1, sizeof(wd1) },
    652  1.11.6.1      yamt 	{ &wd2, sizeof(wd2) },
    653  1.11.6.1      yamt 	{ &tkk, sizeof(tkk) },
    654  1.11.6.1      yamt };
    655  1.11.6.1      yamt static const unsigned num_save_blobs = __arraycount(save_blobs);
    656  1.11.6.1      yamt #endif
    657  1.11.6.1      yamt 
    658  1.11.6.1      yamt /*
    659  1.11.6.1      yamt  * Write out a save file. Returns nonzero on error.
    660  1.11.6.1      yamt  */
    661  1.11.6.1      yamt int
    662  1.11.6.1      yamt save(const char *outfile)
    663  1.11.6.1      yamt {
    664  1.11.6.1      yamt 	struct savefile *sf;
    665  1.11.6.1      yamt 	struct timespec now;
    666  1.11.6.1      yamt 	uint32_t key, writeable_key;
    667  1.11.6.1      yamt 	uint32_t version;
    668  1.11.6.1      yamt 	unsigned i, j, n;
    669  1.11.6.1      yamt 	uint32_t val, sum;
    670  1.11.6.1      yamt 
    671  1.11.6.1      yamt 	sf = savefile_open(outfile, true);
    672  1.11.6.1      yamt 	if (sf == NULL) {
    673  1.11.6.1      yamt 		return 1;
    674  1.11.6.1      yamt 	}
    675  1.11.6.1      yamt 
    676  1.11.6.1      yamt 	if (savefile_rawwrite(sf, header, strlen(header))) {
    677  1.11.6.1      yamt 		savefile_close(sf);
    678  1.11.6.1      yamt 		return 1;
    679  1.11.6.1      yamt 	}
    680  1.11.6.1      yamt 
    681  1.11.6.1      yamt 	version = htonl(FORMAT_VERSION);
    682  1.11.6.1      yamt 	if (savefile_binwrite(sf, &version, sizeof(version))) {
    683  1.11.6.1      yamt 		savefile_close(sf);
    684  1.11.6.1      yamt 		return 1;
    685  1.11.6.1      yamt 	}
    686  1.11.6.1      yamt 
    687  1.11.6.1      yamt 	clock_gettime(CLOCK_REALTIME, &now);
    688  1.11.6.1      yamt 	key = (uint32_t)(now.tv_sec & 0xffffffff) ^ (uint32_t)(now.tv_nsec);
    689  1.11.6.1      yamt 
    690  1.11.6.1      yamt 	writeable_key = htonl(key);
    691  1.11.6.1      yamt 	if (savefile_binwrite(sf, &writeable_key, sizeof(writeable_key))) {
    692  1.11.6.1      yamt 		savefile_close(sf);
    693  1.11.6.1      yamt 		return 1;
    694  1.11.6.1      yamt 	}
    695  1.11.6.1      yamt 
    696  1.11.6.1      yamt 	/* other parts of the code may depend on us doing this here */
    697  1.11.6.1      yamt 	srandom(key);
    698  1.11.6.1      yamt 
    699  1.11.6.1      yamt 	savefile_key(sf, key);
    700  1.11.6.1      yamt 
    701  1.11.6.1      yamt 	/*
    702  1.11.6.1      yamt 	 * Integers
    703  1.11.6.1      yamt 	 */
    704  1.11.6.1      yamt 	for (i=0; i<num_save_ints; i++) {
    705  1.11.6.1      yamt 		val = *(save_ints[i]);
    706  1.11.6.1      yamt 		val = htonl(val);
    707  1.11.6.1      yamt 		if (savefile_cwrite(sf, &val, sizeof(val))) {
    708  1.11.6.1      yamt 			savefile_close(sf);
    709  1.11.6.1      yamt 			return 1;
    710  1.11.6.1      yamt 		}
    711  1.11.6.1      yamt 	}
    712  1.11.6.1      yamt 
    713  1.11.6.1      yamt 	/*
    714  1.11.6.1      yamt 	 * Arrays of integers
    715  1.11.6.1      yamt 	 */
    716  1.11.6.1      yamt 	for (i=0; i<num_save_intarrays; i++) {
    717  1.11.6.1      yamt 		n = save_intarrays[i].num;
    718  1.11.6.1      yamt 		for (j=0; j<n; j++) {
    719  1.11.6.1      yamt 			val = save_intarrays[i].ptr[j];
    720  1.11.6.1      yamt 			val = htonl(val);
    721  1.11.6.1      yamt 			if (savefile_cwrite(sf, &val, sizeof(val))) {
    722  1.11.6.1      yamt 				savefile_close(sf);
    723  1.11.6.1      yamt 				return 1;
    724  1.11.6.1      yamt 			}
    725  1.11.6.1      yamt 		}
    726  1.11.6.1      yamt 	}
    727  1.11.6.1      yamt 
    728  1.11.6.1      yamt #if 0
    729  1.11.6.1      yamt 	/*
    730  1.11.6.1      yamt 	 * Blobs
    731  1.11.6.1      yamt 	 */
    732  1.11.6.1      yamt 	for (i=0; i<num_save_blobs; i++) {
    733  1.11.6.1      yamt 		if (savefile_cwrite(sf, save_blobs[i].ptr, save_blobs[i].len)) {
    734  1.11.6.1      yamt 			savefile_close(sf);
    735  1.11.6.1      yamt 			return 1;
    736  1.11.6.1      yamt 		}
    737  1.11.6.1      yamt 	}
    738  1.11.6.1      yamt #endif
    739  1.11.6.1      yamt 
    740  1.11.6.1      yamt 	sum = htonl(crc_get(&sf->crc));
    741  1.11.6.1      yamt 	if (savefile_binwrite(sf, &sum, sizeof(&sum))) {
    742  1.11.6.1      yamt 		savefile_close(sf);
    743  1.11.6.1      yamt 		return 1;
    744  1.11.6.1      yamt 	}
    745  1.11.6.1      yamt 	savefile_close(sf);
    746  1.11.6.1      yamt 	return 0;
    747  1.11.6.1      yamt }
    748  1.11.6.1      yamt 
    749  1.11.6.1      yamt /*
    750  1.11.6.1      yamt  * Read in a save file. Returns nonzero on error.
    751  1.11.6.1      yamt  */
    752  1.11.6.1      yamt int
    753  1.11.6.1      yamt restore(const char *infile)
    754  1.11.6.1      yamt {
    755  1.11.6.1      yamt 	struct savefile *sf;
    756  1.11.6.1      yamt 	char buf[sizeof(header)];
    757  1.11.6.1      yamt 	size_t headersize = strlen(header);
    758  1.11.6.1      yamt 	uint32_t version, key, sum;
    759  1.11.6.1      yamt 	unsigned i, j, n;
    760  1.11.6.1      yamt 	uint32_t val;
    761  1.11.6.1      yamt 	bool skipsum = false;
    762  1.11.6.1      yamt 
    763  1.11.6.1      yamt 	sf = savefile_open(infile, false);
    764  1.11.6.1      yamt 	if (sf == NULL) {
    765  1.11.6.1      yamt 		return 1;
    766  1.11.6.1      yamt 	}
    767  1.11.6.1      yamt 
    768  1.11.6.1      yamt 	if (savefile_rawread(sf, buf, headersize)) {
    769  1.11.6.1      yamt 		savefile_close(sf);
    770  1.11.6.1      yamt 		return 1;
    771  1.11.6.1      yamt 	}
    772  1.11.6.1      yamt 	buf[headersize] = 0;
    773  1.11.6.1      yamt 	if (strcmp(buf, header) != 0) {
    774  1.11.6.1      yamt 		savefile_close(sf);
    775  1.11.6.1      yamt 		fprintf(stderr, "Oh dear, that isn't one of my save files.\n");
    776  1.11.6.1      yamt 		fprintf(stderr,
    777  1.11.6.1      yamt 		    "Trying the Olde Waye; this myte notte Worke.\n");
    778  1.11.6.1      yamt 		return compat_restore(infile);
    779  1.11.6.1      yamt 	}
    780  1.11.6.1      yamt 
    781  1.11.6.1      yamt 	if (savefile_binread(sf, &version, sizeof(version))) {
    782  1.11.6.1      yamt 		savefile_close(sf);
    783  1.11.6.1      yamt 		return 1;
    784  1.11.6.1      yamt 	}
    785  1.11.6.1      yamt 	version = ntohl(version);
    786  1.11.6.1      yamt 	switch (version) {
    787  1.11.6.1      yamt 	    case FORMAT_VERSION:
    788  1.11.6.1      yamt 		break;
    789  1.11.6.1      yamt 	    case FORMAT_VERSION_NOSUM:
    790  1.11.6.1      yamt 		skipsum = true;
    791  1.11.6.1      yamt 		break;
    792  1.11.6.1      yamt 	    default:
    793  1.11.6.1      yamt 		savefile_close(sf);
    794  1.11.6.1      yamt 		fprintf(stderr,
    795  1.11.6.1      yamt 		    "Oh dear, that file must be from the future. I don't know"
    796  1.11.6.1      yamt 		    " how to read it!\n");
    797  1.11.6.1      yamt 		return 1;
    798  1.11.6.1      yamt 	}
    799  1.11.6.1      yamt 
    800  1.11.6.1      yamt 	if (savefile_binread(sf, &key, sizeof(key))) {
    801  1.11.6.1      yamt 		savefile_close(sf);
    802  1.11.6.1      yamt 		return 1;
    803  1.11.6.1      yamt 	}
    804  1.11.6.1      yamt 	key = ntohl(key);
    805  1.11.6.1      yamt 	savefile_key(sf, key);
    806  1.11.6.1      yamt 
    807  1.11.6.1      yamt 	/* other parts of the code may depend on us doing this here */
    808  1.11.6.1      yamt 	srandom(key);
    809  1.11.6.1      yamt 
    810  1.11.6.1      yamt 	/*
    811  1.11.6.1      yamt 	 * Integers
    812  1.11.6.1      yamt 	 */
    813  1.11.6.1      yamt 	for (i=0; i<num_save_ints; i++) {
    814  1.11.6.1      yamt 		if (savefile_cread(sf, &val, sizeof(val))) {
    815  1.11.6.1      yamt 			savefile_close(sf);
    816  1.11.6.1      yamt 			return 1;
    817  1.11.6.1      yamt 		}
    818  1.11.6.1      yamt 		val = ntohl(val);
    819  1.11.6.1      yamt 		*(save_ints[i]) = val;
    820  1.11.6.1      yamt 	}
    821  1.11.6.1      yamt 
    822  1.11.6.1      yamt 	/*
    823  1.11.6.1      yamt 	 * Arrays of integers
    824  1.11.6.1      yamt 	 */
    825  1.11.6.1      yamt 	for (i=0; i<num_save_intarrays; i++) {
    826  1.11.6.1      yamt 		n = save_intarrays[i].num;
    827  1.11.6.1      yamt 		for (j=0; j<n; j++) {
    828  1.11.6.1      yamt 			if (savefile_cread(sf, &val, sizeof(val))) {
    829  1.11.6.1      yamt 				savefile_close(sf);
    830  1.11.6.1      yamt 				return 1;
    831  1.11.6.1      yamt 			}
    832  1.11.6.1      yamt 			val = ntohl(val);
    833  1.11.6.1      yamt 			save_intarrays[i].ptr[j] = val;
    834  1.11.6.1      yamt 		}
    835  1.11.6.1      yamt 	}
    836  1.11.6.1      yamt 
    837  1.11.6.1      yamt #if 0
    838  1.11.6.1      yamt 	/*
    839  1.11.6.1      yamt 	 * Blobs
    840  1.11.6.1      yamt 	 */
    841  1.11.6.1      yamt 	for (i=0; i<num_save_blobs; i++) {
    842  1.11.6.1      yamt 		if (savefile_cread(sf, save_blobs[i].ptr, save_blobs[i].len)) {
    843  1.11.6.1      yamt 			savefile_close(sf);
    844  1.11.6.1      yamt 			return 1;
    845  1.11.6.1      yamt 		}
    846  1.11.6.1      yamt 	}
    847  1.11.6.1      yamt #endif
    848  1.11.6.1      yamt 
    849  1.11.6.1      yamt 	if (savefile_binread(sf, &sum, sizeof(&sum))) {
    850  1.11.6.1      yamt 		savefile_close(sf);
    851  1.11.6.1      yamt 		return 1;
    852  1.11.6.1      yamt 	}
    853  1.11.6.1      yamt 	sum = ntohl(sum);
    854  1.11.6.1      yamt 	/* See if she cheated */
    855  1.11.6.1      yamt 	if (!skipsum && sum != crc_get(&sf->crc)) {
    856  1.11.6.1      yamt 		/* Tsk tsk, altered the file */
    857  1.11.6.1      yamt 		savefile_close(sf);
    858  1.11.6.1      yamt 		return 2;
    859  1.11.6.1      yamt 	}
    860  1.11.6.1      yamt 	savefile_close(sf);
    861  1.11.6.1      yamt 
    862  1.11.6.1      yamt 	/* Load theoretically invalidates these */
    863  1.11.6.1      yamt 	tkk = NULL;
    864  1.11.6.1      yamt 	wd1 = NULL;
    865  1.11.6.1      yamt 	wd2 = NULL;
    866  1.11.6.1      yamt 
    867       1.1       jtc 	return 0;
    868       1.1       jtc }
    869