home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / mac / macmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-25  |  12.7 KB  |  591 lines

  1. /*    SCCS Id: @(#)macmain.c    3.1    92/12/04    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* main.c - Mac NetHack */
  6.  
  7. #include "hack.h"
  8.  
  9. #include <OSUtils.h>
  10. #include <files.h>
  11. #include <Types.h>
  12. #ifdef MAC_MPW32
  13. #include <String.h>
  14. #include <Strings.h>
  15. #endif
  16. #ifdef MAC_THINKC5
  17. #include <pascal.h>
  18. #endif
  19. #include <Dialogs.h>
  20. #include <Packages.h>
  21. #include <ToolUtils.h>
  22. #include <Resources.h>
  23. #include <SysEqu.h>
  24. #include <Errors.h>
  25.  
  26. #ifndef O_RDONLY
  27. #include <fcntl.h>
  28. #endif
  29.  
  30. int NDECL(main);
  31. void NDECL(ListGUnloads);
  32.  
  33. static void NDECL(process_options);
  34. static void NDECL(whoami);
  35.  
  36. extern char * PtoCstr ( unsigned char * ) ;
  37. extern unsigned char * CtoPstr ( char * ) ;
  38. void SetFrameItem ( DialogPtr , short , short ) ;
  39.  
  40. extern void NDECL ( finder_file_request ) ;
  41. // void NDECL( askname ) ;
  42.  
  43. extern void NDECL ( InitMac ) ;
  44.  
  45. int
  46. main ( void )
  47. {
  48.     register int fd;
  49.  
  50.     windowprocs = mac_procs ;
  51.     InitMac ( ) ;
  52.  
  53.     hname = "Mac Hack" ;
  54.     hackpid = getpid();
  55.  
  56.     initoptions();
  57.     init_nhwindows();
  58.     whoami();
  59.  
  60.     /*
  61.      * It seems you really want to play.
  62.      */
  63.     setrandom();
  64.     u.uhp = 1;    /* prevent RIP on early quits */
  65.  
  66.     process_options ( ) ;    /* emulate command line options */
  67.     finder_file_request ( ) ;
  68.  
  69. #ifdef WIZARD
  70.     if (wizard)
  71.         Strcpy(plname, "wizard");
  72.     else
  73. #endif
  74.     if(!*plname || !strncmp(plname, "player", 4)
  75.             || !strncmp(plname, "games", 4))
  76.         askname();
  77.     plnamesuffix();        /* strip suffix from name; calls askname() */
  78.                 /* again if suffix was whole name */
  79.                 /* accepts any suffix */
  80.  
  81.     Sprintf ( lock , "%d%s" , getuid ( ) , plname ) ;
  82.     getlock ( ) ;
  83.  
  84.     /*
  85.      * Initialisation of the boundaries of the mazes
  86.      * Both boundaries have to be even.
  87.      */
  88.  
  89.     x_maze_max = COLNO-1;
  90.     if (x_maze_max % 2)
  91.         x_maze_max--;
  92.     y_maze_max = ROWNO-1;
  93.     if (y_maze_max % 2)
  94.         y_maze_max--;
  95.  
  96.     /*
  97.      *  Initialize the vision system.  This must be before mklev() on a
  98.      *  new game or before a level restore on a saved game.
  99.      */
  100.     vision_init();
  101.  
  102.     display_gamewindows();
  103.  
  104.     set_savefile_name();
  105.     uncompress(SAVEF);
  106.  
  107.     if((fd = open_savefile()) >= 0 &&
  108.        /* if not up-to-date, quietly delete file via false condition */
  109.        (uptodate(fd) || delete_savefile())) {
  110. #ifdef WIZARD
  111.         /* Since wizard is actually flags.debug, restoring might
  112.          * overwrite it.
  113.          */
  114.         boolean remember_wiz_mode = wizard;
  115. #endif
  116. #ifdef NEWS
  117.         if(flags.news) display_file(NEWS, FALSE);
  118. #endif
  119.         pline("Restoring save file...");
  120.         mark_synch();    /* flush output */
  121.         if(!dorecover(fd))
  122.             goto not_recovered;
  123. #ifdef WIZARD
  124.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  125. #endif
  126.         pline("Hello %s, welcome back to NetHack!", plname);
  127.         check_special_room(FALSE);
  128.  
  129. #ifdef EXPLORE_MODE
  130.         if (discover)
  131.             You("are in non-scoring discovery mode.");
  132. #endif
  133. #if defined(EXPLORE_MODE) || defined(WIZARD)
  134.         if (discover || wizard) {
  135.             if(yn("Do you want to keep the save file?") == 'n')
  136.                 (void) delete_savefile();
  137.             else {
  138.                 compress(SAVEF);
  139.             }
  140.         }
  141. #endif
  142.         flags.move = 0;
  143.     } else {
  144. not_recovered:
  145.         player_selection();
  146.         newgame();
  147.         /* give welcome message before pickup messages */
  148.         pline("Hello %s, welcome to NetHack!", plname);
  149. #ifdef EXPLORE_MODE
  150.         if (discover)
  151.             You("are in non-scoring discovery mode.");
  152. #endif
  153.         flags.move = 0;
  154.         set_wear();
  155.         pickup(1);
  156.     }
  157.  
  158.     flags.moonphase = phase_of_the_moon();
  159.     if(flags.moonphase == FULL_MOON) {
  160.         You("are lucky!  Full moon tonight.");
  161.         change_luck(1);
  162.     } else if(flags.moonphase == NEW_MOON) {
  163.         pline("Be careful!  New moon tonight.");
  164.     }
  165.     if(flags.friday13 = friday_13th()) {
  166.         pline("Watch out!  Bad things can happen on Friday the 13th.");
  167.         change_luck(-1);
  168.     }
  169.  
  170.     initrack();
  171.  
  172.     UndimMenuBar ( ) ; /* Yes, this is the place for it (!) */
  173.     
  174.     attemptingto("proceed");
  175. #if defined(MAC_MPW32) && !defined(MODEL_FAR)
  176.     UnloadAllSegments();                        /* Do this before naming residents */
  177.     IsResident( (Ptr) display_nhwindow );        /* Sample resident segments */
  178.     IsResident( (Ptr) rhack );
  179.     IsResident( (Ptr) engr_at );
  180.     IsResident( (Ptr) movemon );
  181.     IsResident( (Ptr) attacktype ) ;
  182.     IsResident( (Ptr) mac_get_nh_event ) ;
  183. #endif
  184.     moveloop();
  185.     /*NOTREACHED*/
  186.     return 0;
  187. }
  188.  
  189.  
  190. /*
  191.  * This filter handles the movable-modal dialog
  192.  *
  193.  */
  194. static pascal Boolean
  195. DragFilter ( DialogPtr dp , EventRecord * event , short * item )
  196. {
  197.     WindowPtr wp ;
  198.     short code ;
  199.     Rect r ;
  200.  
  201. /*
  202.  *    Handle shortcut keys
  203.  *    enter, return -> OK
  204.  *    clear, escape, period -> Cancel
  205.  *    all others are handled default
  206.  *
  207.  */
  208.  
  209.     if ( event -> what == keyDown ) {
  210.  
  211.         char c = event -> message & 0xff ;
  212.         unsigned char b = ( event -> message >> 8 ) & 0xff ;
  213.  
  214.         switch ( c ) {
  215.  
  216.         case 3 :    /* 3 == Enter */
  217.         case 10 :    /* Newline */
  218.         case 13 :    /* Return */
  219.             * item = 1 ;
  220.             return 1 ;
  221.  
  222.         case '.' :    /* Cmd-period - we allow only period */
  223.         case 27 :    /* Escape */
  224.             * item = 2 ;
  225.             return 1 ;
  226.         }
  227.  
  228.         switch ( b ) {
  229.  
  230.         case 0x4c :    /* Enter */
  231.         case 0x24 :    /* Return */
  232.             * item = 1 ;
  233.             return 1 ;
  234.  
  235.         case 0x35 :    /* Escape */
  236.         case 0x47 :    /* Clear */
  237.             * item = 2 ;
  238.             return 1 ;
  239.         }
  240.  
  241.         return 0 ;
  242.     }
  243.  
  244. /*
  245.  *    OK, don't handle others
  246.  *
  247.  */
  248.  
  249.     if ( event -> what != mouseDown ) {
  250.  
  251.         return 0 ;
  252.     }
  253.     code = FindWindow ( event -> where , & wp ) ;
  254.     if ( wp != dp || code != inDrag ) {
  255.  
  256.         return 0 ;
  257.     }
  258.     r = ( * GetGrayRgn ( ) ) -> rgnBBox ;
  259.     InsetRect ( & r , 3 , 3 ) ;
  260.  
  261.     DragWindow ( wp , event -> where , & r ) ;
  262.     SaveWindowPos ( wp ) ;
  263.  
  264.     event -> what = nullEvent ;
  265.     return 1 ;
  266. }
  267.  
  268.  
  269. /*
  270.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  271.  * explicitly (by being the wizard) or by askname.
  272.  * It may still contain a suffix denoting pl_character.
  273.  */
  274. void
  275. mac_askname(void) /* Code taken from getlin */
  276. {
  277.     ControlHandle    ctrl ;
  278.     DialogPtr        promptDialog ;
  279.     short            itemHit , type ;
  280.     Rect            box ;
  281.     Str255            pasStr ;
  282.  
  283.     /*
  284.     ** Set the query line as parameter text.
  285.     */
  286.  
  287.     ParamText ( "\PWho are you?" , "\p" , "\p" , "\p" ) ;
  288.  
  289.     promptDialog = GetNewDialog ( 130 , ( Ptr ) NULL , ( WindowPtr ) -1 ) ;
  290.     ShowWindow ( promptDialog ) ;
  291.  
  292.     InitCursor ( ) ;
  293.     SetFrameItem ( promptDialog , 6 , 1 ) ;
  294.     do {
  295.  
  296.         ModalDialog ( ( ModalFilterProcPtr ) DragFilter , & itemHit ) ;
  297.  
  298.     } while ( ( itemHit != 1 ) && ( itemHit != 2 ) ) ;
  299.  
  300.     if ( itemHit == 1 ) {
  301.  
  302.         /*
  303.         ** Get the text from the text edit item.
  304.         */
  305.  
  306.         GetDItem ( promptDialog , 4 , & type , ( Handle * ) & ctrl , & box ) ;
  307.         GetIText ( ( Handle ) ctrl , pasStr ) ;
  308.  
  309.         /*
  310.         ** Convert it to a 'C' string and copy it into the return value.
  311.         */
  312.  
  313.         PtoCstr ( pasStr ) ;
  314.         strcpy ( plname , ( char * ) pasStr ) ;
  315.  
  316.     /*
  317.      * Special check for debugging here
  318.      *
  319.      */
  320. #ifdef WIZARD
  321.         if ( ! strcmp ( plname , WIZARD ) ) {
  322.  
  323.             flags . debug = 1 ;
  324.         }
  325. #endif
  326.  
  327.     } else {
  328.  
  329.         /*
  330.         ** Okay, we didn't want to run
  331.         */
  332.  
  333.     /*    * ( short * ) DSErrCode = dsBadLaunch ; */
  334.         ExitToShell ( ) ;
  335.     }
  336.  
  337.     DisposDialog ( promptDialog ) ;
  338. }
  339.  
  340.  
  341. static void
  342. process_options(void)
  343. {
  344.     int argc = 0 ;
  345.     char * foo [ ] = { "Mac Hack" , NULL } ;
  346.     char * * argv = foo ;
  347.     /*
  348.      * Process options.
  349.      */
  350.     while(argc > 1 && argv[1][0] == '-'){
  351.         argv++;
  352.         argc--;
  353.         switch(argv[0][1]){
  354. #if defined(WIZARD) || defined(EXPLORE_MODE)
  355. # ifndef EXPLORE_MODE
  356.         case 'X':
  357. # endif
  358.         case 'D':
  359. # ifdef WIZARD
  360.             wizard = TRUE ;
  361.             break ;
  362. # endif
  363. # ifdef EXPLORE_MODE
  364.         case 'X':
  365.             discover = TRUE;
  366. # endif
  367.             break;
  368. #endif
  369. #ifdef NEWS
  370.         case 'n':
  371.             flags.news = FALSE;
  372.             break;
  373. #endif
  374.         case 'u':
  375.             if(argv[0][2])
  376.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  377.             else if(argc > 1) {
  378.               argc--;
  379.               argv++;
  380.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  381.             } else
  382.                 raw_print("Player name expected after -u");
  383.             break;
  384.         case 'I':
  385.         case 'i':
  386.             if (!strncmpi(argv[0]+1, "IBM", 3))
  387.                 switch_graphics(IBM_GRAPHICS);
  388.             break;
  389.         /*  case 'D': */
  390.         case 'd':
  391.             if (!strncmpi(argv[0]+1, "DEC", 3))
  392.                 switch_graphics(DEC_GRAPHICS);
  393.             break;
  394.         default:
  395.             /* allow -T for Tourist, etc. */
  396.             (void) strncpy(pl_character, argv[0]+1,
  397.                 sizeof(pl_character)-1);
  398.  
  399.             /* raw_print("Unknown option: %s", *argv); */
  400.         }
  401.     }
  402. }
  403.  
  404.  
  405. static void
  406. whoami ( void )
  407. {
  408.     /*TODO*/
  409.     donull ( ) ;
  410. }
  411.  
  412.  
  413. /*------------------- UnloadAllSegments and support stuff --------------------------*/
  414. /* Derived from MacApp source */
  415.  
  416. typedef Handle **HandleListHandle;
  417. typedef Boolean **BoolListHandle;
  418. typedef short *ShortPtr, **ShortHandle;
  419.  
  420. short FDECL(GetSegNumber,(ShortPtr));
  421. void FDECL(InitSegMgmt,(void *));
  422. pascal long NDECL(GetA5);
  423. pascal short NDECL(GetCurJTOffset);
  424. void NDECL(UnloadAllSegments);
  425. void FDECL(IsResident,(void *));
  426. void FDECL(NotResident, (void *));
  427.  
  428. short              pMaxSegNum = 0,        /* Highest segment number */
  429.                    gCodeRefNum;            /* rsrc refnum of the application */
  430. HandleListHandle gCodeSegs;                /* List of code seg handles */
  431. BoolListHandle   gIsResidentSeg;        /* Resident flags */
  432.  
  433. #define kLoaded   0x4EF9                /* if loaded then a JMP instruction */
  434. #define    kUnLoaded 0x3F3C                /* if unloaded then a LoadSeg trap */
  435.                                         /* Note: probably incorrect for -model far! */
  436.  
  437. /* #define TRACKSEGS /* Utility to print a trace of segment load frequencies. Add
  438.    a call to ListGUnloads into terminate() in end.c to use it */
  439.  
  440. #ifdef TRACKSEGS
  441.  
  442. long      gUnloads[120];
  443. char      gSegNames[120][16];
  444.  
  445. void ListGUnloads(void)
  446. {
  447.   int i;
  448.   FILE *f;
  449.   
  450.   f = fopen("unloads","r+");
  451.   fprintf(f,"%d calls to UnloadAllSegments\n\n",gUnloads[0]);
  452.   for (i=1; i<=pMaxSegNum; i++) {
  453.      fprintf(f,"Unloaded %10s, segment %2d, %6d times\n",gSegNames[i],i,gUnloads[i]);
  454.   }
  455.   fclose(f);
  456. }
  457.  
  458. #endif
  459.  
  460. short GetSegNumber(ShortPtr aProc)
  461. /* Derives seg number from a procedure ptr */
  462.  
  463. {
  464.     if (*aProc == kLoaded)                 /* loaded segment */
  465.         return(*--aProc);
  466.     else if (*aProc == kUnLoaded)          /* unloaded segment */
  467.         return(*++aProc);
  468.     else {
  469.         progerror("GetSegNumber was not passed an jump table address");
  470.         return(1);
  471.     }
  472. }
  473.  
  474. void InitSegMgmt(void * mainSeg)
  475. /* Initialise a list of handles to all the CODE segments and mark the mainseg as resident */
  476. {
  477.     short     i,
  478.             lastRsrc,
  479.             rsrcID,
  480.             oldResFile;
  481.     Handle  seg;
  482.     ResType rsrcType;
  483.     Str255  rsrcName;
  484.      
  485.     gCodeRefNum = HomeResFile(GetResource('CODE', 1));    
  486.     oldResFile = CurResFile();
  487.     UseResFile(gCodeRefNum);
  488.     
  489.     /* Discover the highest CODE rsrc ID: be ready for noncontiguous IDs */
  490.     lastRsrc = Count1Resources('CODE');    
  491.     SetResLoad(false);
  492.     for (i=1; i<=lastRsrc; i++) 
  493.         if (seg = Get1IndResource('CODE', i)) {
  494.             GetResInfo(seg, &rsrcID, &rsrcType, rsrcName);
  495.             if (rsrcID > pMaxSegNum) pMaxSegNum = rsrcID;
  496.         }
  497.         
  498.     /* Make handles of appropriate size to keep flags/segment handles */
  499.     SetResLoad(true);  /* In case we fail */
  500.     gCodeSegs = (HandleListHandle) NewHandle((pMaxSegNum+1) * sizeof(Handle));    
  501.     mustwork(MemError());
  502.     gIsResidentSeg = (BoolListHandle) NewHandle((pMaxSegNum+1) * sizeof(Boolean));
  503.     mustwork(MemError());
  504.     SetResLoad(false);    
  505.  
  506.     #ifdef TRACKSEGS
  507.     gUnloads[0]=0;
  508.     #endif
  509.     for (i=1; i<=pMaxSegNum; i++) {
  510.        (*gIsResidentSeg)[i] = false;
  511.        (*gCodeSegs)[i] = Get1Resource('CODE',i);   /* Will be NIL if it doesn't exist */
  512.        #ifdef TRACKSEGS
  513.        {  /* Go get the segment name and save it */
  514.           short id;
  515.           ResType rType;
  516.           Str255 name;
  517.           char *cptr;
  518.           
  519.           GetResInfo((*gCodeSegs)[i],&id,&rType,&name);
  520.           if (name[0]>15) name[0]=15;
  521.           cptr = p2cstr(&name);
  522.           cptr = strcpy(&gSegNames[i], &name);
  523.           gUnloads[i] = 0;
  524.        }
  525.        #endif
  526.     }
  527.     SetResLoad(true);    
  528.     (*gIsResidentSeg)[GetSegNumber((ShortPtr)mainSeg)] = true;    
  529.     UseResFile(oldResFile);
  530. }
  531.  
  532. #ifdef MAC_MPW32
  533. pascal long GetA5(void) = { 0x2E8D };                    /* MOVE.L A5,(A7) */
  534. pascal short GetCurJTOffset(void) = { 0x3EB8, 0x934 };   /* MOVE.W CurJTOffset,(SP) */
  535. #endif
  536. #ifdef MAC_THINKC5
  537. pascal long GetA5(void) = { 0x2E8D };                    /* MOVE.L A5,(A7) */
  538. pascal short GetCurJTOffset(void) = { 0x3EB8, 0x934 };   /* MOVE.W CurJTOffset,(SP) */
  539. #endif
  540.  
  541. void UnloadAllSegments(void)
  542. {
  543.   short     i,
  544.          oldResFile;
  545.   Handle seg;
  546.   long     jumpTablePtr;
  547.  
  548.   jumpTablePtr = GetA5() + GetCurJTOffset();
  549.   oldResFile = CurResFile();
  550.   UseResFile(gCodeRefNum);
  551. #ifdef TRACKSEGS
  552.   gUnloads[0]++;
  553. #endif
  554.   for (i=1; i<=pMaxSegNum; i++)
  555.       if (!(*gIsResidentSeg)[i]) {
  556.           seg = (*gCodeSegs)[i];
  557.           if ((seg != (Handle) nil) && (*seg != (Ptr) nil))  /* Check it exists and hasn't been purged */
  558.               if (HGetState(seg) & 0x80)  {   /* Is it locked? => loaded */
  559. #ifdef TRACKSEGS
  560.                  gUnloads[i]++;
  561. #endif
  562.                  UnloadSeg( (void *) (jumpTablePtr + **(ShortHandle)seg + 2) );
  563.               }
  564.       }
  565.  
  566.   UseResFile(oldResFile);
  567. }
  568.  
  569. void IsResident( void * routineaddr )
  570. /* We want to move this high up in the heap as it won't be shifted again, so... */
  571. {
  572.     int    segnum;
  573.     Handle theseg;
  574.     
  575.     segnum = GetSegNumber((ShortPtr)routineaddr);
  576.     theseg = (*gCodeSegs)[segnum];
  577.     UnloadSeg( routineaddr );
  578.     if (*theseg != nil) {
  579.        MoveHHi( theseg );  /* If it has been purged we can't do this */
  580.        HLock( theseg );
  581.     }
  582.     (*gIsResidentSeg)[segnum] = true;    
  583. }
  584.  
  585. void NotResident( void * routineaddr )
  586. {
  587.     (*gIsResidentSeg)[GetSegNumber((ShortPtr)routineaddr)] = false;    
  588. }
  589.  
  590. /*macmain.c*/
  591.