NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / mac / macmain.c
blob351420e104393d4a7f97e76ae240c900cbcb64ac
1 /* aNetHack 0.0.1 macmain.c $ANH-Date: 1432512796 2015/05/25 00:13:16 $ $ANH-Branch: master $:$ANH-Revision: 1.21 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
5 /* main.c - Mac aNetHack */
7 #include "hack.h"
8 #include "dlb.h"
9 #include "macwin.h"
10 #include "mactty.h"
12 #if 1 /*!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
23 #ifndef O_RDONLY
24 #include <fcntl.h>
25 #endif
27 static void finder_file_request(void);
28 int main(void);
30 #if __SC__ || __MRC__
31 QDGlobals qd;
32 #endif
34 int
35 main(void)
37 register int fd = -1;
38 int argc = 1;
39 boolean resuming = FALSE; /* assume new game */
41 sys_early_init();
42 windowprocs = mac_procs;
43 InitMac();
45 hname = "Mac Hack";
46 hackpid = getpid();
48 setrandom();
49 initoptions();
50 init_nhwindows(&argc, (char **) &hname);
53 * It seems you really want to play.
55 u.uhp = 1; /* prevent RIP on early quits */
57 finder_file_request();
59 dlb_init(); /* must be before newgame() */
62 * Initialize the vision system. This must be before mklev() on a
63 * new game or before a level restore on a saved game.
65 vision_init();
67 display_gamewindows();
69 set_playmode(); /* sets plname to "wizard" for wizard mode */
70 /* strip role,race,&c suffix; calls askname() if plname[] is empty
71 or holds a generic user name like "player" or "games" */
72 plnamesuffix();
73 /* unlike Unix where the game might be invoked with a script
74 which forces a particular character name for each player
75 using a shared account, we always allow player to rename
76 the character during role/race/&c selection */
77 iflags.renameallowed = TRUE;
79 getlock();
82 * First, try to find and restore a save file for specified character.
83 * We'll return here if new game player_selection() renames the hero.
85 attempt_restore:
86 if ((fd = restore_saved_game()) >= 0) {
87 #ifdef NEWS
88 if (iflags.news) {
89 display_file(NEWS, FALSE);
90 iflags.news = FALSE; /* in case dorecover() fails */
92 #endif
93 pline("Restoring save file...");
94 mark_synch(); /* flush output */
95 game_active = 1;
96 if (dorecover(fd)) {
97 resuming = TRUE; /* not starting new game */
98 if (discover)
99 You("are in non-scoring discovery mode.");
100 if (discover || wizard) {
101 if (yn("Do you want to keep the save file?") == 'n')
102 (void) delete_savefile();
103 else {
104 nh_compress(fqname(SAVEF, SAVEPREFIX, 0));
110 if (!resuming) {
111 /* new game: start by choosing role, race, etc;
112 player might change the hero's name while doing that,
113 in which case we try to restore under the new name
114 and skip selection this time if that didn't succeed */
115 if (!iflags.renameinprogress) {
116 player_selection();
117 if (iflags.renameinprogress) {
118 /* player has renamed the hero while selecting role;
119 discard current lock file and create another for
120 the new character name */
121 delete_levelfile(0); /* remove empty lock file */
122 getlock();
123 goto attempt_restore;
126 game_active = 1; /* done with selection, draw active game window */
127 newgame();
128 if (discover)
129 You("are in non-scoring discovery mode.");
132 UndimMenuBar(); /* Yes, this is the place for it (!) */
134 moveloop(resuming);
136 exit(EXIT_SUCCESS);
137 /*NOTREACHED*/
138 return 0;
141 static OSErr
142 copy_file(short src_vol, long src_dir, short dst_vol, long dst_dir,
143 Str255 fName,
144 pascal OSErr (*opener)(short vRefNum, long dirID,
145 ConstStr255Param fileName,
146 signed char permission, short *refNum))
148 short src_ref, dst_ref;
149 OSErr err = (*opener)(src_vol, src_dir, fName, fsRdPerm, &src_ref);
150 if (err == noErr) {
151 err = (*opener)(dst_vol, dst_dir, fName, fsWrPerm, &dst_ref);
152 if (err == noErr) {
153 long file_len;
154 err = GetEOF(src_ref, &file_len);
155 if (err == noErr) {
156 Handle buf;
157 long count = MaxBlock();
158 if (count > file_len)
159 count = file_len;
161 buf = NewHandle(count);
162 err = MemError();
163 if (err == noErr) {
164 while (count > 0) {
165 OSErr rd_err = FSRead(src_ref, &count, *buf);
166 err = FSWrite(dst_ref, &count, *buf);
167 if (err == noErr)
168 err = rd_err;
169 file_len -= count;
171 if (file_len == 0)
172 err = noErr;
174 DisposeHandle(buf);
177 FSClose(dst_ref);
179 FSClose(src_ref);
182 return err;
185 static void
186 force_hdelete(short vol, long dir, Str255 fName)
188 HRstFLock(vol, dir, fName);
189 HDelete(vol, dir, fName);
192 void
193 process_openfile(short src_vol, long src_dir, Str255 fName, OSType ftype)
195 OSErr err = noErr;
197 if (ftype != SAVE_TYPE)
198 return; /* only deal with save files */
200 if (src_vol != theDirs.dataRefNum
201 || src_dir != theDirs.dataDirID
202 && CatMove(src_vol, src_dir, fName, theDirs.dataDirID, "\p:")
203 != noErr) {
204 HCreate(theDirs.dataRefNum, theDirs.dataDirID, fName, MAC_CREATOR,
205 SAVE_TYPE);
206 err =
207 copy_file(src_vol, src_dir, theDirs.dataRefNum, theDirs.dataDirID,
208 fName, &HOpen); /* HOpenDF is only there under 7.0 */
209 if (err == noErr)
210 err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
211 theDirs.dataDirID, fName, &HOpenRF);
212 if (err == noErr)
213 force_hdelete(src_vol, src_dir, fName);
214 else
215 HDelete(theDirs.dataRefNum, theDirs.dataDirID, fName);
218 if (err == noErr) {
219 short ref;
221 ref = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, fName,
222 fsRdPerm);
223 if (ref != -1) {
224 Handle name = Get1Resource('STR ', PLAYER_NAME_RES_ID);
225 if (name) {
226 Str255 save_f_p;
227 P2C(*(StringHandle) name, plname);
228 set_savefile_name(TRUE);
229 C2P(fqname(SAVEF, SAVEPREFIX, 0), save_f_p);
230 force_hdelete(theDirs.dataRefNum, theDirs.dataDirID,
231 save_f_p);
233 if (HRename(theDirs.dataRefNum, theDirs.dataDirID, fName,
234 save_f_p) == noErr)
235 macFlags.gotOpen = 1;
237 CloseResFile(ref);
242 static void
243 finder_file_request(void)
245 if (macFlags.hasAE) {
246 /* we're capable of handling Apple Events, so let's see if we have any
248 EventRecord event;
249 long toWhen = TickCount()
250 + 20; /* wait a third of a second for all initial AE */
252 while (TickCount() < toWhen) {
253 if (WaitNextEvent(highLevelEventMask, &event, 3L, 0)) {
254 AEProcessAppleEvent(&event);
255 if (macFlags.gotOpen)
256 break;
260 #if 0
261 #ifdef MAC68K
262 else {
263 short finder_msg, file_count;
264 CountAppFiles(&finder_msg, &file_count);
265 if (finder_msg == appOpen && file_count == 1) {
266 OSErr err;
267 AppFile src;
268 FSSpec filespec;
270 GetAppFiles(1, &src);
271 err = FSMakeFSSpec(src.vRefNum, 0, src.fName, &filespec);
272 if (err == noErr && src.fType == SAVE_TYPE) {
273 process_openfile (filespec.vRefNum, filespec.parID, filespec.name, src.fType);
274 if (macFlags.gotOpen)
275 ClrAppFiles(1);
279 #endif /* MAC68K */
280 #endif /* 0 */
283 /* validate wizard mode if player has requested access to it */
284 boolean
285 authorize_wizard_mode()
287 /* other ports validate user name or character name here */
288 return TRUE;
291 /*macmain.c*/