1 /*	SCCS Id: @(#)macmain.c	3.1	97/01/22	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /* main.c - Mac NetHack */
6 
7 #include "hack.h"
8 #include "dlb.h"
9 #include "macwin.h"
10 #include "mactty.h"
11 
12 #if !TARGET_API_MAC_CARBON
13 #include <OSUtils.h>
14 #include <files.h>
15 #include <Types.h>
16 #include <Dialogs.h>
17 #include <Packages.h>
18 #include <ToolUtils.h>
19 #include <Resources.h>
20 #include <Errors.h>
21 #endif
22 
23 #ifndef O_RDONLY
24 #include <fcntl.h>
25 #endif
26 
27 static void finder_file_request(void);
28 int main(void);
29 
30 #if __SC__ || __MRC__
31 QDGlobals qd;
32 #endif
33 
34 
35 int
main(void)36 main (void)
37 {
38 	register int fd = -1;
39 	int argc = 1;
40 
41 	windowprocs = mac_procs;
42 	InitMac ();
43 
44 	hname = "Mac Hack";
45 	hackpid = getpid();
46 
47 	/*
48 	 * Initialisation of the boundaries of the mazes
49 	 * Both boundaries have to be even.
50 	 */
51 
52 	x_maze_max = COLNO-1;
53 	if (x_maze_max % 2)
54 		x_maze_max--;
55 	y_maze_max = ROWNO-1;
56 	if (y_maze_max % 2)
57 		y_maze_max--;
58 
59 	setrandom();
60 	initoptions();
61 	init_nhwindows(&argc, (char **)&hname);
62 
63 	/*
64 	 * It seems you really want to play.
65 	 */
66 	u.uhp = 1;	/* prevent RIP on early quits */
67 
68 	finder_file_request ();
69 
70 	dlb_init();		/* must be before newgame() */
71 
72 	/*
73 	 *  Initialize the vision system.  This must be before mklev() on a
74 	 *  new game or before a level restore on a saved game.
75 	 */
76 	vision_init();
77 
78 	display_gamewindows();
79 
80 #ifdef WIZARD
81 	if (wizard)
82 		Strcpy(plname, "wizard");
83 	else
84 #endif
85 	if(!*plname || !strncmp(plname, "player", 4) || !strncmp(plname, "games", 4))
86 		askname();
87 	plnamesuffix();		/* strip suffix from name; calls askname() */
88 				/* again if suffix was whole name */
89 				/* accepts any suffix */
90 
91 	Sprintf (lock, "%d%s", getuid (), plname);
92 	getlock ();
93 
94 	if ((fd = restore_saved_game()) >= 0) {
95 #ifdef WIZARD
96 		/* Since wizard is actually flags.debug, restoring might
97 		 * overwrite it.
98 		 */
99 		boolean remember_wiz_mode = wizard;
100 #endif
101 #ifdef NEWS
102 		if(iflags.news) {
103 			display_file(NEWS, FALSE);
104 			iflags.news = FALSE;	/* in case dorecover() fails */
105 		}
106 #endif
107 		pline("Restoring save file...");
108 		mark_synch();	/* flush output */
109 		game_active = 1;
110 		if (dorecover(fd)) {
111 #ifdef WIZARD
112 			if(!wizard && remember_wiz_mode) wizard = TRUE;
113 #endif
114 			check_special_room(FALSE);
115 
116 			if (discover || wizard) {
117 				if(yn("Do you want to keep the save file?") == 'n')
118 					(void) delete_savefile();
119 				else {
120 					compress(fqname(SAVEF, SAVEPREFIX, 0));
121 				}
122 			}
123 		}
124 		else {
125 			fd = -1; /* set bad status */
126 		}
127 	}
128 	if (fd < 0) {
129 		player_selection();
130 		game_active = 1;	/* done with selection, draw active game window */
131 		newgame();
132 		set_wear();
133 		(void) pickup(1);
134 	}
135 
136 	if (discover)
137 		You("are in non-scoring discovery mode.");
138 	flags.move = 0;
139 
140 	UndimMenuBar (); /* Yes, this is the place for it (!) */
141 
142 	moveloop();
143 
144 	exit(EXIT_SUCCESS);
145 	/*NOTREACHED*/
146 	return 0;
147 }
148 
149 
150 static OSErr
copy_file(short src_vol,long src_dir,short dst_vol,long dst_dir,Str255 fName,pascal OSErr (* opener)(short vRefNum,long dirID,ConstStr255Param fileName,signed char permission,short * refNum))151 copy_file(short src_vol, long src_dir, short dst_vol, long dst_dir,
152 		Str255 fName,
153 		pascal OSErr (*opener)(short vRefNum, long dirID,
154 								ConstStr255Param fileName,
155 								signed char permission, short *refNum)) {
156 	short src_ref, dst_ref;
157 	OSErr err = (*opener)(src_vol, src_dir, fName, fsRdPerm, &src_ref);
158 	if (err == noErr) {
159 		err = (*opener)(dst_vol, dst_dir, fName, fsWrPerm, &dst_ref);
160 		if (err == noErr) {
161 
162 			long file_len;
163 			err = GetEOF(src_ref, &file_len);
164 			if (err == noErr) {
165 				Handle buf;
166 				long count = MaxBlock();
167 				if (count > file_len)
168 					count = file_len;
169 
170 				buf = NewHandle(count);
171 				err = MemError();
172 				if (err == noErr) {
173 
174 					while (count > 0) {
175 						OSErr rd_err = FSRead(src_ref, &count, *buf);
176 						err = FSWrite(dst_ref, &count, *buf);
177 						if (err == noErr)
178 							err = rd_err;
179 						file_len -= count;
180 					}
181 					if (file_len == 0)
182 						err = noErr;
183 
184 					DisposeHandle(buf);
185 
186 				}
187 			}
188 			FSClose(dst_ref);
189 		}
190 		FSClose(src_ref);
191 	}
192 
193 	return err;
194 }
195 
196 static void
force_hdelete(short vol,long dir,Str255 fName)197 force_hdelete(short vol, long dir, Str255 fName)
198 {
199 	HRstFLock(vol, dir, fName);
200 	HDelete (vol, dir, fName);
201 }
202 
203 
204 void
process_openfile(short src_vol,long src_dir,Str255 fName,OSType ftype)205 process_openfile (short src_vol, long src_dir, Str255 fName, OSType ftype)
206 {
207 	OSErr	err = noErr;
208 
209 	if (ftype != SAVE_TYPE)
210 		return;		/* only deal with save files */
211 
212 	if (src_vol != theDirs.dataRefNum || src_dir != theDirs.dataDirID &&
213 		 CatMove(src_vol, src_dir, fName, theDirs.dataDirID, "\p:") != noErr) {
214 
215 		HCreate(theDirs.dataRefNum, theDirs.dataDirID, fName, MAC_CREATOR, SAVE_TYPE);
216 		err = copy_file(src_vol, src_dir, theDirs.dataRefNum, theDirs.dataDirID,
217 						fName, &HOpen); /* HOpenDF is only there under 7.0 */
218 		if (err == noErr)
219 			err = copy_file(src_vol, src_dir, theDirs.dataRefNum, theDirs.dataDirID,
220 							fName, &HOpenRF);
221 		if (err == noErr)
222 			force_hdelete(src_vol, src_dir, fName);
223 		else
224 			HDelete(theDirs.dataRefNum, theDirs.dataDirID, fName);
225 	}
226 
227 	if (err == noErr) {
228 		short ref;
229 
230 		ref = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, fName, fsRdPerm);
231 		if (ref != -1) {
232 			Handle name = Get1Resource('STR ', PLAYER_NAME_RES_ID);
233 			if (name) {
234 				Str255 save_f_p;
235 				P2C(*(StringHandle)name, plname);
236 				set_savefile_name();
237 				C2P(fqname(SAVEF, SAVEPREFIX, 0), save_f_p);
238 				force_hdelete(theDirs.dataRefNum, theDirs.dataDirID, save_f_p);
239 
240 				if (HRename(theDirs.dataRefNum, theDirs.dataDirID, fName, save_f_p) == noErr)
241 					macFlags.gotOpen = 1;
242 			}
243 			CloseResFile(ref);
244 		}
245 	}
246 }
247 
248 
249 static void
finder_file_request(void)250 finder_file_request(void)
251 {
252 	if (macFlags.hasAE) {
253 		/* we're capable of handling Apple Events, so let's see if we have any */
254 		EventRecord event;
255 		long toWhen = TickCount () + 20;	/* wait a third of a second for all initial AE */
256 
257 		while (TickCount () < toWhen) {
258 			if (WaitNextEvent (highLevelEventMask, &event, 3L, 0)) {
259 				AEProcessAppleEvent(&event);
260 				if (macFlags.gotOpen)
261 					break;
262 			}
263 		}
264 	}
265 #if 0
266 #ifdef MAC68K
267 	else {
268 		short finder_msg, file_count;
269 		CountAppFiles(&finder_msg, &file_count);
270 		if (finder_msg == appOpen && file_count == 1) {
271 			OSErr	err;
272 			AppFile src;
273 			FSSpec filespec;
274 
275 			GetAppFiles(1, &src);
276 			err = FSMakeFSSpec(src.vRefNum, 0, src.fName, &filespec);
277 			if (err == noErr && src.fType == SAVE_TYPE) {
278 				process_openfile (filespec.vRefNum, filespec.parID, filespec.name, src.fType);
279 				if (macFlags.gotOpen)
280 					ClrAppFiles(1);
281 			}
282 		}
283 	}
284 #endif /* MAC68K */
285 #endif /* 0 */
286 }
287 
288 /*macmain.c*/
289