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