#include "angband.h"
+#ifdef MACH_O_CARBON
+
+#include <Carbon/Carbon.h>
+#include <QuickTime/QuickTime.h>
+#include <CoreServices/CoreServices.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#define TARGET_API_MAC_CARBON 1
+
+#else /* MACH_O_CARBON */
+
#include <Types.h>
#include <Gestalt.h>
#include <QuickDraw.h>
#include <Sound.h>
#if TARGET_API_MAC_CARBON
#include <Navigation.h>
+#include <CFPreferences.h>
+#include <CFNumber.h>
# ifdef MAC_MPW
# include <CarbonStdCLib.h>
# endif
#endif
+#endif /* MACH_O_CARBON */
+
+/*
+ * Use rewritten asynchronous sound player
+ */
+#define USE_ASYNC_SOUND
+
/*
* Cleaning up a couple of things to make these easier to change --AR
*/
/* #define USE_MALLOC */
+/* Default creator signature */
+#ifndef ANGBAND_CREATOR
+# define ANGBAND_CREATOR 'Heng'
+#endif
+
+
#if defined(powerc) || defined(__powerc)
/*
+#ifndef MACH_O_CARBON
#ifdef USE_SFL_CODE
/*
#include <Folders.h>
#endif
-
+#endif /* !MACH_O_CARBON */
/*
* Globals for MPW compilation
*/
#if defined(MACH_O_CARBON) || defined(MAC_MPW)
/* Globals needed */
+#if !TARGET_API_MAC_CARBON
+ QDGlobals qd;
+#endif
OSType _ftype;
OSType _fcreator;
#endif
*/
static bool CheckEvents(bool wait);
+#ifndef MACH_O_CARBON
/*
* Hack -- location of the main directory
static short app_vol;
static long app_dir;
+#endif /* !MACH_O_CARBON */
/*
* Delay handling of double-clicked savefiles
static long mac_os_version;
+#if defined(__MWERKS__)
/*
* CodeWarrior uses Universal Procedure Pointers
*/
static ModalFilterUPP ynfilterUPP;
+#endif /* __MWERKS__ */
+
#ifdef USE_SFL_CODE
/*
#endif
+# ifdef USE_ASYNC_SOUND
+
+/*
+ * Asynchronous sound player revised
+ */
+#if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
+# undef USE_QT_SOUND
+#endif /* USE_QT_SOUND && !MACH_O_CARBON */
+
+
+/*
+ * Number of channels in the channel pool
+ */
+#if TARGET_API_MAC_CARBON
+#define MAX_CHANNELS 8
+#else
+#define MAX_CHANNELS 4
+#endif
+
+/*
+ * A pool of sound channels
+ */
+static SndChannelPtr channels[MAX_CHANNELS];
+
+/*
+ * Status of the channel pool
+ */
+static Boolean channel_initialised = FALSE;
+
+/*
+ * Data handles containing sound samples
+ */
+static SndListHandle samples[SOUND_MAX];
+
+/*
+ * Reference counts of sound samples
+ */
+static SInt16 sample_refs[SOUND_MAX];
+
+
+/*
+ * Sound effects
+ *
+ * These constants aren't used by the program at the moment.
+ */
+#define SOUND_VOLUME_MIN 0 /* Default minimum sound volume */
+#define SOUND_VOLUME_MAX 255 /* Default maximum sound volume */
+#define VOLUME_MIN 0 /* Minimum sound volume in % */
+#define VOLUME_MAX 100 /* Maximum sound volume in % */
+#define VOLUME_INC 5 /* Increment sound volume in % */
+
+/* I'm just too lazy to write a panel for this XXX XXX */
+static SInt16 sound_volume = SOUND_VOLUME_MAX;
+
+#ifdef USE_QT_SOUND
+
+/*
+ * Moving graphics resources into data fork -- pelpel
+ *
+ * (Carbon, Bundle)
+ * Given base and type names of a resource, find a file in the
+ * current application bundle and return its FSSpec in the third argument.
+ * Returns true on success, false otherwise.
+ * e.g. get_resource_spec(CFSTR("8x8"), CFSTR("png"), &spec);
+ */
+static Boolean get_resource_spec(
+ CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
+{
+ CFURLRef res_url;
+ FSRef ref;
+
+ /* Find resource (=file) in the current bundle */
+ res_url = CFBundleCopyResourceURL(
+ CFBundleGetMainBundle(), base_name, type_name, NULL);
+
+ /* Oops */
+ if (res_url == NULL) return (false);
+
+ /* Convert CFURL to FSRef */
+ (void)CFURLGetFSRef(res_url, &ref);
+
+ /* Convert FSRef to FSSpec */
+ (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+
+ /* Free allocated CF data */
+ CFRelease(res_url);
+
+ /* Success */
+ return (true);
+}
+
+/*
+ * QuickTime sound, by Ron Anderson
+ *
+ * I didn't choose to use Windows-style .ini files (Ron wrote a parser
+ * for it, but...), nor did I use lib/xtra directory, hoping someone
+ * would code plist-based configuration code in the future -- pelpel
+ */
+
+/*
+ * (QuickTime)
+ * Load sound effects from data-fork resources. They are wav files
+ * with the same names as angband_sound_name[] (variable.c)
+ *
+ * Globals referenced: angband_sound_name[]
+ * Globals updated: samples[] (they can be *huge*)
+ */
+static void load_sounds(void)
+{
+ OSErr err;
+ int i;
+
+ /* Start QuickTime */
+ err = EnterMovies();
+
+ /* Error */
+ if (err != noErr) return;
+
+ /*
+ * This loop may take a while depending on the count and size of samples
+ * to load.
+ *
+ * We should use a progress dialog for this.
+ */
+ for (i = 1; i < SOUND_MAX; i++)
+ {
+ /* Apple APIs always give me headacke :( */
+ CFStringRef name;
+ FSSpec spec;
+ SInt16 file_id;
+ SInt16 res_id;
+ Str255 movie_name;
+ Movie movie;
+ Track track;
+ Handle h;
+ Boolean res;
+
+ /* Allocate CFString with the name of sound event to be processed */
+ name = CFStringCreateWithCString(NULL, angband_sound_name[i],
+ kTextEncodingUS_ASCII);
+
+ /* Error */
+ if (name == NULL) continue;
+
+ /* Find sound sample resource with the same name */
+ res = get_resource_spec(name, CFSTR("wav"), &spec);
+
+ /* Free the reference to CFString */
+ CFRelease(name);
+
+ /* Error */
+ if (!res) continue;
+
+ /* Open the sound file */
+ err = OpenMovieFile(&spec, &file_id, fsRdPerm);
+
+ /* Error */
+ if (err != noErr) continue;
+
+ /* Create Movie from the file */
+ err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
+ newMovieActive, NULL);
+
+ /* Error */
+ if (err != noErr) goto close_file;
+
+ /* Get the first track of the movie */
+ track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
+ movieTrackCharacteristic | movieTrackEnabledOnly );
+
+ /* Error */
+ if (track == NULL) goto close_movie;
+
+ /* Allocate a handle to store sample */
+ h = NewHandle(0);
+
+ /* Error */
+ if (h == NULL) goto close_track;
+
+ /* Dump the sample into the handle */
+ err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
+ GetTrackDuration(track), 0L, NULL);
+
+ /* Success */
+ if (err == noErr)
+ {
+ /* Store the handle in the sample list */
+ samples[i] = (SndListHandle)h;
+ }
+
+ /* Failure */
+ else
+ {
+ /* Free unused handle */
+ DisposeHandle(h);
+ }
+
+ /* Free the track */
+ close_track: DisposeMovieTrack(track);
+
+ /* Free the movie */
+ close_movie: DisposeMovie(movie);
+
+ /* Close the movie file */
+ close_file: CloseMovieFile(file_id);
+ }
+
+ /* Stop QuickTime */
+ ExitMovies();
+}
+
+#else /* USE_QT_SOUND */
+
+/*
+ * Return a handle of 'snd ' resource given Angband sound event number,
+ * or NULL if it isn't found.
+ *
+ * Globals referenced: angband_sound_name[] (variable.c)
+ */
+static SndListHandle find_sound(int num)
+{
+ Str255 sound;
+
+ /* Get the proper sound name */
+ strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
+ sound[0] = strlen((char*)sound + 1);
+
+ /* Obtain resource XXX XXX XXX */
+ return ((SndListHandle)GetNamedResource('snd ', sound));
+}
+
+#endif /* USE_QT_SOUND */
+
+
+/*
+ * Clean up sound support - to be called when the game exits.
+ *
+ * Globals referenced: channels[], samples[], sample_refs[].
+ */
+static void cleanup_sound(void)
+{
+ int i;
+
+ /* No need to clean it up */
+ if (!channel_initialised) return;
+
+ /* Dispose channels */
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ /* Drain sound commands and free the channel */
+ SndDisposeChannel(channels[i], TRUE);
+ }
+
+ /* Free sound data */
+ for (i = 1; i < SOUND_MAX; i++)
+ {
+ /* Still locked */
+ if ((sample_refs[i] > 0) && (samples[i] != NULL))
+ {
+ /* Unlock it */
+ HUnlock((Handle)samples[i]);
+ }
+
+#ifndef USE_QT_SOUND
+
+ /* Release it */
+ if (samples[i]) ReleaseResource((Handle)samples[i]);
+#else
+
+ /* Free handle */
+ if (samples[i]) DisposeHandle((Handle)samples[i]);
+#endif /* !USE_QT_SOUND */
+ }
+}
+
+
+/*
+ * Play sound effects asynchronously -- pelpel
+ *
+ * I don't believe those who first started using the previous implementations
+ * imagined this is *much* more complicated as it may seem. Anyway,
+ * introduced round-robin scheduling of channels and made it much more
+ * paranoid about HLock/HUnlock.
+ *
+ * XXX XXX de-refcounting, HUnlock and ReleaseResource should be done
+ * using channel's callback procedures, which set global flags, and
+ * a procedure hooked into CheckEvents does housekeeping. On the other
+ * hand, this lazy reclaiming strategy keeps things simple (no interrupt
+ * time code) and provides a sort of cache for sound data.
+ *
+ * Globals referenced: channel_initialised, channels[], samples[],
+ * sample_refs[].
+ * Globals updated: ditto.
+ */
+static void play_sound(int num, SInt16 vol)
+{
+ OSErr err;
+ int i;
+ int prev_num;
+ SndListHandle h;
+ SndChannelPtr chan;
+ SCStatus status;
+
+ static int next_chan;
+ static SInt16 channel_occupants[MAX_CHANNELS];
+ static SndCommand volume_cmd, quiet_cmd;
+
+
+ /* Initialise sound channels */
+ if (!channel_initialised)
+ {
+ for (i = 0; i < MAX_CHANNELS; i++)
+ {
+ /* Paranoia - Clear occupant table */
+ /* channel_occupants[i] = 0; */
+
+ /* Create sound channel for all sounds to play from */
+ err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
+
+ /* Error */
+ if (err != noErr)
+ {
+ /* Free channels */
+ while (--i >= 0)
+ {
+ SndDisposeChannel(channels[i], TRUE);
+ }
+
+ /* Notify error */
+#ifdef JP
+ plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
+#else
+ plog("Cannot initialise sound channels!");
+#endif
+
+ /* Cancel request */
+ use_sound = arg_sound = FALSE;
+
+ /* Failure */
+ return;
+ }
+ }
+
+ /* First channel to use */
+ next_chan = 0;
+
+ /* Prepare volume command */
+ volume_cmd.cmd = volumeCmd;
+ volume_cmd.param1 = 0;
+ volume_cmd.param2 = 0;
+
+ /* Prepare quiet command */
+ quiet_cmd.cmd = quietCmd;
+ quiet_cmd.param1 = 0;
+ quiet_cmd.param2 = 0;
+
+ /* Initialisation complete */
+ channel_initialised = TRUE;
+ }
+
+ /* Paranoia */
+ if ((num <= 0) || (num >= SOUND_MAX)) return;
+
+ /* Prepare volume command */
+ volume_cmd.param2 = ((SInt32)vol << 16) | vol;
+
+ /* Channel to use (round robin) */
+ chan = channels[next_chan];
+
+ /* See if the resource is already in use */
+ if (sample_refs[num] > 0)
+ {
+ /* Resource in use */
+ h = samples[num];
+
+ /* Increase the refcount */
+ sample_refs[num]++;
+ }
+
+ /* Sound is not currently in use */
+ else
+ {
+ /* Get handle for the sound */
+#ifdef USE_QT_SOUND
+ h = samples[num];
+#else
+ h = find_sound(num);
+#endif /* USE_QT_SOUND */
+
+ /* Sample not available */
+ if (h == NULL) return;
+
+#ifndef USE_QT_SOUND
+
+ /* Load resource */
+ LoadResource((Handle)h);
+
+ /* Remember it */
+ samples[num] = h;
+
+#endif /* !USE_QT_SOUND */
+
+ /* Lock the handle */
+ HLockHi((Handle)h);
+
+ /* Initialise refcount */
+ sample_refs[num] = 1;
+ }
+
+ /* Poll the channel */
+ err = SndChannelStatus(chan, sizeof(SCStatus), &status);
+
+ /* It isn't available */
+ if ((err != noErr) || status.scChannelBusy)
+ {
+ /* Shut it down */
+ SndDoImmediate(chan, &quiet_cmd);
+ }
+
+ /* Previously played sound on this channel */
+ prev_num = channel_occupants[next_chan];
+
+ /* Process previously played sound */
+ if (prev_num != 0)
+ {
+ /* Decrease refcount */
+ sample_refs[prev_num]--;
+
+ /* We can free it now */
+ if (sample_refs[prev_num] <= 0)
+ {
+ /* Unlock */
+ HUnlock((Handle)samples[prev_num]);
+
+#ifndef USE_QT_SOUND
+
+ /* Release */
+ ReleaseResource((Handle)samples[prev_num]);
+
+ /* Forget handle */
+ samples[prev_num] = NULL;
+
+#endif /* !USE_QT_SOUND */
+
+ /* Paranoia */
+ sample_refs[prev_num] = 0;
+ }
+ }
+
+ /* Remember this sound as the current occupant of the channel */
+ channel_occupants[next_chan] = num;
+
+ /* Set up volume for channel */
+ SndDoImmediate(chan, &volume_cmd);
+
+ /* Play new sound asynchronously */
+ SndPlay(chan, h, TRUE);
+
+ /* Schedule next channel (round robin) */
+ next_chan++;
+ if (next_chan >= MAX_CHANNELS) next_chan = 0;
+}
+
+# else /* USE_ASYNC_SOUND */
+
+/*
+ * Play sound synchronously
+ *
+ * This may not be your choice, but much safer and much less resource hungry.
+ */
+static void play_sound(int num, SInt16 vol)
+{
+ Handle handle;
+ Str255 sound;
+
+ /* Get the proper sound name */
+ strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
+ sound[0] = strlen((char*)sound + 1);
+
+ /* Obtain resource XXX XXX XXX */
+ handle = GetNamedResource('snd ', sound);
+
+ /* Oops */
+ if (handle == NULL) return;
+
+ /* Load and Lock */
+ LoadResource(handle);
+ HLockHi(handle);
+
+ /* Play sound (wait for completion) */
+ SndPlay(NULL, (SndListHandle)handle, FALSE);
+
+ /* Unlock and release */
+ HUnlock(handle);
+ ReleaseResource(handle);
+}
+
+# endif /* USE_ASYNC_SOUND */
+
+#ifndef MACH_O_CARBON
+
/*
Extra Sound Mode
*/
SND_TRAP,
};
-static int soundmode[8];
-
static int ext_graf = 0;
+#endif /* !MACH_O_CARBON */
+
+static short soundmode[8];
/*
static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
{
CInfoPBRec pb;
- Str255 name;
int err;
int i, j;
#endif
+#if !TARGET_API_MAC_CARBON
static void local_to_global( Rect *r )
{
Point temp;
r->right = temp.h;
r->bottom = temp.v;
}
+#endif /* !TARGET_API_MAC_CARBON */
static void global_to_local( Rect *r )
{
}
+#ifdef MACH_O_CARBON
+
+/* Carbon File Manager utilities by pelpel */
+
+/*
+ * (Carbon)
+ * Convert a pathname to a corresponding FSSpec.
+ * Returns noErr on success.
+ */
+static OSErr path_to_spec(const char *path, FSSpec *spec)
+{
+ OSErr err;
+ FSRef ref;
+
+ /* Convert pathname to FSRef ... */
+ err = FSPathMakeRef(path, &ref, NULL);
+ if (err != noErr) return (err);
+
+ /* ... then FSRef to FSSpec */
+ err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+
+ /* Inform caller of success or failure */
+ return (err);
+}
+
+
+/*
+ * (Carbon)
+ * Convert a FSSpec to a corresponding pathname.
+ * Returns noErr on success.
+ */
+static OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
+{
+ OSErr err;
+ FSRef ref;
+
+ /* Convert FSSpec to FSRef ... */
+ err = FSpMakeFSRef(spec, &ref);
+ if (err != noErr) return (err);
+
+ /* ... then FSRef to pathname */
+ err = FSRefMakePath(&ref, buf, size);
+
+ /* Inform caller of success or failure */
+ return (err);
+}
+
+
+/*
+ * (Carbon) [via path_to_spec]
+ * Set creator and filetype of a file specified by POSIX-style pathname.
+ * Returns 0 on success, -1 in case of errors.
+ */
+void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
+{
+ OSErr err;
+ FSSpec spec;
+ FInfo info;
+
+ /* Convert pathname to FSSpec */
+ if (path_to_spec(pathname, &spec) != noErr) return;
+
+ /* Obtain current finder info of the file */
+ if (FSpGetFInfo(&spec, &info) != noErr) return;
+
+ /* Overwrite creator and type */
+ info.fdCreator = fcreator;
+ info.fdType = ftype;
+ err = FSpSetFInfo(&spec, &info);
+
+ /* Done */
+ return;
+}
+
+
+#else /* MACH_O_CARBON */
+
+
/*
* Convert a pascal string in place
*
}
#endif
-
-#if TARGET_API_MAC_CARBON
-
-static OSErr ChooseFile( StringPtr filename, FSSpec selfld )
-{
- NavReplyRecord reply;
- NavDialogOptions dialogOptions;
- NavTypeListHandle navTypeList = NULL;
- OSErr err;
- AEDesc deffld;
-
- AECreateDesc( typeFSS, &selfld, sizeof(FSSpec), &deffld );
-
- err = NavGetDefaultDialogOptions( &dialogOptions );
-
- if( err == noErr ){
-
- err = NavChooseFile( &deffld, &reply, &dialogOptions, NULL, NULL, NULL, navTypeList, NULL );
-
- if ( reply.validRecord && err == noErr ){
- // grab the target FSSpec from the AEDesc:
- FSSpec finalFSSpec;
- AEKeyword keyWord;
- DescType typeCode;
- Size actualSize = 0;
-
- // retrieve the returned selection:
- // there is only one selection here we get only the first AEDescList:
- if (( err = AEGetNthPtr( &(reply.selection), 1, typeFSS, &keyWord, &typeCode, &finalFSSpec, sizeof( FSSpec ), &actualSize )) == noErr )
- {
- refnum_to_name( (char *)filename, finalFSSpec.parID, finalFSSpec.vRefNum, (char *)finalFSSpec.name );
- // 'finalFSSpec' is the chosen file¥Î
- }
-
- err = NavDisposeReply( &reply );
- }
- if( navTypeList != NULL )
- {
- DisposeHandle( (Handle)navTypeList );
- navTypeList = NULL;
- }
- }
-
- AEDisposeDesc( &deffld );
-
- return err;
-}
-
-#endif
+#endif /* MACH_O_CARBON */
/*
* Activate a given window, if necessary
/* Block */
{
- Rect tempRect;
Rect globalRect;
GDHandle mainGDH;
GDHandle currentGDH;
/* Make a sound */
case TERM_XTRA_SOUND:
{
- Handle handle;
-
- Str255 sound;
-
-#if 0
- short oldResFile;
- short newResFile;
-
- /* Open the resource file */
- oldResFile = CurResFile();
- newResFile = OpenResFile(sound);
-
- /* Close the resource file */
- CloseResFile(newResFile);
- UseResFile(oldResFile);
-#endif
-
- /* Get the proper sound name */
- sprintf((char*)sound + 1, "%.16s.wav", angband_sound_name[v]);
- sound[0] = strlen((char*)sound + 1);
-
- /* Obtain resource XXX XXX XXX */
- handle = Get1NamedResource('snd ', sound);
- if( handle == NULL || ext_sound )
- handle = GetNamedResource('snd ', sound);
-
- /* Oops */
- if (handle && soundmode[soundchoice[v]] == true)
- {
- /* Load and Lock */
- LoadResource(handle);
- HLock(handle);
-
- /* Play sound (wait for completion) */
- SndPlay(nil, (SndListHandle)handle, true);
+ /* Play sound */
+ play_sound(v, sound_volume);
- /* Unlock and release */
- HUnlock(handle);
- ReleaseResource(handle);
- }
/* Success */
return (0);
}
* Even if ticks are 0, it's worth calling for
* the above mentioned reasons.
*/
- WaitNextEvent(~everyEvent, &tmp, ticks, nil);
+ WaitNextEvent((EventMask)~everyEvent, &tmp, ticks, nil);
#else
long m = TickCount() + (v * 60L) / 1000;
*
* Erase "n" characters starting at (x,y)
*/
-#ifdef USE_TRANSPARENCY
static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp,
const byte *tap, const char *tcp)
-#else
-static errr Term_pict_mac(int x, int y, int n, const byte *ap, const char *cp)
-#endif
{
int i;
Rect r2;
GDHandle saveGDevice;
GWorldPtr saveGWorld;
- PixMapHandle PortPix;
-
/* Save GWorld */
GetGWorld(&saveGWorld, &saveGDevice);
int col, row;
Rect r1;
-#ifdef USE_TRANSPARENCY
Rect terrain_r;
bool terrain_flag = FALSE;
byte ta = tap[i];
terrain_flag = TRUE;
}
-#endif
/* Row and Col */
row = ((byte)a & 0x7F);
#endif
if (use_bigtile) r2.right += td->tile_wid;
-#ifdef USE_TRANSPARENCY
if (terrain_flag)
{
/*
#endif
}
else
-#endif /* USE_TRANSPARENCY */
{
#if TARGET_API_MAC_CARBON
CopyBits( (BitMap *) *srcBitMap, (BitMap *) *destBitMap, &r1, &r2, srcCopy, NULL);
+#ifdef MACH_O_CARBON
+
+/*
+ * (Carbon, Bundle)
+ * Return a POSIX pathname of the lib directory, or NULL if it can't be
+ * located. Caller must supply a buffer along with its size in bytes,
+ * where returned pathname will be stored.
+ * I prefer use of goto's to several nested if's, if they involve error
+ * handling. Sorry if you are offended by their presence. Modern
+ * languages have neater constructs for this kind of jobs -- pelpel
+ */
+static char *locate_lib(char *buf, size_t size)
+{
+ CFURLRef main_url = NULL;
+ CFStringRef main_str = NULL;
+ char *p;
+ char *res = NULL;
+
+ /* Obtain the URL of the main bundle */
+ main_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
+
+ /* Oops */
+ if (main_url == NULL) goto ret;
+
+ /* Convert it to POSIX pathname */
+ main_str = CFURLCopyFileSystemPath(main_url, kCFURLPOSIXPathStyle);
+
+ /* Oops */
+ if (main_str == NULL) goto ret;
+
+ /* Convert it again from darn unisomething encoding to ASCII */
+ if (CFStringGetCString(main_str, buf, size, kTextEncodingUS_ASCII) == FALSE)
+ goto ret;
+
+ /* Find the last '/' in the pathname */
+ p = strrchr(buf, '/');
+
+ /* Paranoia - cannot happen */
+ if (p == NULL) goto ret;
+
+ /* Remove the trailing path */
+ *p = '\0';
+
+ /*
+ * Paranoia - bounds check, with 5 being the length of "/lib/"
+ * and 1 for terminating '\0'.
+ */
+ if (strlen(buf) + 5 + 1 > size) goto ret;
+
+ /* Append "/lib/" */
+ strcat(buf, "/lib/");
+
+ /* Set result */
+ res = buf;
+
+ret:
+
+ /* Release objects allocated and implicitly retained by the program */
+ if (main_str) CFRelease(main_str);
+ if (main_url) CFRelease(main_url);
+
+ /* pathname of the lib folder or NULL */
+ return (res);
+}
+
+
+#else /* MACH_O_CARBON */
+
+
+/*
+ * Set the "current working directory" (also known as the "default"
+ * volume/directory) to the location of the current application.
+ *
+ * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
+ *
+ * This function does not appear to work correctly with System 6.
+ */
+static void SetupAppDir(void)
+{
+ FCBPBRec fcbBlock;
+ OSErr err = noErr;
+ char errString[100];
+
+ /* Get the location of the Angband executable */
+ fcbBlock.ioCompletion = NULL;
+ fcbBlock.ioNamePtr = NULL;
+ fcbBlock.ioVRefNum = 0;
+ fcbBlock.ioRefNum = CurResFile();
+ fcbBlock.ioFCBIndx = 0;
+ err = PBGetFCBInfo(&fcbBlock, FALSE);
+ if (err != noErr)
+ {
+#ifdef JP
+ sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
+#else
+ sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
+#endif
+ mac_warning(errString);
+ ExitToShell();
+ }
+
+ /* Extract the Vol and Dir */
+ app_vol = fcbBlock.ioFCBVRefNum;
+ app_dir = fcbBlock.ioFCBParID;
+
+ /* Set the current working directory to that location */
+ err = HSetVol(NULL, app_vol, app_dir);
+ if (err != noErr)
+ {
+#ifdef JP
+ sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
+#else
+ sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
+#endif
+ mac_warning(errString);
+ ExitToShell();
+ }
+}
+
+#endif
+
+
+
+#if TARGET_API_MAC_CARBON
+/*
+ * Using Core Foundation's Preferences services -- pelpel
+ *
+ * Requires OS 8.6 or greater with CarbonLib 1.1 or greater. Or OS X,
+ * of course.
+ *
+ * Without this, we can support older versions of OS 8 as well
+ * (with CarbonLib 1.0.4).
+ *
+ * Frequent allocation/deallocation of small chunks of data is
+ * far from my liking, but since this is only called at the
+ * beginning and the end of a session, I hope this hardly matters.
+ */
+
+
+/*
+ * Store "value" as the value for preferences item name
+ * pointed by key
+ */
+static void save_pref_short(const char *key, short value)
+{
+ CFStringRef cf_key;
+ CFNumberRef cf_value;
+
+ /* allocate and initialise the key */
+ cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
+
+ /* allocate and initialise the value */
+ cf_value = CFNumberCreate(NULL, kCFNumberShortType, &value);
+
+ if ((cf_key != NULL) && (cf_value != NULL))
+ {
+ /* Store the key-value pair in the applications preferences */
+ CFPreferencesSetAppValue(
+ cf_key,
+ cf_value,
+ kCFPreferencesCurrentApplication);
+ }
+
+ /*
+ * Free CF data - the reverse order is a vain attempt to
+ * minimise memory fragmentation.
+ */
+ if (cf_value) CFRelease(cf_value);
+ if (cf_key) CFRelease(cf_key);
+}
+
+
+/*
+ * Load preference value for key, returns TRUE if it succeeds with
+ * vptr updated appropriately, FALSE otherwise.
+ */
+static bool query_load_pref_short(const char *key, short *vptr)
+{
+ CFStringRef cf_key;
+ CFNumberRef cf_value;
+
+ /* allocate and initialise the key */
+ cf_key = CFStringCreateWithCString(NULL, key, kTextEncodingUS_ASCII);
+
+ /* Oops */
+ if (cf_key == NULL) return (FALSE);
+
+ /* Retrieve value for the key */
+ cf_value = CFPreferencesCopyAppValue(
+ cf_key,
+ kCFPreferencesCurrentApplication);
+
+ /* Value not found */
+ if (cf_value == NULL)
+ {
+ CFRelease(cf_key);
+ return (FALSE);
+ }
+
+ /* Convert the value to short */
+ CFNumberGetValue(
+ cf_value,
+ kCFNumberShortType,
+ vptr);
+
+ /* Free CF data */
+ CFRelease(cf_value);
+ CFRelease(cf_key);
+
+ /* Success */
+ return (TRUE);
+}
+
+
+/*
+ * Update short data pointed by vptr only if preferences
+ * value for key is located.
+ */
+static void load_pref_short(const char *key, short *vptr)
+{
+ short tmp;
+
+ if (query_load_pref_short(key, &tmp)) *vptr = tmp;
+ return;
+}
+
+
+/*
+ * Save preferences to preferences file for current host+current user+
+ * current application.
+ */
+static void cf_save_prefs()
+{
+ int i;
+
+ /* Version stamp */
+ save_pref_short("version.major", FAKE_VERSION);
+ save_pref_short("version.minor", FAKE_VER_MAJOR);
+ save_pref_short("version.patch", FAKE_VER_MINOR);
+ save_pref_short("version.extra", FAKE_VER_PATCH);
+
+ /* Gfx settings */
+ save_pref_short("arg.arg_sound", arg_sound);
+ save_pref_short("arg.arg_graphics", arg_graphics);
+ save_pref_short("arg.arg_newstyle_graphics", arg_newstyle_graphics);
+ save_pref_short("arg.arg_bigtile", arg_bigtile);
+
+#ifndef MACH_O_CARBON
+
+ /* SoundMode */
+ for( i = 0 ; i < 7 ; i++ )
+ save_pref_short(format("sound%d.on", i), soundmode[i]);
+
+#endif /* MACH_O_CARBON */
+
+ /* Windows */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ term_data *td = &data[i];
+
+ save_pref_short(format("term%d.mapped", i), td->mapped);
+
+ save_pref_short(format("term%d.font_id", i), td->font_id);
+ save_pref_short(format("term%d.font_size", i), td->font_size);
+ save_pref_short(format("term%d.font_face", i), td->font_face);
+
+ save_pref_short(format("term%d.tile_wid", i), td->tile_wid);
+ save_pref_short(format("term%d.tile_hgt", i), td->tile_hgt);
+
+ save_pref_short(format("term%d.cols", i), td->cols);
+ save_pref_short(format("term%d.rows", i), td->rows);
+ save_pref_short(format("term%d.left", i), td->r.left);
+ save_pref_short(format("term%d.top", i), td->r.top);
+ }
+
+ /*
+ * Make sure preferences are persistent
+ */
+ CFPreferencesAppSynchronize(
+ kCFPreferencesCurrentApplication);
+}
+
/*
- * Set the "current working directory" (also known as the "default"
- * volume/directory) to the location of the current application.
- *
- * Code by: Maarten Hazewinkel (mmhazewi@cs.ruu.nl)
- *
- * This function does not appear to work correctly with System 6.
+ * Load preferences from preferences file for current host+current user+
+ * current application.
*/
-static void SetupAppDir(void)
+static void cf_load_prefs()
{
- FCBPBRec fcbBlock;
- OSErr err = noErr;
- char errString[100];
+ bool ok;
+ short pref_major, pref_minor, pref_patch, pref_extra;
+ int i;
- /* Get the location of the Angband executable */
- fcbBlock.ioCompletion = NULL;
- fcbBlock.ioNamePtr = NULL;
- fcbBlock.ioVRefNum = 0;
- fcbBlock.ioRefNum = CurResFile();
- fcbBlock.ioFCBIndx = 0;
- err = PBGetFCBInfo(&fcbBlock, FALSE);
- if (err != noErr)
+ MenuHandle m;
+
+ /* Assume nothing is wrong, yet */
+ ok = TRUE;
+
+ /* Load version information */
+ ok &= query_load_pref_short("version.major", &pref_major);
+ ok &= query_load_pref_short("version.minor", &pref_minor);
+ ok &= query_load_pref_short("version.patch", &pref_patch);
+ ok &= query_load_pref_short("version.extra", &pref_extra);
+
+ /* Any of the above failed */
+ if (!ok)
{
+ /* This may be the first run */
#ifdef JP
- sprintf(errString, "PBGetFCBInfo ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
+ mac_warning("½é´üÀßÄê¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤ê¤Þ¤»¤ó¡£");
#else
- sprintf(errString, "Fatal PBGetFCBInfo Error #%d.\r Exiting.", err);
+ mac_warning("Preferences are not found.");
#endif
- mac_warning(errString);
- ExitToShell();
+
+ /* Ignore the rest */
+ return;
}
- /* Extract the Vol and Dir */
- app_vol = fcbBlock.ioFCBVRefNum;
- app_dir = fcbBlock.ioFCBParID;
+#if 0
- /* Set the current working directory to that location */
- err = HSetVol(NULL, app_vol, app_dir);
- if (err != noErr)
+ /* Check version */
+ if ((pref_major != PREF_VER_MAJOR) ||
+ (pref_minor != PREF_VER_MINOR) ||
+ (pref_patch != PREF_VER_PATCH) ||
+ (pref_extra != PREF_VER_EXTRA))
{
-#ifdef JP
- sprintf(errString, "HSetVol ¥¨¥é¡¼ #%d.\r ½ªÎ»¤·¤Þ¤¹.", err);
-#else
- sprintf(errString, "Fatal HSetVol Error #%d.\r Exiting.", err);
+ /* Message */
+ mac_warning(
+ format("Ignoring %d.%d.%d.%d preferences.",
+ pref_major, pref_minor, pref_patch, pref_extra));
+
+ /* Ignore */
+ return;
+ }
+
#endif
- mac_warning(errString);
- ExitToShell();
+
+ /* Gfx settings */
+ {
+ short pref_tmp;
+
+ /* sound */
+ if (query_load_pref_short("arg.arg_sound", &pref_tmp))
+ arg_sound = pref_tmp;
+
+ /* graphics */
+ if (query_load_pref_short("arg.arg_graphics", &pref_tmp))
+ arg_graphics = pref_tmp;
+
+ /*newstyle graphics*/
+ if (query_load_pref_short("arg.arg_newstyle_graphics", &pref_tmp))
+ {
+ use_newstyle_graphics = pref_tmp;
+ }
+
+ if (use_newstyle_graphics == true)
+ {
+ ANGBAND_GRAF = "new";
+ arg_newstyle_graphics = true;
+ grafWidth = grafHeight = 16;
+ pictID = 1002;
+ }
+ else
+ {
+ ANGBAND_GRAF = "old";
+ arg_newstyle_graphics = false;
+ grafWidth = grafHeight = 8;
+ pictID = 1001;
+ }
+
+ /* double-width tiles */
+ if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
+ {
+ use_bigtile = pref_tmp;
+ }
+
}
-}
+#ifndef MACH_O_CARBON
+
+ /* SoundMode */
+ for( i = 0 ; i < 7 ; i++ )
+ {
+ query_load_pref_short(format("sound%d.on", i), &soundmode[i]);
+ }
+
+#endif /* MACH_O_CARBON */
+
+ /* Special menu */
+ m = GetMenuHandle(134);
+
+ /* Item "arg_sound" */
+ CheckMenuItem(m, 1, arg_sound);
+
+ /* Item "arg_graphics" */
+ CheckMenuItem(m, 2, arg_graphics);
+
+ /* Item "arg_newstyle_graphics"*/
+ CheckMenuItem(m, 8, arg_newstyle_graphics);
+
+ /* Item "arg_bigtile"*/
+ CheckMenuItem(m, 9, arg_bigtile);
+
+ /* Windows */
+ for (i = 0; i < MAX_TERM_DATA; i++)
+ {
+ term_data *td = &data[i];
+
+ load_pref_short(format("term%d.mapped", i), &td->mapped);
+
+ load_pref_short(format("term%d.font_id", i), &td->font_id);
+ load_pref_short(format("term%d.font_size", i), &td->font_size);
+ load_pref_short(format("term%d.font_face", i), &td->font_face);
+ load_pref_short(format("term%d.tile_wid", i), &td->tile_wid);
+ load_pref_short(format("term%d.tile_hgt", i), &td->tile_hgt);
+ load_pref_short(format("term%d.cols", i), &td->cols);
+ load_pref_short(format("term%d.rows", i), &td->rows);
+ load_pref_short(format("term%d.left", i), &td->r.left);
+ load_pref_short(format("term%d.top", i), &td->r.top);
+ }
+}
+#else
/*
* Global "preference" file pointer
*/
/* Special menu */
m = GetMenuHandle(134);
-#if TARGET_API_MAC_CARBON
- /* Item "arg_sound" */
- CheckMenuItem(m, 1, arg_sound);
-
- /* Item "arg_graphics" */
- CheckMenuItem(m, 2, arg_graphics);
-
- /* Item "arg_newstyle_graphics"*/
- CheckMenuItem(m, 8, arg_newstyle_graphics);
-#else
/* Item "arg_sound" */
CheckItem(m, 1, arg_sound);
/* Item "arg_newstyle_graphics"*/
CheckItem(m, 8, arg_newstyle_graphics);
-#endif
+
+ /* Item "arg_bigtile"*/
+ CheckItem(m, 9, arg_bigtile);
/* Windows */
for (i = 0; i < MAX_TERM_DATA; i++)
if (feof(fff)) break;
}
}
-
+#endif /* TARGET_API_MAC_CARBON */
{
short fid;
-#ifdef JP
#if TARGET_API_MAC_CARBON
+#ifdef JP
/* Default to Osaka font (Japanese) */
fid = FMGetFontFamilyFromName( "\pOsaka¡ÝÅùÉý" );
#else
+ /* Default to Monaco font */
+ fid = FMGetFontFamilyFromName("\pmonaco");
+#endif
+#else
+#ifdef JP
+ /* Default to ÅùÉýÌÀÄ« font (Japanese) */
GetFNum( "\pÅùÉýÌÀÄ«", &fid);
SetFScaleDisable( true );
-#endif
#else
/* Default to Monaco font */
GetFNum("\pmonaco", &fid);
#endif
+#endif
/* Wipe it */
WIPE(td, term_data);
term_data *td;
+#if !TARGET_API_MAC_CARBON
+
SysEnvRec env;
short savev;
long saved;
bool oops;
+#endif /* !TARGET_API_MAC_CARBON */
+
/*** Default values ***/
/*** Load preferences ***/
-
+
+#if TARGET_API_MAC_CARBON
+ cf_load_prefs();
+#else
/* Assume failure */
oops = TRUE;
#endif /* USE_SFL_CODE */
-#if TARGET_API_MAC_CARBON
-#else
/* Oops */
if (oops)
{
/* Restore */
HSetVol(0, savev, saved);
}
-#endif
/* Load preferences */
if (fff)
/* Close the file */
my_fclose(fff);
}
+#endif /* TARGET_API_MAC_CARBON */
/*** Instantiate ***/
Term_activate(td->t);
}
+#ifndef MACH_O_CARBON
+
static void init_sound( void )
{
int err, i;
}
}
+#endif /* MACH_O_CARBON */
+
#ifdef CHUUKEI
/*
void SoundConfigDLog(void)
{
DialogPtr dialog;
- Rect r;
short item_hit;
int i;
/*
* Exit the program
*/
+#if TARGET_API_MAC_CARBON
+static void save_pref_file(void)
+{
+ cf_save_prefs();
+}
+#else
static void save_pref_file(void)
{
bool oops;
#endif /* USE_SFL_CODE */
-#if TARGET_API_MAC_CARBON
-#else
/* Oops */
if (oops)
{
/* Restore */
HSetVol(0, savev, saved);
}
-#endif
/* Save preferences */
if (fff)
my_fclose(fff);
}
}
+#endif
+
+#if defined(__MWERKS__)
/*
* A simple "Yes/No" filter to parse "key press" events in dialog windows
return (0);
}
+#endif /* __MWERKS__ */
+
+
+#if TARGET_API_MAC_CARBON
+
+/*
+ * Prepare savefile dialogue and set the variable
+ * savefile accordingly. Returns true if it succeeds, false (or
+ * aborts) otherwise. If all is false, only allow files whose type
+ * is 'SAVE'.
+ * Originally written by Peter Ammon
+ */
+static bool select_savefile(bool all)
+{
+ OSErr err;
+ FSSpec theFolderSpec;
+ FSSpec savedGameSpec;
+ NavDialogOptions dialogOptions;
+ NavReplyRecord reply;
+ /* Used only when 'all' is true */
+ NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}};
+ NavTypeListHandle myTypeList;
+ AEDesc defaultLocation;
+
+#ifdef MACH_O_CARBON
+
+ /* Find the save folder */
+ err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec);
+
+#else
+
+ /* Find :lib:save: folder */
+ err = FSMakeFSSpec(app_vol, app_dir, "\p:lib:save:", &theFolderSpec);
+
+#endif
+
+ /* Oops */
+ if (err != noErr) quit("Unable to find the folder :lib:save:");
+
+ /* Get default Navigator dialog options */
+ err = NavGetDefaultDialogOptions(&dialogOptions);
+
+ /* Clear preview option */
+ dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews;
+
+ /* Disable multiple file selection */
+ dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles;
+
+ /* Make descriptor for default location */
+ err = AECreateDesc(typeFSS, &theFolderSpec, sizeof(FSSpec),
+ &defaultLocation);
+
+ /* Oops */
+ if (err != noErr) quit("Unable to allocate descriptor");
+
+ /* We are indifferent to signature and file types */
+ if (all)
+ {
+ myTypeList = (NavTypeListHandle)nil;
+ }
+
+ /* Set up type handle */
+ else
+ {
+ err = PtrToHand(&types, (Handle *)&myTypeList, sizeof(NavTypeList));
+
+ /* Oops */
+ if (err != noErr) quit("Error in PtrToHand. Try enlarging heap");
+
+ }
+
+ /* Call NavGetFile() with the types list */
+ err = NavChooseFile(&defaultLocation, &reply, &dialogOptions, NULL,
+ NULL, NULL, myTypeList, NULL);
+
+ /* Free type list */
+ if (!all) DisposeHandle((Handle)myTypeList);
+
+ /* Error */
+ if (err != noErr)
+ {
+ /* Nothing */
+ }
+
+ /* Invalid response -- allow the user to cancel */
+ else if (!reply.validRecord)
+ {
+ /* Hack -- Fake error */
+ err = -1;
+ }
+
+ /* Retrieve FSSpec from the reply */
+ else
+ {
+ AEKeyword theKeyword;
+ DescType actualType;
+ Size actualSize;
+
+ /* Get a pointer to selected file */
+ (void)AEGetNthPtr(&reply.selection, 1, typeFSS, &theKeyword,
+ &actualType, &savedGameSpec, sizeof(FSSpec), &actualSize);
+
+ /* Dispose NavReplyRecord, resources and descriptors */
+ (void)NavDisposeReply(&reply);
+ }
+
+ /* Dispose location info */
+ AEDisposeDesc(&defaultLocation);
+
+ /* Error */
+ if (err != noErr) return (FALSE);
+
+#ifdef MACH_O_CARBON
+
+ /* Convert FSSpec to pathname and store it in variable savefile */
+ (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile));
+
+#else
+
+ /* Convert FSSpec to pathname and store it in variable savefile */
+ refnum_to_name(
+ savefile,
+ savedGameSpec.parID,
+ savedGameSpec.vRefNum,
+ (char *)savedGameSpec.name);
+
+#endif
+
+ /* Success */
+ return (TRUE);
+}
+#endif
+
/*
* Handle menu: "File" + "New"
#if TARGET_API_MAC_CARBON
static void do_menu_file_open(bool all)
{
- int err;
- short vrefnum;
- long drefnum;
- long junk;
- DirInfo pb;
- SFTypeList types;
- SFReply reply;
- Point topleft;
- BitMap screen;
- FSSpec fsp;
- char path[1024];
-
- refnum_to_name(path, app_dir, app_vol, (char*)("\plib:save:"));
-
- FSpLocationFromFullPath( strlen(path), path, &fsp );
-
- /* Get any file */
- ChooseFile( (StringPtr)savefile, fsp );
-
- /* Allow cancel */
- if (err != noErr) return;
+ /* Let the player to choose savefile */
+ if (!select_savefile(all)) return;
- /* Extract textual file name for save file */
-/* GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
- refnum_to_name(savefile, drefnum, vrefnum, (char*)reply.fName);
-*/
/* Hack */
HiliteMenu(0);
/* Game is in progress */
- game_in_progress = 1;
+ game_in_progress = TRUE;
/* Flush input */
flush();
/* Ignore non 'SAVE' files */
if (myFileInfo.fdType != 'SAVE') return noErr;
+#ifdef MACH_O_CARBON
+
+ /* Extract a file name */
+ (void)spec_to_path(&myFSS, savefile, sizeof(savefile));
+
+#else
+
/* XXX XXX XXX Extract a file name */
PathNameFromDirID(myFSS.parID, myFSS.vRefNum, (StringPtr)savefile);
pstrcat((StringPtr)savefile, (StringPtr)&myFSS.name);
/* Convert the string */
ptocstr((StringPtr)savefile);
+#endif /* MACH_O_CARBON */
+
/* Delay actual open */
open_when_ready = TRUE;
#pragma unused (size)
- vptr mem = NULL;
+ /* vptr mem = NULL; */
/* Free the lifeboat */
if (lifeboat)
/* Warning if needed */
if (str) mac_warning(str);
+#ifdef USE_ASYNC_SOUND
+
+ /* Clean up sound support */
+ cleanup_sound();
+
+#endif /* USE_ASYNC_SOUND */
+
/* Write a preference file */
save_pref_file();
{
int i;
+#if !TARGET_API_MAC_CARBON
short vrefnum;
long drefnum;
long junk;
SFTypeList types;
SFReply reply;
+#endif
Rect r;
Point topleft;
/* Default to the "lib" folder with the application */
+#ifdef MACH_O_CARBON
+ if (locate_lib(path, sizeof(path)) == NULL) quit(NULL);
+#else
refnum_to_name(path, app_dir, app_vol, (char*)("\plib:"));
+#endif
/* Check until done */
/*
* Macintosh Main loop
*/
-void main(void)
+int main(void)
{
EventRecord tempEvent;
int numberOfMasters = 10;
# else
+#if TARGET_API_MAC_CARBON
+
+ {
+ OSErr err;
+ long response;
+
+ /* Check for existence of Carbon */
+ err = Gestalt(gestaltCarbonVersion, &response);
+
+ if (err != noErr) quit("This program requires Carbon API");
+ }
+
+#else
/* Block */
if (TRUE)
{
}
}
-# endif
+#endif /* CARBON */
+#endif
#endif /* ANGBAND_LITE_MAC */
0L, FALSE);
#endif
+#ifndef MACH_O_CARBON
/* Find the current application */
SetupAppDir();
-
+#endif
/* Mark ourself as the file creator */
- _fcreator = 'Heng';
+ _fcreator = ANGBAND_CREATOR;
/* Default to saving a "text" file */
_ftype = 'TEXT';
/* Prepare the windows */
init_windows();
+#ifndef MACH_O_CARBON
+
init_sound();
init_graf();
+
+#endif
/* Hack -- process all events */
while (CheckEvents(TRUE)) /* loop */;
/* Initialize */
init_stuff();
+ /* Catch nasty signals */
+ signals_init();
+
/* Initialize */
init_angband();