OSDN Git Service

メニューの構成を変更。
authormacband <macband@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 17 Aug 2004 02:15:28 +0000 (02:15 +0000)
committermacband <macband@0568b783-4c39-0410-ac80-bf13821ea2a2>
Tue, 17 Aug 2004 02:15:28 +0000 (02:15 +0000)
OSXバイナリではタイルとサウンドをパッケージに含められるように変更。
タイルはpngフォーマット、サウンドはwavフォーマットが利用出来る。

src/main-mac.c

index 03c12a1..a7256c9 100644 (file)
 #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
  */
 #ifdef JP
  */
 # define USE_SFL_CODE
 
+/*
+ * Use rewritten asynchronous sound player
+ */
+#define USE_ASYNC_SOUND
+
+
+#ifdef MACH_O_CARBON
+
+#define USE_QT_SOUND
+
+#endif /* MACH_O_CARBON */
 #endif /* ANGBAND_LITE_MAC */
 
 
@@ -458,1645 +464,1793 @@ AEEventHandlerUPP AEH_Open_UPP;
 
 #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
+ * Convert refnum+vrefnum+fname into a full file name
+ * Store this filename in 'buf' (make sure it is long enough)
+ * Note that 'fname' looks to be a "pascal" string
  */
 #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;
+static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
+{
+       CInfoPBRec pb;
+       int err;
+       int i, j;
 
-/*
- * Data handles containing sound samples
- */
-static SndListHandle samples[SOUND_MAX];
+       char res[1000];
+       
+       FSSpec spec;
+       short   vref;
+    long       dirID;
+    
+       i=999;
 
-/*
- * Reference counts of sound samples
- */
-static SInt16 sample_refs[SOUND_MAX];
+       res[i]=0; i--;
+       for (j=1; j<=fname[0]; j++)
+       {
+               res[i-fname[0]+j] = fname[j];
+       }
+       i-=fname[0];
 
+       vref = vrefnum;
+       dirID = refnum;
 
-/*
- * 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 % */
+       while (1)
+       {
+               pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
+               err = FSMakeFSSpec( vref, dirID, "\p", &spec );
+               
+               if( err != noErr )
+                   break;
+               
+               res[i] = ':'; i--;
+               for (j=1; j<=spec.name[0]; j++)
+               {
+                       res[i-spec.name[0]+j] = spec.name[j];
+               }
+               i -= spec.name[0];
+               
+               dirID = spec.parID;
+       }
 
-/* I'm just too lazy to write a panel for this XXX XXX */
-static SInt16 sound_volume = SOUND_VOLUME_MAX;
+       /* Extract the result */
+       for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
+       buf[j] = 0;
+}
+#else
+static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
+{
+       DirInfo pb;
+       Str255 name;
+       int err;
+       int i, j;
 
-#ifdef USE_QT_SOUND
+       char res[1000];
 
-/*
- * 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;
+       i=999;
 
-       /* Find resource (=file) in the current bundle */
-       res_url = CFBundleCopyResourceURL(
-               CFBundleGetMainBundle(), base_name, type_name, NULL);
+       res[i]=0; i--;
+       for (j=1; j<=fname[0]; j++)
+       {
+               res[i-fname[0]+j] = fname[j];
+       }
+       i-=fname[0];
 
-       /* Oops */
-       if (res_url == NULL) return (false);
+       pb.ioCompletion=NULL;
+       pb.ioNamePtr=name;
+       pb.ioVRefNum=vrefnum;
+       pb.ioDrParID=refnum;
+       pb.ioFDirIndex=-1;
 
-       /* Convert CFURL to FSRef */
-       (void)CFURLGetFSRef(res_url, &ref);
+       while (1)
+       {
+               pb.ioDrDirID=pb.ioDrParID;
+               err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
+               res[i] = ':'; i--;
+               for (j=1; j<=name[0]; j++)
+               {
+                       res[i-name[0]+j] = name[j];
+               }
+               i -= name[0];
 
-       /* Convert FSRef to FSSpec */
-       (void)FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+               if (pb.ioDrDirID == fsRtDirID) break;
+       }
 
-       /* Free allocated CF data */
-       CFRelease(res_url);
+       /* Extract the result */
+       for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
+       buf[j] = 0;
+}
+#endif
 
-       /* Success */
-       return (true);
+#if TARGET_API_MAC_CARBON
+pascal OSErr FSpLocationFromFullPath(short fullPathLength,
+                                                                        const void *fullPath,
+                                                                        FSSpec *spec)
+{
+       AliasHandle     alias;
+       OSErr           result;
+       Boolean         wasChanged;
+       Str32           nullString;
+       
+       /* Create a minimal alias from the full pathname */
+       nullString[0] = 0;      /* null string to indicate no zone or server name */
+       result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
+       if ( result == noErr )
+       {
+               /* Let the Alias Manager resolve the alias. */
+               result = ResolveAlias(NULL, alias, spec, &wasChanged);
+               
+               /* work around Alias Mgr sloppy volume matching bug */
+               if ( spec->vRefNum == 0 )
+               {
+                       /* invalidate wrong FSSpec */
+                       spec->parID = 0;
+                       spec->name[0] =  0;
+                       result = nsvErr;
+               }
+               DisposeHandle((Handle)alias);   /* Free up memory used */
+       }
+       return ( result );
 }
+#endif
 
-/*
- * 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
- */
+#if 0
 
 /*
- * (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*)
+ * XXX XXX XXX Allow the system to ask us for a filename
  */
-static void load_sounds(void)
+static bool askfor_file(char *buf, int len)
 {
-       OSErr err;
-       int i;
+       SFReply reply;
+       Str255 dflt;
+       Point topleft;
+       short vrefnum;
+       long drefnum, junk;
 
-       /* Start QuickTime */
-       err = EnterMovies();
+       /* Default file name */
+       sprintf((char*)dflt + 1, "%s's description", buf);
+       dflt[0] = strlen((char*)dflt + 1);
 
-       /* Error */
-       if (err != noErr) return;
+       /* Ask for a file name */
+       topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
+       topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
+       SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
+       /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
 
-       /*
-        * 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++)
+       /* Process */
+       if (reply.good)
        {
-               /* 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;
+               int fc;
 
-               /* Allocate CFString with the name of sound event to be processed */
-               name = CFStringCreateWithCString(NULL, angband_sound_name[i],
-                       kTextEncodingUS_ASCII);
+               /* Get info */
+               GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
 
-               /* Error */
-               if (name == NULL) continue;
+               /* Extract the name */
+               refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
 
-               /* Find sound sample resource with the same name */
-               res = get_resource_spec(name, CFSTR("wav"), &spec);
+               /* Success */
+               return (TRUE);
+       }
 
-               /* Free the reference to CFString */
-               CFRelease(name);
+       /* Failure */
+       return (FALSE);
+}
 
-               /* Error */
-               if (!res) continue;
+#endif
 
-               /* Open the sound file */
-               err = OpenMovieFile(&spec, &file_id, fsRdPerm);
+#if !TARGET_API_MAC_CARBON
+static void local_to_global( Rect *r )
+{
+       Point           temp;
+       
+       temp.h = r->left;
+       temp.v = r->top;
+       
+       LocalToGlobal( &temp );
+       
+       r->left = temp.h;
+       r->top = temp.v;
+       
+       temp.h = r->right;
+       temp.v = r->bottom;
+       
+       LocalToGlobal( &temp );
+       
+       r->right = temp.h;
+       r->bottom = temp.v;
+}
+#endif /* !TARGET_API_MAC_CARBON */
 
-               /* Error */
-               if (err != noErr) continue;
+static void global_to_local( Rect *r )
+{
+       Point           temp;
+       
+       temp.h = r->left;
+       temp.v = r->top;
+       
+       GlobalToLocal( &temp );
+       
+       r->left = temp.h;
+       r->top = temp.v;
+       
+       temp.h = r->right;
+       temp.v = r->bottom;
+       
+       GlobalToLocal( &temp );
+       
+       r->right = temp.h;
+       r->bottom = temp.v;
+}
 
-               /* Create Movie from the file */
-               err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
-                       newMovieActive, NULL);
 
-               /* Error */
-               if (err != noErr) goto close_file;
+#ifdef MAC_MPW
 
-               /* Get the first track of the movie */
-               track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
-                       movieTrackCharacteristic | movieTrackEnabledOnly );
+/*
+ * Convert pathname to an appropriate format, because MPW's
+ * CarbonStdCLib chose to use system's native path format,
+ * making our lives harder to create binaries that run on
+ * OS 8/9 and OS X :( -- pelpel
+ */
+void convert_pathname(char* path)
+{
+       char buf[1024];
 
-               /* Error */
-               if (track == NULL) goto close_movie;
+       /* Nothing has to be done for CarbonLib on Classic */
+       if (mac_os_version >= 0x1000)
+       {
+               /* Convert to POSIX style */
+               ConvertHFSPathToUnixPath(path, buf);
 
-               /* Allocate a handle to store sample */
-               h = NewHandle(0);
+               /* Copy the result back */
+               strcpy(path, buf);
+       }
 
-               /* Error */
-               if (h == NULL) goto close_track;
+       /* Done. */
+       return;
+}
 
-               /* Dump the sample into the handle */
-               err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
-                       GetTrackDuration(track), 0L, NULL);
+# ifdef CHECK_MODIFICATION_TIME
 
-               /* Success */
-               if (err == noErr)
-               {
-                       /* Store the handle in the sample list */
-                       samples[i] = (SndListHandle)h;
-               }
+/*
+ * Although there is no easy way to emulate fstat in the old interface,
+ * we still can do stat-like things, because Mac OS is an OS.
+ */
+static int get_modification_time(cptr path, u32b *mod_time)
+{
+       CInfoPBRec pb;
+       Str255 pathname;
+       int i;
 
-               /* Failure */
-               else
-               {
-                       /* Free unused handle */
-                       DisposeHandle(h);
-               }
+       /* Paranoia - make sure the pathname fits in Str255 */
+       i = strlen(path);
+       if (i > 255) return (-1);
 
-               /* Free the track */
-               close_track: DisposeMovieTrack(track);
+       /* Convert pathname to a Pascal string */
+       strncpy((char *)pathname + 1, path, 255);
+       pathname[0] = i;
 
-               /* Free the movie */
-               close_movie: DisposeMovie(movie);
+       /* Set up parameter block */
+       pb.hFileInfo.ioNamePtr = pathname;
+       pb.hFileInfo.ioFDirIndex = 0;
+       pb.hFileInfo.ioVRefNum = app_vol;
+       pb.hFileInfo.ioDirID = 0;
 
-               /* Close the movie file */
-               close_file: CloseMovieFile(file_id);
-       }
+       /* Get catalog information of the file */
+       if (PBGetCatInfoSync(&pb) != noErr) return (-1);
 
-       /* Stop QuickTime */
-       ExitMovies();
+       /* Set modification date and time */
+       *mod_time = pb.hFileInfo.ioFlMdDat;
+
+       /* Success */
+       return (0);
 }
 
-#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)
+ * A (non-Mach-O) Mac OS version of check_modification_time, for those
+ * compilers without good enough POSIX-compatibility libraries XXX XXX
  */
-static SndListHandle find_sound(int num)
+errr check_modification_date(int fd, cptr template_file)
 {
-       Str255 sound;
+#pragma unused(fd)
+       u32b txt_stat, raw_stat;
+       char *p;
+       char fname[32];
+       char buf[1024];
 
-       /* Get the proper sound name */
-       strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
-       sound[0] = strlen((char*)sound + 1);
+       /* Build the file name */
+       path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
 
-       /* Obtain resource XXX XXX XXX */
-       return ((SndListHandle)GetNamedResource('snd ', sound));
-}
+       /* XXX XXX XXX */
+       convert_pathname(buf);
 
-#endif /* USE_QT_SOUND */
+       /* Obtain modification time */
+       if (get_modification_time(buf, &txt_stat)) return (-1);
 
+       /* XXX Build filename of the corresponding *.raw file */
+       strnfmt(fname, sizeof(fname), "%s", template_file);
 
-/*
- * Clean up sound support - to be called when the game exits.
- *
- * Globals referenced: channels[], samples[], sample_refs[].
- */
-static void cleanup_sound(void)
-{
-       int i;
+       /* Find last '.' */
+       p = strrchr(fname, '.');
 
-       /* No need to clean it up */
-       if (!channel_initialised) return;
+       /* Can't happen */
+       if (p == NULL) return (-1);
 
-       /* Dispose channels */
-       for (i = 0; i < MAX_CHANNELS; i++)
-       {
-               /* Drain sound commands and free the channel */
-               SndDisposeChannel(channels[i], TRUE);
-       }
+       /* Substitute ".raw" for ".txt" */
+       strcpy(p, ".raw");
 
-       /* 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]);
-               }
+       /* Build the file name of the raw file */
+       path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
 
-#ifndef USE_QT_SOUND
+       /* XXX XXX XXX */
+       convert_pathname(buf);
 
-               /* Release it */
-               if (samples[i]) ReleaseResource((Handle)samples[i]);
-#else
+       /* Obtain modification time */
+       if (get_modification_time(buf, &raw_stat)) return (-1);
 
-               /* Free handle */
-               if (samples[i]) DisposeHandle((Handle)samples[i]);
-#endif /* !USE_QT_SOUND */
-       }
+       /* Ensure the text file is not newer than the raw file */
+       if (txt_stat > raw_stat) return (-1);
+
+       /* Keep using the current .raw file */
+       return (0);
 }
 
+# endif /* CHECK_MODIFICATION_TIME */
+
+#endif /* MAC_MPW */
 
 /*
- * 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.
+ * Center a rectangle inside another rectangle
  */
-static void play_sound(int num, SInt16 vol)
+static void center_rect(Rect *r, Rect *s)
 {
-       OSErr err;
-       int i;
-       int prev_num;
-       SndListHandle h;
-       SndChannelPtr chan;
-       SCStatus status;
+       int centerx = (s->left + s->right)/2;
+       int centery = (2*s->top + s->bottom)/3;
+       int dx = centerx - (r->right - r->left)/2 - r->left;
+       int dy = centery - (r->bottom - r->top)/2 - r->top;
+       r->left += dx;
+       r->right += dx;
+       r->top += dy;
+       r->bottom += dy;
+}
 
-       static int next_chan;
-       static SInt16 channel_occupants[MAX_CHANNELS];
-       static SndCommand volume_cmd, quiet_cmd;
 
+#ifdef MACH_O_CARBON
 
-       /* Initialise sound channels */
-       if (!channel_initialised)
-       {
-               for (i = 0; i < MAX_CHANNELS; i++)
-               {
-                       /* Paranoia - Clear occupant table */
-                       /* channel_occupants[i] = 0; */
+/* Carbon File Manager utilities by pelpel */
 
-                       /* Create sound channel for all sounds to play from */
-                       err = SndNewChannel(&channels[i], sampledSynth, initMono, 0L);
+/*
+ * (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;
 
-                       /* Error */
-                       if (err != noErr)
-                       {
-                               /* Free channels */
-                               while (--i >= 0)
-                               {
-                                       SndDisposeChannel(channels[i], TRUE);
-                               }
+       /* Convert pathname to FSRef ... */
+       err = FSPathMakeRef(path, &ref, NULL);
+       if (err != noErr) return (err);
 
-                               /* Notify error */
-#ifdef JP
-                               plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
-#else
-                               plog("Cannot initialise sound channels!");
-#endif
+       /* ... then FSRef to FSSpec */
+       err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+       
+       /* Inform caller of success or failure */
+       return (err);
+}
 
-                               /* Cancel request */
-                               use_sound = arg_sound = FALSE;
 
-                               /* Failure */
-                               return;
-                       }
-               }
+/*
+ * (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;
 
-               /* First channel to use */
-               next_chan = 0;
+       /* Convert FSSpec to FSRef ... */
+       err = FSpMakeFSRef(spec, &ref);
+       if (err != noErr) return (err);
 
-               /* Prepare volume command */
-               volume_cmd.cmd = volumeCmd;
-               volume_cmd.param1 = 0;
-               volume_cmd.param2 = 0;
+       /* ... then FSRef to pathname */
+       err = FSRefMakePath(&ref, buf, size);
 
-               /* Prepare quiet command */
-               quiet_cmd.cmd = quietCmd;
-               quiet_cmd.param1 = 0;
-               quiet_cmd.param2 = 0;
+       /* Inform caller of success or failure */
+       return (err);
+}
 
-               /* Initialisation complete */
-               channel_initialised = TRUE;
-       }
 
-       /* Paranoia */
-       if ((num <= 0) || (num >= SOUND_MAX)) return;
+/*
+ * (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;
 
-       /* Prepare volume command */
-       volume_cmd.param2 = ((SInt32)vol << 16) | vol;
+       /* Convert pathname to FSSpec */
+       if (path_to_spec(pathname, &spec) != noErr) return;
 
-       /* Channel to use (round robin) */
-       chan = channels[next_chan];
+       /* Obtain current finder info of the file */
+       if (FSpGetFInfo(&spec, &info) != noErr) return;
 
-       /* See if the resource is already in use */
-       if (sample_refs[num] > 0)
-       {
-               /* Resource in use */
-               h = samples[num];
+       /* Overwrite creator and type */
+       info.fdCreator = fcreator;
+       info.fdType = ftype;
+       err = FSpSetFInfo(&spec, &info);
 
-               /* Increase the refcount */
-               sample_refs[num]++;
-       }
+       /* Done */
+       return;
+}
 
-       /* 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;
+#else /* MACH_O_CARBON */
 
-#ifndef USE_QT_SOUND
 
-               /* Load resource */
-               LoadResource((Handle)h);
+/*
+ * Convert a pascal string in place
+ *
+ * This function may be defined elsewhere, but since it is so
+ * small, it is not worth finding the proper function name for
+ * all the different platforms.
+ */
+static void ptocstr(StringPtr src)
+{
+       int i;
 
-               /* Remember it */
-               samples[num] = h;
+       /* Hack -- pointer */
+       char *s = (char*)(src);
 
-#endif /* !USE_QT_SOUND */
+       /* Hack -- convert the string */
+       for (i = s[0]; i; i--, s++) s[0] = s[1];
 
-               /* Lock the handle */
-               HLockHi((Handle)h);
+       /* Hack -- terminate the string */
+       s[0] = '\0';
+}
 
-               /* Initialise refcount */
-               sample_refs[num] = 1;
-       }
 
-       /* Poll the channel */
-       err = SndChannelStatus(chan, sizeof(SCStatus), &status);
+#if defined(USE_SFL_CODE)
 
-       /* 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];
+/*
+ * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
+ * were taken from the Think Reference section called "Getting a Full Pathname"
+ * (under the File Manager section).  We need PathNameFromDirID to get the
+ * full pathname of the opened savefile, making no assumptions about where it
+ * is.
+ *
+ * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
+ * nice.
+ */
+static void pstrcat(StringPtr dst, StringPtr src)
+{
+       /* copy string in */
+       BlockMove(src + 1, dst + *dst + 1, *src);
 
-       /* Process previously played sound */
-       if (prev_num != 0)
-       {
-               /* Decrease refcount */
-               sample_refs[prev_num]--;
+       /* adjust length byte */
+       *dst += *src;
+}
 
-               /* We can free it now */
-               if (sample_refs[prev_num] <= 0)
-               {
-                       /* Unlock */
-                       HUnlock((Handle)samples[prev_num]);
+/*
+ * pstrinsert - insert string 'src' at beginning of string 'dst'
+ */
+static void pstrinsert(StringPtr dst, StringPtr src)
+{
+       /* make room for new string */
+       BlockMove(dst + 1, dst + *src + 1, *dst);
 
-#ifndef USE_QT_SOUND
+       /* copy new string in */
+       BlockMove(src + 1, dst + 1, *src);
 
-                       /* Release */
-                       ReleaseResource((Handle)samples[prev_num]);
+       /* adjust length byte */
+       *dst += *src;
+}
 
-                       /* Forget handle */
-                       samples[prev_num] = NULL;
+static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
+{
+       CInfoPBRec      block;
+       Str255  directoryName;
+       OSErr   err;
 
-#endif /* !USE_QT_SOUND */
+       fullPathName[0] = '\0';
 
-                       /* Paranoia */
-                       sample_refs[prev_num] = 0;
-               }
+       block.dirInfo.ioDrParID = dirID;
+       block.dirInfo.ioNamePtr = directoryName;
+
+       while (1)
+       {
+               block.dirInfo.ioVRefNum = vRefNum;
+               block.dirInfo.ioFDirIndex = -1;
+               block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
+               err = PBGetCatInfo(&block, FALSE);
+               pstrcat(directoryName, (StringPtr)"\p:");
+               pstrinsert(fullPathName, directoryName);
+               if (block.dirInfo.ioDrDirID == 2) break;
        }
+}
 
-       /* Remember this sound as the current occupant of the channel */
-       channel_occupants[next_chan] = num;
+#endif
+#endif /* MACH_O_CARBON */
 
-       /* Set up volume for channel */
-       SndDoImmediate(chan, &volume_cmd);
-
-       /* Play new sound asynchronously */
-       SndPlay(chan, h, TRUE);
+/*
+ * Activate a given window, if necessary
+ */
+static void activate(WindowPtr w)
+{
+       /* Activate */
+       if (active != w)
+       {
+               /* Activate */
+#if TARGET_API_MAC_CARBON
+               if (w) SetPortWindowPort(w);
+#else
+               if (w) SetPort(w);
+#endif
 
-       /* Schedule next channel (round robin) */
-       next_chan++;
-       if (next_chan >= MAX_CHANNELS) next_chan = 0;
+               /* Remember */
+               active = w;
+       }
 }
 
-# else /* USE_ASYNC_SOUND */
 
 /*
- * Play sound synchronously
- *
- * This may not be your choice, but much safer and much less resource hungry.
+ * Display a warning message
  */
-static void play_sound(int num, SInt16 vol)
+static void mac_warning(cptr warning)
 {
-       Handle handle;
-       Str255 sound;
+       Str255 text;
+       int len, i;
 
-       /* Get the proper sound name */
-       strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
-       sound[0] = strlen((char*)sound + 1);
+       /* Limit of 250 chars */
+       len = strlen(warning);
+       if (len > 250) len = 250;
 
-       /* Obtain resource XXX XXX XXX */
-       handle = GetNamedResource('snd ', sound);
+       /* Make a "Pascal" string */
+       text[0] = len;
+       for (i=0; i<len; i++) text[i+1] = warning[i];
 
-       /* Oops */
-       if (handle == NULL) return;
+       /* Prepare the dialog box values */
+       ParamText(text, "\p", "\p", "\p");
 
-       /* Load and Lock */
-       LoadResource(handle);
-       HLockHi(handle);
+       /* Display the Alert, wait for Okay */
+       Alert(129, 0L);
+}
 
-       /* Play sound (wait for completion) */
-       SndPlay(NULL, (SndListHandle)handle, FALSE);
 
-       /* Unlock and release */
-       HUnlock(handle);
-       ReleaseResource(handle);
-}
 
-# endif /* USE_ASYNC_SOUND */
+/*** Some generic functions ***/
 
-#ifndef MACH_O_CARBON
+
+#ifdef ANGBAND_LITE_MAC
 
 /*
-       Extra Sound Mode
-*/
+ * Hack -- activate a color (0 to 255)
+ */
+#define term_data_color(TD,A) /* Nothing */
 
-static int ext_sound = 0;
+#else /* ANGBAND_LITE_MAC */
 
-#define                SND_NON         0
-#define                SND_ATTACK      1
-#define                SND_MOVE                2
-#define                SND_TRAP                3
-#define                SND_SHOP                4
-#define                SND_ME          5
-#define                SND_CMD_ERROR   6
+/*
+ * Hack -- activate a color (0 to 255)
+ */
+static void term_data_color(term_data *td, int a)
+{
+       u16b rv, gv, bv;
 
-static int soundchoice[] = {
-       SND_NON,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ME,
-       SND_ME,
-       SND_ME,
-       SND_MOVE,
-       SND_ATTACK,
-       SND_ME,
-       SND_ATTACK,
-       SND_NON,
-       SND_MOVE,
-       SND_MOVE,
-       SND_ME,
-       SND_SHOP,
-       SND_SHOP,
-       SND_SHOP,
-       SND_SHOP,
-       SND_MOVE,
-       SND_MOVE,
-       SND_MOVE,
-       SND_MOVE,
-       SND_ATTACK,
-       SND_SHOP,
-       SND_SHOP,
-       SND_ME,
-       SND_NON,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_NON,
-       SND_CMD_ERROR,
-       SND_TRAP,
-       SND_NON,
-       SND_NON,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_TRAP,
-       SND_ATTACK,
-       SND_ATTACK,
-       SND_NON,
-       SND_TRAP,
-};
+       RGBColor color;
 
-static int ext_graf = 0;
+       /* Extract the R,G,B data */
+       rv = angband_color_table[a][1];
+       gv = angband_color_table[a][2];
+       bv = angband_color_table[a][3];
 
-#endif /* !MACH_O_CARBON */
+       /* Set the color */
+       color.red = (rv | (rv << 8));
+       color.green = (gv | (gv << 8));
+       color.blue = (bv | (bv << 8));
 
-static short                   soundmode[8];
+       /* Activate the color */
+       RGBForeColor(&color);
+
+       /* Memorize color */
+       td->last = a;
+}
+
+#endif /* ANGBAND_LITE_MAC */
 
 
 /*
- * Convert refnum+vrefnum+fname into a full file name
- * Store this filename in 'buf' (make sure it is long enough)
- * Note that 'fname' looks to be a "pascal" string
+ * Hack -- Apply and Verify the "font" info
+ *
+ * This should usually be followed by "term_data_check_size()"
  */
-#if TARGET_API_MAC_CARBON
-static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
+static void term_data_check_font(term_data *td)
 {
-       CInfoPBRec pb;
-       int err;
-       int i, j;
+       int i;
 
-       char res[1000];
-       
-       FSSpec spec;
-       short   vref;
-    long       dirID;
-    
-       i=999;
+       FontInfo info;
 
-       res[i]=0; i--;
-       for (j=1; j<=fname[0]; j++)
+       WindowPtr old = active;
+
+
+       /* Activate */
+       activate(td->w);
+
+       /* Instantiate font */
+       TextFont(td->font_id);
+       TextSize(td->font_size);
+       TextFace(td->font_face);
+
+       /* Extract the font info */
+       GetFontInfo(&info);
+
+       /* Assume monospaced */
+       td->font_mono = TRUE;
+
+       /* Extract the font sizing values XXX XXX XXX */
+       td->font_wid = CharWidth('@'); /* info.widMax; */
+       td->font_hgt = info.ascent + info.descent;
+       td->font_o_x = 0;
+       td->font_o_y = info.ascent;
+
+       /* Check important characters */
+       for (i = 33; i < 127; i++)
        {
-               res[i-fname[0]+j] = fname[j];
+               /* Hack -- notice non-mono-space */
+               if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
+
+               /* Hack -- collect largest width */
+               if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
        }
-       i-=fname[0];
 
-       vref = vrefnum;
-       dirID = refnum;
+       /* Set default offsets */
+       td->tile_o_x = td->font_o_x;
+       td->tile_o_y = td->font_o_y;
 
-       while (1)
-       {
-               pb.dirInfo.ioDrDirID=pb.dirInfo.ioDrParID;
-               err = FSMakeFSSpec( vref, dirID, "\p", &spec );
-               
-               if( err != noErr )
-                   break;
-               
-               res[i] = ':'; i--;
-               for (j=1; j<=spec.name[0]; j++)
-               {
-                       res[i-spec.name[0]+j] = spec.name[j];
-               }
-               i -= spec.name[0];
-               
-               dirID = spec.parID;
+       /* Set default tile size */
+       if( td->tile_wid == 0 && td->tile_hgt == 0 ){
+               td->tile_wid = td->font_wid;
+               td->tile_hgt = td->font_hgt;
        }
 
-       /* Extract the result */
-       for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
-       buf[j] = 0;
+       /* Re-activate the old window */
+       activate(old);
 }
-#else
-static void refnum_to_name(char *buf, long refnum, short vrefnum, char *fname)
-{
-       DirInfo pb;
-       Str255 name;
-       int err;
-       int i, j;
 
-       char res[1000];
 
-       i=999;
+/*
+ * Hack -- Apply and Verify the "size" info
+ */
+static void term_data_check_size(term_data *td)
+{
+       BitMap          screen;
+       
+#if TARGET_API_MAC_CARBON
+       GetQDGlobalsScreenBits( &screen );
+#else
+       screen = qd.screenBits;
+#endif
+       /* Minimal window size */
+       if (td == &data[0])
+       {
+               /* Enforce minimal size */
+               if (td->cols < 80) td->cols = 80;
+               if (td->rows < 24) td->rows = 24;
+       }
 
-       res[i]=0; i--;
-       for (j=1; j<=fname[0]; j++)
+       /* Allow small windows for the rest */
+       else
        {
-               res[i-fname[0]+j] = fname[j];
+               if (td->cols < 1) td->cols = 1;
+               if (td->rows < 1) td->rows = 1;
        }
-       i-=fname[0];
 
-       pb.ioCompletion=NULL;
-       pb.ioNamePtr=name;
-       pb.ioVRefNum=vrefnum;
-       pb.ioDrParID=refnum;
-       pb.ioFDirIndex=-1;
+       /* Minimal tile size */
+       if (td->tile_wid < 4) td->tile_wid = 4;
+       if (td->tile_hgt < 4) td->tile_hgt = 4;
 
-       while (1)
-       {
-               pb.ioDrDirID=pb.ioDrParID;
-               err = PBGetCatInfo((CInfoPBPtr)&pb, FALSE);
-               res[i] = ':'; i--;
-               for (j=1; j<=name[0]; j++)
-               {
-                       res[i-name[0]+j] = name[j];
-               }
-               i -= name[0];
+       /* Default tile offsets */
+       td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
+       td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
 
-               if (pb.ioDrDirID == fsRtDirID) break;
+       /* Minimal tile offsets */
+       if (td->tile_o_x < 0) td->tile_o_x = 0;
+       if (td->tile_o_y < 0) td->tile_o_y = 0;
+
+       /* Apply font offsets */
+       td->tile_o_x += td->font_o_x;
+       td->tile_o_y += td->font_o_y;
+
+       /* Calculate full window size */
+       td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
+       td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
+
+       /* Verify the top */
+       if (td->r.top > screen.bounds.bottom - td->size_hgt)
+       {
+               td->r.top = screen.bounds.bottom - td->size_hgt;
        }
 
-       /* Extract the result */
-       for (j = 0, i++; res[i]; j++, i++) buf[j] = res[i];
-       buf[j] = 0;
-}
-#endif
+       /* Verify the top */
+       if (td->r.top < screen.bounds.top + 30)
+       {
+               td->r.top = screen.bounds.top + 30;
+       }
 
-#if TARGET_API_MAC_CARBON
-pascal OSErr FSpLocationFromFullPath(short fullPathLength,
-                                                                        const void *fullPath,
-                                                                        FSSpec *spec)
-{
-       AliasHandle     alias;
-       OSErr           result;
-       Boolean         wasChanged;
-       Str32           nullString;
-       
-       /* Create a minimal alias from the full pathname */
-       nullString[0] = 0;      /* null string to indicate no zone or server name */
-       result = NewAliasMinimalFromFullPath(fullPathLength, fullPath, nullString, nullString, &alias);
-       if ( result == noErr )
+       /* Verify the left */
+       if (td->r.left > screen.bounds.right - td->size_wid)
        {
-               /* Let the Alias Manager resolve the alias. */
-               result = ResolveAlias(NULL, alias, spec, &wasChanged);
-               
-               /* work around Alias Mgr sloppy volume matching bug */
-               if ( spec->vRefNum == 0 )
-               {
-                       /* invalidate wrong FSSpec */
-                       spec->parID = 0;
-                       spec->name[0] =  0;
-                       result = nsvErr;
-               }
-               DisposeHandle((Handle)alias);   /* Free up memory used */
+               td->r.left = screen.bounds.right - td->size_wid;
        }
-       return ( result );
-}
-#endif
 
-#if 0
+       /* Verify the left */
+       if (td->r.left < screen.bounds.left)
+       {
+               td->r.left = screen.bounds.left;
+       }
 
-/*
- * XXX XXX XXX Allow the system to ask us for a filename
- */
-static bool askfor_file(char *buf, int len)
-{
-       SFReply reply;
-       Str255 dflt;
-       Point topleft;
-       short vrefnum;
-       long drefnum, junk;
+       /* Calculate bottom right corner */
+       td->r.right = td->r.left + td->size_wid;
+       td->r.bottom = td->r.top + td->size_hgt;
 
-       /* Default file name */
-       sprintf((char*)dflt + 1, "%s's description", buf);
-       dflt[0] = strlen((char*)dflt + 1);
+       /* Assume no graphics */
+       td->t->higher_pict = FALSE;
+       td->t->always_pict = FALSE;
 
-       /* Ask for a file name */
-       topleft.h=(qd.screenBits.bounds.left+qd.screenBits.bounds.right)/2-344/2;
-       topleft.v=(2*qd.screenBits.bounds.top+qd.screenBits.bounds.bottom)/3-188/2;
-       SFPutFile(topleft, "\pSelect a filename:", dflt, NULL, &reply);
-       /* StandardPutFile("\pSelect a filename:", dflt, &reply); */
+#ifdef ANGBAND_LITE_MAC
 
-       /* Process */
-       if (reply.good)
-       {
-               int fc;
+       /* No graphics */
 
-               /* Get info */
-               GetWDInfo(reply.vRefNum, &vrefnum, &drefnum, &junk);
+#else /* ANGBAND_LITE_MAC */
 
-               /* Extract the name */
-               refnum_to_name(buf, drefnum, vrefnum, (char*)reply.fName);
+       /* Handle graphics */
+       if (use_graphics)
+       {
+               /* Use higher_pict whenever possible */
+               if (td->font_mono) td->t->higher_pict = TRUE;
 
-               /* Success */
-               return (TRUE);
+               /* Use always_pict only when necessary */
+               else td->t->always_pict = TRUE;
        }
 
-       /* Failure */
-       return (FALSE);
-}
-
-#endif
+#endif /* ANGBAND_LITE_MAC */
 
-#if !TARGET_API_MAC_CARBON
-static void local_to_global( Rect *r )
-{
-       Point           temp;
-       
-       temp.h = r->left;
-       temp.v = r->top;
-       
-       LocalToGlobal( &temp );
-       
-       r->left = temp.h;
-       r->top = temp.v;
-       
-       temp.h = r->right;
-       temp.v = r->bottom;
-       
-       LocalToGlobal( &temp );
-       
-       r->right = temp.h;
-       r->bottom = temp.v;
+       /* Fake mono-space */
+       if (!td->font_mono ||
+           (td->font_wid != td->tile_wid) ||
+               (td->font_hgt != td->tile_hgt))
+       {
+               /* Handle fake monospace -- this is SLOW */
+               if (td->t->higher_pict) td->t->higher_pict = FALSE;
+               td->t->always_pict = TRUE;
+       }
 }
-#endif /* !TARGET_API_MAC_CARBON */
 
-static void global_to_local( Rect *r )
+/*
+ * Hack -- resize a term_data
+ *
+ * This should normally be followed by "term_data_resize()"
+ */
+static void term_data_resize(term_data *td)
 {
-       Point           temp;
-       
-       temp.h = r->left;
-       temp.v = r->top;
-       
-       GlobalToLocal( &temp );
-       
-       r->left = temp.h;
-       r->top = temp.v;
-       
-       temp.h = r->right;
-       temp.v = r->bottom;
-       
-       GlobalToLocal( &temp );
-       
-       r->right = temp.h;
-       r->bottom = temp.v;
+       /* Actually resize the window */
+       SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
 }
 
 
-#ifdef MAC_MPW
 
 /*
- * Convert pathname to an appropriate format, because MPW's
- * CarbonStdCLib chose to use system's native path format,
- * making our lives harder to create binaries that run on
- * OS 8/9 and OS X :( -- pelpel
+ * Hack -- redraw a term_data
+ *
+ * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
  */
-void convert_pathname(char* path)
+static void term_data_redraw(term_data *td)
 {
-       char buf[1024];
+       term *old = Term;
 
-       /* Nothing has to be done for CarbonLib on Classic */
-       if (mac_os_version >= 0x1000)
-       {
-               /* Convert to POSIX style */
-               ConvertHFSPathToUnixPath(path, buf);
+       /* Activate the term */
+       Term_activate(td->t);
 
-               /* Copy the result back */
-               strcpy(path, buf);
-       }
+       /* Redraw the contents */
+       Term_redraw();
 
-       /* Done. */
-       return;
-}
+       /* Flush the output */
+       Term_fresh();
 
-# ifdef CHECK_MODIFICATION_TIME
+       /* Restore the old term */
+       Term_activate(old);
+       
+       /* No need to redraw */
+#if TARGET_API_MAC_CARBON
+       {
+               RgnHandle               theRgn = NewRgn();
+               GetWindowRegion( td->w, kWindowContentRgn, theRgn );
+               ValidWindowRgn( (WindowRef)(td->w), theRgn );
+               DisposeRgn( theRgn );
+       }
+#else
+       ValidRect(&td->w->portRect);
+#endif
 
-/*
- * Although there is no easy way to emulate fstat in the old interface,
- * we still can do stat-like things, because Mac OS is an OS.
- */
-static int get_modification_time(cptr path, u32b *mod_time)
-{
-       CInfoPBRec pb;
-       Str255 pathname;
-       int i;
+}
 
-       /* Paranoia - make sure the pathname fits in Str255 */
-       i = strlen(path);
-       if (i > 255) return (-1);
 
-       /* Convert pathname to a Pascal string */
-       strncpy((char *)pathname + 1, path, 255);
-       pathname[0] = i;
 
-       /* Set up parameter block */
-       pb.hFileInfo.ioNamePtr = pathname;
-       pb.hFileInfo.ioFDirIndex = 0;
-       pb.hFileInfo.ioVRefNum = app_vol;
-       pb.hFileInfo.ioDirID = 0;
 
-       /* Get catalog information of the file */
-       if (PBGetCatInfoSync(&pb) != noErr) return (-1);
+#ifdef ANGBAND_LITE_MAC
 
-       /* Set modification date and time */
-       *mod_time = pb.hFileInfo.ioFlMdDat;
+/* No graphics */
 
-       /* Success */
-       return (0);
-}
+#else /* ANGBAND_LITE_MAC */
 
 
 /*
- * A (non-Mach-O) Mac OS version of check_modification_time, for those
- * compilers without good enough POSIX-compatibility libraries XXX XXX
+ * Graphics support
  */
-errr check_modification_date(int fd, cptr template_file)
-{
-#pragma unused(fd)
-       u32b txt_stat, raw_stat;
-       char *p;
-       char fname[32];
-       char buf[1024];
-
-       /* Build the file name */
-       path_build(buf, sizeof(buf), ANGBAND_DIR_EDIT, template_file);
 
-       /* XXX XXX XXX */
-       convert_pathname(buf);
-
-       /* Obtain modification time */
-       if (get_modification_time(buf, &txt_stat)) return (-1);
-
-       /* XXX Build filename of the corresponding *.raw file */
-       strnfmt(fname, sizeof(fname), "%s", template_file);
+/*
+ * PICT id of image tiles, set by Term_xtra_mac_react
+ */
+#ifdef MACH_O_CARBON
+static CFStringRef pictID = NULL;
+#else
+static int pictID = 0;
+#endif /* MACH_O_CARBON */
 
-       /* Find last '.' */
-       p = strrchr(fname, '.');
+/*
+ * Width and height of a tile in pixels
+ */
+static int grafWidth = 0;
+static int grafHeight = 0;
 
-       /* Can't happen */
-       if (p == NULL) return (-1);
+/*
+ * Numbers of rows and columns in tiles, calculated by
+ * the PICT loading code
+ */
+static int pictCols = 0;
+static int pictRows = 0;
 
-       /* Substitute ".raw" for ".txt" */
-       strcpy(p, ".raw");
+/*
+ * Available graphics modes - 32x32 tiles don't work on Classic
+ */
+#define GRAF_MODE_NONE 0
+#define GRAF_MODE_8X8  1
+#define GRAF_MODE_16X16        2
+#define GRAF_MODE_32X32        3
 
-       /* Build the file name of the raw file */
-       path_build(buf, sizeof(buf), ANGBAND_DIR_DATA, fname);
+/*
+ * Current and requested graphics modes
+ */
+static int graf_mode = GRAF_MODE_NONE;
+static int graf_mode_req = GRAF_MODE_NONE;
 
-       /* XXX XXX XXX */
-       convert_pathname(buf);
 
-       /* Obtain modification time */
-       if (get_modification_time(buf, &raw_stat)) return (-1);
+/*
+ * Forward Declare
+ */
+typedef struct FrameRec FrameRec;
 
-       /* Ensure the text file is not newer than the raw file */
-       if (txt_stat > raw_stat) return (-1);
+/*
+ * Frame
+ *
+ *     - GWorld for the frame image
+ *     - Handle to pix map (saved for unlocking/locking)
+ *     - Pointer to color pix map (valid only while locked)
+ */
+struct FrameRec
+{
+       GWorldPtr               framePort;
+       PixMapHandle    framePixHndl;
+       PixMapPtr               framePix;
+       
+};
 
-       /* Keep using the current .raw file */
-       return (0);
-}
 
-# endif /* CHECK_MODIFICATION_TIME */
+/*
+ * The global picture data
+ */
+static FrameRec *frameP = NULL;
 
-#endif /* MAC_MPW */
 
 /*
- * Center a rectangle inside another rectangle
+ * Lock a frame
  */
-static void center_rect(Rect *r, Rect *s)
+static void BenSWLockFrame(FrameRec *srcFrameP)
 {
-       int centerx = (s->left + s->right)/2;
-       int centery = (2*s->top + s->bottom)/3;
-       int dx = centerx - (r->right - r->left)/2 - r->left;
-       int dy = centery - (r->bottom - r->top)/2 - r->top;
-       r->left += dx;
-       r->right += dx;
-       r->top += dy;
-       r->bottom += dy;
-}
-
+       PixMapHandle            pixMapH;
 
-#ifdef MACH_O_CARBON
+       pixMapH = GetGWorldPixMap(srcFrameP->framePort);
+       (void)LockPixels(pixMapH);
+       HLockHi((Handle)pixMapH);
+       srcFrameP->framePixHndl = pixMapH;
+#if TARGET_API_MAC_CARBON
+       srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
+#else
+       srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
+#endif
+       
+}
 
-/* Carbon File Manager utilities by pelpel */
 
 /*
- * (Carbon)
- * Convert a pathname to a corresponding FSSpec.
- * Returns noErr on success.
+ * Unlock a frame
  */
-static OSErr path_to_spec(const char *path, FSSpec *spec)
+static void BenSWUnlockFrame(FrameRec *srcFrameP)
 {
-       OSErr err;
-       FSRef ref;
-
-       /* Convert pathname to FSRef ... */
-       err = FSPathMakeRef(path, &ref, NULL);
-       if (err != noErr) return (err);
+       if (srcFrameP->framePort != NULL)
+       {
+               HUnlock((Handle)srcFrameP->framePixHndl);
+               UnlockPixels(srcFrameP->framePixHndl);
+       }
 
-       /* ... then FSRef to FSSpec */
-       err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, spec, NULL);
+       srcFrameP->framePix = NULL;
        
-       /* Inform caller of success or failure */
-       return (err);
 }
 
+#ifdef MACH_O_CARBON
 
 /*
- * (Carbon)
- * Convert a FSSpec to a corresponding pathname.
- * Returns noErr on success.
+ * 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 OSErr spec_to_path(const FSSpec *spec, char *buf, size_t size)
+static Boolean get_resource_spec(
+       CFStringRef base_name, CFStringRef type_name, FSSpec *spec)
 {
-       OSErr err;
+       CFURLRef res_url;
        FSRef ref;
 
-       /* Convert FSSpec to FSRef ... */
-       err = FSpMakeFSRef(spec, &ref);
-       if (err != noErr) return (err);
+       /* Find resource (=file) in the current bundle */
+       res_url = CFBundleCopyResourceURL(
+               CFBundleGetMainBundle(), base_name, type_name, NULL);
 
-       /* ... then FSRef to pathname */
-       err = FSRefMakePath(&ref, buf, size);
+       /* Oops */
+       if (res_url == NULL) return (false);
 
-       /* Inform caller of success or failure */
-       return (err);
+       /* 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);
 }
 
 
 /*
- * (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.
+ * (QuickTime)
+ * Create a off-screen GWorld from contents of a file specified by a FSSpec.
+ * Based on BenSWCreateGWorldFromPict.
+ *
+ * Globals referenced: data[0], graf_height, graf_width
+ * Globals updated: pict_rows, pict_cols.
  */
-void fsetfileinfo(cptr pathname, OSType fcreator, OSType ftype)
+static OSErr create_gworld_from_spec(
+       GWorldPtr *tile_gw, FSSpec *tile_spec)
 {
        OSErr err;
-       FSSpec spec;
-       FInfo info;
+       GraphicsImportComponent gi;
+       GWorldPtr gw, tmp_gw;
+       GDHandle gdh, tmp_gdh;
+       Rect r;
+       SInt16 depth;
 
-       /* Convert pathname to FSSpec */
-       if (path_to_spec(pathname, &spec) != noErr) return;
+       /* See if QuickTime understands the file format */
+       err = GetGraphicsImporterForFile(tile_spec, &gi);
 
-       /* Obtain current finder info of the file */
-       if (FSpGetFInfo(&spec, &info) != noErr) return;
+       /* Oops */
+       if (err != noErr) return (err);
 
-       /* Overwrite creator and type */
-       info.fdCreator = fcreator;
-       info.fdType = ftype;
-       err = FSpSetFInfo(&spec, &info);
+       /* Get depth */
+       depth = data[0].pixelDepth;
 
-       /* Done */
-       return;
-}
+       /* Get GDH */
+       gdh = data[0].theGDH;
 
+       /* Retrieve the rect of the image */
+       err = GraphicsImportGetNaturalBounds(gi, &r);
 
-#else /* MACH_O_CARBON */
+       /* Adjust it, so that the upper left corner becomes (0, 0) */
+       OffsetRect(&r, -r.left, -r.top);
 
+       /* Calculate and set numbers of rows and columns */
+       pictRows = r.bottom / grafHeight;
+       pictCols = r.right / grafWidth;
 
-/*
- * Convert a pascal string in place
- *
- * This function may be defined elsewhere, but since it is so
- * small, it is not worth finding the proper function name for
- * all the different platforms.
- */
-static void ptocstr(StringPtr src)
-{
-       int i;
+       /* Create a GWorld */
+       err = NewGWorld(&gw, depth, &r, NULL, gdh, noNewDevice);
 
-       /* Hack -- pointer */
-       char *s = (char*)(src);
+       /* Oops */
+       if (err != noErr) return (err);
 
-       /* Hack -- convert the string */
-       for (i = s[0]; i; i--, s++) s[0] = s[1];
+       /* Save the pointer to the GWorld */
+       *tile_gw = gw;
 
-       /* Hack -- terminate the string */
-       s[0] = '\0';
-}
+       /* Save the current GWorld */
+       GetGWorld(&tmp_gw, &tmp_gdh);
 
+       /* Activate the newly created GWorld */
+       (void)GraphicsImportSetGWorld(gi, gw, NULL);
 
-#if defined(USE_SFL_CODE)
+       /* Prevent pixmap from moving while drawing */
+       (void)LockPixels(GetGWorldPixMap(gw));
 
+       /* Clear the pixels */
+       EraseRect(&r);
 
-/*
- * The following three routines (pstrcat, pstrinsert, and PathNameFromDirID)
- * were taken from the Think Reference section called "Getting a Full Pathname"
- * (under the File Manager section).  We need PathNameFromDirID to get the
- * full pathname of the opened savefile, making no assumptions about where it
- * is.
- *
- * I had to hack PathNameFromDirID a little for MetroWerks, but it's awfully
- * nice.
- */
-static void pstrcat(StringPtr dst, StringPtr src)
-{
-       /* copy string in */
-       BlockMove(src + 1, dst + *dst + 1, *src);
+       /* Draw the image into it */
+       (void)GraphicsImportDraw(gi);
 
-       /* adjust length byte */
-       *dst += *src;
-}
+       /* Release the lock*/
+       UnlockPixels(GetGWorldPixMap(gw));
 
-/*
- * pstrinsert - insert string 'src' at beginning of string 'dst'
- */
-static void pstrinsert(StringPtr dst, StringPtr src)
-{
-       /* make room for new string */
-       BlockMove(dst + 1, dst + *src + 1, *dst);
+       /* Restore GWorld */
+       SetGWorld(tmp_gw, tmp_gdh);
 
-       /* copy new string in */
-       BlockMove(src + 1, dst + 1, *src);
+       /* Close the image importer */
+       CloseComponent(gi);
 
-       /* adjust length byte */
-       *dst += *src;
+       /* Success */
+       return (noErr);
 }
 
-static void PathNameFromDirID(long dirID, short vRefNum, StringPtr fullPathName)
+#else /* MACH_O_CARBON */
+
+static OSErr BenSWCreateGWorldFromPict(
+       GWorldPtr *pictGWorld,
+       PicHandle pictH)
 {
-       CInfoPBRec      block;
-       Str255  directoryName;
-       OSErr   err;
+       OSErr err;
+       GWorldPtr saveGWorld;
+       GDHandle saveGDevice;
+       GWorldPtr tempGWorld;
+       Rect pictRect;
+       short depth;
+       GDHandle theGDH;
 
-       fullPathName[0] = '\0';
+       /* Reset */
+       *pictGWorld = NULL;
 
-       block.dirInfo.ioDrParID = dirID;
-       block.dirInfo.ioNamePtr = directoryName;
+       /* Get depth */
+       depth = data[0].pixelDepth;
 
-       while (1)
+       /* Get GDH */
+       theGDH = data[0].theGDH;
+
+       /* Obtain size rectangle */
+       pictRect = (**pictH).picFrame;
+       OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
+
+       /* Create a GWorld */
+       err = NewGWorld(&tempGWorld, depth, &pictRect, nil, 
+                                       theGDH, noNewDevice);
+
+       /* Success */
+       if (err != noErr)
        {
-               block.dirInfo.ioVRefNum = vRefNum;
-               block.dirInfo.ioFDirIndex = -1;
-               block.dirInfo.ioDrDirID = block.dirInfo.ioDrParID;
-               err = PBGetCatInfo(&block, FALSE);
-               pstrcat(directoryName, (StringPtr)"\p:");
-               pstrinsert(fullPathName, directoryName);
-               if (block.dirInfo.ioDrDirID == 2) break;
+               return (err);
        }
+
+       /* Save pointer */
+       *pictGWorld = tempGWorld;
+
+       /* Save GWorld */
+       GetGWorld(&saveGWorld, &saveGDevice);
+
+       /* Activate */
+       SetGWorld(tempGWorld, nil);
+
+       /* Dump the pict into the GWorld */
+       (void)LockPixels(GetGWorldPixMap(tempGWorld));
+       EraseRect(&pictRect);
+       DrawPicture(pictH, &pictRect);
+       UnlockPixels(GetGWorldPixMap(tempGWorld));
+
+       /* Restore GWorld */
+       SetGWorld(saveGWorld, saveGDevice);
+       
+       /* Success */
+       return (0);
 }
 
-#endif
 #endif /* MACH_O_CARBON */
 
+
 /*
- * Activate a given window, if necessary
+ * Init the global "frameP"
  */
-static void activate(WindowPtr w)
+
+static errr globe_init(void)
 {
-       /* Activate */
-       if (active != w)
-       {
-               /* Activate */
+       OSErr err;
+       
+       GWorldPtr tempPictGWorldP;
+
+#ifdef MACH_O_CARBON
+       FSSpec pict_spec;
+#else
+       PicHandle newPictH;
+#endif /* MACH_O_CARBON */
+
+       /* Use window XXX XXX XXX */
 #if TARGET_API_MAC_CARBON
-               if (w) SetPortWindowPort(w);
+       SetPortWindowPort(data[0].w);
 #else
-               if (w) SetPort(w);
+       SetPort(data[0].w);
 #endif
 
-               /* Remember */
-               active = w;
-       }
-}
 
+#ifdef MACH_O_CARBON
 
-/*
- * Display a warning message
- */
-static void mac_warning(cptr warning)
-{
-       Str255 text;
-       int len, i;
+       /* Get the tile resources */
+       if (!get_resource_spec(pictID, CFSTR("png"), &pict_spec)) return (-1);
+
+       /* Create GWorld */
+       err = create_gworld_from_spec(&tempPictGWorldP, &pict_spec);
+
+       /* Error */
+       if (err != noErr) return (err);
+
+       /* Create the frame */
+       frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
+
+       /* Analyze result */
+       if (frameP == NULL)
+       {
+               /* Dispose of image GWorld */
+               DisposeGWorld(tempPictGWorldP);
+
+               /* Fake error code */
+               return (-1);
+       }
+
+       /* Save GWorld */
+       frameP->framePort = tempPictGWorldP;
 
-       /* Limit of 250 chars */
-       len = strlen(warning);
-       if (len > 250) len = 250;
+       /* Lock it */
+       BenSWLockFrame(frameP);
 
-       /* Make a "Pascal" string */
-       text[0] = len;
-       for (i=0; i<len; i++) text[i+1] = warning[i];
+#else /* MACH_O_CARBON */
 
-       /* Prepare the dialog box values */
-       ParamText(text, "\p", "\p", "\p");
+       /* Get the pict resource */
+       newPictH = GetPicture(pictID);
 
-       /* Display the Alert, wait for Okay */
-       Alert(129, 0L);
-}
+       /* Analyze result */
+       err = (newPictH ? 0 : -1);
 
+       /* Oops */
+       if (err == noErr)
+       {
+
+               /* Create GWorld */
+               err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
+               
+               /* Release resource */
+               ReleaseResource((Handle)newPictH);
 
+               /* Error */
+               if (err == noErr)
+               {
+                       /* Create the frame */
+                       frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
 
-/*** Some generic functions ***/
+                       /* Analyze result */
+                       err = (frameP ? 0 : -1);
 
+                       /* Oops */
+                       if (err == noErr)
+                       {
+                               /* Save GWorld */
+                               frameP->framePort = tempPictGWorldP;
 
-#ifdef ANGBAND_LITE_MAC
+                               /* Lock it */
+                               BenSWLockFrame(frameP);
+                       }
+               }
+       }
+#endif /* MACH_O_CARBON */
 
-/*
- * Hack -- activate a color (0 to 255)
- */
-#define term_data_color(TD,A) /* Nothing */
 
-#else /* ANGBAND_LITE_MAC */
+       /* Result */
+       return (err);
+}
+
 
 /*
- * Hack -- activate a color (0 to 255)
+ * Nuke the global "frameP"
  */
-static void term_data_color(term_data *td, int a)
+static errr globe_nuke(void)
 {
-       u16b rv, gv, bv;
+       /* Dispose */
+       if (frameP)
+       {
+               /* Unlock */
+               BenSWUnlockFrame(frameP);
 
-       RGBColor color;
+               /* Dispose of the GWorld */
+               DisposeGWorld(frameP->framePort);
 
-       /* Extract the R,G,B data */
-       rv = angband_color_table[a][1];
-       gv = angband_color_table[a][2];
-       bv = angband_color_table[a][3];
+               /* Dispose of the memory */
+               DisposePtr((Ptr)frameP);
 
-       /* Set the color */
-       color.red = (rv | (rv << 8));
-       color.green = (gv | (gv << 8));
-       color.blue = (bv | (bv << 8));
+               /* Forget */
+               frameP = NULL;
+       }
 
-       /* Activate the color */
-       RGBForeColor(&color);
+       /* Flush events */      
+       FlushEvents(everyEvent, 0);
 
-       /* Memorize color */
-       td->last = a;
+       /* Success */
+       return (0);
 }
 
-#endif /* ANGBAND_LITE_MAC */
 
+# ifdef USE_ASYNC_SOUND
 
 /*
- * Hack -- Apply and Verify the "font" info
- *
- * This should usually be followed by "term_data_check_size()"
+ * Asynchronous sound player revised
  */
-static void term_data_check_font(term_data *td)
-{
-       int i;
-
-       FontInfo info;
-
-       WindowPtr old = active;
-
+#if defined(USE_QT_SOUND) && !defined(MACH_O_CARBON)
+# undef USE_QT_SOUND
+#endif /* USE_QT_SOUND && !MACH_O_CARBON */
 
-       /* Activate */
-       activate(td->w);
 
-       /* Instantiate font */
-       TextFont(td->font_id);
-       TextSize(td->font_size);
-       TextFace(td->font_face);
+/*
+ * Number of channels in the channel pool
+ */
+#if TARGET_API_MAC_CARBON
+#define MAX_CHANNELS           8
+#else
+#define MAX_CHANNELS           4
+#endif
 
-       /* Extract the font info */
-       GetFontInfo(&info);
+/*
+ * A pool of sound channels
+ */
+static SndChannelPtr channels[MAX_CHANNELS];
 
-       /* Assume monospaced */
-       td->font_mono = TRUE;
+/*
+ * Status of the channel pool
+ */
+static Boolean channel_initialised = FALSE;
 
-       /* Extract the font sizing values XXX XXX XXX */
-       td->font_wid = CharWidth('@'); /* info.widMax; */
-       td->font_hgt = info.ascent + info.descent;
-       td->font_o_x = 0;
-       td->font_o_y = info.ascent;
+/*
+ * Data handles containing sound samples
+ */
+static SndListHandle samples[SOUND_MAX];
 
-       /* Check important characters */
-       for (i = 33; i < 127; i++)
-       {
-               /* Hack -- notice non-mono-space */
-               if (td->font_wid != CharWidth(i)) td->font_mono = FALSE;
+/*
+ * Reference counts of sound samples
+ */
+static SInt16 sample_refs[SOUND_MAX];
 
-               /* Hack -- collect largest width */
-               if (td->font_wid < CharWidth(i)) td->font_wid = CharWidth(i);
-       }
 
-       /* Set default offsets */
-       td->tile_o_x = td->font_o_x;
-       td->tile_o_y = td->font_o_y;
+/*
+ * 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 % */
 
-       /* Set default tile size */
-       if( td->tile_wid == 0 && td->tile_hgt == 0 ){
-               td->tile_wid = td->font_wid;
-               td->tile_hgt = td->font_hgt;
-       }
+/* I'm just too lazy to write a panel for this XXX XXX */
+static SInt16 sound_volume = SOUND_VOLUME_MAX;
 
-       /* Re-activate the old window */
-       activate(old);
-}
+#ifdef USE_QT_SOUND
 
+/*
+ * 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
+ */
 
 /*
- * Hack -- Apply and Verify the "size" info
+ * (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 term_data_check_size(term_data *td)
+static void load_sounds(void)
 {
-       BitMap          screen;
-       
-#if TARGET_API_MAC_CARBON
-       GetQDGlobalsScreenBits( &screen );
-#else
-       screen = qd.screenBits;
-#endif
-       /* Minimal window size */
-       if (td == &data[0])
-       {
-               /* Enforce minimal size */
-               if (td->cols < 80) td->cols = 80;
-               if (td->rows < 24) td->rows = 24;
-       }
+       OSErr err;
+       int i;
 
-       /* Allow small windows for the rest */
-       else
+       /* 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++)
        {
-               if (td->cols < 1) td->cols = 1;
-               if (td->rows < 1) td->rows = 1;
-       }
+               /* 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;
 
-       /* Minimal tile size */
-       if (td->tile_wid < 4) td->tile_wid = 4;
-       if (td->tile_hgt < 4) td->tile_hgt = 4;
+               /* Allocate CFString with the name of sound event to be processed */
+               name = CFStringCreateWithCString(NULL, angband_sound_name[i],
+                       kTextEncodingUS_ASCII);
 
-       /* Default tile offsets */
-       td->tile_o_x = (td->tile_wid - td->font_wid) / 2;
-       td->tile_o_y = (td->tile_hgt - td->font_hgt) / 2;
+               /* Error */
+               if (name == NULL) continue;
 
-       /* Minimal tile offsets */
-       if (td->tile_o_x < 0) td->tile_o_x = 0;
-       if (td->tile_o_y < 0) td->tile_o_y = 0;
+               /* Find sound sample resource with the same name */
+               res = get_resource_spec(name, CFSTR("wav"), &spec);
 
-       /* Apply font offsets */
-       td->tile_o_x += td->font_o_x;
-       td->tile_o_y += td->font_o_y;
+               /* Free the reference to CFString */
+               CFRelease(name);
 
-       /* Calculate full window size */
-       td->size_wid = td->cols * td->tile_wid + td->size_ow1 + td->size_ow2;
-       td->size_hgt = td->rows * td->tile_hgt + td->size_oh1 + td->size_oh2;
+               /* Error */
+               if (!res) continue;
 
-       /* Verify the top */
-       if (td->r.top > screen.bounds.bottom - td->size_hgt)
-       {
-               td->r.top = screen.bounds.bottom - td->size_hgt;
-       }
+               /* Open the sound file */
+               err = OpenMovieFile(&spec, &file_id, fsRdPerm);
 
-       /* Verify the top */
-       if (td->r.top < screen.bounds.top + 30)
-       {
-               td->r.top = screen.bounds.top + 30;
-       }
+               /* Error */
+               if (err != noErr) continue;
 
-       /* Verify the left */
-       if (td->r.left > screen.bounds.right - td->size_wid)
-       {
-               td->r.left = screen.bounds.right - td->size_wid;
-       }
+               /* Create Movie from the file */
+               err = NewMovieFromFile(&movie, file_id, &res_id, movie_name,
+                       newMovieActive, NULL);
 
-       /* Verify the left */
-       if (td->r.left < screen.bounds.left)
-       {
-               td->r.left = screen.bounds.left;
-       }
+               /* Error */
+               if (err != noErr) goto close_file;
 
-       /* Calculate bottom right corner */
-       td->r.right = td->r.left + td->size_wid;
-       td->r.bottom = td->r.top + td->size_hgt;
+               /* Get the first track of the movie */
+               track = GetMovieIndTrackType(movie, 1, AudioMediaCharacteristic,
+                       movieTrackCharacteristic | movieTrackEnabledOnly );
 
-       /* Assume no graphics */
-       td->t->higher_pict = FALSE;
-       td->t->always_pict = FALSE;
+               /* Error */
+               if (track == NULL) goto close_movie;
 
-#ifdef ANGBAND_LITE_MAC
+               /* Allocate a handle to store sample */
+               h = NewHandle(0);
 
-       /* No graphics */
+               /* Error */
+               if (h == NULL) goto close_track;
 
-#else /* ANGBAND_LITE_MAC */
+               /* Dump the sample into the handle */
+               err = PutMovieIntoTypedHandle(movie, track, soundListRsrc, h, 0,
+                       GetTrackDuration(track), 0L, NULL);
 
-       /* Handle graphics */
-       if (use_graphics)
-       {
-               /* Use higher_pict whenever possible */
-               if (td->font_mono) td->t->higher_pict = TRUE;
+               /* Success */
+               if (err == noErr)
+               {
+                       /* Store the handle in the sample list */
+                       samples[i] = (SndListHandle)h;
+               }
 
-               /* Use always_pict only when necessary */
-               else td->t->always_pict = TRUE;
-       }
+               /* Failure */
+               else
+               {
+                       /* Free unused handle */
+                       DisposeHandle(h);
+               }
 
-#endif /* ANGBAND_LITE_MAC */
+               /* Free the track */
+               close_track: DisposeMovieTrack(track);
 
-       /* Fake mono-space */
-       if (!td->font_mono ||
-           (td->font_wid != td->tile_wid) ||
-               (td->font_hgt != td->tile_hgt))
-       {
-               /* Handle fake monospace -- this is SLOW */
-               if (td->t->higher_pict) td->t->higher_pict = FALSE;
-               td->t->always_pict = TRUE;
+               /* Free the movie */
+               close_movie: DisposeMovie(movie);
+
+               /* Close the movie file */
+               close_file: CloseMovieFile(file_id);
        }
+
+       /* Stop QuickTime */
+       ExitMovies();
 }
 
+#else /* USE_QT_SOUND */
+
 /*
- * Hack -- resize a term_data
+ * Return a handle of 'snd ' resource given Angband sound event number,
+ * or NULL if it isn't found.
  *
- * This should normally be followed by "term_data_resize()"
+ * Globals referenced: angband_sound_name[] (variable.c)
  */
-static void term_data_resize(term_data *td)
+static SndListHandle find_sound(int num)
 {
-       /* Actually resize the window */
-       SizeWindow(td->w, td->size_wid, td->size_hgt, 0);
+       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 */
 
 
 /*
- * Hack -- redraw a term_data
+ * Clean up sound support - to be called when the game exits.
  *
- * Note that "Term_redraw()" calls "TERM_XTRA_CLEAR"
+ * Globals referenced: channels[], samples[], sample_refs[].
  */
-static void term_data_redraw(term_data *td)
+static void cleanup_sound(void)
 {
-       term *old = Term;
-
-       /* Activate the term */
-       Term_activate(td->t);
-
-       /* Redraw the contents */
-       Term_redraw();
+       int i;
 
-       /* Flush the output */
-       Term_fresh();
+       /* No need to clean it up */
+       if (!channel_initialised) return;
 
-       /* Restore the old term */
-       Term_activate(old);
-       
-       /* No need to redraw */
-#if TARGET_API_MAC_CARBON
+       /* Dispose channels */
+       for (i = 0; i < MAX_CHANNELS; i++)
        {
-               RgnHandle               theRgn = NewRgn();
-               GetWindowRegion( td->w, kWindowContentRgn, theRgn );
-               ValidWindowRgn( (WindowRef)(td->w), theRgn );
-               DisposeRgn( theRgn );
+               /* Drain sound commands and free the channel */
+               SndDisposeChannel(channels[i], TRUE);
        }
-#else
-       ValidRect(&td->w->portRect);
-#endif
 
-}
+       /* 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 */
+       }
+}
 
-#ifdef ANGBAND_LITE_MAC
 
-/* No graphics */
+/*
+ * 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;
 
-#else /* ANGBAND_LITE_MAC */
+       static int next_chan;
+       static SInt16 channel_occupants[MAX_CHANNELS];
+       static SndCommand volume_cmd, quiet_cmd;
 
 
-/*
- * Constants
- */
+       /* 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);
 
-static int pictID = 1001;      /* 8x8 tiles; 16x16 tiles are 1002 */
+                       /* Error */
+                       if (err != noErr)
+                       {
+                               /* Free channels */
+                               while (--i >= 0)
+                               {
+                                       SndDisposeChannel(channels[i], TRUE);
+                               }
 
-static int grafWidth = 8;      /* Always equal to grafHeight */
-static int grafHeight = 8;     /* Either 8 or 16 */
+                               /* Notify error */
+#ifdef JP
+                               plog("¥µ¥¦¥ó¥É¥Á¥ã¥ó¥Í¥ë¤ò½é´ü²½½ÐÍè¤Þ¤»¤ó!");
+#else
+                               plog("Cannot initialise sound channels!");
+#endif
 
-static bool arg_newstyle_graphics;
-static bool use_newstyle_graphics;
+                               /* Cancel request */
+                               use_sound = arg_sound = FALSE;
 
-/*
- * Forward Declare
- */
-typedef struct FrameRec FrameRec;
+                               /* Failure */
+                               return;
+                       }
+               }
 
-/*
- * Frame
- *
- *     - GWorld for the frame image
- *     - Handle to pix map (saved for unlocking/locking)
- *     - Pointer to color pix map (valid only while locked)
- */
-struct FrameRec
-{
-       GWorldPtr               framePort;
-       PixMapHandle    framePixHndl;
-       PixMapPtr               framePix;
-       
-};
+               /* First channel to use */
+               next_chan = 0;
 
+               /* Prepare volume command */
+               volume_cmd.cmd = volumeCmd;
+               volume_cmd.param1 = 0;
+               volume_cmd.param2 = 0;
 
-/*
- * The global picture data
- */
-static FrameRec *frameP = NULL;
+               /* Prepare quiet command */
+               quiet_cmd.cmd = quietCmd;
+               quiet_cmd.param1 = 0;
+               quiet_cmd.param2 = 0;
 
+               /* Initialisation complete */
+               channel_initialised = TRUE;
+       }
 
-/*
- * Lock a frame
- */
-static void BenSWLockFrame(FrameRec *srcFrameP)
-{
-       PixMapHandle            pixMapH;
+       /* Paranoia */
+       if ((num <= 0) || (num >= SOUND_MAX)) return;
 
-       pixMapH = GetGWorldPixMap(srcFrameP->framePort);
-       (void)LockPixels(pixMapH);
-       HLockHi((Handle)pixMapH);
-       srcFrameP->framePixHndl = pixMapH;
-#if TARGET_API_MAC_CARBON
-       srcFrameP->framePix = (PixMapPtr)*(Handle)pixMapH;
-#else
-       srcFrameP->framePix = (PixMapPtr)StripAddress(*(Handle)pixMapH);
-#endif
-       
-}
+       /* Prepare volume command */
+       volume_cmd.param2 = ((SInt32)vol << 16) | vol;
 
+       /* Channel to use (round robin) */
+       chan = channels[next_chan];
 
-/*
- * Unlock a frame
- */
-static void BenSWUnlockFrame(FrameRec *srcFrameP)
-{
-       if (srcFrameP->framePort != NULL)
+       /* See if the resource is already in use */
+       if (sample_refs[num] > 0)
        {
-               HUnlock((Handle)srcFrameP->framePixHndl);
-               UnlockPixels(srcFrameP->framePixHndl);
+               /* Resource in use */
+               h = samples[num];
+
+               /* Increase the refcount */
+               sample_refs[num]++;
        }
 
-       srcFrameP->framePix = NULL;
-       
-}
+       /* 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 */
 
-static OSErr BenSWCreateGWorldFromPict(
-       GWorldPtr *pictGWorld,
-       PicHandle pictH)
-{
-       OSErr err;
-       GWorldPtr saveGWorld;
-       GDHandle saveGDevice;
-       GWorldPtr tempGWorld;
-       Rect pictRect;
-       short depth;
-       GDHandle theGDH;
+               /* Sample not available */
+               if (h == NULL) return;
 
-       /* Reset */
-       *pictGWorld = NULL;
+#ifndef USE_QT_SOUND
 
-       /* Get depth */
-       depth = data[0].pixelDepth;
+               /* Load resource */
+               LoadResource((Handle)h);
 
-       /* Get GDH */
-       theGDH = data[0].theGDH;
+               /* Remember it */
+               samples[num] = h;
 
-       /* Obtain size rectangle */
-       pictRect = (**pictH).picFrame;
-       OffsetRect(&pictRect, -pictRect.left, -pictRect.top);
+#endif /* !USE_QT_SOUND */
 
-       /* Create a GWorld */
-       err = NewGWorld(&tempGWorld, depth, &pictRect, nil, 
-                                       theGDH, noNewDevice);
+               /* Lock the handle */
+               HLockHi((Handle)h);
 
-       /* Success */
-       if (err != noErr)
-       {
-               return (err);
+               /* Initialise refcount */
+               sample_refs[num] = 1;
        }
 
-       /* Save pointer */
-       *pictGWorld = tempGWorld;
+       /* Poll the channel */
+       err = SndChannelStatus(chan, sizeof(SCStatus), &status);
 
-       /* Save GWorld */
-       GetGWorld(&saveGWorld, &saveGDevice);
+       /* It isn't available */
+       if ((err != noErr) || status.scChannelBusy)
+       {
+               /* Shut it down */
+               SndDoImmediate(chan, &quiet_cmd);
+       }
 
-       /* Activate */
-       SetGWorld(tempGWorld, nil);
+       /* Previously played sound on this channel */
+       prev_num = channel_occupants[next_chan];
 
-       /* Dump the pict into the GWorld */
-       (void)LockPixels(GetGWorldPixMap(tempGWorld));
-       EraseRect(&pictRect);
-       DrawPicture(pictH, &pictRect);
-       UnlockPixels(GetGWorldPixMap(tempGWorld));
+       /* Process previously played sound */
+       if (prev_num != 0)
+       {
+               /* Decrease refcount */
+               sample_refs[prev_num]--;
 
-       /* Restore GWorld */
-       SetGWorld(saveGWorld, saveGDevice);
-       
-       /* Success */
-       return (0);
-}
+               /* 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;
 
-/*
- * Init the global "frameP"
- */
+#endif /* !USE_QT_SOUND */
 
-static errr globe_init(void)
-{
-       OSErr err;
-       
-       GWorldPtr tempPictGWorldP;
+                       /* Paranoia */
+                       sample_refs[prev_num] = 0;
+               }
+       }
 
-       PicHandle newPictH;
+       /* Remember this sound as the current occupant of the channel */
+       channel_occupants[next_chan] = num;
 
-       /* Use window XXX XXX XXX */
-#if TARGET_API_MAC_CARBON
-       SetPortWindowPort(data[0].w);
-#else
-       SetPort(data[0].w);
-#endif
+       /* Set up volume for channel */
+       SndDoImmediate(chan, &volume_cmd);
 
+       /* Play new sound asynchronously */
+       SndPlay(chan, h, TRUE);
 
-       /* Get the pict resource */
-       newPictH = GetPicture(pictID);
+       /* Schedule next channel (round robin) */
+       next_chan++;
+       if (next_chan >= MAX_CHANNELS) next_chan = 0;
+}
 
-       /* Analyze result */
-       err = (newPictH ? 0 : -1);
+# else /* USE_ASYNC_SOUND */
 
-       /* Oops */
-       if (err == noErr)
-       {
+/*
+ * 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;
 
-               /* Create GWorld */
-               err = BenSWCreateGWorldFromPict(&tempPictGWorldP, newPictH);
-               
-               /* Release resource */
-               ReleaseResource((Handle)newPictH);
+       /* Get the proper sound name */
+       strnfmt((char*)sound + 1, 255, "%.16s.wav", angband_sound_name[num]);
+       sound[0] = strlen((char*)sound + 1);
 
-               /* Error */
-               if (err == noErr)
-               {
-                       /* Create the frame */
-                       frameP = (FrameRec*)NewPtrClear((Size)sizeof(FrameRec));
+       /* Obtain resource XXX XXX XXX */
+       handle = GetNamedResource('snd ', sound);
 
-                       /* Analyze result */
-                       err = (frameP ? 0 : -1);
+       /* Oops */
+       if (handle == NULL) return;
 
-                       /* Oops */
-                       if (err == noErr)
-                       {
-                               /* Save GWorld */
-                               frameP->framePort = tempPictGWorldP;
+       /* Load and Lock */
+       LoadResource(handle);
+       HLockHi(handle);
 
-                               /* Lock it */
-                               BenSWLockFrame(frameP);
-                       }
-               }
-       }
+       /* Play sound (wait for completion) */
+       SndPlay(NULL, (SndListHandle)handle, FALSE);
 
-       /* Result */
-       return (err);
+       /* Unlock and release */
+       HUnlock(handle);
+       ReleaseResource(handle);
 }
 
+# endif /* USE_ASYNC_SOUND */
 
 /*
- * Nuke the global "frameP"
- */
-static errr globe_nuke(void)
-{
-       /* Dispose */
-       if (frameP)
-       {
-               /* Unlock */
-               BenSWUnlockFrame(frameP);
+       Extra Sound Mode
+*/
 
-               /* Dispose of the GWorld */
-               DisposeGWorld(frameP->framePort);
 
-               /* Dispose of the memory */
-               DisposePtr((Ptr)frameP);
+static short soundmode[8];
 
-               /* Forget */
-               frameP = NULL;
-       }
+#define                SND_NON         0
+#define                SND_ATTACK      1
+#define                SND_MOVE                2
+#define                SND_TRAP                3
+#define                SND_SHOP                4
+#define                SND_ME          5
+#define                SND_CMD_ERROR   6
+
+#ifndef MACH_O_CARBON
 
-       /* Flush events */      
-       FlushEvents(everyEvent, 0);
+static int soundchoice[] = {
+       SND_NON,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ME,
+       SND_ME,
+       SND_ME,
+       SND_MOVE,
+       SND_ATTACK,
+       SND_ME,
+       SND_ATTACK,
+       SND_NON,
+       SND_MOVE,
+       SND_MOVE,
+       SND_ME,
+       SND_SHOP,
+       SND_SHOP,
+       SND_SHOP,
+       SND_SHOP,
+       SND_MOVE,
+       SND_MOVE,
+       SND_MOVE,
+       SND_MOVE,
+       SND_ATTACK,
+       SND_SHOP,
+       SND_SHOP,
+       SND_ME,
+       SND_NON,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_NON,
+       SND_CMD_ERROR,
+       SND_TRAP,
+       SND_NON,
+       SND_NON,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_TRAP,
+       SND_ATTACK,
+       SND_ATTACK,
+       SND_NON,
+       SND_TRAP,
+};
 
-       /* Success */
-       return (0);
-}
+static int ext_sound = 0;
+static int ext_graf = 0;
 
+#endif /* !MACH_O_CARBON */
 
 #endif /* ANGBAND_LITE_MAC */
 
@@ -2290,48 +2444,77 @@ static errr Term_xtra_mac_react(void)
        }
 
        
-       /* Handle transparency */
-       if (use_newstyle_graphics != arg_newstyle_graphics)
+       /* Handle graphics */
+       if (graf_mode_req != graf_mode)
        {
+               /* dispose old GWorld's if present */
                globe_nuke();
 
-               if (globe_init() != 0)
+               /* Setup parameters according to request */
+               switch (graf_mode_req)
                {
-                       plog("Cannot initialize graphics!");
-                       arg_graphics = FALSE;
-                       arg_newstyle_graphics = FALSE;
-               }
-
-               /* Apply request */
-               use_newstyle_graphics = arg_newstyle_graphics;
+                       /* ASCII - no graphics whatsoever */
+                       case GRAF_MODE_NONE:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_NONE;
+                               break;
+                       }
 
-               /* Apply and Verify */
-               term_data_check_size(td);
+                       /*
+                        * 8x8 tiles (PICT id 1001)
+                        * no transparency effect
+                        * "old" graphics definitions
+                        */
+                       case GRAF_MODE_8X8:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_ORIGINAL;
+                               ANGBAND_GRAF = "old";
+#ifdef MACH_O_CARBON
+                               pictID = CFSTR("8x8");
+#else
+                               pictID = 1001;
+#endif /* MACH_O_CARBON */
+                               grafWidth = grafHeight = 8;
+                               break;
+                       }
 
-               /* Resize the window */
-               term_data_resize(td);
-               /* Reset visuals */
-               reset_visuals();
-       }
-       
-       /* Handle graphics */
-       if (use_graphics != arg_graphics)
-       {
-               /* Initialize graphics */
+                       /*
+                        * 16x16 tiles (images: PICT id 1002)
+                        * with transparency effect
+                        * "new" graphics definitions
+                        */
+                       case GRAF_MODE_16X16:
+                       {
+                               use_graphics = arg_graphics = GRAPHICS_ADAM_BOLT;
+                               ANGBAND_GRAF = "new";
+#ifdef MACH_O_CARBON
+                               pictID = CFSTR("16x16");
+#else
+                               pictID = 1002;
+#endif /* MACH_O_CARBON */
+                               grafWidth = grafHeight = 16;
+                               break;
+                       }
+               }
 
-               if (!use_graphics && !frameP && (globe_init() != 0))
+               if ((graf_mode_req != GRAF_MODE_NONE) && !frameP && (globe_init() != 0))
                {
 #ifdef JP
                        plog("¥°¥é¥Õ¥£¥Ã¥¯¤Î½é´ü²½¤Ï½ÐÍè¤Þ¤»¤ó¤Ç¤·¤¿.");
 #else
                        plog("Cannot initialize graphics!");
 #endif
-                       arg_graphics = FALSE;
+
+                       /* reject request */
+                       graf_mode_req = GRAF_MODE_NONE;
+
+                       /* reset graphics flags */
+                       use_graphics = arg_graphics = FALSE;
+
                }
 
-               /* Apply request */
-               use_graphics = arg_graphics;
+               /* update current graphics mode */
+               graf_mode = graf_mode_req;
 
                /* Apply and Verify */
                term_data_check_size(td);
@@ -3153,18 +3336,13 @@ static void cf_save_prefs()
 
        /* 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
+       save_pref_short("arg.graf_mode", graf_mode);
+       save_pref_short("arg.arg_bigtile", use_bigtile);
 
        /* 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++)
        {
@@ -3203,8 +3381,6 @@ static void cf_load_prefs()
        short pref_major, pref_minor, pref_patch, pref_extra;
        int i;
 
-       MenuHandle m;
-
        /* Assume nothing is wrong, yet */
        ok = TRUE;
 
@@ -3228,25 +3404,6 @@ static void cf_load_prefs()
                return;
        }
 
-#if 0
-
-       /* Check version */
-       if ((pref_major != PREF_VER_MAJOR) ||
-               (pref_minor != PREF_VER_MINOR) ||
-               (pref_patch != PREF_VER_PATCH) ||
-               (pref_extra != PREF_VER_EXTRA))
-       {
-               /* Message */
-               mac_warning(
-                       format("Ignoring %d.%d.%d.%d preferences.",
-                               pref_major, pref_minor, pref_patch, pref_extra));
-
-               /* Ignore */
-               return;
-       }
-
-#endif
-
        /* Gfx settings */
        {
                short pref_tmp;
@@ -3256,29 +3413,8 @@ static void cf_load_prefs()
                        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;
-               }
+               if (query_load_pref_short("arg.graf_mode", &pref_tmp))
+                       graf_mode_req = pref_tmp;
 
                /* double-width tiles */
                if (query_load_pref_short("arg.arg_bigtile", &pref_tmp))
@@ -3288,31 +3424,12 @@ static void cf_load_prefs()
 
        }
 
-#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++)
        {
@@ -3379,8 +3496,7 @@ static void save_prefs(void)
        putshort(FAKE_VER_PATCH);
 
        putshort(arg_sound);
-       putshort(arg_graphics);
-       putshort(arg_newstyle_graphics);
+       putshort(graf_mode);
        putshort(arg_bigtile);
        
        /* SoundMode */
@@ -3451,25 +3567,7 @@ static void load_prefs(void)
        }
 
        arg_sound = getshort();
-       arg_graphics = getshort();
-       arg_newstyle_graphics = getshort();
-       use_newstyle_graphics = arg_newstyle_graphics;
-       
-       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;
-       }
-
+       graf_mode_req = getshort();
        arg_bigtile = getshort();
        use_bigtile = arg_bigtile;
        
@@ -3477,21 +3575,6 @@ static void load_prefs(void)
        for( i = 0 ; i < 7 ; i++ )
                soundmode[i] = getshort();
        
-       /* Special menu */
-       m = GetMenuHandle(134);
-
-       /* Item "arg_sound" */
-       CheckItem(m, 1, arg_sound);
-
-       /* Item "arg_graphics" */
-       CheckItem(m, 2, arg_graphics);
-       
-       /* Item "arg_newstyle_graphics"*/
-       CheckItem(m, 8, arg_newstyle_graphics);
-
-       /* Item "arg_bigtile"*/
-       CheckItem(m, 9, arg_bigtile);
-
        /* Windows */
        for (i = 0; i < MAX_TERM_DATA; i++)
        {
@@ -4476,11 +4559,6 @@ static void handle_open_when_ready(void)
 /*
  * Initialize the menus
  *
- * Verify menus 128, 129, 130
- * Create menus 131, 132, 133, 134
- *
- * The standard menus are:
- *
  *   Apple (128) =   { About, -, ... }
  *   File (129) =    { New,Open,Import,Close,Save,-,Exit,Quit }
  *   Edit (130) =    { Cut, Copy, Paste, Clear }   (?)
@@ -4488,9 +4566,70 @@ static void handle_open_when_ready(void)
  *   Size (132) =    { ... }
  *   Window (133) =  { Angband, Mirror, Recall, Choice,
  *                     Term-4, Term-5, Term-6, Term-7 }
- *   Special (134) = { arg_sound, arg_graphics, -,
- *                     arg_fiddle, arg_wizard }
+ *   Special (134) = { Sound, Graphics, TileWidth, TileHeight, -,
+ *                     Fiddle, Wizard }
  */
+
+/* Apple menu */
+#define MENU_APPLE     128
+#define ITEM_ABOUT     1
+
+/* File menu */
+#define MENU_FILE      129
+# define ITEM_NEW      1
+# define ITEM_OPEN     2
+# define ITEM_IMPORT   3
+# define ITEM_CLOSE    4
+# define ITEM_SAVE     5
+#  define ITEM_QUIT    7
+
+/* Edit menu */
+#define MENU_EDIT      130
+# define ITEM_UNDO     1
+# define ITEM_CUT      3
+# define ITEM_COPY     4
+# define ITEM_PASTE    5
+# define ITEM_CLEAR    6
+
+/* Font menu */
+#define MENU_FONT      131
+# define ITEM_BOLD     1
+# define ITEM_WIDE     2
+
+/* Size menu */
+#define MENU_SIZE      132
+
+/* Windows menu */
+#define MENU_WINDOWS   133
+
+/* Special menu */
+#define MENU_SPECIAL   134
+# define ITEM_SOUND    1
+# define ITEM_GRAPH    2
+# define ITEM_TILEWIDTH 3
+# define ITEM_TILEHEIGHT 4
+# define ITEM_FIDDLE   6
+# define ITEM_WIZARD   7
+
+/* Sounds submenu */
+#define SUBMENU_SOUND  143
+# define ITEM_USE_SOUND        1
+# define ITEM_SOUND_SETTING    2
+
+/* Graphics submenu */
+#define SUBMENU_GRAPH  144
+# define ITEM_NONE     1
+# define ITEM_8X8      2
+# define ITEM_16X16    3
+# define ITEM_BIGTILE 5        
+
+/* TileWidth submenu */
+#define SUBMENU_TILEWIDTH      145
+
+/* TileHeight submenu */
+#define SUBMENU_TILEHEIGHT     146
+
+
 static void init_menubar(void)
 {
        int i, n;
@@ -4500,62 +4639,55 @@ static void init_menubar(void)
        WindowPtr tmpw;
 
        MenuHandle m;
-       OSErr           err;
-       long            response;
+
+       Handle mbar;
+
+#if TARGET_API_MAC_CARBON
+       OSErr err;
+       long response;
+#endif
 
        /* Get the "apple" menu */
-       m = GetMenu(128);
+       mbar = GetNewMBar(128);
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Whoops! */
+#ifdef JP
+       if (mbar == nil) quit("¥á¥Ë¥å¡¼¥Ð¡¼ ID 128¤ò¸«¤Ä¤±¤ë»ö¤¬¤Ç¤­¤Þ¤»¤ó!");
+#else
+       if (mbar == nil) quit("Cannot find menubar('MBAR') id 128!");
+#endif
+
+       /* Insert them into the current menu list */
+       SetMenuBar(mbar);
+
+       /* Free handle */
+       DisposeHandle(mbar);
+
+#if !TARGET_API_MAC_CARBON
+       /* Apple menu (id 128) */
+       m = GetMenuHandle(MENU_APPLE);
 
        /* Add the DA's to the "apple" menu */
-#if TARGET_API_MAC_CARBON
-#else
        AppendResMenu   (m, 'DRVR');
 #endif
 
        /* Get the "File" menu */
 #if TARGET_API_MAC_CARBON
-       m = GetMenu(129);
+       m = GetMenu(MENU_FILE);
        err = Gestalt( gestaltSystemVersion, &response );
        if ( (err == noErr) && (response >= 0x00000A00) )
        {
-               DeleteMenuItem( m, 7 );
+               DeleteMenuItem(m, ITEM_QUIT);
        }
-#else
-       m = GetMenu(129);
 #endif
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-
-       /* Get the "Edit" menu */
-       m = GetMenu(130);
-
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-
-       /* Make the "Font" menu */
-       #ifdef JP
-       m = NewMenu(131, "\p¥Õ¥©¥ó¥È");
-       #else
-       m = NewMenu(131, "\pFont");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
-
-       /* Add "bold" */
-       AppendMenu(m, "\pBold");
+       /* Edit menu (id 130) - we don't have to do anything */
 
-       /* Add "wide" */
-       AppendMenu(m, "\pWide");
-
-       /* Add a separator */
-       AppendMenu(m, "\p-");
+       /*
+        * Font menu (id 131) - append names of mono-spaced fonts
+        * followed by all available ones
+        */
+       m = GetMenuHandle(MENU_FONT);
 
        /* Fake window */
        r.left = r.right = r.top = r.bottom = 0;
@@ -4623,15 +4755,8 @@ static void init_menubar(void)
        AppendResMenu   (m, 'FONT');
 
 
-       /* Make the "Size" menu */
-       #ifdef JP
-       m = NewMenu(132, "\p¥µ¥¤¥º");
-       #else
-       m = NewMenu(132, "\pSize");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Size menu (id 132) */
+       m = GetMenuHandle(MENU_SIZE);
 
        /* Add some sizes (stagger choices) */
        for (i = 8; i <= 32; i += ((i / 16) + 1))
@@ -4647,15 +4772,8 @@ static void init_menubar(void)
        }
 
 
-       /* Make the "Windows" menu */
-       #ifdef JP
-       m = NewMenu(133, "\p¥¦¥¤¥ó¥É¥¦");
-       #else
-       m = NewMenu(133, "\pWindows");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Windows menu (id 133) */
+       m = GetMenuHandle(MENU_WINDOWS);
 
        /* Default choices */
        for (i = 0; i < MAX_TERM_DATA; i++)
@@ -4669,53 +4787,109 @@ static void init_menubar(void)
                /* Add the item */
                AppendMenu(m, buf);
 
-               /* Command-Key shortcuts */
-               if (i < 8) SetItemCmd(m, i + 1, '0' + i);
-       }
+               /* Command-Key shortcuts */
+               if (i < 8) SetItemCmd(m, i + 1, '0' + i);
+       }
+
+
+#if TARGET_API_MAC_CARBON && !defined(MAC_MPW)
+
+       /* CW or gcc -- Use recommended interface for hierarchical menus */
+
+       /* Special menu (id 134) */
+       m = GetMenuHandle(MENU_SPECIAL);
+
+       /* Insert Graphics submenu (id 143) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_SOUND);
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_SOUND, submenu);
+       }
+
+       /* Insert Graphics submenu (id 144) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_GRAPH);
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_GRAPH, submenu);
+       }
+
+       /* Insert TileWidth submenu (id 145) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_TILEWIDTH);
+
+               /* Add some sizes */
+               for (i = 4, n = 1; i <= 32; i++, n++)
+               {
+                       Str15 buf;
+
+                       /* Textual size */
+                       strnfmt((char*)buf + 1, 15, "%d", i);
+                       buf[0] = strlen((char*)buf + 1);
+
+                       /* Append item */
+                       AppendMenu(submenu, buf);
+               }
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, submenu);
+       }
+
+       /* Insert TileHeight submenu (id 146) */
+       {
+               MenuHandle submenu;
+
+               /* Get the submenu */
+               submenu = GetMenu(SUBMENU_TILEHEIGHT);
+
+
+               /* Add some sizes */
+               for (i = 4, n = 1; i <= 32; i++, n++)
+               {
+                       Str15 buf;
+
+                       /* Textual size */
+                       strnfmt((char*)buf + 1, 15, "%d", i);
+                       buf[0] = strlen((char*)buf + 1);
+
+                       /* Append item */
+                       AppendMenu(submenu, buf);
+               }
+
+               /* Insert it */
+               SetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, submenu);
+       }
+
+#else
+
+       /* Special menu (id 134) */
+
+       /* Get graphics (sub)menu (id 143) */
+       m = GetMenu(SUBMENU_SOUND);
+
+       /* Insert it as a submenu */            
+       InsertMenu(m, hierMenu);
 
 
-       /* Make the "Special" menu */
-       #ifdef JP
-       m = NewMenu(134, "\pÆÃÊÌ");
-       #else
-       m = NewMenu(134, "\pSpecial");
-       #endif
-       
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Get graphics (sub)menu (id 144) */
+       m = GetMenu(SUBMENU_GRAPH);
 
-       /* Append the choices */
-       #ifdef JP
-       AppendMenu(m, "\p¥µ¥¦¥ó¥É»ÈÍÑ");
-       AppendMenu(m, "\p¥°¥é¥Õ¥£¥Ã¥¯»ÈÍÑ");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\parg_fiddle");
-       AppendMenu(m, "\parg_wizard");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\p¥µ¥¦¥ó¥ÉÀßÄê...");
-       AppendMenu(m, "\p16X16¥°¥é¥Õ¥£¥Ã¥¯");
-       AppendMenu(m, "\p£²ÇÜÉý¥¿¥¤¥ëɽ¼¨");
-       #else
-       AppendMenu(m, "\parg_sound");
-       AppendMenu(m, "\parg_graphics");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\parg_fiddle");
-       AppendMenu(m, "\parg_wizard");
-       AppendMenu(m, "\p-");
-       AppendMenu(m, "\pSound config");
-       AppendMenu(m, "\pAdam Bolt tile");
-       AppendMenu(m, "\pBigtile Mode");
-       #endif
+       /* Insert it as a submenu */            
+       InsertMenu(m, hierMenu);
 
-       /* Make the "TileWidth" menu */
-       #ifdef JP
-       m = NewMenu(135, "\p¥¿¥¤¥ëÉý");
-       #else
-       m = NewMenu(135, "\pTileWidth");
-       #endif
 
-       /* Insert the menu */
-       InsertMenu(m, 0);
+       /* Get TileWidth (sub)menu (id 145) */
+       m = GetMenu(SUBMENU_TILEWIDTH);
 
        /* Add some sizes */
        for (i = 4; i <= 32; i++)
@@ -4731,15 +4905,11 @@ static void init_menubar(void)
        }
 
 
-       /* Make the "TileHeight" menu */
-       #ifdef JP
-       m = NewMenu(136, "\p¥¿¥¤¥ë¹â");
-       #else
-       m = NewMenu(136, "\pTileHeight");
-       #endif
+       /* Insert it as a submenu */
+       InsertMenu(m, hierMenu);
 
-       /* Insert the menu */
-       InsertMenu(m, 255);
+       /* Get TileHeight (sub)menu (id 146) */
+       m = GetMenu(SUBMENU_TILEHEIGHT);
 
        /* Add some sizes */
        for (i = 4; i <= 32; i++)
@@ -4755,6 +4925,10 @@ static void init_menubar(void)
        }
 
 
+       /* Insert the menu */
+       InsertMenu(m, hierMenu);
+
+#endif
        /* Update the menu bar */
        DrawMenuBar();
 }
@@ -4788,7 +4962,7 @@ static void setup_menus(void)
 
 
        /* File menu */
-       m = GetMenuHandle(129);
+       m = GetMenuHandle(MENU_FILE);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4814,13 +4988,13 @@ static void setup_menus(void)
        if (initialized && !game_in_progress)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 1);
-               EnableMenuItem(m, 2);
-               EnableMenuItem(m, 3);
+               EnableMenuItem(m, ITEM_NEW);
+               EnableMenuItem(m, ITEM_OPEN);
+               EnableMenuItem(m, ITEM_IMPORT);
 #else
-               EnableItem(m, 1);
-               EnableItem(m, 2);
-               EnableItem(m, 3);
+               EnableItem(m, ITEM_NEW);
+               EnableItem(m, ITEM_OPEN);
+               EnableItem(m, ITEM_IMPORT);
 #endif
        }
 
@@ -4828,9 +5002,9 @@ static void setup_menus(void)
        if (initialized)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 4);
+               EnableMenuItem(m, ITEM_CLOSE);
 #else
-               EnableItem(m, 4);
+               EnableItem(m, ITEM_CLOSE);
 #endif
        }
 
@@ -4838,9 +5012,9 @@ static void setup_menus(void)
        if (initialized && character_generated)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 5);
+               EnableMenuItem(m, ITEM_SAVE);
 #else
-               EnableItem(m, 5);
+               EnableItem(m, ITEM_SAVE);
 #endif
        }
 
@@ -4848,15 +5022,15 @@ static void setup_menus(void)
        if (TRUE)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 7);
+               EnableMenuItem(m, ITEM_QUIT);
 #else
-               EnableItem(m, 7);
+               EnableItem(m, ITEM_QUIT);
 #endif
        }
 
 
        /* Edit menu */
-       m = GetMenuHandle(130);
+       m = GetMenuHandle(MENU_EDIT);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4882,23 +5056,23 @@ static void setup_menus(void)
        if (!td)
        {
 #if TARGET_API_MAC_CARBON
-               EnableMenuItem(m, 1);
-               EnableMenuItem(m, 3);
-               EnableMenuItem(m, 4);
-               EnableMenuItem(m, 5);
-               EnableMenuItem(m, 6);
+               EnableMenuItem(m, ITEM_UNDO);
+               EnableMenuItem(m, ITEM_CUT);
+               EnableMenuItem(m, ITEM_COPY);
+               EnableMenuItem(m, ITEM_PASTE);
+               EnableMenuItem(m, ITEM_CLEAR);
 #else
-               EnableItem(m, 1);
-               EnableItem(m, 3);
-               EnableItem(m, 4);
-               EnableItem(m, 5);
-               EnableItem(m, 6);
+               EnableItem(m, ITEM_UNDO);
+               EnableItem(m, ITEM_CUT);
+               EnableItem(m, ITEM_COPY);
+               EnableItem(m, ITEM_PASTE);
+               EnableItem(m, ITEM_CLEAR);
 #endif
        }
 
 
        /* Font menu */
-       m = GetMenuHandle(131);
+       m = GetMenuHandle(MENU_FONT);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -4931,16 +5105,16 @@ static void setup_menus(void)
        {
 #if TARGET_API_MAC_CARBON
                /* Enable "bold" */
-               EnableMenuItem(m, 1);
+               EnableMenuItem(m, ITEM_BOLD);
 
                /* Enable "extend" */
-               EnableMenuItem(m, 2);
+               EnableMenuItem(m, ITEM_WIDE);
 
                /* Check the appropriate "bold-ness" */
-               if (td->font_face & bold) CheckMenuItem(m, 1, TRUE);
+               if (td->font_face & bold) CheckMenuItem(m, ITEM_BOLD, TRUE);
 
                /* Check the appropriate "wide-ness" */
-               if (td->font_face & extend) CheckMenuItem(m, 2, TRUE);
+               if (td->font_face & extend) CheckMenuItem(m, ITEM_WIDE, TRUE);
 
                /* Analyze fonts */
                for (i = 4; i <= n; i++)
@@ -4957,16 +5131,16 @@ static void setup_menus(void)
                }
 #else
                /* Enable "bold" */
-               EnableItem(m, 1);
+               EnableItem(m, ITEM_BOLD);
 
                /* Enable "extend" */
-               EnableItem(m, 2);
+               EnableItem(m, ITEM_WIDE);
 
                /* Check the appropriate "bold-ness" */
-               if (td->font_face & bold) CheckItem(m, 1, TRUE);
+               if (td->font_face & bold) CheckItem(m, ITEM_BOLD, TRUE);
 
                /* Check the appropriate "wide-ness" */
-               if (td->font_face & extend) CheckItem(m, 2, TRUE);
+               if (td->font_face & extend) CheckItem(m, ITEM_WIDE, TRUE);
 
                /* Analyze fonts */
                for (i = 4; i <= n; i++)
@@ -4986,7 +5160,7 @@ static void setup_menus(void)
 
 
        /* Size menu */
-       m = GetMenuHandle(132);
+       m = GetMenuHandle(MENU_SIZE);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -5014,23 +5188,18 @@ static void setup_menus(void)
                /* Analyze sizes */
                for (i = 1; i <= n; i++)
                {
-#if TARGET_API_MAC_CARBON
                        /* Analyze size */
                        GetMenuItemText(m, i, s);
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
+#if TARGET_API_MAC_CARBON
                        /* Enable the "real" sizes */
                        if (RealFont(td->font_id, value)) EnableMenuItem(m, i);
 
                        /* Check the current size */
                        if (td->font_size == value) CheckMenuItem(m, i, TRUE);
 #else
-                       /* Analyze size */
-                       GetMenuItemText(m, i, s);
-                       s[s[0]+1] = '\0';
-                       value = atoi((char*)(s+1));
-
                        /* Enable the "real" sizes */
                        if (RealFont(td->font_id, value)) EnableItem(m, i);
 
@@ -5042,7 +5211,7 @@ static void setup_menus(void)
 
 
        /* Windows menu */
-       m = GetMenuHandle(133);
+       m = GetMenuHandle(MENU_WINDOWS);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -5064,7 +5233,7 @@ static void setup_menus(void)
 
 
        /* Special menu */
-       m = GetMenuHandle(134);
+       m = GetMenuHandle(MENU_SPECIAL);
 
        /* Get menu size */
 #if TARGET_API_MAC_CARBON
@@ -5079,90 +5248,312 @@ static void setup_menus(void)
                /* Reset */
 #if TARGET_API_MAC_CARBON
                DisableMenuItem(m, i);
+
+#ifdef MAC_MPW
+               /* XXX Oh no, this removes submenu... */
+               if ((i != ITEM_SOUND) &&
+                   (i != ITEM_GRAPH) &&
+                   (i != ITEM_TILEWIDTH) &&
+                   (i != ITEM_TILEHEIGHT)) CheckMenuItem(m, i, FALSE);
+#else
+
                CheckMenuItem(m, i, FALSE);
+#endif
+
 #else
                DisableItem(m, i);
-               CheckItem(m, i, FALSE);
+
+               /* XXX Oh no, this removes submenu... */
+               if ((i != ITEM_SOUND) &&
+                   (i != ITEM_GRAPH) &&
+                   (i != ITEM_TILEWIDTH) &&
+                   (i != ITEM_TILEHEIGHT)) CheckItem(m, i, FALSE);
 #endif
        }
 
 #if TARGET_API_MAC_CARBON
        /* Item "arg_sound" */
-       EnableMenuItem(m, 1);
-       CheckMenuItem(m, 1, arg_sound);
+       EnableMenuItem(m, ITEM_SOUND);
+       {
+               MenuRef submenu;
 
-       /* Item "arg_graphics" */
-       EnableMenuItem(m, 2);
-       CheckMenuItem(m, 2, arg_graphics);
+#ifdef MAC_MPW
 
-       /* Item "arg_fiddle" */
-       EnableMenuItem(m, 4);
-       CheckMenuItem(m, 4, arg_fiddle);
+               /* MPW's Universal Interface is a bit out of date */
 
-       /* Item "arg_wizard" */
-       EnableMenuItem(m, 5);
-       CheckMenuItem(m, 5, arg_wizard);
+               /* Graphics submenu */
+               submenu = GetMenuHandle(SUBMENU_SOUND);
+
+#else
+
+               /* Graphics submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_SOUND, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Item "Sound On/Off" */
+               EnableMenuItem(submenu, ITEM_USE_SOUND);
+               CheckMenuItem(submenu, ITEM_USE_SOUND, arg_sound);
+
+               /* Item "Sounf Config" */
+#ifndef MACH_O_CARBON
+               EnableMenuItem(submenu, ITEM_SOUND_SETTING);
+#endif
+       }
+
+       /* Item "Graphics" */
+       EnableMenuItem(m, ITEM_GRAPH);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* Graphics submenu */
+               submenu = GetMenuHandle(SUBMENU_GRAPH);
+
+#else
+
+               /* Graphics submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_GRAPH, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Item "None" */
+               EnableMenuItem(submenu, ITEM_NONE);
+               CheckMenuItem(submenu, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
+
+               /* Item "8x8" */
+               EnableMenuItem(submenu, ITEM_8X8);
+               CheckMenuItem(submenu, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
+
+               /* Item "16x16" */
+               EnableMenuItem(submenu, ITEM_16X16);
+               CheckMenuItem(submenu, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
+
+               /* Item "Big tiles" */
+               EnableMenuItem(submenu, ITEM_BIGTILE);
+               CheckMenuItem(submenu, ITEM_BIGTILE, arg_bigtile);
+       }
+
+       /* Item "TileWidth" */
+       EnableMenuItem(m, ITEM_TILEWIDTH);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* TIleWidth submenu */
+               submenu = GetMenuHandle(SUBMENU_TILEWIDTH);
+
+#else
+
+               /* TileWidth submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEWIDTH, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Active window */
+               if (td)
+               {
+                       /* Analyze sizes */
+                       for (i = 1; i <= n; i++)
+                       {
+                               /* Analyze size */
+                               /* GetMenuItemText(m,i,s); */
+                               GetMenuItemText(submenu, i, s);
+                               s[s[0]+1] = '\0';
+                               value = atoi((char*)(s+1));
+
+                               /* Enable */
+                               if (value >= td->font_wid) EnableMenuItem(submenu, i);
+
+                               /* Check the current size */
+                               if (td->tile_wid == value) CheckMenuItem(submenu, i, TRUE);
+                       }
+               }
+       }
+
+       /* Item "TileHeight" */
+       EnableMenuItem(m, ITEM_TILEHEIGHT);
+       {
+               MenuRef submenu;
+
+#ifdef MAC_MPW
+
+               /* MPW's Universal Interface is a bit out of date */
+
+               /* TileHeight submenu */
+               submenu = GetMenuHandle(SUBMENU_TILEHEIGHT);
+
+#else
+
+               /* TileWidth submenu */
+               (void)GetMenuItemHierarchicalMenu(m, ITEM_TILEHEIGHT, &submenu);
+
+#endif
+
+               /* Get menu size */
+               n = CountMenuItems(submenu);
+
+               /* Reset menu */
+               for (i = 1; i <= n; i++)
+               {
+                       /* Reset */
+                       DisableMenuItem(submenu, i);
+                       CheckMenuItem(submenu, i, FALSE);
+               }
+
+               /* Active window */
+               if (td)
+               {
+                       /* Analyze sizes */
+                       for (i = 1; i <= n; i++)
+                       {
+                               /* Analyze size */
+                               /* GetMenuItemText(m,i,s); */
+                               GetMenuItemText(submenu, i, s);
+                               s[s[0]+1] = '\0';
+                               value = atoi((char*)(s+1));
+
+                               /* Enable */
+                               if (value >= td->font_hgt) EnableMenuItem(submenu, i);
+
+                               /* Check the current size */
+                               if (td->tile_hgt == value) CheckMenuItem(submenu, i, TRUE);
+                       }
+               }
+       }
 
-       /* Item "SoundSetting" */
-       EnableMenuItem(m, 7);
+       /* Item "arg_fiddle" */
+       EnableMenuItem(m, ITEM_FIDDLE);
+       CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle);
 
-       /* Item NewStyle Graphics */
-       EnableMenuItem(m, 8);
-       CheckMenuItem(m, 8, use_newstyle_graphics);
+       /* Item "arg_wizard" */
+       EnableMenuItem(m, ITEM_WIZARD);
+       CheckMenuItem(m, ITEM_WIZARD, arg_wizard);
 
-       /* Item Bigtile Mode */
-       EnableMenuItem(m, 9);
-       CheckMenuItem(m, 9, arg_bigtile);
 #else
        /* Item "arg_sound" */
-       EnableItem(m, 1);
-       CheckItem(m, 1, arg_sound);
+       EnableItem(m, ITEM_SOUND);
 
        /* Item "arg_graphics" */
-       EnableItem(m, 2);
-       CheckItem(m, 2, arg_graphics);
+       EnableItem(m, ITEM_GRAPH);
+
+       /* Item "TileWidth" */
+       EnableItem(m, ITEM_TILEWIDTH);
+
+       /* Item "TileHeight" */
+       EnableItem(m, ITEM_TILEHEIGHT);
 
        /* Item "arg_fiddle" */
-       EnableItem(m, 4);
-       CheckItem(m, 4, arg_fiddle);
+       EnableItem(m, ITEM_FIDDLE);
+       CheckItem(m, ITEM_FIDDLE, arg_fiddle);
 
        /* Item "arg_wizard" */
-       EnableItem(m, 5);
-       CheckItem(m, 5, arg_wizard);
+       EnableItem(m, ITEM_WIZARD);
+       CheckItem(m, ITEM_WIZARD, arg_wizard);
 
-       /* Item "SoundSetting" */
-       EnableItem(m, 7);
+       /* Sounds submenu */
+       m = GetMenuHandle(SUBMENU_SOUND);
 
-       /* Item NewStyle Graphics */
-       EnableItem(m, 8);
-       CheckItem(m, 8, use_newstyle_graphics);
+       /* Get menu size */
+       n = CountMItems(m);
 
-       /* Item Bigtile Mode */
-       EnableItem(m, 9);
-       CheckItem(m, 9, arg_bigtile);
-#endif
+       /* Reset menu */
+       for (i = 1; i <= n; i++)
+       {
+               /* Reset */
+               DisableItem(m, i);
+               CheckItem(m, i, FALSE);
+       }
+       
+       /* Item "Sound On/Off" */
+       EnableItem(m, ITEM_USE_SOUND);
+       CheckItem(m, ITEM_USE_SOUND, arg_sound);
+
+       /* Item "Sound Config" */
+       EnableItem(m, ITEM_SOUND_SETTING);
 
-       /* TileWidth menu */
-       m = GetMenuHandle(135);
+       /* Graphics submenu */
+       m = GetMenuHandle(SUBMENU_GRAPH);
+
+       /* Get menu size */
+       n = CountMItems(m);
+
+       /* Reset menu */
+       for (i = 1; i <= n; i++)
+       {
+               /* Reset */
+               DisableItem(m, i);
+               CheckItem(m, i, FALSE);
+       }
+       
+       /* Item "None" */
+       EnableItem(m, ITEM_NONE);
+       CheckItem(m, ITEM_NONE, (graf_mode == GRAF_MODE_NONE));
+
+       /* Item "8x8" */
+       EnableItem(m, ITEM_8X8);
+       CheckItem(m, ITEM_8X8, (graf_mode == GRAF_MODE_8X8));
+
+       /* Item "16x16" */
+       EnableItem(m, ITEM_16X16);
+       CheckItem(m, ITEM_16X16, (graf_mode == GRAF_MODE_16X16));
+
+       /* Item "Bigtile" */
+       EnableItem(m, ITEM_BIGTILE);
+       CheckItem(m, ITEM_BIGTILE, arg_bigtile);
+
+
+       /* TIleWidth submenu */
+       m = GetMenuHandle(SUBMENU_TILEWIDTH);
 
        /* Get menu size */
-#if TARGET_API_MAC_CARBON
-       n = CountMenuItems(m);
-#else
        n = CountMItems(m);
-#endif
 
        /* Reset menu */
        for (i = 1; i <= n; i++)
        {
                /* Reset */
-#if TARGET_API_MAC_CARBON
-               DisableMenuItem(m, i);
-               CheckMenuItem(m, i, FALSE);
-#else
                DisableItem(m, i);
                CheckItem(m, i, FALSE);
-#endif
        }
 
        /* Active window */
@@ -5177,44 +5568,27 @@ static void setup_menus(void)
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
-#if TARGET_API_MAC_CARBON
-                       /* Enable */
-                       EnableMenuItem(m, i);
-
-                       /* Check the current size */
-                       if (td->tile_wid == value) CheckMenuItem(m, i, TRUE);
-#else
                        /* Enable */
-                       EnableItem(m, i);
+                       if (value >= td->font_wid) EnableItem(m, i);
 
                        /* Check the current size */
                        if (td->tile_wid == value) CheckItem(m, i, TRUE);
-#endif
                }
        }
 
 
-       /* TileHeight menu */
-       m = GetMenuHandle(136);
+       /* TileHeight submenu */
+       m = GetMenuHandle(SUBMENU_TILEHEIGHT);
 
        /* Get menu size */
-#if TARGET_API_MAC_CARBON
-       n = CountMenuItems(m);
-#else
        n = CountMItems(m);
-#endif
 
        /* Reset menu */
        for (i = 1; i <= n; i++)
        {
                /* Reset */
-#if TARGET_API_MAC_CARBON
-               DisableMenuItem(m, i);
-               CheckMenuItem(m, i, FALSE);
-#else
                DisableItem(m, i);
                CheckItem(m, i, FALSE);
-#endif
        }
 
        /* Active window */
@@ -5228,21 +5602,15 @@ static void setup_menus(void)
                        s[s[0]+1] = '\0';
                        value = atoi((char*)(s+1));
 
-#if TARGET_API_MAC_CARBON
-                       /* Enable */
-                       EnableMenuItem(m, i);
-
-                       /* Check the current size */
-                       if (td->tile_hgt == value) CheckMenuItem(m, i, TRUE);
-#else
                        /* Enable */
-                       EnableItem(m, i);
+                       if (value >= td->font_hgt) EnableItem(m, i);
 
                        /* Check the current size */
                        if (td->tile_hgt == value) CheckItem(m, i, TRUE);
-#endif
                }
        }
+#endif
+
 }
 
 
@@ -5287,11 +5655,11 @@ static void menu(long mc)
        switch (menuid)
        {
                /* Apple Menu */
-               case 128:
+               case MENU_APPLE:
                {
                        /* About Angband... */
 #if TARGET_API_MAC_CARBON
-                       if (selection == 1)
+                       if (selection == ITEM_ABOUT)
                        {
                                DialogPtr dialog;
                                short item_hit;
@@ -5319,7 +5687,7 @@ static void menu(long mc)
                                break;
                        }
 #else
-                       if (selection == 1)
+                       if (selection == ITEM_ABOUT)
                        {
                                DialogPtr dialog;
                                Rect r;
@@ -5337,41 +5705,40 @@ static void menu(long mc)
                        }
 
                        /* Desk accessory */
-                       /* GetMenuItemText(GetMHandle(128),selection,s); */
-                       GetMenuItemText(GetMenuHandle(128), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_APPLE), selection, s);
                        OpenDeskAcc(s);
                        break;
 #endif
                }
 
                /* File Menu */
-               case 129:
+               case MENU_FILE:
                {
                        switch (selection)
                        {
                                /* New */
-                               case 1:
+                               case ITEM_NEW:
                                {
                                        do_menu_file_new();
                                        break;
                                }
 
                                /* Open... */
-                               case 2:
+                               case ITEM_OPEN:
                                {
                                        do_menu_file_open(FALSE);
                                        break;
                                }
 
                                /* Import... */
-                               case 3:
+                               case ITEM_IMPORT:
                                {
                                        do_menu_file_open(TRUE);
                                        break;
                                }
 
                                /* Close */
-                               case 4:
+                               case ITEM_CLOSE:
                                {
                                        /* No window */
                                        if (!td) break;
@@ -5389,7 +5756,7 @@ static void menu(long mc)
                                }
 
                                /* Save */
-                               case 5:
+                               case ITEM_SAVE:
                                {
                                        if (!can_save){
 #ifdef JP
@@ -5410,7 +5777,7 @@ static void menu(long mc)
                                }
 
                                /* Quit (with save) */
-                               case 7:
+                               case ITEM_QUIT:
                                {
                                        /* Save the game (if necessary) */
                                        if (game_in_progress && character_generated)
@@ -5443,14 +5810,14 @@ static void menu(long mc)
                }
 
                /* Edit menu */
-               case 130:
+               case MENU_EDIT:
                {
                        /* Unused */
                        break;
                }
 
                /* Font menu */
-               case 131:
+               case MENU_FONT:
                {
                        /* Require a window */
                        if (!td) break;
@@ -5462,7 +5829,7 @@ static void menu(long mc)
                        activate(td->w);
 
                        /* Toggle the "bold" setting */
-                       if (selection == 1)
+                       if (selection == ITEM_BOLD)
                        {
                                /* Toggle the setting */
                                if (td->font_face & bold)
@@ -5489,7 +5856,7 @@ static void menu(long mc)
                        }
 
                        /* Toggle the "wide" setting */
-                       if (selection == 2)
+                       if (selection == ITEM_WIDE)
                        {
                                /* Toggle the setting */
                                if (td->font_face & extend)
@@ -5516,7 +5883,7 @@ static void menu(long mc)
                        }
 
                        /* Get a new font name */
-                       GetMenuItemText(GetMenuHandle(131), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_FONT), selection, s);
                        GetFNum(s, &fid);
 
                        /* Save the new font id */
@@ -5568,7 +5935,7 @@ static void menu(long mc)
                }
 
                /* Size menu */
-               case 132:
+               case MENU_SIZE:
                {
                        if (!td) break;
 
@@ -5578,7 +5945,7 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(132), selection, s);
+                       GetMenuItemText(GetMenuHandle(MENU_SIZE), selection, s);
                        s[s[0]+1]=0;
                        td->font_size = atoi((char*)(s+1));
 
@@ -5600,7 +5967,7 @@ static void menu(long mc)
                }
 
                /* Window menu */
-               case 133:
+               case MENU_WINDOWS:
                {
                        /* Parse */
                        i = selection - 1;
@@ -5630,11 +5997,32 @@ static void menu(long mc)
                }
 
                /* Special menu */
-               case 134:
+               case MENU_SPECIAL:
+               {
+                       switch (selection)
+                       {
+                               case ITEM_FIDDLE:
+                               {
+                                       arg_fiddle = !arg_fiddle;
+                                       break;
+                               }
+
+                               case ITEM_WIZARD:
+                               {
+                                       arg_wizard = !arg_wizard;
+                                       break;
+                               }
+                       }
+
+                       break;
+               }
+
+               /* Sounds submenu */
+               case SUBMENU_SOUND:
                {
                        switch (selection)
                        {
-                               case 1:
+                               case ITEM_USE_SOUND:
                                {
                                        /* Toggle arg_sound */
                                        arg_sound = !arg_sound;
@@ -5645,75 +6033,48 @@ static void menu(long mc)
                                        break;
                                }
 
-                               case 2:
+                               case ITEM_SOUND_SETTING:
                                {
-                                       /* Toggle arg_graphics */
-                                       arg_graphics = !arg_graphics;
-                                       if( arg_graphics == true ){
-                                               ANGBAND_GRAF = "old";
-                                               arg_newstyle_graphics = false;
-                                               grafWidth = grafHeight = 8;
-                                               pictID = 1001;
-                                       }
-
-                                       /* Hack -- Force redraw */
-                                       Term_key_push(KTRL('R'));
+                                       SoundConfigDLog();
 
                                        break;
                                }
+                       }
 
-                               case 4:
-                               {
-                                       arg_fiddle = !arg_fiddle;
-                                       break;
-                               }
+                       break;
+               }
 
-                               case 5:
+               /* Graphics submenu */
+               case SUBMENU_GRAPH:
+               {
+                       switch (selection)
+                       {
+                               case ITEM_NONE:
                                {
-                                       arg_wizard = !arg_wizard;
+                                       graf_mode_req = GRAF_MODE_NONE;
+
                                        break;
                                }
 
-                               case 7:
+                               case ITEM_8X8:
                                {
-                                       SoundConfigDLog();
+                                       graf_mode_req = GRAF_MODE_8X8;
+
                                        break;
                                }
-                               case 8:
+
+                               case ITEM_16X16:
                                {
-                                       if (streq(ANGBAND_GRAF, "old"))
-                                       {
-                                               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;
-                                       }
+                                       graf_mode_req = GRAF_MODE_16X16;
 
-                                       /* Hack -- Force redraw */
-                                       Term_key_push(KTRL('R'));
                                        break;
                                }
 
-                               case 9: /* bigtile mode */
+                               case ITEM_BIGTILE:
                                {
+                                       term *old = Term;
                                        term_data *td = &data[0];
 
-                                       if (!can_save){
-#ifdef JP
-                                               plog("º£¤ÏÊѹ¹½ÐÍè¤Þ¤»¤ó¡£");
-#else
-                                               plog("You may not do that right now.");
-#endif
-                                               break;
-                                       }
-
                                        /* Toggle "arg_bigtile" */
                                        arg_bigtile = !arg_bigtile;
 
@@ -5723,16 +6084,21 @@ static void menu(long mc)
                                        /* Resize the term */
                                        Term_resize(td->cols, td->rows);
 
+                                       /* Activate old */
+                                       Term_activate(old);
+
                                        break;
                                }
-
                        }
 
+                       /* Hack -- Force redraw */
+                       Term_key_push(KTRL('R'));
+
                        break;
                }
 
-               /* TileWidth menu */
-               case 135:
+               /* TileWidth submenu */
+               case SUBMENU_TILEWIDTH:
                {
                        if (!td) break;
 
@@ -5742,7 +6108,8 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(135), selection, s);
+                       /* Analyse value */
+                       GetMenuItemText(GetMenuHandle(SUBMENU_TILEWIDTH), selection, s);
                        s[s[0]+1]=0;
                        td->tile_wid = atoi((char*)(s+1));
 
@@ -5759,8 +6126,8 @@ static void menu(long mc)
                        break;
                }
 
-               /* TileHeight menu */
-               case 136:
+               /* TileHeight submenu */
+               case SUBMENU_TILEHEIGHT:
                {
                        if (!td) break;
 
@@ -5770,7 +6137,8 @@ static void menu(long mc)
                        /* Activate */
                        activate(td->w);
 
-                       GetMenuItemText(GetMenuHandle(136), selection, s);
+                       /* Analyse value */
+                       GetMenuItemText(GetMenuHandle(SUBMENU_TILEHEIGHT), selection, s);
                        s[s[0]+1]=0;
                        td->tile_hgt = atoi((char*)(s+1));
 
@@ -5837,6 +6205,7 @@ static pascal OSErr AEH_Quit(const AppleEvent *theAppleEvent,
 {
 #pragma unused(reply, handlerRefCon)
 #if TARGET_API_MAC_CARBON
+#pragma unused(theAppleEvent)
 
        /* Save the game (if necessary) */
        if (game_in_progress && character_generated)
@@ -7055,6 +7424,13 @@ int main(void)
        /* Mega-Hack -- Allocate a "lifeboat" */
        lifeboat = NewPtr(16384);
 
+#ifdef USE_QT_SOUND
+
+       /* Load sound effect resources */
+       load_sounds();
+
+#endif /* USE_QT_SOUND */
+
        /* Note the "system" */
        ANGBAND_SYS = "mac";