Commit 97bb5845 authored by Steven Fuller's avatar Steven Fuller

Prepared makefile, time to start the port

parent 2fa9feb4
#include "hidemenubar.h"
static Boolean MenuBarHidden = FALSE; /* Current state of the menu bar. */
static Rect OldeMBarRect; /* Saves rectangle enclosing real menu bar. */
static RgnHandle OldeGrayRgn; /* Saves the region defining the desktop */
static short OldMBarHeight; /* Previous menu bar height */
extern GDHandle gMainGDH;
/********************************
Hide the menu bar (If visible)
********************************/
void HideMenuBar(void)
{
RgnHandle menuRgn;
WindowPeek theWindow;
GDHandle TempHand;
TempHand = GetMainDevice();
if (TempHand!=gMainGDH) { /* Main graphics handle */
return;
}
if (!MenuBarHidden) { /* Already hidden? */
OldMBarHeight = LMGetMBarHeight(); /* Get the height in pixels */
OldeGrayRgn = NewRgn(); /* Make a new region */
CopyRgn(GetGrayRgn(), OldeGrayRgn); /* Copy the background region */
OldeMBarRect = qd.screenBits.bounds; /* Make a region from the rect or the monitor width */
OldeMBarRect.bottom = OldeMBarRect.top + OldMBarHeight; /* Top to bottom of menu */
menuRgn = NewRgn(); /* Convert to region */
RectRgn(menuRgn, &OldeMBarRect);
UnionRgn(GetGrayRgn(), menuRgn, GetGrayRgn()); /* Add the menu area to background */
theWindow = (WindowPeek)FrontWindow();
PaintOne((WindowPtr)theWindow, menuRgn); /* Redraw the front window */
PaintBehind((WindowPtr)theWindow, menuRgn); /* Redraw all other windows */
CalcVis((WindowPtr)theWindow); /* Resize the visible region */
CalcVisBehind((WindowPtr)theWindow, menuRgn); /* Resize the visible regions for all others */
DisposeRgn(menuRgn); /* Release the menu region */
MenuBarHidden = TRUE; /* It is now hidden */
ZapMHeight(); /* Zap the height */
}
}
/********************************
Show the menu bar (If hidden)
********************************/
void ShowMenuBar(void)
{
WindowPeek theWindow;
if (MenuBarHidden) { /* Hidden? */
FixMHeight();
MenuBarHidden = FALSE; /* The bar is here */
CopyRgn(OldeGrayRgn, GetGrayRgn()); /* Get the region */
RectRgn(OldeGrayRgn, &OldeMBarRect); /* Convert menu rect to region */
theWindow = (WindowPeek)FrontWindow(); /* Get the front window */
CalcVis((WindowPtr)theWindow); /* Reset the visible region */
CalcVisBehind((WindowPtr)theWindow,OldeGrayRgn); /* Remove the menu bar from windows */
DisposeRgn(OldeGrayRgn); /* Bye bye region */
OldeGrayRgn = 0; /* Zap the handle */
HiliteMenu(0); /* Don't hilite any menu options */
DrawMenuBar(); /* Redraw the menu bar */
}
}
/********************************
Restore the menu bar height so that
the OS can handle menu bar events
********************************/
void FixMHeight(void)
{
if (MenuBarHidden) { /* Hidden? */
LMSetMBarHeight(OldMBarHeight); /* Reset the height */
}
}
/********************************
Zap the menu bar height so that things
like MenuClock won't draw
********************************/
void ZapMHeight(void)
{
if (MenuBarHidden) { /* Hidden? */
LMSetMBarHeight(0); /* Zap the height */
}
}
extern void HideMenuBar(void);
extern void ShowMenuBar(void);
extern void FixMHeight(void);
extern void ZapMHeight(void);
\ No newline at end of file
/*********************
Main Macintosh code
*********************/
#include "Wolfdef.h" /* All the game equates */
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <palettes.h>
#include <qdoffscreen.h>
#include <Gestalt.h>
#include "SoundMusicSystem.h"
#include "PickAMonitor.h"
#include "Hidemenubar.h"
#include "Prefs.h"
#include <AppleEvents.h>
static Word DoMyAlert(Word AlertNum);
static void CenterSFWindow(Point *MyPoint,Word x,Word y);
static void CenterAWindow(WindowPtr MyWindow);
static void FixPauseMenu(void);
Boolean LoadGame(void);
pascal Boolean StandardModalFilterProc(DialogPtr theDialog, EventRecord *theEvent, short *itemHit);
Word ChooseGameDiff(void);
Word DoEvent(EventRecord *event);
void DoUpdate(WindowPtr window);
void DrawWindow(WindowPtr window);
void AdjustMenus(void);
void DoMenuCommand(LongWord menuResult);
Boolean DoCloseWindow(WindowPtr window);
void InitTools(void);
void SaveGame(void);
void LoadPrefs(void);
void SavePrefs(void);
Boolean ChooseLoadGame(void);
Boolean ChooseSaveGame(void);
OSErr MyEventHandler(AppleEvent *MyAppleEvent,AppleEvent *AppleReply,long MyRefCon);
Boolean MouseHit; /* True if a mouse was pressed */
static MenuHandle PauseMenu;
static Boolean WaitNextOK; /* True if WaitNextEvent is present */
static Boolean LowOnMem; /* True if sound is disabled for low memory */
static Boolean OpenPending; /* True if a load game apple event occured */
static Byte *SaveFileName; /* Pointer to the save file name */
static short SaveFileVol; /* Directory referance for save file name */
static long SaveFileParID; /* Parent directory id of save-game file */
static Boolean ValidRects; /* Are there blank rects in the window? */
static RgnHandle BlackRgn; /* Blank region for window blanking */
static Rect QDGameRect; /* Rect of the game playing area */
static Rect GameRect = {0,0,200,320}; /* Size of the playfield */
static Rect BlackRect = {0,0,480,640}; /* Rect for the Black Window (Set to main window size) */
static Rect BlackRect2 = {0,0,480,640}; /* True rect for the Black window (Global) */
static Word OldPixDepth; /* Previous pixel depth of screen */
Word MacWidth; /* Width of play screen (Same as GameRect.right) */
Word MacHeight; /* Height of play screen (Same as GameRect.bottom) */
Word MacViewHeight; /* Height of 3d screen (Bottom of 3D view */
static Word MonitorWidth=640; /* Width of the monitor in pixels */
static Word MonitorHeight=480; /* Height of the monitor in pixels */
Word QuitFlag; /* I quit if true */
Word TrueVideoWidth; /* Width of video monitor in bytes */
Byte *TrueVideoPointer; /* Pointer to the video monitor memory */
Byte *GameVideoPointer; /* Pointer to start of 3D view on monitor memory (Used by BlastScreen) */
Boolean DoQuickDraw = TRUE; /* Use quickdraw for updates? */
static Boolean DimQD; /* Force QuickDraw forever! */
Word IgnoreMessage; /* Variable set by prefs to ignore messages */
static CursHandle WatchHandle; /* Handle to a watch cursor */
#define RectX ((MonitorWidth-MacWidth)/2)
#define RectY ((MonitorHeight-MacHeight)/2)
Word VidXs[] = {320,512,640,640}; /* Screen sizes to play with */
Word VidYs[] = {200,384,400,480};
Word VidVs[] = {160,320,320,400};
Word VidPics[] = {rFaceShapes,rFace512,rFace640,rFace640}; /* Resource #'s for art */
static Word MouseBaseX;
static Word MouseBaseY;
static Boolean InPause; /* Pause active? */
extern jmp_buf ResetJmp;
extern Boolean JumpOK;
extern CWindowPtr GameWindow; /* Pointer to main game window */
extern CGrafPtr GameGWorld; /* Grafport to offscreen buffer */
GDHandle gMainGDH; /* Main graphics handle */
CTabHandle MainColorHandle; /* Main color table handle */
static void WaitCursor(void);
static void ResetPalette(void);
static void DoBackground(EventRecord *event);
static void InitAEStuff(void);
static void FixTheCursor(void);
/***************************
Dialog filter for 68020/30 version speed warning
***************************/
#ifndef __powerc
static pascal Boolean InitFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
{
char theChar;
Handle theHandle;
short theType;
Rect theRect;
switch (theEvent->what) {
case keyDown:
theChar = theEvent->message & charCodeMask;
switch (theChar) {
case 0x0D: /* Return */
case 0x03: /* Enter */
*itemHit = 1;
return (TRUE);
}
case updateEvt:
GetDialogItem(theDialog,1, &theType, &theHandle, &theRect);
InsetRect(&theRect, -4, -4);
PenSize(3,3);
FrameRoundRect(&theRect, 16, 16);
}
return (FALSE); /* Tells dialog manager to handle the event */
}
#endif
/***************************
Init the Macintosh and all the
system tools
***************************/
void InitTools(void)
{
Handle menuBar; /* Handle to menu bar record */
Word i; /* Temp */
long Feature; /* Gestalt return value */
short int *SoundListPtr; /* Pointer to sound list for Halestorm driver */
MaxApplZone(); /* Expand the heap so code segments load at the top */
InitGraf((Ptr) &qd.thePort); /* Init the graphics system */
InitFonts(); /* Init the font manager */
InitWindows(); /* Init the window manager */
InitMenus(); /* Init the menu manager */
TEInit(); /* Init text edit */
InitDialogs(nil); /* Init the dialog manager */
i = 16; /* Make 64*16 handle records */
do {
MoreMasters(); /* Create a BUNCH of new handles */
} while (--i);
#ifdef __powerc
WaitNextOK = TRUE;
#else
if (NGetTrapAddress(0xA860,1) != (void *)0xa89F) {
WaitNextOK = TRUE;
}
#endif
InitAEStuff(); /* Apple events shit */
InitCursor(); /* Reset the cursor */
WatchHandle = GetCursor(watchCursor); /* Get the watch cursor */
HLock((Handle)WatchHandle); /* Lock it down */
WaitCursor(); /* Set the watch cursor */
LoadPrefs(); /* Load the prefs file */
/* Now that the mac is started up, let's make sure I can run on this particular mac */
#ifndef __powerc /* Power macs REQUIRE 7.1 to run so don't even check on power macs */
if (Gestalt(gestaltVersion,&Feature)) { /* Is gestalt working? */
goto Not607; /* Oh oh... */
}
/* Check for System 6.0.7 or later */
if (Gestalt(gestaltSystemVersion, &Feature) ||
(short)Feature < 0x0607) { /* Is it 6.0.7 or later? */
goto Not607;
}
#endif
/* Check for Color QuickDraw. If there's no color, quit. Below, we check for
32-bit color QuickDraw. */
if (Gestalt(gestaltQuickdrawVersion, &Feature)) {
Not607:
DoMyAlert(Not607Win); /* Alert the user */
GoodBye(); /* Exit now */
}
/* Check for 32-bit Color QuickDraw */
if( (Feature & 0x0000ffff) < 0x0200) { /* Not 32 bit? */
DoMyAlert(Not32QDWin); /* I need 32 bit quickdraw! */
GoodBye(); /* Exit */
}
/* Check the Mac's processor. If it's a 68030 or earlier, warn the user it
might be slow, and note the best ways to speed it up. */
#ifndef __powerc /* Power macs don't need this message */
Gestalt(gestaltProcessorType,&Feature);
i = 0;
switch(Feature) {
case gestalt68000:
++i;
ParamText("\p68000","\p","\p","\p");
break;
case gestalt68020:
++i;
ParamText("\p68020","\p","\p","\p");
break;
case gestalt68030:
++i;
ParamText("\p68030","\p","\p","\p");
break;
}
if (i && !IgnoreMessage) {
short theValue,itemHit,iType;
Handle iHndl;
Rect iRect;
DialogPtr MyDialog;
ModalFilterUPP theDialogFilter;
theDialogFilter = NewModalFilterProc(InitFilter); /* Create a code pointer */
MyDialog = GetNewDialog(SlowWarnWin,0L,(WindowPtr)-1); /* Load my dialog from disk */
CenterAWindow(MyDialog);
ShowWindow(MyDialog); /* Display with OK button framed */
SetPort((WindowPtr) MyDialog);
InitCursor(); /* Init the cursor */
do {
ModalDialog(theDialogFilter,&itemHit); /* Handle the dialog */
if (itemHit==2) { /* The checkbox */
GetDialogItem(MyDialog,2, &iType, &iHndl, &iRect);
theValue = GetControlValue((ControlHandle)iHndl);
SetControlValue( (ControlHandle) iHndl, !theValue );
}
} while (itemHit!=1);
GetDialogItem(MyDialog,2, &iType, &iHndl, &iRect); /* Get the check box state */
IgnoreMessage = GetControlValue((ControlHandle)iHndl);
if (IgnoreMessage) { /* If I should ignore... */
SavePrefs(); /* Save the prefs file */
}
DisposeDialog(MyDialog); /* Release the dialog memory */
}
#endif
/* Let's set up the environment... */
InitSoundMusicSystem(8,8,5,jxLowQuality);
PurgeSongs(TRUE); /* Allow songs to stay in memory */
SoundListPtr = (short int *) LoadAResource(MySoundList); /* Get the list of sounds */
RegisterSounds(SoundListPtr,FALSE);
ReleaseAResource(MySoundList); /* Release the sound list */
GetTableMemory(); /* Get memory for far tables math tables */
MapListPtr = (maplist_t *) LoadAResource(rMapList); /* Get the map list */
SongListPtr = (unsigned short *) LoadAResource(rSongList);
WallListPtr = (unsigned short *) LoadAResource(MyWallList);
/* Alert the user that you MUST pay! */
if (MapListPtr->MaxMap==3) { /* Shareware version? */
DoMyAlert(ShareWareWin); /* Show the shareware message */
}
if (FreeMem() < 3000000L) { /* Are you low on memory? */
DoMyAlert(LowMemWin);
SystemState = 0; /* Turn off music and sound (Just in case) */
LowOnMem = TRUE;
}
ShowCursor(); /* Make sure the cursor is ok */
WaitCursor(); /* Restore the watch cursor */
/* Try to set up 8-bit color mode */
gMainGDH = PickAMonitor(8,TRUE,512,384); /* Pick a monitor to play on */
if (!gMainGDH) { /* No macs that can display or canceled */
GoodBye(); /* Exit */
}
OldPixDepth = (**(**gMainGDH).gdPMap).pixelSize; /* Get the previous mode */
if (OldPixDepth != 8) { /* Was it 8 bit already? */
if (SetDepth(gMainGDH,8, 1 << gdDevType,1)) { /* Set to 8 bit */
BailOut(); /* Oh oh... */
}
}
MainColorHandle = (*(*gMainGDH)->gdPMap)->pmTable; /* Get my main device's color handle */
BlackRect2 = (**gMainGDH).gdRect; /* Init the black rect */
LockPixels((**gMainGDH).gdPMap); /* Lock down the memory FOREVER! */
TrueVideoPointer = (Byte *) GetPixBaseAddr((**gMainGDH).gdPMap); /* Get pointer to screen mem */
TrueVideoWidth = (Word) ((**(**gMainGDH).gdPMap).rowBytes & 0x3FFF); /* Get width of screen mem */
if (!TrueVideoPointer || !TrueVideoWidth) {
DimQD = TRUE; /* Don't allow offscreen drawing */
DoQuickDraw = TRUE; /* Force QD */
}
MonitorHeight = BlackRect2.bottom - BlackRect2.top; /* Get the size of the video screen */
MonitorWidth = BlackRect2.right - BlackRect2.left;
MouseBaseX = BlackRect2.left+256;
MouseBaseY = BlackRect2.top+192;
menuBar = GetNewMBar(MyMenuBar); /* read menus into menu bar */
if (!menuBar) {
BailOut(); /* Menu bar error */
}
SetMenuBar(menuBar); /* install menus */
DisposeHandle(menuBar); /* Release the menu bar */
AppendResMenu(GetMenuHandle(mApple),'DRVR'); /* add DA names to Apple menu */
DrawMenuBar(); /* Show the menu bar */
HideMenuBar(); /* Hide the menu bar */
GameWindow = (CWindowPtr)NewCWindow(nil,&BlackRect2, "\p",TRUE, plainDBox, (WindowPtr) -1L, FALSE, 0);
if (!GameWindow) { /* No background window? */
BailOut();
}
BlackRgn = NewRgn(); /* Make a region for the black area */
SetPort((WindowPtr)GameWindow); /* Use this grafport */
ActivatePalette((WindowPtr)GameWindow);
BlackRect.top = 0; /* Init the main rect */
BlackRect.left = 0;
BlackRect.bottom = MonitorHeight;
BlackRect.right = MonitorWidth;
FillRect(&BlackRect,&qd.black); /* Erase the screen to black */
NewGameWindow(1); /* Create a game window at 512x384 */
ClearTheScreen(BLACK); /* Force the offscreen memory blank */
BlastScreen();
FixTheCursor(); /* Fix the cursor */
}
/************************************
Set the hardware palette to match my window palette for high speed
copybits operation
************************************/
extern Byte CurrentPal[768]; /* Last palette the game was set to */
static void ResetPalette(void)
{
SetPort((WindowPtr) GameWindow); /* Reset the game window */
if ((**(**gMainGDH).gdPMap).pixelSize != 8) { /* Get the previous mode */
SetDepth(gMainGDH,8, 1 << gdDevType,1); /* Set to 8 bit color */
}
SetAPalettePtr(CurrentPal); /* Restore the palette */
}
/************************************
Process the suspend/resume events
************************************/
static void DoBackground(EventRecord *event)
{
EventRecord PauseEvent;
if ((event->message & 0xff000000) ==0x01000000) { /* Suspend/Resume events */
if (!(event->message & resumeFlag)) { /* Suspend event? */
if (!InPause) {
PauseSoundMusicSystem(); /* Stop the music */
ShowMenuBar(); /* Display the menu bar */
}
InitCursor(); /* Restore the arrow cursor */
/* Call a new event loop while in background to let us know when we've returned. */
do {
WaitNextEvent2(everyEvent, &PauseEvent, 0xFF, nil);
if (PauseEvent.what==updateEvt) { /* Time for update? */
DoUpdate((WindowPtr) PauseEvent.message); /* Redraw the window */
}
} while (PauseEvent.what!=mouseDown && PauseEvent.what!=activateEvt && PauseEvent.what!=app4Evt);
/* Turn the main game window back on and update its contents. */
ResetPalette(); /* Reset the game palette */
FixTheCursor(); /* Make it disappear for game if needed */
if (!InPause) {
HideMenuBar(); /* Make the menu bar disappear */
ResumeSoundMusicSystem(); /* Restart the music */
}
}
}
}
/************************************
Call Wait next event if present
************************************/
Boolean WaitNextEvent2(short EventMask,EventRecord *theEvent,long sleep,RgnHandle mouseRgn)
{
if (WaitNextOK) {
return WaitNextEvent(EventMask,theEvent,sleep,mouseRgn);
}
SystemTask();
return GetNextEvent(EventMask,theEvent);
}
/************************************
Execute the apple event
************************************/
static void HandleHighLevelEvent(EventRecord *event)
{
AEProcessAppleEvent(event);
if (QuitFlag) {
GoodBye();
}
}
/************************************
Do the right thing for an event. Determine what kind of
event it is, and call the appropriate routines.
This is like TaskMaster for the IIgs
************************************/
Word DoEvent(EventRecord *event)
{
Word part;
WindowPtr window;
Word key;
Point aPoint;
switch (event->what) { /* Process the event */
case kHighLevelEvent: /* Apple events? */
HandleHighLevelEvent(event); /* Pass it on... */
break;
case mouseDown: /* Pressed the mouse? */
FixMHeight(); /* Allow menu bar clicks */
part = FindWindow(event->where, &window); /* Choose the hit */
ZapMHeight(); /* Don't click anymore */
switch (part) {
case inMenuBar: /* process a mouse menu command (if any) */
AdjustMenus(); /* Enable/disable menu items */
ShowMenuBar(); /* Display the menu bar */
DoMenuCommand(MenuSelect(event->where)); /* Handle the command */
if (!InPause) {
HideMenuBar(); /* Hide the menu bar */
}
break;
case inSysWindow: /* let the system handle the mouseDown */
SystemClick(event, window); /* Pass on the event */
break;
case inContent:
if (window != FrontWindow() ) {
SelectWindow(window); /* Make it the front window */
}
if (window == (WindowPtr)GameWindow) {
MouseHit = TRUE;
}
break;
case inDrag: /* pass screenBits.bounds to get all gDevices */
DragWindow(window, event->where, &qd.screenBits.bounds);
break;
case inGoAway:
if (TrackGoAway(window,event->where)) { /* Handle the close box */
DoCloseWindow(window); /* Close my window */
}
break;
case inZoomIn:
case inZoomOut:
if (TrackBox(window, event->where, part)) { /* Track the zoom box */
SetPort(window); /* the window must be the current port... */
EraseRect(&window->portRect); /* because of a bug in ZoomWindow */
ZoomWindow(window,part,TRUE); /* note that we invalidate and erase... */
InvalRect(&window->portRect); /* to make things look better on-screen */
}
break;
}
break;
case keyDown:
case autoKey: /* check for menukey equivalents */
key = event->message & charCodeMask;
if (event->modifiers & cmdKey) { /* Command key down */
if (event->what == keyDown) {
AdjustMenus(); /* enable/disable/check menu items properly */
DoMenuCommand(MenuKey(key)); /* Process the key */
}
return 0; /* Ignore the event */
}
return key; /* Return the key pressed */
case updateEvt:
DoUpdate((WindowPtr) event->message); /* Force redraw of my window */
break;
case diskEvt:
if ((event->message>>16) != noErr ) { /* Was there an error? */
SetPt(&aPoint, kDILeft, kDITop);
DIBadMount(aPoint, event->message); /* Format the disk? */
}
break;
case activateEvt:
if (event->modifiers & 1) {
FixTheCursor(); /* Reset the cursor to the hidden state */
SetPort((WindowPtr)GameWindow);
ResetPalette(); /* Set my system palette */
}
break;
case osEvt:
DoBackground(event); /* Process suspend / resume */
break;
}
if (OpenPending && JumpOK) {
OpenPending=FALSE; /* Ack the event */
if (LoadGame()) { /* Load the game into memory */
longjmp(ResetJmp,EX_LOADGAME); /* Restart a loaded game */
}
}
if (!InPause) {
HideMenuBar(); /* Make SURE the menu bar is gone! */
}
return 0; /* No event processed */
}
/**********************************
Call this when I receive an update event
**********************************/
void DoUpdate(WindowPtr window)
{
if (((WindowPeek) window)->windowKind >=0) { /* Is this my window? */
BeginUpdate(window); /* this sets up the visRgn */
DrawWindow(window); /* Draw the game window */
EndUpdate(window); /* Fix the visRgn */
}
}
/************************
Update the contents of the window
************************/
void DrawWindow(WindowPtr window)
{
Word OldQuick; /* Previous state of the quickdraw flag */
if (window == (WindowPtr) GameWindow) { /* Is it my window? */
SetPort((WindowPtr)GameWindow);
OldQuick = DoQuickDraw; /* Save the quickdraw flag */
DoQuickDraw = TRUE; /* Force quickdraw */
BlastScreen(); /* Update the screen */
DoQuickDraw = OldQuick; /* Restore quickdraw flag */
if (ValidRects) { /* Black region valid? */
FillRgn(BlackRgn,&qd.black); /* Fill the black region */
}
}
}
/****************************
Set an item's mark with a check mark
****************************/
static void SetAMark(MenuHandle MyHand,Word Which,Word Var)
{
Var = (Var) ? 0x12 : 0;
SetItemMark(MyHand,Which,Var);
}
/****************************
Enable and disable menu items
****************************/
void AdjustMenus(void)
{
WindowPtr window;
MenuHandle FileMenu,EditMenu,OptionMenu;
window = FrontWindow(); /* Which window is in front */
FileMenu = GetMenuHandle(mFile); /* Get the file menu handle */
EditMenu = GetMenuHandle(mEdit); /* Get the edit menu handle */
OptionMenu = GetMenuHandle(mOptions);
if (window!=(WindowPtr)GameWindow) { /* Enable if there is a window */
EnableItem(FileMenu,iClose);
EnableItem(EditMenu,0);
} else {
DisableItem(FileMenu,iClose);
DisableItem(EditMenu,0);
}
if (playstate == EX_STILLPLAYING) { /* Game is in progress */
EnableItem(FileMenu,iSaveAs); /* Save the game */
EnableItem(FileMenu,iSave); /* Quicksave the game */
} else {
DisableItem(FileMenu,iSaveAs); /* Can't save game when isn't in the mode */
DisableItem(FileMenu,iSave);
}
if (LowOnMem) {
DisableItem(OptionMenu,iSound);
DisableItem(OptionMenu,iMusic);
}
if (DimQD) {
DisableItem(OptionMenu,iUseQuickDraw);
}
if (playstate==EX_AUTOMAP || playstate==EX_DIED) {
DisableItem(OptionMenu,iScreenSize);
} else {
EnableItem(OptionMenu,iScreenSize);
}
SetAMark(OptionMenu,iSound,SystemState&SfxActive); /* Check the sound menu */
SetAMark(OptionMenu,iMusic,SystemState&MusicActive); /* Check the music menu */
SetAMark(OptionMenu,iGovenor,SlowDown); /* Check the Speed goveror */
SetAMark(OptionMenu,iMouseControl,MouseEnabled); /* Check the mouse flag */
SetAMark(OptionMenu,iUseQuickDraw,DoQuickDraw); /* Check the mouse flag */
}
/**********************************
Process a menu bar event
**********************************/
void DoMenuCommand(LongWord menuResult)
{
Word menuID; /* the resource ID of the selected menu */
Word menuItem; /* the item number of the selected menu */
Str255 daName; /* Name of desk acc */
Word i; /* Temp */
menuID = menuResult>>16;
menuItem = menuResult&0xffff; /* get menu item number and menu number */
switch (menuID) {
case mApple: /* Apple menu */
switch (menuItem) {
case iAbout: /* Bring up alert for About */
PlaySound(SND_MENU);
DoMyAlert(rAboutAlert); /* Show the credits */
PlaySound(SND_OK);
break;
case iSpeedHint:
PlaySound(SND_MENU);
DoMyAlert(SpeedTipsWin); /* Show the hints for speed */
PlaySound(SND_OK);
break;
case iShareWare:
PlaySound(SND_MENU);
DoMyAlert(ShareWareWin); /* Ask about $$$ */
PlaySound(SND_OK);
break;
default: /* all non-About items in this menu are DAs */
GetMenuItemText(GetMenuHandle(mApple), menuItem, daName);
OpenDeskAcc(daName);
break;
}
break;
case mFile: /* File menu */
switch (menuItem) {
case iNew:
if (ChooseGameDiff()) { /* Choose level of difficulty */
HiliteMenu(0);
FixPauseMenu();
SaveFileName = 0; /* Zap the save game name */
longjmp(ResetJmp,EX_NEWGAME);
}
break;
case iClose:
DoCloseWindow(FrontWindow());
break;
case iOpen:
if (ChooseLoadGame()) { /* Choose a game to load */
if (LoadGame()) { /* Load the game into memory */
HiliteMenu(0);
FixPauseMenu();
longjmp(ResetJmp,EX_LOADGAME); /* Restart a loaded game */
}
}
break;
case iSave:
if (SaveFileName) { /* Save the file automatically? */
SaveGame(); /* Save it */
break;
}
case iSaveAs:
if (ChooseSaveGame()) { /* Select a save game name */
SaveGame(); /* Save it */
}
break;
case iQuit:
GoodBye(); /* Try to quit */
break;
}
break;
case mEdit: /* call SystemEdit for DA editing & MultiFinder */
SystemEdit(menuItem-1); /* since we don't do any Editing */
break;
case mOptions:
switch (menuItem) {
case iSound:
SystemState^=SfxActive; /* Sound on/off flags */
if (!(SystemState&SfxActive)) {
if (InPause) {
ResumeSoundMusicSystem();
}
PlaySound(0); /* Turn off all existing sounds */
if (InPause) {
PauseSoundMusicSystem();
}
}
break;
case iMusic:
SystemState^=MusicActive; /* Music on/off flags */
if (InPause) {
ResumeSoundMusicSystem();
}
if (SystemState&MusicActive) {
PlaySong(KilledSong); /* Restart the music */
} else {
PlaySong(0); /* Shut down the music */
}
if (InPause) {
PauseSoundMusicSystem();
}
break;
case iScreenSize:
i = DoMyAlert(AskSizeWin); /* Should I change the size? */
if (i && i<5) {
--i;
if (GameViewSize!=i) { /* Did you change the size? */
if (!InPause) {
HideMenuBar();
}
MouseHit = TRUE; /* Get out of pause mode */
GameViewSize = i; /* Set the new size */
if (playstate==EX_STILLPLAYING || playstate==EX_AUTOMAP) {
TryIt:
GameViewSize = NewGameWindow(GameViewSize); /* Make a new window */
if (!StartupRendering(GameViewSize)) { /* Set the size of the game screen */
ReleaseScalers();
if (!GameViewSize) {
BailOut();
}
--GameViewSize;
goto TryIt;
}
if (playstate==EX_STILLPLAYING) {
RedrawStatusBar(); /* Redraw the lower area */
}
playstate=EX_STILLPLAYING;
SetAPalette(rGamePal); /* Reset the game palette */
}
}
}
break;
case iGovenor:
SlowDown^=1; /* Toggle the slow down flag */
break;
case iMouseControl:
MouseEnabled = (!MouseEnabled); /* Toggle the cursor */
FixTheCursor();
if (MouseEnabled) {
ReadSystemJoystick();
mousex = 0;
mousey = 0;
mouseturn=0;
ReadSystemJoystick();
mousex =0; /* Discard the results */
mousey =0;
mouseturn=0;
}
break;
case iUseQuickDraw:
DoQuickDraw^=TRUE; /* Toggle the quickdraw flag */
break;
}
SavePrefs();
break;
}
HiliteMenu(0); /* unhighlight what MenuSelect (or MenuKey) hilited */
}
/*********************************
Close a window, return TRUE if successful
*********************************/
Boolean DoCloseWindow(WindowPtr window)
{
int Kind;
if (window) { /* Valid pointer? */
Kind = ((WindowPeek) window)->windowKind; /* Get the kind */
if (Kind<0) {
CloseDeskAcc(Kind);
}
}
return TRUE; /* I closed it! */
}
/***************************
I can't load! Bail out now!
****************************/
void BailOut(void)
{
DoMyAlert(rUserAlert); /* Show the alert window */
GoodBye(); /* Bail out! */
}
/**********************************
Update the wolf screen as fast as possible
Make sure that ForeColor = BLACK and Color = WHITE,
ROWBYTES should be long aligned (4,8,12,16...)
Source and dest should be EXACTLY the same bit depth
ctSeed should match the WINDOW's color seed
Both rects should be multiples of 4 to make long word transfers only
**********************************/
void BlastScreen2(Rect *BlastRect)
{
Rect QDRect;
CTabHandle ColorHandle,ColorHandle2;
QDRect = *BlastRect;
OffsetRect(&QDRect,QDGameRect.left,QDGameRect.top);
SetPort((WindowPtr) GameWindow); /* Make sure the port is set */
ColorHandle = (**(*GameGWorld).portPixMap).pmTable; /* Get the color table */
ColorHandle2 = (**(*GameWindow).portPixMap).pmTable; /* Get the color table */
PtrToXHand(*MainColorHandle,(Handle)ColorHandle,8+8*256);
PtrToXHand(*MainColorHandle,(Handle)ColorHandle2,8+8*256);
CopyBits((BitMap *) *((*GameGWorld).portPixMap),(BitMap *) *((*GameWindow).portPixMap),
BlastRect,&QDRect,srcCopy,NULL);
}
void BlastScreen(void)
{
Word i,j,k,m;
Byte *Screenad;
LongWord *Dest;
union {
LongWord * L;
Byte *B;
} Src;
Point MyPoint;
MyPoint.h = BlackRect2.left;
MyPoint.v = BlackRect2.top;
ShieldCursor(&GameRect,MyPoint);
if (!DoQuickDraw) {
i = MacHeight;
k = MacWidth/64;
m = VideoWidth - MacWidth;
Src.B = VideoPointer; /* Pointer to video */
Screenad = GameVideoPointer; /* Get dest video address */
do {
j = k; /* Init width (In Longs) */
Dest = (LongWord *) Screenad; /* Reset the dest pointer */
do {
Dest[0] = Src.L[0];
Dest[1] = Src.L[1];
Dest[2] = Src.L[2];
Dest[3] = Src.L[3];
Dest[4] = Src.L[4];
Dest[5] = Src.L[5];
Dest[6] = Src.L[6];
Dest[7] = Src.L[7];
Dest[8] = Src.L[8];
Dest[9] = Src.L[9];
Dest[10] = Src.L[10];
Dest[11] = Src.L[11];
Dest[12] = Src.L[12];
Dest[13] = Src.L[13];
Dest[14] = Src.L[14];
Dest[15] = Src.L[15];
Dest+=16;
Src.L+=16;
} while (--j);
Src.B += m;
Screenad+=TrueVideoWidth;
} while (--i);
} else {
BlastScreen2(&GameRect);
}
ShowCursor();
if (!InPause) {
ObscureCursor();
}
}
/**********************************
Create a new game window
**********************************/
Word NewGameWindow(Word NewVidSize)
{
Byte *DestPtr;
LongWord *LongPtr;
Word i,j;
Boolean Pass2;
RgnHandle TempRgn;
Pass2 = FALSE; /* Assume memory is OK */
/* First, kill ALL previous permenant records */
if (NewVidSize>=2) { /* Is this 640 mode? */
if (MonitorWidth<640) { /* Can I show 640 mode? */
NewVidSize=1; /* Reduce to 512 mode */
} else {
if (MonitorHeight<480) { /* Can I display 480 lines? */
NewVidSize=2; /* Show 400 instead */
}
}
}
if (NewVidSize==MacVidSize) { /* Same size being displayed? */
return MacVidSize; /* Exit then... */
}
SetPort((WindowPtr)GameWindow); /* Blank out the screen! */
ForeColor(blackColor); /* Make sure the colors are set */
BackColor(whiteColor);
FillRect(&BlackRect,&qd.black); /* Blank it out! */
TryAgain:
if (GameGWorld) {
DisposeGWorld(GameGWorld); /* Release the old GWorld */
GameGWorld=0;
}
if (GameShapes) {
FreeSomeMem(GameShapes); /* All the permanent game shapes */
GameShapes=0;
}
MacVidSize = NewVidSize; /* Set the new data size */
MacWidth = VidXs[NewVidSize];
MacHeight = VidYs[NewVidSize];
MacViewHeight = VidVs[NewVidSize];
GameRect.bottom = MacHeight; /* Set new video height */
GameRect.right = MacWidth; /* Set new video width */
QDGameRect.top = RectY;
QDGameRect.left = RectX;
QDGameRect.bottom = RectY+MacHeight;
QDGameRect.right = RectX+MacWidth;
if (MacHeight==MonitorHeight && MacWidth==MonitorWidth) {
ValidRects = FALSE;
} else {
ValidRects = TRUE; /* The 4 bar rects are valid */
RectRgn(BlackRgn,&BlackRect);
TempRgn = NewRgn();
RectRgn(TempRgn,&QDGameRect);
DiffRgn(BlackRgn,TempRgn,BlackRgn);
DisposeRgn(TempRgn);
}
GameVideoPointer = &TrueVideoPointer[(LongWord)QDGameRect.top*TrueVideoWidth+QDGameRect.left];
if (NewGWorld(&GameGWorld,8,&GameRect,nil,nil,0)) {
goto OhShit;
}
LockPixels(GameGWorld->portPixMap); /* Lock down the memory FOREVER! */
VideoPointer = (Byte *)GetPixBaseAddr(GameGWorld->portPixMap); /* Get the video pointer */
VideoWidth = (Word) (**(*GameGWorld).portPixMap).rowBytes & 0x3FFF;
InitYTable(); /* Init the game's YTable */
SetAPalette(rBlackPal); /* Set the video palette */
ClearTheScreen(BLACK); /* Set the screen to black */
BlastScreen();
LongPtr = (LongWord *) LoadAResource(VidPics[MacVidSize]);
if (!LongPtr) {
goto OhShit;
}
GameShapes = (Byte **) AllocSomeMem(LongPtr[0]); /* All the permanent game shapes */
if (!GameShapes) { /* Can't load in the shapes */
ReleaseAResource(VidPics[MacVidSize]); /* Release it NOW! */
goto OhShit;
}
DLZSS((Byte *)GameShapes,(Byte *) &LongPtr[1],LongPtr[0]);
ReleaseAResource(VidPics[MacVidSize]);
i = 0;
j = (MacVidSize==1) ? 47+10 : 47; /* 512 mode has 10 shapes more */
DestPtr = (Byte *) GameShapes;
LongPtr = (LongWord *) GameShapes;
do {
GameShapes[i] = DestPtr+LongPtr[i];
} while (++i<j);
if (Pass2) { /* Low memory? */
if (!StartupRendering(NewVidSize)) { /* Reset the scalers... */
ReleaseScalers();
goto OhShit;
}
}
return MacVidSize;
OhShit: /* Oh oh.... */
if (Pass2) {
if (!NewVidSize) { /* At the smallest screen size? */
BailOut();
}
--NewVidSize; /* Smaller size */
} else {
PlaySong(0); /* Release song memory */
ReleaseScalers(); /* Release the compiled scalers */
PurgeAllSounds(1000000); /* Force sounds to be purged */
Pass2 = TRUE;
}
goto TryAgain; /* Let's try again */
}
/**********************************
Scale the system X coord
**********************************/
Word ScaleX(Word x)
{
switch(MacVidSize) {
case 1:
return x*8/5;
case 2:
case 3:
return x*2;
}
return x;
}
/**********************************
Scale the system Y coord
**********************************/
Word ScaleY(Word y)
{
switch(MacVidSize) {
case 1: /* 512 resolution */
y = (y*8/5)+64;
if (y==217) { /* This hack will line up the gun on 512 mode */
++y;
}
return y;
case 2: /* 640 x 400 */
return y*2;
case 3: /* 640 x 480 */
return y*2+80;
}
return y; /* 320 resolution */
}
/**********************************
Shut down and exit
**********************************/
void GoodBye(void)
{
ShowMenuBar(); /* Restore the menu bar */
ReleaseScalers(); /* Release all my memory */
FinisSoundMusicSystem(); /* Shut down the Halestorm driver */
if (gMainGDH && OldPixDepth) { /* Old pixel depth */
SetDepth(gMainGDH,OldPixDepth, 1 << gdDevType,1); /* Restore the depth */
}
InitCursor();
ExitToShell(); /* Exit to System 7 */
}
/**********************************
Read from the Mac's keyboard/mouse system
**********************************/
Word MyKey;
typedef struct MacKeys2Joy {
Word Index;
Word BitField;
Word JoyValue;
} MacKeys2Joy;
MacKeys2Joy KeyMatrix[] = {
{11,1<<1,JOYPAD_LFT|JOYPAD_UP}, /* Keypad 7 */
{10,1<<6,JOYPAD_LFT}, /* Keypad 4 */
{10,1<<3,JOYPAD_LFT|JOYPAD_DN}, /* Keypad 1 */
{11,1<<3,JOYPAD_UP}, /* Keypad 8 */
{10,1<<7,JOYPAD_DN}, /* Keypad 5 */
{10,1<<4,JOYPAD_DN}, /* Keypad 2 */
{11,1<<4,JOYPAD_RGT|JOYPAD_UP}, /* Keypad 9 */
{11,1<<0,JOYPAD_RGT}, /* Keypad 6 */
{10,1<<5,JOYPAD_RGT|JOYPAD_DN}, /* Keypad 3 */
{15,1<<6,JOYPAD_UP}, /* Arrow up */
{15,1<<5,JOYPAD_DN}, /* Arrow down */
{15,1<<3,JOYPAD_LFT}, /* Arrow Left */
{15,1<<4,JOYPAD_RGT}, /* Arrow Right */
{ 1,1<<5,JOYPAD_UP}, /* W */
{ 0,1<<0,JOYPAD_LFT}, /* A */
{ 0,1<<1,JOYPAD_DN}, /* S */
{ 0,1<<2,JOYPAD_RGT}, /* D */
{ 4,1<<2,JOYPAD_UP}, /* I */
{ 4,1<<6,JOYPAD_LFT}, /* J */
{ 5,1<<0,JOYPAD_DN}, /* K */
{ 4,1<<5,JOYPAD_RGT}, /* L */
{ 6,1<<1,JOYPAD_A}, /* Space */
{ 4,1<<4,JOYPAD_A}, /* Return */
{10,1<<2,JOYPAD_A}, /* Keypad 0 */
{ 9,1<<4,JOYPAD_A}, /* keypad enter */
{ 7,1<<7,JOYPAD_TR}, /* Option */
{ 7,1<<2,JOYPAD_TR}, /* Option */
{ 7,1<<0,JOYPAD_X}, /* Shift L */
{ 7,1<<1,JOYPAD_X}, /* Caps Lock */
{ 7,1<<4,JOYPAD_X}, /* Shift R */
{ 6,1<<0,JOYPAD_SELECT}, /* Tab */
{ 7,1<<3,JOYPAD_B}, /* Ctrl */
{ 7,1<<6,JOYPAD_B} /* Ctrl */
};
static char *CheatPtr[] = { /* Cheat strings */
"XUSCNIELPPA",
"IDDQD",
"BURGER",
"WOWZERS",
"LEDOUX",
"SEGER",
"MCCALL",
"APPLEIIGS"
};
static Word Cheat; /* Which cheat is active */
static Word CheatIndex; /* Index to the cheat string */
static void FixPauseMenu(void)
{
if (PauseMenu) { /* Is there a pause menu? */
InPause = FALSE;
DeleteMenu(55); /* Remove it from the menu bar */
DrawMenuBar(); /* Redraw the menu bar */
HideMenuBar(); /* Hide the menu bar */
DisposeMenu(PauseMenu); /* Free the memory */
PauseMenu = 0; /* Ack the flag */
ResumeSoundMusicSystem(); /* Restart the music */
}
}
void ReadSystemJoystick(void)
{
Word i;
Word Index;
MacKeys2Joy *MacPtr;
Point MyPoint;
union {
unsigned char Keys[16];
KeyMap Macy;
} Keys;
joystick1 = 0; /* Assume that joystick not moved */
i = GetAKey(); /* Allow menu events */
if (i==0x1b) { /* Pause key? */
ShowMenuBar();
InitCursor();
PauseMenu = NewMenu(55,"\p<< Game is Paused! >>");
InsertMenu(PauseMenu,0);
DrawMenuBar();
PauseSoundMusicSystem(); /* Pause the music */
InPause = TRUE; /* Hack to prevent the menu bar from disappearing */
WaitTicksEvent(0);
LastTicCount = ReadTick(); /* Reset the timer for the pause key */
FixPauseMenu(); /* Exit pause */
FixTheCursor();
}
/* Switch weapons like in DOOM! */
if (i) { /* Was a key hit? */
i = toupper(i); /* Force UPPER case */
if (CheatIndex) { /* Cheat in progress */
if (CheatPtr[Cheat][CheatIndex]==i) { /* Match the current string? */
++CheatIndex; /* Next char */
if (!CheatPtr[Cheat][CheatIndex]) { /* End of the string? */
PlaySound(SND_BONUS); /* I got a bonus! */
switch (Cheat) { /* Execute the cheat */
case 1:
gamestate.godmode^=TRUE; /* I am invincible! */
break;
case 5:
GiveKey(0);
GiveKey(1); /* Award the keys */
break;
case 6:
playstate=EX_WARPED; /* Force a jump to the next level */
nextmap = gamestate.mapon+1; /* Next level */
if (MapListPtr->MaxMap<=nextmap) { /* Too high? */
nextmap = 0; /* Reset to zero */
}
break;
case 7:
ShowPush ^= TRUE;
break;
case 0:
case 4:
GiveKey(0); /* Award the keys */
GiveKey(1);
gamestate.godmode = TRUE; /* I am a god */
case 2:
gamestate.machinegun = TRUE;
gamestate.chaingun = TRUE;
gamestate.flamethrower = TRUE;
gamestate.missile = TRUE;
GiveAmmo(gamestate.maxammo);
GiveGas(99);
GiveMissile(99);
break;
case 3:
gamestate.maxammo = 999;
GiveAmmo(999);
}
}
} else {
CheatIndex = 0;
goto TryFirst;
}
} else {
TryFirst:
Index = 0; /* Init the scan routine */
do {
if (CheatPtr[Index][0] == i) {
Cheat = Index; /* This is my current cheat I am scanning */
CheatIndex = 1; /* Index to the second char */
break; /* Exit */
}
} while (++Index<8); /* All words scanned? */
}
switch (ScanCode) { /* Use the SCAN code to make sure I hit the right key! */
case 0x12 : /* 1 */
gamestate.pendingweapon = WP_KNIFE;
break;
case 0x13 : /* 2 */
if (gamestate.ammo) {
gamestate.pendingweapon = WP_PISTOL;
}
break;
case 0x14 : /* 3 */
if (gamestate.ammo && gamestate.machinegun) {
gamestate.pendingweapon = WP_MACHINEGUN;
}
break;
case 0x15 : /* 4 */
if (gamestate.ammo && gamestate.chaingun) {
gamestate.pendingweapon = WP_CHAINGUN;
}
break;
case 0x17 : /* 5 */
if (gamestate.gas && gamestate.flamethrower) {
gamestate.pendingweapon = WP_FLAMETHROWER;
}
break;
case 0x16 : /* 6 */
if (gamestate.missiles && gamestate.missile) {
gamestate.pendingweapon = WP_MISSILE;
}
break;
case 0x41: /* Keypad Period */
case 0x2C: /* Slash */
joystick1 = JOYPAD_START;
}
}
GetKeys(Keys.Macy); /* Get the keyboard from the mac */
i = 0; /* Init the count */
MacPtr = KeyMatrix;
do {
Index = MacPtr->Index; /* Get the byte index */
if (Keys.Keys[Index] & MacPtr->BitField) {
joystick1 |= MacPtr->JoyValue; /* Set the joystick value */
}
MacPtr++; /* Next index */
} while (++i<33); /* All done? */
if (MouseEnabled) { /* Mouse control turned on? */
if (Button()) { /* Get the mouse button */
joystick1 |= JOYPAD_B; /* Mouse button */
}
GetMouse(&MyPoint); /* Get the mouse location */
LocalToGlobal(&MyPoint); /* Convert mouse to global coordinate system */
if (joystick1&JOYPAD_TR) { /* Strafing? */
mousex += (MyPoint.h-MouseBaseX); /* Move horizontally for strafe */
} else {
mouseturn += (MouseBaseX-MyPoint.h); /* Turn left or right */
}
mousey += (MyPoint.v-MouseBaseY); /* Forward motion */
(*(unsigned short *) 0x082C) = MouseBaseY; /* Set RawMouse */
(*(unsigned short *) 0x082E) = MouseBaseX;
(*(unsigned short *) 0x0828) = MouseBaseY; /* MTemp */
(*(unsigned short *) 0x082A) = MouseBaseX;
(*(Byte *) 0x08CE) = 255; /* CrsrNew */
(*(Byte *) 0x08CF) = 255; /* CrsrCouple */
}
if (joystick1 & JOYPAD_TR) { /* Handle the side scroll (Special case) */
if (joystick1&JOYPAD_LFT) {
joystick1 = (joystick1 & ~(JOYPAD_TR|JOYPAD_LFT)) | JOYPAD_TL;
} else if (joystick1&JOYPAD_RGT) {
joystick1 = joystick1 & ~JOYPAD_RGT;
} else {
joystick1 &= ~JOYPAD_TR;
}
}
}
/**********************************
Handle GET PSYCHED!
**********************************/
static Rect PsychedRect;
static Word LeftMargin;
#define PSYCHEDWIDE 184
#define PSYCHEDHIGH 5
#define PSYCHEDX 20
#define PSYCHEDY 46
#define MAXINDEX (66+S_LASTONE)
/**********************************
Draw the initial shape
**********************************/
void ShowGetPsyched(void)
{
LongWord *PackPtr;
Byte *ShapePtr;
LongWord PackLength;
Word X,Y;
SetPort((WindowPtr)GameWindow);
ClearTheScreen(BLACK);
BlastScreen();
PackPtr = LoadAResource(rGetPsychPic);
PackLength = PackPtr[0];
ShapePtr = AllocSomeMem(PackLength);
DLZSS(ShapePtr,(Byte *) &PackPtr[1],PackLength);
X = (MacWidth-224)/2;
Y = (MacViewHeight-56)/2;
DrawShape(X,Y,ShapePtr);
FreeSomeMem(ShapePtr);
ReleaseAResource(rGetPsychPic);
BlastScreen();
SetAPalette(rGamePal);
SetPort((WindowPtr)GameWindow);
ForeColor(redColor);
PsychedRect.top = Y + PSYCHEDY + QDGameRect.top;
PsychedRect.bottom = PsychedRect.top + PSYCHEDHIGH;
PsychedRect.left = X + PSYCHEDX + QDGameRect.left;
PsychedRect.right = PsychedRect.left;
LeftMargin = PsychedRect.left;
}
/**********************************
Update the thermomitor
**********************************/
void DrawPsyched(Word Index)
{
Word Factor;
Factor = Index * PSYCHEDWIDE; /* Calc the relative X pixel factor */
Factor = Factor / MAXINDEX;
PsychedRect.left = PsychedRect.right; /* Adjust the left pixel */
PsychedRect.right = Factor+LeftMargin;
PaintRect(&PsychedRect); /* Draw the pixel in the bar */
}
/**********************************
Erase the Get Psyched screen
**********************************/
void EndGetPsyched(void)
{
ForeColor(blackColor); /* Reset the color to black for high speed */
SetAPalette(rBlackPal); /* Zap the palette */
}
/**********************************
Choose the game difficulty
**********************************/
static void DrawNewRect(DialogPtr theDialog,Word Item,Word Color)
{
short iType;
Handle iHndl;
Rect iRect;
ForeColor(Color);
GetDialogItem(theDialog,Item, &iType, &iHndl, &iRect);
InsetRect(&iRect,-4,-4);
PenSize(3,3); /* Nice thick line */
FrameRect(&iRect);
PenNormal();
}
/**********************************
Choose the game difficulty
**********************************/
static Word OldVal; /* Make semi-global so the filter can use it as input */
Word ChooseGameDiff(void)
{
ModalFilterUPP theDialogFilter;
DialogPtr MyDialog;
short itemHit;
Word donewithdialog;
Word RetVal;
Word OldTick;
unsigned short DblClick;
Byte OldPal[768];
memcpy(OldPal,CurrentPal,768);
SetPort((WindowPtr)GameWindow);
FillRect(&BlackRect,&qd.black);
SetAPalette(rGamePal);
MyDialog = GetNewDialog(NewGameWin,0L,(WindowPtr)-1); /* Open the dialog window */
OldVal = difficulty+1; /* Save the current difficulty */
PlaySound(SND_MENU);
CenterAWindow(MyDialog);
ShowWindow(MyDialog); /* Display with OK button framed */
InitCursor();
SetPort((WindowPtr) MyDialog);
DrawNewRect(MyDialog,OldVal,blackColor);
DblClick = 0;
donewithdialog = FALSE;
RetVal = TRUE; /* Assume ok */
theDialogFilter = NewModalFilterProc(StandardModalFilterProc);
do {
ModalDialog(theDialogFilter, &itemHit);
switch (itemHit) {
case 1:
case 2:
case 3:
case 4: /* The checkbox */
if (OldVal!=itemHit) {
DrawNewRect(MyDialog,OldVal,whiteColor); /* Erase the old rect */
DrawNewRect(MyDialog,itemHit,blackColor);
OldVal = itemHit;
}
PlaySound(SND_GUNSHT); /* Gun shot */
if (DblClick==itemHit) { /* Hit the same item? */
if (((Word)ReadTick()-OldTick)<(Word)15) { /* Double click time? */
donewithdialog = TRUE;
difficulty = OldVal-1;
break; /* Ok! */
}
}
OldTick=ReadTick(); /* Save the tick mark */
DblClick=itemHit; /* Save the last item hit */
break;
case 5:
RetVal = FALSE;
donewithdialog = TRUE;
PlaySound(SND_OK);
break;
case 6: /* OK Button */
donewithdialog = TRUE;
difficulty = OldVal-1;
PlaySound(SND_OK);
break;
}
} while (!donewithdialog);
DisposeRoutineDescriptor(theDialogFilter);
DisposeDialog(MyDialog);
SetAPalettePtr(OldPal); /* Restore the palette */
SetPort((WindowPtr) GameWindow);
DrawWindow((WindowPtr)GameWindow); /* Draw it NOW! */
FixTheCursor();
return RetVal;
}
static Byte BoxUp[] = {3,4,1,2}; /* Up/Down */
static Byte BoxLeft[] = {2,1,4,3}; /* Left/Right */
static Byte TabLeft[] = {2,3,4,1}; /* Tab */
pascal Boolean StandardModalFilterProc(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
{
char theChar;
Handle theHandle;
short theType;
Rect theRect;
switch (theEvent->what) {
case keyDown:
theChar = toupper(theEvent->message & charCodeMask);
switch (theChar) {
case '8': /* Up */
case 0x1E: /* Up */
case '5': /* Down */
case '2': /* Down */
case 0x1F: /* Down */
case 'W':
case 'S':
case 'I':
case 'K':
*itemHit = BoxUp[OldVal-1];
return TRUE;
case '4': /* Left */
case '6': /* Right */
case 0x1C: /* Left */
case 0x1D: /* Right */
case 'A':
case 'D':
case 'J':
case 'L':
*itemHit = BoxLeft[OldVal-1];
return TRUE;
case 9:
*itemHit = TabLeft[OldVal-1];
return TRUE;
case 0x0D: /* Return */
case 0x03: /* Enter */
*itemHit = 6;
return (TRUE);
case 'Q': /* Cmd-Q */
case '.': /* Cmd-Period */
if (theEvent->modifiers & cmdKey) {
case 0x1b: /* Esc */
*itemHit = 5;
return (TRUE);
}
break;
}
break;
case updateEvt:
GetDialogItem(theDialog, 6, &theType, &theHandle, &theRect);
InsetRect(&theRect, -4, -4);
PenSize(3, 3);
FrameRoundRect(&theRect, 16, 16);
}
return (FALSE); // Tells dialog manager to handle the event
}
/**********************************
Load the prefs file into memory and use defaults
for ANY errors that could occur
**********************************/
typedef struct { /* Save game data field */
unsigned short State; /* Game state flags */
unsigned short Mouse; /* Mouse control */
unsigned short QuickDraw; /* Quickdraw for updates */
unsigned short Goveror; /* Speed governor */
unsigned short ViewSize; /* Game screen size */
unsigned short Difficulty; /* Game difficulty */
unsigned short Ignore; /* Ignore message flag */
} Prefs_t;
void LoadPrefs(void)
{
Prefs_t Prefs;
Prefs.State = 3; /* Assume sound & music enabled */
Prefs.Mouse = FALSE; /* Mouse control shut off */
Prefs.QuickDraw = TRUE; /* Use quickdraw for screen updates */
Prefs.Goveror = TRUE; /* Enable speed governor */
Prefs.ViewSize = 0; /* 320 mode screen */
Prefs.Difficulty = 2; /* Medium difficulty */
Prefs.Ignore = FALSE; /* Enable message */
InitPrefsFile('WOLF',(Byte *)"Wolfenstein 3D Prefs"); /* Create the prefs file (If it doesn't exist) */
LoadPrefsFile((Byte *)&Prefs,sizeof(Prefs)); /* Load in the prefs (Assume it may NOT!) */
SystemState = Prefs.State; /* Store the defaults from either the presets or the file */
MouseEnabled = Prefs.Mouse;
DoQuickDraw = Prefs.QuickDraw;
SlowDown = Prefs.Goveror;
GameViewSize = Prefs.ViewSize;
difficulty = Prefs.Difficulty;
IgnoreMessage = Prefs.Ignore;
}
/**********************************
Save the prefs file to disk but ignore any errors
**********************************/
void SavePrefs(void)
{
Prefs_t Prefs; /* Structure to save to disk */
Prefs.State = SystemState; /* Init the prefs structure */
Prefs.Mouse = MouseEnabled;
Prefs.QuickDraw = DoQuickDraw;
Prefs.Goveror = SlowDown;
Prefs.ViewSize = GameViewSize;
Prefs.Difficulty = difficulty;
Prefs.Ignore = IgnoreMessage;
SavePrefsFile((Byte *)&Prefs,sizeof(Prefs)); /* Save the prefs file */
}
/**********************************
Save the game
**********************************/
#ifdef __powerc
Byte MachType[4] = "PPC3";
#else
Byte MachType[4] = "68K3";
#endif
void SaveGame(void)
{
short FileRef;
long Count;
Word PWallWord;
HCreate(SaveFileVol,SaveFileParID,SaveFileName,'WOLF','SAVE'); /* Create the save game file */
if (HOpen(SaveFileVol,SaveFileParID,SaveFileName,fsWrPerm,&FileRef)) { /* Can I open it? */
return; /* Abort! */
}
Count = 4; /* Default length */
FSWrite(FileRef,&Count,&MachType); /* Save a machine type ID */
Count = sizeof(unsigned short);
FSWrite(FileRef,&Count,&MapListPtr->MaxMap); /* Number of maps (ID) */
Count = sizeof(gamestate);
FSWrite(FileRef,&Count,&gamestate); /* Save the game stats */
Count = sizeof(PushWallRec);
FSWrite(FileRef,&Count,&PushWallRec); /* Save the pushwall stats */
Count = sizeof(nummissiles);
FSWrite(FileRef,&Count,&nummissiles); /* Save missiles in motion */
if (nummissiles) {
Count = nummissiles*sizeof(missile_t);
FSWrite(FileRef,&Count,&missiles[0]);
}
Count = sizeof(numactors);
FSWrite(FileRef,&Count,&numactors); /* Save actors */
if (numactors) {
Count = numactors*sizeof(actor_t);
FSWrite(FileRef,&Count,&actors[0]);
}
Count = sizeof(numdoors);
FSWrite(FileRef,&Count,&numdoors); /* Save doors */
if (numdoors) {
Count = numdoors*sizeof(door_t);
FSWrite(FileRef,&Count,&doors[0]);
}
Count = sizeof(numstatics);
FSWrite(FileRef,&Count,&numstatics);
if (numstatics) {
Count = numstatics*sizeof(static_t);
FSWrite(FileRef,&Count,&statics[0]);
}
Count = 64*64;
FSWrite(FileRef,&Count,MapPtr);
Count = sizeof(tilemap); /* Tile map */
FSWrite(FileRef,&Count,&tilemap);
Count = sizeof(ConnectCount);
FSWrite(FileRef,&Count,&ConnectCount);
if (ConnectCount) {
Count = ConnectCount * sizeof(connect_t);
FSWrite(FileRef,&Count,&areaconnect[0]);
}
Count = sizeof(areabyplayer);
FSWrite(FileRef,&Count,&areabyplayer[0]);
Count = (128+5)*64;
FSWrite(FileRef,&Count,&textures[0]);
Count = sizeof(Word);
PWallWord = 0; /* Assume no pushwall pointer in progress */
if (pwallseg) {
PWallWord = (pwallseg-(saveseg_t*)nodes)+1; /* Convert to number offset */
}
FSWrite(FileRef,&Count,&PWallWord);
Count = MapPtr->numnodes*sizeof(savenode_t); /* How large is the BSP tree? */
FSWrite(FileRef,&Count,nodes); /* Save it to disk */
FSClose(FileRef); /* Close the file */
PlaySound(SND_BONUS);
}
/**********************************
Load the game
**********************************/
void *SaveRecord;
void *SaveRecordMem;
Boolean LoadGame(void)
{
LongWord FileSize;
union {
Byte *B;
unsigned short *S;
Word *W;
LongWord *L;
} FilePtr;
void *TheMem;
short FileRef;
if (HOpen(SaveFileVol, SaveFileParID, SaveFileName, fsRdPerm, &FileRef)) {
return FALSE;
}
GetEOF(FileRef,(long*)&FileSize); /* Get the size of the file */
FilePtr.B = TheMem = AllocSomeMem(FileSize); /* Get memory for the file */
if (!FilePtr.B) { /* No memory! */
return FALSE;
}
FSRead(FileRef,(long*)&FileSize,(Ptr)FilePtr.B); /* Open the file */
FSClose(FileRef); /* Close the file */
if (memcmp(MachType,FilePtr.B,4)) { /* Is this the proper machine type? */
goto Bogus;
}
FilePtr.B+=4; /* Index past signature */
if (MapListPtr->MaxMap!=*FilePtr.S) { /* Map count the same? */
goto Bogus; /* Must be differant game */
}
++FilePtr.S; /* Index past count */
memcpy(&gamestate,FilePtr.B,sizeof(gamestate)); /* Reset the game state */
SaveRecord = FilePtr.B;
SaveRecordMem = TheMem;
return TRUE;
Bogus:
FreeSomeMem(TheMem);
return FALSE;
}
void FinishLoadGame(void)
{
union {
Byte *B;
unsigned short *S;
Word *W;
LongWord *L;
} FilePtr;
FilePtr.B = SaveRecord;
memcpy(&gamestate,FilePtr.B,sizeof(gamestate)); /* Reset the game state */
FilePtr.B+=sizeof(gamestate);
memcpy(&PushWallRec,FilePtr.B,sizeof(PushWallRec)); /* Record for the single pushwall in progress */
FilePtr.B+=sizeof(PushWallRec);
nummissiles = *FilePtr.W;
++FilePtr.W;
if (nummissiles) {
memcpy(&missiles[0],FilePtr.B,sizeof(missile_t)*nummissiles);
FilePtr.B += sizeof(missile_t)*nummissiles;
}
numactors = *FilePtr.W;
++FilePtr.W;
if (numactors) {
memcpy(&actors[0],FilePtr.B,sizeof(actor_t)*numactors);
FilePtr.B += sizeof(actor_t)*numactors;
}
numdoors = *FilePtr.W;
++FilePtr.W;
if (numdoors) {
memcpy(&doors[0],FilePtr.B,sizeof(door_t)*numdoors);
FilePtr.B += sizeof(door_t)*numdoors;
}
numstatics = *FilePtr.W;
++FilePtr.W;
if (numstatics) {
memcpy(&statics[0],FilePtr.B,sizeof(static_t)*numstatics);
FilePtr.B += sizeof(static_t)*numstatics;
}
memcpy(MapPtr,FilePtr.B,64*64);
FilePtr.B += 64*64;
memcpy(&tilemap,FilePtr.B,sizeof(tilemap)); /* Tile map */
FilePtr.B += sizeof(tilemap); /* Index past data */
ConnectCount = *FilePtr.W; /* Number of valid interconnects */
FilePtr.W++;
if (ConnectCount) {
memcpy(areaconnect,FilePtr.B,sizeof(connect_t)*ConnectCount); /* Is this area mated with another? */
FilePtr.B+= sizeof(connect_t)*ConnectCount;
}
memcpy(areabyplayer,FilePtr.B,sizeof(areabyplayer));
FilePtr.B+=sizeof(areabyplayer); /* Which areas can I see into? */
memcpy(&textures[0],FilePtr.B,(128+5)*64);
FilePtr.B+=((128+5)*64); /* Texture array for pushwalls */
pwallseg = 0; /* Assume bogus */
if (*FilePtr.W) {
pwallseg = (saveseg_t *)nodes;
pwallseg = &pwallseg[*FilePtr.W-1];
}
++FilePtr.W;
memcpy(nodes,FilePtr.B,MapPtr->numnodes*sizeof(savenode_t));
/* FilePtr.B+=(MapPtr->numnodes*sizeof(savenode_t)); /* Next entry */
FreeSomeMem(SaveRecordMem);
}
/**********************************
Process an alert and center it on my game monitor
Note : I am cheating like a son of a bitch by modifing the
resources directly!
**********************************/
static Word DoMyAlert(Word AlertNum)
{
Word Val;
Rect **AlertRect; /* Handle to the alert rect */
Rect MyRect;
InitCursor(); /* Fix the cursor */
AlertRect = (Rect **)GetResource('ALRT',AlertNum); /* Load in the template */
MyRect = **AlertRect; /* Copy the rect */
MyRect.right -= MyRect.left; /* Get the width */
MyRect.bottom -= MyRect.top; /* Get the height */
CenterSFWindow((Point *)&MyRect,MyRect.right,MyRect.bottom); /* Center the window */
MyRect.right += MyRect.left; /* Fix the rect */
MyRect.bottom += MyRect.top;
**AlertRect = MyRect;
ChangedResource((Handle)AlertRect);
Val = Alert(AlertNum,nil);
if (!InPause) { /* If paused then don't fix the cursor */
FixTheCursor();
}
return Val;
}
/**********************************
Beg for $$$ at the end of the shareware version
**********************************/
void ShareWareEnd(void)
{
SetAPalette(rGamePal);
DoMyAlert(EndGameWin);
SetAPalette(rBlackPal);
}
/**********************************
Show the standard file dialog
for opening a new game
**********************************/
SFTypeList MyList = {'SAVE'};
SFReply Reply;
static void CenterSFWindow(Point *MyPoint,Word Width,Word Height)
{
GDHandle MainDevice;
Rect TheRect;
Word H,W; /* Device width of main device */
if (gMainGDH) { /* Has the video device been selected? */
MyPoint->v = ((MonitorHeight-Height)/3)+BlackRect2.top; /* Center the window then */
MyPoint->h = ((MonitorWidth-Width)/2)+BlackRect2.left;
return;
}
MainDevice = GetMainDevice(); /* Get the default device */
TheRect = (**MainDevice).gdRect; /* Get the rect of the device */
H = TheRect.bottom - TheRect.top; /* Get the size of the video screen */
W = TheRect.right - TheRect.left;
MyPoint->v = ((H-Height)/3)+TheRect.top; /* Center the window */
MyPoint->h = ((W-Width)/2)+TheRect.left;
}
static void CenterAWindow(WindowPtr MyWindow)
{
Rect MyRect;
Point MyPoint;
MyRect = ((WindowPeek)MyWindow)->port.portRect;
CenterSFWindow(&MyPoint,MyRect.right-MyRect.left,MyRect.bottom-MyRect.top);
MoveWindow(MyWindow,MyPoint.h,MyPoint.v,FALSE);
}
Boolean ChooseLoadGame(void)
{
long ProcID;
Point MyPoint;
InitCursor();
CenterSFWindow(&MyPoint,348,136);
SFGetFile(MyPoint,0,0,1,MyList,0,&Reply);
FixTheCursor();
if (!Reply.good) { /* Pressed cancel? */
return FALSE;
}
SaveFileName = (Byte *)&Reply.fName;
SaveFileVol = Reply.vRefNum;
GetWDInfo(SaveFileVol,&SaveFileVol,&SaveFileParID,&ProcID);
return TRUE;
}
/**********************************
Show the standard file dialog
for saving a new game
**********************************/
Boolean ChooseSaveGame(void)
{
Byte *SaveTemp;
Point MyPoint;
long ProcID;
InitCursor();
SaveTemp = SaveFileName;
if (!SaveTemp) {
SaveTemp = "\pUntitled";
}
CenterSFWindow(&MyPoint,304,104);
SFPutFile(MyPoint,"\pSave your game as:",SaveTemp,0,&Reply);
FixTheCursor();
if (!Reply.good) {
return FALSE;
}
SaveFileName = (Byte *)&Reply.fName;
SaveFileVol = Reply.vRefNum;
GetWDInfo(SaveFileVol,&SaveFileVol,&SaveFileParID,&ProcID);
return TRUE;
}
/**********************************
Process Apple Events
**********************************/
#if 1
struct AEinstalls {
AEEventClass theClass;
AEEventID theEvent;
void *Code;
AEEventHandlerUPP theProc;
};
typedef struct AEinstalls AEinstalls;
static OSErr GotRequiredParams(AppleEvent *theAppleEvent)
{
DescType returnedType;
Size actualSize;
OSErr theErr;
theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
typeWildCard, &returnedType, nil, 0, &actualSize);
if (theErr == errAEDescNotFound)
return noErr;
if (!theErr)
return errAEParamMissed;
return theErr;
}
/* This is the standard Open Application event. */
static pascal OSErr AEOpenHandler(AppleEvent *theAppleEvent, AppleEvent *reply, long refIn)
{
OSErr theErr;
// This event occurs when the application is opened. In most cases
// nothing needs to be done, but we must make sure that we received
// no parameters, since none are supposed to be received.
theErr = GotRequiredParams(theAppleEvent);
if (theErr)
return theErr;
// do whatever is needed (e.g., open new untitled document)
return noErr;
}
/* Open Doc, opens our documents. Remember, this can happen at application start AND */
/* anytime else. If your app is up and running and the user goes to the desktop, hilites one */
/* of your files, and double-clicks or selects Open from the finder File menu this event */
/* handler will get called. Which means you don't do any initialization of globals here, or */
/* anything else except open then doc. */
/* SO-- Do NOT assume that you are at app start time in this */
/* routine, or bad things will surely happen to you. */
static pascal OSErr AEOpenDocHandler(AppleEvent *theAppleEvent, AppleEvent reply, long refCon)
{
AEDescList docList;
OSErr theErr;
long index, itemsInList;
Size actualSize;
AEKeyword keywd;
DescType returnedType;
FSSpec theFSS;
// In response to this event, we must open all documents specified in
// the Apple Event.
AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
// check for missing required parameters
theErr = GotRequiredParams(theAppleEvent);
if (theErr != noErr)
return AEDisposeDesc(&docList);
// count the number of descriptor records in the list
theErr = AECountItems(&docList, &itemsInList);
// get each descriptor record from the list, coerce the returned
// data to an FSSpec record, and open the associated file
index = 1;
if (index <= itemsInList) {
AEGetNthPtr(&docList, index, typeFSS, &keywd, &returnedType,
(Ptr)&theFSS, sizeof(theFSS), &actualSize);
// open FSSpec
OpenPending = TRUE;
SaveFileVol = theFSS.vRefNum;
SaveFileParID = theFSS.parID;
SaveFileName = (Byte *)&Reply.fName;
memcpy(&Reply.fName,&theFSS.name,*theFSS.name+1);
}
AEDisposeDesc(&docList);
return noErr;
}
static pascal OSErr AEPrintHandler(AppleEvent *theAppleEvent, AppleEvent reply, long refCon)
{
AEDescList docList;
OSErr theErr;
long index, itemsInList;
Size actualSize;
AEKeyword keywd;
DescType returnedType;
FSSpec theFSS;
// In response to this event, we must print all documents specified in
// the Apple Event.
theErr = AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList);
// check for missing required parameters
theErr = GotRequiredParams(theAppleEvent);
if (theErr != noErr)
return AEDisposeDesc(&docList);
// count the number of descriptor records in the list
theErr = AECountItems(&docList, &itemsInList);
// get each descriptor record from the list, coerce the returned
// data to an FSSpec record, and open the associated file
for (index = 1; index <= itemsInList; index++)
{
theErr = AEGetNthPtr(&docList, index, typeFSS, &keywd, &returnedType,
(Ptr)&theFSS, sizeof(theFSS), &actualSize);
// print FSSpec <no printing in this application>
}
AEDisposeDesc(&docList);
return noErr;
}
/* Standard Quit event handler, to handle a Quit event from the Finder, for example.
Note that we may not exit from the AppleEvent handler! We have to set a flag,
and exit from within the normal application code. */
static pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
QuitFlag = 1; /* I quit! */
return noErr;
}
/* InitAEStuff installs my appleevent handlers */
void InitAEStuff(void);
static AEinstalls HandlersToInstall[] = {
{kCoreEventClass, kAEOpenApplication,AEOpenHandler,0},
{kCoreEventClass, kAEOpenDocuments, AEOpenDocHandler,0},
{kCoreEventClass, kAEQuitApplication, AEQuitHandler,0},
{kCoreEventClass, kAEPrintDocuments, AEPrintHandler,0}
};
void InitAEStuff(void)
{
Word i;
/* Check this machine for AppleEvents. If they are not here (ie not 7.0)
* then we return. */
#ifndef __powerc
long aLong;
short Code,Count;
short Index;
AppFile Stuff;
/* This is for the WONDERFUL system 6.0.7 filenames */
/* Only execute on 680x0 macs */
CountAppFiles(&Code,&Count);
for (Index=1;Index<=Count;++Count) {
GetAppFiles(Index,&Stuff);
if (Index==1) {
OpenPending = TRUE;
SaveFileVol = Stuff.vRefNum;
SaveFileName = (Byte *)&Reply.fName;
memcpy(&Reply.fName,&Stuff.fName,*Stuff.fName+1);
GetWDInfo(SaveFileVol,&SaveFileVol,&SaveFileParID,&aLong);
}
ClrAppFiles(Index);
}
if (Gestalt(gestaltAppleEventsAttr, &aLong)) { /* Are Apple events present? */
return;
}
if (!(aLong & (1<<gestaltAppleEventsPresent))) {
return;
}
#endif
/* The following series of calls installs all our AppleEvent Handlers.
* These handlers are added to the application event handler list that
* the AppleEvent manager maintains. So, whenever an AppleEvent happens
* and we call AEProcessEvent, the AppleEvent manager will check our
* list of handlers and dispatch to it if there is one.
*/
i = 0;
do {
HandlersToInstall[i].theProc = NewAEEventHandlerProc(HandlersToInstall[i].Code);
AEInstallEventHandler(HandlersToInstall[i].theClass, HandlersToInstall[i].theEvent,
HandlersToInstall[i].theProc,0,FALSE);
} while (++i<4);
}
#endif
/**********************************
Make the cursor disappear if needed
**********************************/
static void FixTheCursor(void)
{
InitCursor();
if (MouseEnabled && !InPause) {
HideCursor();
}
}
/**********************************
Show a watch cursor
**********************************/
static void WaitCursor(void)
{
SetCursor(*WatchHandle);
}
CC = gcc
#CFLAGS = -Wall -O6 -fomit-frame-pointer -ffast-math -funroll-loops -mpentiumpro -mcpu=pentiumpro -march=pentiumpro
#CFLAGS = -g -Wall
CFLAGS = -g
#CFLAGS = -Os
#CFLAGS = -g -Wall -I/home/relnev/cvs/oal/include
OBJS = Data.o Doors.o EnMove.o EnThink.o InterMis.o Intro.o Level.o \
Missiles.o Music.o PlMove.o PlStuff.o PlThink.o PushWall.o \
RefBsp.o RefSprite.o Refresh.o Refresh2.o Sight.o Main.o \
StateDef.o WolfMain.o WolfIO.o Burger.o
SOBJS = $(OBJS)
XOBJS = $(OBJS)
GOBJS = $(OBJS)
LFLAGS = -lm
#LFLAGS = -lm -L/home/relnev/cvs/oal/linux/src -lopenal -lpthread -ldl
SLFLAGS = $(LFLAGS) -lvga
XLFLAGS = $(LFLAGS) -L/usr/X11R6/lib -lX11 -lXext -lXxf86vm -lXxf86dga
GLFLAGS = $(LFLAGS) -L/usr/X11R6/lib -lX11 -lXext -lGL
NASM = nasm
.SUFFIXES: .asm
all: swolf3d xwolf3d gwolf3d
$(SOBJS):
$(XOBJS):
$(GOBJS):
.asm.o:
$(NASM) -f elf -o $@ $<
swolf3d: $(SOBJS)
gcc -o swolf3d $(SOBJS) $(SLFLAGS)
xwolf3d: $(XOBJS)
gcc -o xwolf3d $(XOBJS) $(XLFLAGS)
gwolf3d: $(GOBJS)
gcc -o gwolf3d $(GOBJS) $(GLFLAGS)
clean:
rm -rf swolf3d xwolf3d gwolf3d *.o
distclean: clean
rm -rf *~ DEADJOE
forced: distclean all
rm -rf *.o
#include "WolfDef.h"
#include <Palettes.h>
#include <gestalt.h>
#include "PickAMonitor.h"
#define PAMStrings 2001
#define NoColorString 1
#define NoDepthString 2
#define NoSizeString 3
#define NoProblemString 4
void CheckMonitor(DialogPtr theWindow, int bitDepth, Boolean colorRequired, short minWidth, short minHeight);
void OutlineOK(DialogPtr theDialog, Boolean enabled);
/**********************************
Take a window pointer and center it onto the
current video device
**********************************/
void CenterWindowOnMonitor(WindowPtr theWindow, GDHandle theMonitor)
{
short newH, newV;
Rect mRect;
mRect = (**theMonitor).gdRect; /* Get the rect of the monitor */
/* Find the difference between the two monitors' sizes */
newH = (mRect.right - mRect.left) - (theWindow->portRect.right - theWindow->portRect.left);
newV = (mRect.bottom - mRect.top) - (theWindow->portRect.bottom - theWindow->portRect.top);
/* Half the difference so that it's centered top-to-bottom and left-to-right */
/* Add that offset to the upper-left of the monitor */
MoveWindow(theWindow,(newH>>1)+mRect.left,(newV>>1)+mRect.top,TRUE); /* Move and bring to front */
}
/**********************************
Returns true if the device supports color
**********************************/
Boolean SupportsColor(GDHandle theMonitor)
{
return TestDeviceAttribute(theMonitor,gdDevType); /* Is it color? */
}
/**********************************
Returns true if the device supports a specific color depth
**********************************/
short SupportsDepth(GDHandle theMonitor, int theDepth, Boolean needsColor)
{
return HasDepth(theMonitor,theDepth,1<<gdDevType,needsColor);
}
/**********************************
Returns true if the device supports a specific video size
**********************************/
Boolean SupportsSize(GDHandle theMonitor, short theWidth, short theHeight)
{
Rect theRect;
/* Grab the dimensions of the monitor */
theRect = (**theMonitor).gdRect;
/* Offset it to (0, 0) references */
OffsetRect(&theRect, -theRect.left, -theRect.top);
/* Check the dimensions to see if they are large enough */
if ((theRect.right < theWidth) || (theRect.bottom < theHeight)) {
return FALSE; /* No good! */
}
return TRUE;
}
/**********************************
Return the GDevice from a specific quickdraw point
**********************************/
GDHandle MonitorFromPoint(Point *thePoint)
{
GDHandle theMonitor;
/* Loop through the list of monitors to see one encompasses the point */
theMonitor = GetDeviceList(); /* Get the first monitor */
do {
if (PtInRect(*thePoint,&(**theMonitor).gdRect)) { /* Is this it? */
break; /* Exit now */
}
theMonitor = GetNextDevice(theMonitor); /* Get the next device in list */
} while (theMonitor); /* All done now? */
/* Just in case some weird evil happened, return a fail value (THEORETICALLY can't happen) */
return theMonitor;
}
// ---------------------------------------- PickAMonitor
GDHandle PickAMonitor(int theDepth, Boolean colorRequired, short minWidth, short minHeight)
{
GDHandle theMonitor;
GDHandle tempMonitor;
Point thePoint;
EventRecord theEvent;
DialogPtr theDialog;
short itemHit;
char theChar;
Word validCount;
GrafPtr savedPort;
/* Loop through the monitor list once to make sure there is at least one good monitor */
theMonitor = GetDeviceList(); /* Get the first monitor */
tempMonitor = 0; /* No monitor found */
validCount = 0; /* None found */
do {
if (colorRequired && !SupportsColor(theMonitor)) { /* Check for color? */
continue;
}
if (!SupportsDepth(theMonitor, theDepth, colorRequired)) { /* Check for bit depth */
continue;
}
if (!SupportsSize(theMonitor, minWidth, minHeight)) { /* Check for monitor size */
continue;
}
tempMonitor = theMonitor; /* Save the valid record */
++validCount; /* Inc the count */
} while ((theMonitor = GetNextDevice(theMonitor)) != 0);
/* If there was only one valid monitor, goodMonitor will be referencing it. Return it immediately. */
if (validCount == 1) {
return (tempMonitor); /* Exit now */
}
/* If there are no valid monitors then put up a dialog saying so. Then return nil. */
if (!validCount) {
StopAlert(2001, nil);
return 0;
}
// Start an event loop going. Rather than using modalDialog with a gnarly filter, we'll just display the dialog
// then use a gnarly event loop to accommodate it. This will go on until the user selects either "This Monitor"
// (ok) or "Quit" (cancel).
theDialog = GetNewDialog(2000, nil, (WindowPtr) -1L);
CenterWindowOnMonitor((WindowPtr) theDialog, GetMainDevice());
InitCursor();
GetPort(&savedPort);
SetPort(theDialog);
ShowWindow(theDialog);
CheckMonitor(theDialog, theDepth, colorRequired, minWidth, minHeight);
do {
itemHit = 0;
/* Get next event from the event queue */
if (WaitNextEvent2(everyEvent&(~highLevelEventMask), &theEvent, 30, nil)) {
switch (theEvent.what) {
case keyDown:
theChar = theEvent.message & charCodeMask;
if ((theEvent.modifiers & cmdKey) && ((theChar == '.') || (theChar == 'q') || (theChar == 'Q'))) {
itemHit = cancel;
break;
}
if (theChar == 0x1B) {
itemHit = cancel;
break;
}
if ((theChar == 0x0D) || (theChar == 0x03)) {
itemHit = ok;
break;
}
break;
// Did we mouse-down in the dialogs drag-bar?
case mouseDown:
if (FindWindow(theEvent.where, (WindowPtr *) &theDialog) == inDrag)
{
DragWindow((WindowPtr) theDialog, theEvent.where, &qd.screenBits.bounds);
GetMouse(&thePoint);
LocalToGlobal(&thePoint);
tempMonitor = MonitorFromPoint(&thePoint);
CenterWindowOnMonitor((WindowPtr) theDialog, tempMonitor);
CheckMonitor(theDialog, theDepth, colorRequired, minWidth, minHeight);
break;
}
default:
// If not, perform regular dialog event processing
DialogSelect(&theEvent, &theDialog, &itemHit);
}
}
} while ((itemHit != ok) && (itemHit != cancel));
// Ok, the dialog is still the active grafport so all coordinates are in its local system. If I define a point
// as (0, 0) now it will be the upper left corner of the dialog's drawing area. I then turn this to a global screen
// coordinate and call GetMonitorFromPoint.
SetPt(&thePoint, 0, 0);
LocalToGlobal(&thePoint);
theMonitor = MonitorFromPoint(&thePoint);
// Restore our current graphics environment and return the monitor reference.
SetPort(savedPort);
DisposeDialog(theDialog);
if (itemHit == ok) {
return (theMonitor);
}
return (nil);
}
// ---------------------------------------- CheckMonitor
void CheckMonitor(DialogPtr theDialog, int bitDepth, Boolean colorRequired, short minWidth, short minHeight)
{
GDHandle theMonitor;
Point thePoint;
short theType;
Handle theHandle;
Rect theRect;
Str255 message;
Boolean badMonitor = FALSE;
GrafPtr savedPort;
GetPort(&savedPort);
SetPort((WindowPtr) theDialog);
SetPt(&thePoint, 0, 0);
LocalToGlobal(&thePoint);
theMonitor = MonitorFromPoint(&thePoint);
GetDialogItem(theDialog, 4, &theType, &theHandle, &theRect);
if (colorRequired && ! SupportsColor(theMonitor)) {
GetIndString(message, PAMStrings, NoColorString);
SetDialogItemText(theHandle, message);
badMonitor = TRUE;
}
if (!SupportsDepth(theMonitor, bitDepth, colorRequired)) {
GetIndString(message, PAMStrings, NoDepthString);
SetDialogItemText(theHandle, message);
badMonitor = TRUE;
}
if (! SupportsSize(theMonitor, minWidth, minHeight)) {
GetIndString(message, PAMStrings, NoDepthString);
SetDialogItemText(theHandle, message);
badMonitor = TRUE;
}
SetPort(savedPort);
if (badMonitor) {
// Gray-out the "This Monitor" button
GetDialogItem(theDialog, ok, &theType, &theHandle, &theRect);
HiliteControl((ControlHandle) theHandle, 255);
OutlineOK(theDialog, FALSE);
BeginUpdate((WindowPtr) theDialog);
UpdateDialog(theDialog, theDialog->visRgn);
EndUpdate((WindowPtr) theDialog);
return;
}
// Activate the "This Monitor" button and put up the no problem text.
GetIndString(message, PAMStrings, NoProblemString);
SetDialogItemText(theHandle, message);
GetDialogItem(theDialog, ok, &theType, &theHandle, &theRect);
HiliteControl((ControlHandle) theHandle, 0);
OutlineOK(theDialog, TRUE);
BeginUpdate((WindowPtr) theDialog);
UpdateDialog(theDialog, theDialog->visRgn);
EndUpdate((WindowPtr) theDialog);
}
// ---------------------------------------- OutlineOK
void OutlineOK(DialogPtr theDialog, Boolean enabled)
{
GrafPtr savedPort;
ColorSpec saveColor;
PenState savedState;
short theType;
Handle theHandle;
Rect theRect;
GetPenState(&savedState);
PenMode(patCopy);
PenSize(2, 2);
SaveFore(&saveColor);
ForeColor(blackColor);
GetPort(&savedPort);
SetPort((WindowPtr) theDialog);
GetDialogItem(theDialog, ok, &theType, &theHandle, &theRect);
InsetRect(&theRect, -4, -4);
if (enabled)
PenPat(&qd.black);
else
PenPat(&qd.gray);
FrameRoundRect(&theRect, 16, 16);
SetPort(savedPort);
RestoreFore(&saveColor);
SetPenState(&savedState);
}
extern void CenterWindowOnMonitor(WindowPtr theWindow, GDHandle theMonitor);
extern Boolean SupportsColor(GDHandle theMonitor);
extern short SupportsDepth(GDHandle theMonitor, int theDepth, Boolean needsColor);
extern Boolean SupportsSize(GDHandle theMonitor, short theWidth, short theHeight);
extern GDHandle MonitorFromPoint(Point *thePoint);
extern GDHandle PickAMonitor(int bitDepth, Boolean colorRequired, short minWidth, short minHeight);
extern Boolean WaitNextEvent2(short EventMask,EventRecord *theEvent,long sleep,RgnHandle mouseRgn);
\ No newline at end of file
void InitPrefsFile(OSType creator,Byte *PrefsName);
OSErr LoadPrefsFile(Byte *PrefsPtr,Word PrefsLen);
OSErr SavePrefsFile(Byte *PrefsPtr,Word PrefsLen);
#include <Folders.h>
#include <Gestalt.h>
#include <Processes.h>
#include "Wolfdef.h"
#include <String.h>
#include "prefs.h"
typedef struct {
Byte fileName[34]; /* Enough space for filename */
OSType creator; /* Creator TYPE */
OSType fileType; /* File type */
OSType resType; /* Resource type */
short resID; /* Open resource file ID */
} PrefsInfo;
static PrefsInfo prefsInfo; /* My internal prefs record */
static Boolean prefsInited = FALSE; /* Is the struct valid? */
/**********************************
I miss the Apple IIgs where all you need to set the prefs directory
was to pass a filename of "@:Prefs file" and it will automatically place
the prefs file in either the proper Network folder or system prefs folder...
Instead I have to do this bullshit to scan the volumes to find the prefs
folder and volume...
If the file was not found, then create it.
return TRUE if the file was found and could not be created
**********************************/
static Boolean FindPrefsFile(short *prefVRefNum, long *prefDirID)
{
OSErr theErr;
long response;
CInfoPBRec infoPB;
if (!prefsInited) { /* Only look if the prefs structure is valid */
return FALSE; /* Exit NOW! */
}
/* First, try it the easy way... */
if ( !Gestalt(gestaltFindFolderAttr, &response) && /* Is the easy way available? */
( (1<<gestaltFindFolderPresent) & response)) {
/* Call the OS to do the dirty work */
theErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
prefVRefNum, prefDirID);
/* OK, try it the hard way... :( */
} else {
SysEnvRec theSysEnv;
StringPtr prefFolderName = "\pPreferences";
/* yeachh -- we have to do it all by hand! */
if (SysEnvirons(1, &theSysEnv)) { /* Is the system disk present? */
return FALSE; /* Forget it! */
}
*prefVRefNum = theSysEnv.sysVRefNum; /* Save off the boot volume ID */
/* check whether Preferences folder already exists */
infoPB.hFileInfo.ioCompletion = 0; /* Wait for completion */
infoPB.hFileInfo.ioNamePtr = prefFolderName; /* Get folder name */
infoPB.hFileInfo.ioVRefNum = *prefVRefNum; /* Pass the volume # */
infoPB.hFileInfo.ioFDirIndex = 0; /* Scan directories */
infoPB.hFileInfo.ioDirID = 0; /* Init dir id */
theErr = PBGetCatInfo(&infoPB, FALSE); /* Get the catalog info */
if (!theErr) {
*prefDirID = infoPB.hFileInfo.ioDirID; /* Return the folder id */
} else if (theErr == fnfErr) { /* Preferences doesn't already exist */
HParamBlockRec dirPB;
/* create "Preferences" folder */
dirPB.fileParam.ioCompletion = 0;
dirPB.fileParam.ioVRefNum = *prefVRefNum;
dirPB.fileParam.ioNamePtr = prefFolderName;
dirPB.fileParam.ioDirID = 0;
theErr = PBDirCreate(&dirPB, FALSE); /* Create the folder */
if (!theErr) {
*prefDirID = dirPB.fileParam.ioDirID; /* Save the ID */
}
}
}
/* if we make it here OK, create Preferences file if necessary */
if (!theErr) {
infoPB.hFileInfo.ioCompletion = 0;
infoPB.hFileInfo.ioNamePtr = prefsInfo.fileName;
infoPB.hFileInfo.ioVRefNum = *prefVRefNum;
infoPB.hFileInfo.ioFDirIndex = 0;
infoPB.hFileInfo.ioDirID = *prefDirID;
theErr = PBGetCatInfo(&infoPB, FALSE); /* Get the file info */
if (theErr == fnfErr) { /* Not present? */
theErr = HCreate(*prefVRefNum, *prefDirID, prefsInfo.fileName,
prefsInfo.creator, prefsInfo.fileType);
if (!theErr) {
HCreateResFile(*prefVRefNum, *prefDirID, prefsInfo.fileName);
theErr = ResError(); /* Was there an error? */
}
}
}
return (!theErr);
}
/**********************************
Init the record for the "Prefs" file
All this does is preset the prefsfile structure
for the filename of the prefs file.
**********************************/
void InitPrefsFile(OSType creator,Byte *PrefsName)
{
Word FLen;
FLen = strlen((char *)PrefsName); /* How long is the string? */
prefsInfo.fileName[0] = FLen; /* Make a PASCAL string */
BlockMove(PrefsName,&prefsInfo.fileName[1],FLen); /* Copy the bulk */
prefsInfo.creator = creator; /* 4 Letter creator filetype */
prefsInfo.fileType = 'PREF'; /* Pref's filetype */
prefsInfo.resType = 'PREF'; /* Pref's resource */
prefsInfo.resID = 0; /* No resource ID assigned yet */
prefsInited = TRUE; /* All numbers are set... */
}
/**********************************
Load in a prefs file and store it
into a passed pointer IF the file was
loaded properly.
Return any error codes.
**********************************/
OSErr LoadPrefsFile(Byte *PrefsPtr,Word PrefsLen)
{
short prefVRefNum, prefRefNum;
long prefDirID;
Handle origHdl;
LongWord origSize;
if (!FindPrefsFile(&prefVRefNum, &prefDirID)) { /* Search for the file */
return fnfErr; /* File was NOT found error */
}
prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
if (prefRefNum == -1) { /* Resource error? */
return ResError(); /* Return the resource manager error */
}
/* Not finding the resource is not an error -- caller will use default data */
origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID);
if (origHdl) { /* Valid handle? */
origSize = GetHandleSize(origHdl); /* How much data is here? */
if (origSize < PrefsLen) { /* Less data than expected? */
PrefsLen = origSize; /* Use the smaller size */
}
BlockMove(*origHdl,PrefsPtr,PrefsLen); /* Copy the NEW prefs data */
ReleaseResource(origHdl); /* Release the data */
}
CloseResFile(prefRefNum); /* Close the resource file */
return ResError(); /* Return any errors */
}
/**********************************
Save data for a new prefs file
**********************************/
OSErr SavePrefsFile(Byte *PrefsPtr,Word PrefsLen)
{
short prefVRefNum, prefRefNum;
long prefDirID;
Handle origHdl;
LongWord origSize;
OSErr theErr = noErr;
if (!FindPrefsFile(&prefVRefNum, &prefDirID)) { /* File not present? */
return fnfErr; /* File not found error */
}
prefRefNum = HOpenResFile(prefVRefNum, prefDirID, prefsInfo.fileName, fsRdWrPerm);
if (prefRefNum == -1) { /* Bad resource fork? */
return ResError(); /* Return the error */
}
origHdl = Get1Resource(prefsInfo.resType, prefsInfo.resID); /* Get the resource */
if (origHdl) { /* Overwrite the existing resource */
origSize = GetHandleSize(origHdl); /* How large is it? */
if (PrefsLen != origSize) { /* Different size? */
SetHandleSize(origHdl, PrefsLen); /* Set the new size */
}
BlockMove(PrefsPtr,*origHdl,PrefsLen); /* Copy the data */
ChangedResource(origHdl); /* Mark as changed */
WriteResource(origHdl); /* Save to disk */
ReleaseResource(origHdl); /* Release it */
} else {
/* store specified preferences for the first time */
origHdl = NewHandle(PrefsLen); /* Make some temp memory */
if (origHdl) {
BlockMove(PrefsPtr,*origHdl,PrefsLen);
AddResource(origHdl, prefsInfo.resType, prefsInfo.resID, "\p");
WriteResource(origHdl); /* Write to disk */
ReleaseResource(origHdl); /* Release it */
}
}
CloseResFile(prefRefNum); /* Close the resource file */
if (!theErr) { /* No errors? */
return ResError(); /* Return any resource error */
}
return theErr; /* Return the last error */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment