1 /*
2  * save and restore routines
3  *
4  * save.c	1.32	(A.I. Design)	12/13/84
5  */
6 
7 /*
8  *  routines for saving a program in any given state.
9  *  This is the first pass of this, so I have no idea
10  *  how it is really going to work.
11  *  The two basic functions here will be "save" and "restor".
12  */
13 
14 #include "rogue.h"
15 #include "curses.h"
16 
17 /*
18  * we need to know location of screen being saved
19  */
20 extern char *savewin;
21 extern int errno;
22 extern char _lowmem;			/* Adresss of first save-able memory */
23 extern char _Uend;				/* Address of end of user data space */
24 extern char do_force;
25 extern int bwflag;
26 
27 #define MIDSIZE 10
28 char *msaveid = "AI Design";
29 
30 #define printf printw
31 /*
32  * BLKSZ: size of block read/written on each io operation
33  *        Has to be less than 4096 and a factor of 4096
34  *        so the screen can be read in exactly.
35  */
36 #define BLKSZ 512
37 
38 /*
39  * save_game:
40  *	Implement the "save game" command
41  */
42 save_game()
43 {
44 #ifndef DEMO
45 	register int retcode;
46 	char savename[20];
47 
48     msg("");
49     mpos = 0;
50 	if (terse)
51 		addstr("Save file ? ");
52 	else
53     	printw("Save file (press enter (\x11\xd9) to default to \"%s\") ? ",
54     			s_save );
55 	retcode = getinfo(savename,19);
56 	if (*savename == 0)
57 		strcpy(savename,s_save);
58 	msg("");
59     mpos = 0;
60 	if (retcode != ESCAPE)
61 	{
62 		if ((retcode = save_ds(savename)) == -1)
63 		{
64 		    if (unlink(savename) == 0)
65 		    	ifterse1("out of space?","out of space, can not write %s",savename);
66 			msg("Sorry, you can't save the game just now");
67 		    is_saved = FALSE;
68 		}
69 		else if (retcode > 0)
70 			fatal("\nGame saved as %s.", savename);
71 	}
72 #endif	
73 }
74 #ifndef DEMO
75 /*
76  *  Save:
77  * 		Determine the entire data area that needs to be saved,
78  *		Open save file, first write in to save file a header
79  *		that demensions the data area that will be saved,
80  *		and then dump data area determined previous to opening
81  *		file.
82  */
83 save_ds(savename)
84 	char *savename;
85 {
86 	register int sfd;
87 	register char answer;
88 
89 	if ((sfd = open(savename, 0)) >= 0)
90 	{
91 		close(sfd);
92 		msg("%s %sexists, overwrite (y/n) ?",savename,noterse("already "));
93 		answer = readchar();
94 		msg("");
95 		if ((answer != 'y') && (answer != 'Y'))
96 			return(-2);
97 	}
98 	
99 	if ((sfd = creat(savename, 0666))  <= 0)
100 	{
101 		msg("Could not creat %s",savename);
102 		return (-2);
103 	}
104     is_saved = TRUE;
105     mpos = 0;
106 
107 	errno = 1;
108 	if (write(sfd,msaveid,MIDSIZE) != MIDSIZE
109 		|| write(sfd, &_lowmem , &_Uend - &_lowmem) != &_Uend-&_lowmem
110 			|| write(sfd, end_sb, startmem - end_sb) != startmem - end_sb)
111 			goto wr_err;
112 	/*
113 	 * save the screen (have to bring it into current data segment first)
114 	 */
115 	wdump();
116 	if (write(sfd,savewin,4000) == 4000)
117 		errno = 0;
118 	wrestor();
119 
120     wr_err:
121 		close(sfd);
122 		switch (errno)
123 		{
124 		    default:
125 		        msg("Could not write savefile to disk!");
126 		        return -1;
127 		    case 0:
128                 move(24,0);
129                 clrtoeol();
130                 move(23,0);
131 		        return 1;
132 		}
133 }
134 #endif DEMO
135 /*
136  *	Restore:
137  *		Open saved data file, read in header, and determine how much
138  *		data area is going to be restored,
139  *		Close save data file,
140  *		Allocate enough data space so that open data file information
141  *		will be stored outside the data area that will be restored,
142  *		Now reopen data save file,
143  *		skip header,
144  *		dump into memory all saved data.
145  */
146 restore(savefile)
147 char *savefile;
148 {
149 #ifndef DEMO
150     int oldrev, oldver, old_check;
151     register int oldcols, fd;
152     char errbuf[11], save_name[MAXSTR];
153     char *read_error = "Read Error";
154 	struct sw_regs *oregs;
155 	unsigned nbytes;
156 	char idbuf[MIDSIZE];
157 
158 	oregs = regs;
159 	winit();
160    	if (bwflag) 
161    	    forcebw();
162 	if (no_check == 0)
163 		no_check = do_force;
164 	old_check = no_check;
165 	strcpy(errbuf,read_error);
166 	/*
167 	 * save things that will be bombed on when the 
168 	 * restor takes place
169 	 */
170 	oldrev = revno;
171 	oldver = verno;
172 
173 	if (!strcmp(s_drive,"?"))
174 	{
175 		int ot = scr_type;
176 		printw("Press space to restart game");
177 		scr_type = -1;
178 		wait_for(' ');
179 		scr_type = ot;
180 		addstr("\n");
181 	}
182 	if ((fd = open(savefile, 0)) < 0) 
183 	    fatal("%s not found\n",savefile);
184 	else
185 	    printf("Restoring %s",savefile);
186 	strcpy(save_name, savefile);
187 	nbytes = &_Uend - &_lowmem;
188 	if (read(fd,idbuf,MIDSIZE) != MIDSIZE || strcmp(idbuf,msaveid) )
189 		addstr("\nNot a savefile\n");
190 	else 
191 	{
192 		if (read(fd, &_lowmem, nbytes) == nbytes)
193 			if (read(fd, end_sb,nbytes=startmem-end_sb) == nbytes)
194 				goto rok;
195 		addstr(errbuf);
196 	}
197 	close(fd);
198 	exit();
199 	
200 rok:
201 	regs = oregs;
202 	if (revno != oldrev || verno != oldver)
203 	{
204 		close(fd);
205 	    exit();
206 	}
207 
208     oldcols = COLS;
209 	brk(end_sb);					/* Restore heap to empty state */
210     init_ds();
211 	wclose();
212     winit();
213 	if (oldcols != COLS)
214 	{
215 		close(fd);
216 		fatal("Restore Error: new screen size\n");
217 	}
218 
219 	wdump();
220 	if (read(fd,savewin,4000) != 4000)
221 	{
222 		close(fd);
223 		fatal("Serious restore error");
224 	}
225     wrestor();
226 
227 	close (fd);
228 	no_check = old_check;
229     mpos = 0;
230     ifterse1("%s, Welcome back!","Hello %s, Welcome back to the Dungeons of Doom!",whoami);
231 	dnum = srand();     /* make it a little tougher on cheaters */
232 	unlink(save_name);
233 #endif DEMO
234 }
235 