]> git.jsancho.org Git - lugaru.git/blob - Source/OpenGL_Full_Screen.cpp
Find Vorbis via CMake instead of just assuming it's installed
[lugaru.git] / Source / OpenGL_Full_Screen.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22 #include "Game.h"
23 #include "nommgr.h"
24
25 extern bool buttons[3];
26 extern float multiplier;
27 extern float screenwidth,screenheight;
28 extern float sps;
29 extern float realmultiplier;
30 extern int slomo;
31 extern bool ismotionblur;
32 extern float usermousesensitivity;
33 extern int detail;
34 extern bool floatjump;
35 extern bool cellophane;
36 extern int terraindetail;
37 extern int texdetail;
38 extern int bloodtoggle;
39 extern bool osx;
40 extern bool autoslomo;
41 extern bool foliage;
42 extern bool musictoggle;
43 extern bool trilinear;
44 extern float gamespeed;
45 extern int difficulty;
46 extern bool damageeffects;
47 extern int numplayers;
48 extern bool decals;
49 extern bool invertmouse;
50 extern bool texttoggle;
51 extern bool ambientsound;
52 extern bool mousejump;
53 extern bool freeze;
54 extern Person player[maxplayers];
55 extern bool vblsync;
56 extern bool stillloading;
57 extern bool showpoints;
58 extern bool alwaysblur;
59 extern bool immediate;
60 extern bool velocityblur;
61 extern bool debugmode;
62 extern int mainmenu;
63 extern int kBitsPerPixel;
64 extern float slomospeed;
65 extern float slomofreq;
66 extern float oldgamespeed;
67
68  #define kUseAGLFullScreenX 1
69  #define kUseFades 1
70  
71 // system includes ----------------------------------------------------------
72
73 #ifdef __APPLE_CC__
74     #include "Carbon Include.h"
75     #include <Carbon/Carbon.h>
76     
77     #include <DrawSprocket/DrawSprocket.h>
78         #include <AGL/agl.h>
79         #include <AGL/aglRenderers.h>
80         #include <OpenGL/gl.h>
81         #include <OpenGL/glu.h>
82 #else
83     #include <DrawSprocket.h>
84     
85     #include <Devices.h>
86     #include <Dialogs.h>
87     #include <DriverServices.h>
88     #include <Events.h>
89     #include <Gestalt.h>
90     #include <LowMem.h>
91     #include <Sound.h>
92     #include <TextEdit.h>
93     #include <ToolUtils.h>
94     #include <Windows.h>
95
96     // profile
97     #include <Profiler.h>
98
99         #include "agl.h"
100     #include "gamegl.h"
101         #include "glu.h"
102 #endif
103
104 #include <math.h>
105 #include <stdio.h>
106 #include <string.h>
107 #include <Folders.h>
108 #include <fstream.h>
109  
110 // project includes ---------------------------------------------------------
111
112 #include "aglString.h"
113 #include "MacInput.h"
114
115 // functions (internal/private) ---------------------------------------------
116
117 static UInt32 CheckMacOSX (void);
118 void CToPStr (StringPtr outString, const char *inString);
119 void ReportError (char * strError);
120 OSStatus DSpDebugStr (OSStatus error);
121 GLenum aglDebugStr (void);
122 GLenum glDebugStr (void);
123
124 CGrafPtr SetupDSpFullScreen (GDHandle hGD);
125 void ShutdownDSp (CGrafPtr pDSpPort);
126
127 AGLContext SetupAGL (GDHandle hGD, AGLDrawable win);
128 AGLContext SetupAGLFullScreen (GDHandle display, short * pDepth, short * pWidth, short * pHeight);
129 void CleanupAGL (AGLContext ctx);
130 void DrawGL (Rect * pRectPort);
131
132 void InitToolbox(void);
133 void CreateGLWindow (void);
134 Boolean SetUp (void);
135 void DoMenu (SInt32 menuResult);
136 void DoKey (SInt8 theKey, SInt8 theCode);
137 void DoUpdate (void);
138
139 pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData);
140 EventLoopTimerUPP GetTimerUPP (void);
141 static Boolean RunningOnCarbonX(void);
142
143 void DoEvent (void);
144 void CleanUp (void);
145
146 // profile wrappers
147 Boolean WaitNextEventWrapper (EventMask eventMask, EventRecord *theEvent, unsigned long sleep,RgnHandle mouseRgn);
148 OSStatus DSpProcessEventWrapper (EventRecord *inEvent, Boolean *outEventWasProcessed);
149 void UpdateWrapper (EventRecord *theEvent);
150
151 // statics/globals (internal only) ------------------------------------------
152
153 Point delta;
154
155 // Menu defs
156 enum 
157 {
158         kMenuApple = 128,
159         kMenuFile = 129,
160         
161         kAppleAbout = 1,
162         kFileQuit = 1
163 };
164
165 enum 
166 {
167         kForegroundSleep = 10,
168         kBackgroundSleep = 10000
169 };
170 EventLoopTimerRef gTimer = NULL;
171
172 int kContextWidth;
173 int kContextHeight;
174
175 const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
176
177 NumVersion gVersionDSp;
178 DSpContextAttributes gContextAttributes;
179 DSpContextReference gContext = 0;
180 extern AGLContext gaglContext;
181 GLuint gFontList;
182 char gcstrMode [256] = "";
183
184 AGLDrawable gpDSpPort = NULL; // will be NULL for full screen under X
185 Rect gRectPort = {0, 0, 0, 0};
186
187 UInt32 gSleepTime = kForegroundSleep;
188 Boolean gDone = false, gfFrontProcess = true;
189
190 Game game;
191
192 // profile
193 #if __profile__
194 OSErr gProfErr = noErr;
195 #endif
196
197 #pragma mark -
198
199 //-----------------------------------------------------------------------------------------------------------------------
200
201 // are we running on Mac OS X
202 // returns 0 if < Mac OS X or version number of Mac OS X (10.0 for GM)
203
204 static UInt32 CheckMacOSX (void)
205 {
206         UInt32 response;
207     
208         if ((Gestalt(gestaltSystemVersion, (SInt32 *) &response) == noErr) && (response >= 0x01000))
209                 return response;
210         else
211                 return 0;
212 }
213
214 //-----------------------------------------------------------------------------------------------------------------------
215
216 // Copy C string to Pascal string
217
218 void CToPStr (StringPtr outString, const char *inString)
219 {       
220         unsigned char x = 0;
221         do
222                 *(((char*)outString) + x + 1) = *(inString + x++);
223         while ((*(inString + x) != 0)  && (x < 256));
224         *((char*)outString) = (char) x;                                                                 
225 }
226
227 // --------------------------------------------------------------------------
228
229 void ReportError (char * strError)
230 {
231         char errMsgCStr [256];
232         Str255 strErr;
233
234         sprintf (errMsgCStr, "%s", strError); 
235
236         // out as debug string
237         CToPStr (strErr, errMsgCStr);
238         DebugStr (strErr);
239 }
240
241 //-----------------------------------------------------------------------------------------------------------------------
242
243 OSStatus DSpDebugStr (OSStatus error)
244 {
245         switch (error)
246         {
247                 case noErr:
248                         break;
249                 case kDSpNotInitializedErr:
250                         ReportError ("DSp Error: Not initialized");
251                         break;
252                 case kDSpSystemSWTooOldErr:
253                         ReportError ("DSp Error: system Software too old");
254                         break;
255                 case kDSpInvalidContextErr:
256                         ReportError ("DSp Error: Invalid context");
257                         break;
258                 case kDSpInvalidAttributesErr:
259                         ReportError ("DSp Error: Invalid attributes");
260                         break;
261                 case kDSpContextAlreadyReservedErr:
262                         ReportError ("DSp Error: Context already reserved");
263                         break;
264                 case kDSpContextNotReservedErr:
265                         ReportError ("DSp Error: Context not reserved");
266                         break;
267                 case kDSpContextNotFoundErr:
268                         ReportError ("DSp Error: Context not found");
269                         break;
270                 case kDSpFrameRateNotReadyErr:
271                         ReportError ("DSp Error: Frame rate not ready");
272                         break;
273                 case kDSpConfirmSwitchWarning:
274 //                      ReportError ("DSp Warning: Must confirm switch"); // removed since it is just a warning, add back for debugging
275                         return 0; // don't want to fail on this warning
276                         break;
277                 case kDSpInternalErr:
278                         ReportError ("DSp Error: Internal error");
279                         break;
280                 case kDSpStereoContextErr:
281                         ReportError ("DSp Error: Stereo context");
282                         break;
283         }
284         return error;
285 }
286
287 //-----------------------------------------------------------------------------------------------------------------------
288
289 // if error dump agl errors to debugger string, return error
290
291 GLenum aglDebugStr (void)
292 {
293         GLenum err = aglGetError();
294         if (AGL_NO_ERROR != err)
295                 ReportError ((char *)aglErrorString(err));
296         return err;
297 }
298
299 //-----------------------------------------------------------------------------------------------------------------------
300
301 // if error dump agl errors to debugger string, return error
302
303 GLenum glDebugStr (void)
304 {
305         GLenum err = glGetError();
306         if (GL_NO_ERROR != err)
307                 ReportError ((char *)gluErrorString(err));
308         return err;
309 }
310
311 #pragma mark -
312 //-----------------------------------------------------------------------------------------------------------------------
313
314 // Set up DSp screen on graphics device requested
315 // side effect: sets both gpDSpWindow and gpPort
316
317 CGrafPtr SetupDSpFullScreen (GDHandle hGD)
318 {
319         DSpContextAttributes foundAttributes;
320         DisplayIDType displayID = NULL;
321         
322         if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpGetVersion) 
323         {
324                 ReportError ("DrawSprocket not installed.");
325                 return NULL;
326         }
327         else
328                 gVersionDSp = DSpGetVersion ();
329
330         if ((gVersionDSp.majorRev == 0x01) && (gVersionDSp.minorAndBugRev < 0x99))
331         {
332                 // this version of DrawSprocket is not completely functional on Mac OS X
333                 if (CheckMacOSX ())
334                 {
335                         ReportError ("DrawSprocket 1.99 or greate required on Mac OS X, please update to at least Mac OS X 10.1.");
336                         return NULL;
337                 }
338         }
339                         
340         // Note: DSp < 1.7.3 REQUIRES the back buffer attributes even if only one buffer is required
341         memset(&gContextAttributes, 0, sizeof (DSpContextAttributes));
342         gContextAttributes.displayWidth                 = kContextWidth;
343         gContextAttributes.displayHeight                = kContextHeight;
344         gContextAttributes.colorNeeds                   = kDSpColorNeeds_Require;
345         gContextAttributes.displayBestDepth             = kBitsPerPixel;
346         gContextAttributes.backBufferBestDepth  = kBitsPerPixel;
347         gContextAttributes.displayDepthMask             = kDSpDepthMask_All;
348         gContextAttributes.backBufferDepthMask  = kDSpDepthMask_All;
349         gContextAttributes.pageCount                    = 1;                                                            // only the front buffer is needed
350         
351         screenwidth=kContextWidth;
352         screenheight=kContextHeight;
353         
354         DMGetDisplayIDByGDevice (hGD, &displayID, true);
355         
356         if (noErr != DSpDebugStr (DSpFindBestContextOnDisplayID (&gContextAttributes, &gContext, displayID)))
357         {
358                 ReportError ("DSpFindBestContext() had an error.");
359                 return NULL;
360         }
361
362         if (noErr != DSpDebugStr (DSpContext_GetAttributes (gContext, &foundAttributes))) // see what we actually found
363         {
364                 ReportError ("DSpContext_GetAttributes() had an error.");
365                 return NULL;
366         }
367
368         // reset width and height to full screen and handle our own centering
369         // HWA will not correctly center less than full screen size contexts
370         gContextAttributes.displayWidth         = foundAttributes.displayWidth;
371         gContextAttributes.displayHeight        = foundAttributes.displayHeight;
372         gContextAttributes.pageCount            = 1;                                                                    // only the front buffer is needed
373         gContextAttributes.contextOptions       = 0 | kDSpContextOption_DontSyncVBL;    // no page flipping and no VBL sync needed
374
375         DSpSetBlankingColor(&rgbBlack);
376
377         if (noErr !=  DSpDebugStr (DSpContext_Reserve ( gContext, &gContextAttributes))) // reserve our context
378         {
379                 ReportError ("DSpContext_Reserve() had an error.");
380                 return NULL;
381         }
382  
383         HideCursor ();
384
385         if (noErr != DSpDebugStr (DSpContext_SetState (gContext, kDSpContextState_Active))) // activate our context
386         {
387                 ReportError ("DSpContext_SetState() had an error.");
388                 return NULL;
389         }
390
391
392         if ((CheckMacOSX ()) && !((gVersionDSp.majorRev > 0x01) || ((gVersionDSp.majorRev == 0x01) && (gVersionDSp.minorAndBugRev >= 0x99))))// DSp should be supported in version after 1.98
393         {
394                 ReportError ("Mac OS X with DSp < 1.99 does not support DrawSprocket for OpenGL full screen");
395                 return NULL;
396         }
397         else if (CheckMacOSX ()) // DSp should be supported in versions 1.99 and later
398         {
399                 CGrafPtr pPort;
400                 // use DSp's front buffer on Mac OS X
401                 if (noErr != DSpDebugStr (DSpContext_GetFrontBuffer (gContext, &pPort)))
402                 {
403                         ReportError ("DSpContext_GetFrontBuffer() had an error.");
404                         return NULL;
405                 }
406                 // there is a problem in Mac OS X 10.0 GM CoreGraphics that may not size the port pixmap correctly
407                 // this will check the vertical sizes and offset if required to fix the problem
408                 // this will not center ports that are smaller then a particular resolution
409                 {
410                         long deltaV, deltaH;
411                         Rect portBounds;
412                         PixMapHandle hPix = GetPortPixMap (pPort);
413                         Rect pixBounds = (**hPix).bounds;
414                         GetPortBounds (pPort, &portBounds);
415                         deltaV = (portBounds.bottom - portBounds.top) - (pixBounds.bottom - pixBounds.top) +
416                                  (portBounds.bottom - portBounds.top - kContextHeight) / 2;
417                         deltaH = -(portBounds.right - portBounds.left - kContextWidth) / 2;
418                         if (deltaV || deltaH)
419                         {
420                                 GrafPtr pPortSave;
421                                 GetPort (&pPortSave);
422                                 SetPort ((GrafPtr)pPort);
423                                 // set origin to account for CG offset and if requested drawable smaller than screen rez
424                                 SetOrigin (deltaH, deltaV);
425                                 SetPort (pPortSave);
426                         }
427                 }
428                 return pPort;
429         }
430         else // Mac OS 9 or less
431         {
432                 WindowPtr pWindow;
433                 Rect rectWin;
434                 RGBColor rgbSave;
435                 GrafPtr pGrafSave;
436                 // create a new window in our context 
437                 // note: OpenGL is expecting a window so it can enumerate the devices it spans, 
438                 // center window in our context's gdevice
439                 rectWin.top  = (short) ((**hGD).gdRect.top + ((**hGD).gdRect.bottom - (**hGD).gdRect.top) / 2);         // h center
440                 rectWin.top  -= (short) (kContextHeight / 2);
441                 rectWin.left  = (short) ((**hGD).gdRect.left + ((**hGD).gdRect.right - (**hGD).gdRect.left) / 2);       // v center
442                 rectWin.left  -= (short) (kContextWidth / 2);
443                 rectWin.right = (short) (rectWin.left + kContextWidth);
444                 rectWin.bottom = (short) (rectWin.top + kContextHeight);
445                 
446                 pWindow = NewCWindow (NULL, &rectWin, "\p", 0, plainDBox, (WindowPtr)-1, 0, 0);
447
448                 // paint back ground black before fade in to avoid white background flash
449                 ShowWindow(pWindow);
450                 GetPort (&pGrafSave);
451                 SetPortWindowPort (pWindow);
452                 GetForeColor (&rgbSave);
453                 RGBForeColor (&rgbBlack);
454                 {
455                         Rect paintRect;
456                         GetWindowPortBounds (pWindow, &paintRect);
457                         PaintRect (&paintRect);
458                 }
459                 RGBForeColor (&rgbSave);                // ensure color is reset for proper blitting
460                 SetPort (pGrafSave);
461                 return (GetWindowPort (pWindow));
462         }
463 }
464
465 //-----------------------------------------------------------------------------------------------------------------------
466
467 // clean up DSp
468
469 void ShutdownDSp (CGrafPtr pDSpPort)
470 {
471         if ((NULL != pDSpPort) && !CheckMacOSX ())
472                 DisposeWindow (GetWindowFromPort (pDSpPort));
473         DSpContext_SetState( gContext, kDSpContextState_Inactive);
474         DSpContext_Release (gContext);
475 }
476
477 #pragma mark -
478 //-----------------------------------------------------------------------------------------------------------------------
479
480 // OpenGL Setup
481
482
483 AGLContext SetupAGL (GDHandle hGD, AGLDrawable drawable)
484 {
485         GLint                   attrib[64];
486         
487         AGLPixelFormat  fmt;
488         AGLContext      ctx;
489
490 // different possible pixel format choices for different renderers 
491 // basics requirements are RGBA and double buffer
492 // OpenGLz will select acclerated context if available
493
494         short i = 0;
495         attrib [i++] = AGL_RGBA; // red green blue and alpha
496         attrib [i++] = AGL_DOUBLEBUFFER; // double buffered
497         attrib [i++] = AGL_DEPTH_SIZE; 
498         attrib [i++] = 8; 
499         attrib [i++] = AGL_ACCELERATED; // HWA pixel format only
500         attrib [i++] = AGL_NONE;
501
502         if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL
503         {
504                 ReportError ("OpenGL not installed");
505                 return NULL;
506         }       
507
508         if (hGD)
509                 fmt = aglChoosePixelFormat (&hGD, 1, attrib); // get an appropriate pixel format
510         else
511                 fmt = aglChoosePixelFormat(NULL, 0, attrib); // get an appropriate pixel format
512         aglDebugStr ();
513         if (NULL == fmt) 
514         {
515                 ReportError("Could not find valid pixel format");
516                 return NULL;
517         }
518
519         ctx = aglCreateContext (fmt, NULL); // Create an AGL context
520         aglDebugStr ();
521         if (NULL == ctx)
522         {
523                 ReportError ("Could not create context");
524                 return NULL;
525         }
526
527         if (!aglSetDrawable (ctx, drawable)) // attach the window to the context
528         {
529                 ReportError ("SetDrawable failed");
530                 aglDebugStr ();
531                 return NULL;
532         }
533
534
535         if (!aglSetCurrentContext (ctx)) // make the context the current context
536         {
537                 aglDebugStr ();
538                 aglSetDrawable (ctx, NULL);
539                 return NULL;
540         }
541
542         aglDestroyPixelFormat(fmt); // pixel format is no longer needed
543
544         return ctx;
545 }
546
547 //-----------------------------------------------------------------------------------------------------------------------
548
549 // OpenGL Setup
550
551 AGLContext SetupAGLFullScreen (GDHandle display, short * pDepth, short * pWidth, short * pHeight)
552 {
553         //GLint                 attrib[64];
554         GLint attrib[] ={AGL_RGBA, AGL_DOUBLEBUFFER,AGL_DEPTH_SIZE, 16, AGL_FULLSCREEN,AGL_ALL_RENDERERS, AGL_NONE};
555
556         AGLPixelFormat  fmt;
557         AGLContext      ctx;
558
559
560         if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) aglChoosePixelFormat) // check for existance of OpenGL
561         {
562                 ReportError ("OpenGL not installed");
563                 return NULL;
564         }       
565
566         fmt = aglChoosePixelFormat(&display, 1, attrib); // this may fail if looking for acclerated across multiple monitors
567         if (NULL == fmt) 
568         {
569                 ReportError("Could not find valid pixel format");
570                 aglDebugStr ();
571                 return NULL;
572         }
573
574         ctx = aglCreateContext (fmt, NULL); // Create an AGL context
575         if (NULL == ctx)
576         {
577                 ReportError ("Could not create context");
578                 aglDebugStr ();
579                 return NULL;
580         }
581
582         if (!aglSetFullScreen (ctx, *pWidth, *pHeight, 60, 0))
583         {
584                 ReportError ("SetFullScreen failed");
585                 aglDebugStr ();
586                 return NULL;
587         }
588
589         if (!aglSetCurrentContext (ctx)) // make the context the current context
590         {
591                 ReportError ("SetCurrentContext failed");
592                 aglDebugStr ();
593                 aglSetDrawable (ctx, NULL); // turn off full screen
594                 return NULL;
595         }
596
597         aglDestroyPixelFormat(fmt); // pixel format is no longer needed
598
599         return ctx;
600 }
601
602 //-----------------------------------------------------------------------------------------------------------------------
603
604 // OpenGL Cleanup
605
606 void CleanupAGL(AGLContext ctx)
607 {
608         aglSetDrawable (ctx, NULL);
609         aglSetCurrentContext (NULL);
610         aglDestroyContext (ctx);
611 }
612
613 //-----------------------------------------------------------------------------------------------------------------------
614
615 // OpenGL Drawing
616
617 void DrawGL (Rect * pRectPort)
618 {
619         if (gaglContext == 0)
620                 return;
621         aglSetCurrentContext (gaglContext); // ensure our context is current prior to drawing
622         
623     {
624         GLint width = pRectPort->right - pRectPort->left;
625         GLint height = pRectPort->bottom - pRectPort->top;
626         screenwidth=width;
627         screenheight=height;
628        /* glViewport ((width - (width * 1)) / 2, (height - (height * 1)) / 2,
629                     width * 1, height * 1);*/
630      }
631     
632         game.DrawGLScene();
633         
634         
635         //glDebugStr ();
636
637         // draw info
638         /*{
639                 GLint matrixMode;
640         glViewport (0, 0, pRectPort->right - pRectPort->left, pRectPort->bottom - pRectPort->top);
641                 glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
642                 glMatrixMode (GL_PROJECTION);
643                 glPushMatrix();
644                         glLoadIdentity ();
645                         glMatrixMode (GL_MODELVIEW);
646                         glPushMatrix();
647                                 glLoadIdentity ();
648                                 glScalef (2.0 / (pRectPort->right - pRectPort->left), -2.0 /  (pRectPort->bottom - pRectPort->top), 1.0);
649                                 glTranslatef (-(pRectPort->right - pRectPort->left) / 2.0, -(pRectPort->bottom - pRectPort->top) / 2.0, 0.0);
650                                 glColor3f (1.0, 1.0, 1.0);
651                                 glRasterPos3d (10, 12, 0); 
652                                 DrawFrameRate (gFontList);
653                                 glRasterPos3d (10, 24, 0); 
654                                 DrawCStringGL (gcstrMode, gFontList);
655                                 glRasterPos3d (10, (pRectPort->bottom - pRectPort->top) - 15, 0); 
656                                 DrawCStringGL ((char*) glGetString (GL_VENDOR), gFontList);
657                                 glRasterPos3d (10, (pRectPort->bottom - pRectPort->top) - 3, 0); 
658                                 DrawCStringGL ((char*) glGetString (GL_RENDERER), gFontList);
659                                 static char aChar[256] = "";
660                                 sprintf (aChar, "     Mac OS X: %d",  RunningOnCarbonX());
661                                 DrawCStringGL (aChar, gFontList);
662                         glPopMatrix();
663                         glMatrixMode (GL_PROJECTION);
664                 glPopMatrix();
665                 glMatrixMode (matrixMode);
666         }*/
667         //glDebugStr ();
668         //aglSwapBuffers(gaglContext); // send swap command
669 }
670
671 #pragma mark -
672 //-----------------------------------------------------------------------------------------------------------------------
673
674 static pascal OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, SInt32 refcon )
675 {
676         #pragma unused (appleEvt, reply, refcon)
677         //gDone =  true;
678         game.tryquit=1;
679         return false;
680 }
681
682 //-----------------------------------------------------------------------------------------------------------------------
683
684 void InitToolbox(void)
685 {
686         OSErr err;
687         long response;
688         MenuHandle menu;
689         
690         InitCursor();
691         
692 // profile
693 #if __profile__
694 //      prototype:
695 //              ProfilerInit (collection method, time base, num funcs, stack depth)
696         // default call
697         gProfErr = ProfilerInit (collectDetailed, bestTimeBase, 20, 10); // set up profiling
698         // something that you may need to do (may need more memory)
699 //      gProfErr = ProfilerInit (collectSummary, bestTimeBase, 1000, 100); // set up profiling
700 // Note: application will likely run slower, but still should be useful info
701         if (noErr == gProfErr)
702                 ProfilerSetStatus(FALSE);
703 #endif
704         
705         // Init Menus
706         menu = NewMenu (kMenuApple, "\p\024");                  // new  apple menu
707         InsertMenu (menu, 0);                                                   // add menu to end
708
709         menu = NewMenu (kMenuFile, "\pFile");                   // new menu
710         InsertMenu (menu, 0);                                                   // add menu to end
711
712         // insert application menus here
713         
714         // add quit if not under Mac OS X
715         err = Gestalt (gestaltMenuMgrAttr, &response);
716         if ((err == noErr) && !(response & gestaltMenuMgrAquaLayoutMask))
717                         AppendMenu (menu, "\pQuit/Q");                                  // add quit
718
719         DrawMenuBar();
720         err = AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(QuitAppleEventHandler), 0, false );
721         if (err != noErr)
722                 ExitToShell();
723 }
724
725 // --------------------------------------------------------------------------
726
727 static Point gMidPoint;
728
729 Boolean SetUp (void)
730 {
731         char string[10];
732         
733         SetQDGlobalsRandomSeed(TickCount());
734         
735         osx = 0;
736         if(CheckMacOSX ())osx = 1;
737         ifstream ipstream(":Data:config.txt");
738         detail=1;
739         ismotionblur=0;
740         usermousesensitivity=1;
741         kContextWidth=640;
742         kContextHeight=480;
743         kBitsPerPixel = 32;
744         floatjump=0;
745         cellophane=0;
746         texdetail=4;
747         autoslomo=1;
748         decals=1;
749         invertmouse=0;
750         bloodtoggle=0;
751         terraindetail=2;
752         foliage=1;
753         musictoggle=1;
754         trilinear=1;
755         gamespeed=1;
756         difficulty=1;
757         damageeffects=0;
758         texttoggle=1;
759         alwaysblur=0;
760         showpoints=0;
761         immediate=0;
762         velocityblur=0;
763         slomospeed=0.25;
764         slomofreq=8012;
765         
766         game.crouchkey=MAC_SHIFT_KEY;
767     game.jumpkey=MAC_SPACE_KEY;
768     game.leftkey=MAC_A_KEY;
769     game.forwardkey=MAC_W_KEY;
770     game.backkey=MAC_S_KEY;
771     game.rightkey=MAC_D_KEY;
772     game.drawkey=MAC_E_KEY;
773     game.throwkey=MAC_Q_KEY;
774     game.attackkey=MAC_MOUSEBUTTON1;
775     game.chatkey=MAC_T_KEY;
776     numplayers=1;
777     ambientsound=1;
778     vblsync=0;
779     debugmode=0;
780     if(!ipstream) {
781         ofstream opstream(":Data:config.txt"); 
782         opstream << "Screenwidth:\n";
783         opstream << kContextWidth;
784         opstream << "\nScreenheight:\n";
785             opstream << kContextHeight;
786             opstream << "\nMouse sensitivity:\n";
787             opstream << usermousesensitivity;
788             opstream << "\nBlur(0,1):\n";
789             opstream << ismotionblur;
790                 opstream << "\nOverall Detail(0,1,2) higher=better:\n";
791             opstream << detail;
792             opstream << "\nFloating jump:\n";
793             opstream << floatjump;
794             opstream << "\nMouse jump:\n";
795             opstream << mousejump;
796             opstream << "\nAmbient sound:\n";
797             opstream << ambientsound;
798                 opstream << "\nBlood (0,1,2):\n";
799         opstream << bloodtoggle;
800         opstream << "\nAuto slomo:\n";
801         opstream << autoslomo;
802             opstream << "\nFoliage:\n";
803         opstream << foliage;
804         opstream << "\nMusic:\n";
805         opstream << musictoggle;
806         opstream << "\nTrilinear:\n";
807         opstream << trilinear;
808             opstream << "\nDecals(shadows,blood puddles,etc):\n";
809         opstream << decals;
810             opstream << "\nInvert mouse:\n";
811         opstream << invertmouse;
812             opstream << "\nGamespeed:\n";
813         opstream << gamespeed;
814         opstream << "\nDifficulty(0,1,2) higher=harder:\n";
815         opstream << difficulty;
816         opstream << "\nDamage effects(blackout, doublevision):\n";
817         opstream << damageeffects;
818             opstream << "\nText:\n";
819         opstream << texttoggle;
820             opstream << "\nDebug:\n";
821         opstream << debugmode;
822             opstream << "\nVBL Sync:\n";
823         opstream << vblsync;
824         opstream << "\nShow Points:\n";
825         opstream << showpoints;
826         opstream << "\nAlways Blur:\n";
827         opstream << alwaysblur;
828             opstream << "\nImmediate mode (turn on on G5):\n";
829         opstream << immediate;
830             opstream << "\nVelocity blur:\n";
831         opstream << velocityblur;
832             opstream << "\nForward key:\n";
833             opstream << KeyToChar(game.forwardkey);
834             opstream << "\nBack key:\n";
835             opstream << KeyToChar(game.backkey);
836             opstream << "\nLeft key:\n";
837             opstream << KeyToChar(game.leftkey);
838             opstream << "\nRight key:\n";
839             opstream << KeyToChar(game.rightkey);
840             opstream << "\nJump key:\n";
841             opstream << KeyToChar(game.jumpkey);
842             opstream << "\nCrouch key:\n";
843             opstream << KeyToChar(game.crouchkey);
844             opstream << "\nDraw key:\n";
845             opstream << KeyToChar(game.drawkey);
846             opstream << "\nThrow key:\n";
847             opstream << KeyToChar(game.throwkey);
848             opstream << "\nAttack key:\n";
849             opstream << KeyToChar(game.attackkey);
850             opstream << "\nChat key:\n";
851             opstream << KeyToChar(game.chatkey);
852             opstream.close();
853     }
854     if(ipstream){
855                 ipstream.ignore(256,'\n');
856             ipstream >> kContextWidth;
857             ipstream.ignore(256,'\n');
858             ipstream.ignore(256,'\n');
859             ipstream >> kContextHeight;
860             ipstream.ignore(256,'\n');
861             ipstream.ignore(256,'\n');
862             ipstream >> usermousesensitivity;
863             ipstream.ignore(256,'\n');
864             ipstream.ignore(256,'\n');
865             ipstream >> ismotionblur;
866             ipstream.ignore(256,'\n');
867             ipstream.ignore(256,'\n');
868             ipstream >> detail;
869             if(detail!=0)kBitsPerPixel=32;
870             else kBitsPerPixel=16;
871             ipstream.ignore(256,'\n');
872             ipstream.ignore(256,'\n');
873             ipstream >> floatjump;
874             ipstream.ignore(256,'\n');
875             ipstream.ignore(256,'\n');
876             ipstream >> mousejump;
877             ipstream.ignore(256,'\n');
878             ipstream.ignore(256,'\n');
879             ipstream >> ambientsound;
880             ipstream.ignore(256,'\n');
881             ipstream.ignore(256,'\n');
882             ipstream >> bloodtoggle;
883             ipstream.ignore(256,'\n');
884             ipstream.ignore(256,'\n');
885             ipstream >> autoslomo;
886             ipstream.ignore(256,'\n');
887             ipstream.ignore(256,'\n');
888             ipstream >> foliage;
889             ipstream.ignore(256,'\n');
890             ipstream.ignore(256,'\n');
891             ipstream >> musictoggle;
892             ipstream.ignore(256,'\n');
893             ipstream.ignore(256,'\n');
894             ipstream >> trilinear;
895             ipstream.ignore(256,'\n');
896             ipstream.ignore(256,'\n');
897             ipstream >> decals;
898             ipstream.ignore(256,'\n');
899             ipstream.ignore(256,'\n');
900             ipstream >> invertmouse;
901             ipstream.ignore(256,'\n');
902             ipstream.ignore(256,'\n');
903             ipstream >> gamespeed;
904             oldgamespeed=gamespeed;
905             if(oldgamespeed==0){
906                 gamespeed=1;
907                 oldgamespeed=1;
908             }
909             ipstream.ignore(256,'\n');
910             ipstream.ignore(256,'\n');
911             ipstream >> difficulty;
912             ipstream.ignore(256,'\n');
913             ipstream.ignore(256,'\n');
914             ipstream >> damageeffects;
915             ipstream.ignore(256,'\n');
916             ipstream.ignore(256,'\n');
917             ipstream >> texttoggle;
918             ipstream.ignore(256,'\n');
919             ipstream.ignore(256,'\n');
920             ipstream >> debugmode;
921             ipstream.ignore(256,'\n');
922             ipstream.ignore(256,'\n');
923             ipstream >> vblsync;
924             ipstream.ignore(256,'\n');
925             ipstream.ignore(256,'\n');
926             ipstream >> showpoints;
927             ipstream.ignore(256,'\n');
928             ipstream.ignore(256,'\n');
929             ipstream >> alwaysblur;
930             ipstream.ignore(256,'\n');
931             ipstream.ignore(256,'\n');
932             ipstream >> immediate;
933             ipstream.ignore(256,'\n');
934             ipstream.ignore(256,'\n');
935             ipstream >> velocityblur;
936             ipstream.ignore(256,'\n');
937             ipstream.ignore(256,'\n'); 
938             ipstream >> string;
939             game.forwardkey=CharToKey(string);
940             ipstream.ignore(256,'\n');
941             ipstream.ignore(256,'\n');
942             ipstream >> string;
943             game.backkey=CharToKey(string);
944             ipstream.ignore(256,'\n');
945             ipstream.ignore(256,'\n');
946             ipstream >> string;
947             game.leftkey=CharToKey(string);
948             ipstream.ignore(256,'\n');
949             ipstream.ignore(256,'\n');
950             ipstream >> string;
951             game.rightkey=CharToKey(string);
952             ipstream.ignore(256,'\n');
953             ipstream.ignore(256,'\n');
954             ipstream >> string;
955             game.jumpkey=CharToKey(string);
956             ipstream.ignore(256,'\n');
957             ipstream.ignore(256,'\n');
958             ipstream >> string;
959             game.crouchkey=CharToKey(string);
960             ipstream.ignore(256,'\n');
961             ipstream.ignore(256,'\n');
962             ipstream >> string;
963             game.drawkey=CharToKey(string);
964              ipstream.ignore(256,'\n');
965             ipstream.ignore(256,'\n');
966             ipstream >> string;
967             game.throwkey=CharToKey(string);
968               ipstream.ignore(256,'\n');
969             ipstream.ignore(256,'\n');
970             ipstream >> string;
971             game.attackkey=CharToKey(string);
972              ipstream.ignore(256,'\n');
973             ipstream.ignore(256,'\n');
974             ipstream >> string;
975             game.chatkey=CharToKey(string);
976             ipstream.close();
977             
978             if(detail>2)detail=2;
979             if(detail<0)detail=0;
980                 if(screenwidth<0)screenwidth=640;
981                 if(screenheight<0)screenheight=480;
982 #if !USE_SDL  // we'll take anything that works.
983             if(screenwidth>3000)screenwidth=640;
984                 if(screenheight>3000)screenheight=480;
985 #endif
986         }
987
988         
989         if(vblsync){    
990                 GLint swapInt = 1;
991                 aglSetInteger(gaglContext, AGL_SWAP_INTERVAL, &swapInt);
992         }
993         
994         if(kBitsPerPixel!=32&&kBitsPerPixel!=16){
995                 kBitsPerPixel=16;
996         }
997
998         
999         GDHandle hGD, hTargetDevice = NULL;
1000         short numDevices = 0;
1001         short fNum = 0;
1002         short whichDevice = 0; // number of device to try (0 = 1st device)
1003
1004         InitToolbox ();
1005         
1006         gpDSpPort = NULL;
1007         gaglContext = 0;
1008         
1009         // check for DSp
1010         if ((Ptr) kUnresolvedCFragSymbolAddress == (Ptr) DSpStartup) 
1011                 ReportError ("DSp not installed");
1012
1013         if (noErr != DSpDebugStr (DSpStartup()))
1014                 return NULL;
1015 //      DSpSetDebugMode (true);
1016 #if defined kUseFades
1017         DSpDebugStr (DSpContext_FadeGammaOut (NULL, NULL)); // fade display, remove for debug
1018 #endif
1019         
1020         hGD = DMGetFirstScreenDevice (true); // check number of screens
1021         hTargetDevice = hGD; // default to first device                                                 
1022         do
1023         {
1024                 if (numDevices == whichDevice)
1025                         hTargetDevice = hGD; // if device number matches                                                
1026                 numDevices++;
1027                 hGD = DMGetNextScreenDevice (hGD, true);
1028         }
1029         while (hGD);
1030
1031 #if defined (kUseAGLFullScreenX)
1032         if (CheckMacOSX ()) // Try AGL full screen on Mac OS X
1033         {
1034                 short depth = kBitsPerPixel, width = kContextWidth, height = kContextHeight; 
1035                 gaglContext = SetupAGLFullScreen (hTargetDevice, &depth, &width, &height); // Setup the OpenGL context
1036                 SetRect (&gRectPort, 0, 0, width, height); // l, t, r, b
1037                 sprintf (gcstrMode, "AGL Full Screen: %d x %d x %d", width, height, depth);
1038         }
1039 #endif
1040         if (!gaglContext) //try DSp
1041         {
1042                 if (NULL != (gpDSpPort = SetupDSpFullScreen (hTargetDevice))) // Setup DSp for OpenGL sets hTargetDeviceto device actually used 
1043                 {
1044                         GetPortBounds (gpDSpPort, &gRectPort);
1045                         sprintf (gcstrMode, "DrawSprocket Full Screen: %d x %d x %d", gRectPort.right - gRectPort.left, gRectPort.bottom - gRectPort.top, (**(**hTargetDevice).gdPMap).pixelSize);
1046                         gaglContext = SetupAGL (hTargetDevice, gpDSpPort);
1047                 }
1048         }
1049         if (gaglContext)
1050         {
1051                 GetFNum("\pMonaco", &fNum);                                                                     // build font
1052                 gFontList = BuildFontGL (gaglContext, fNum, normal, 9);
1053                 //InstallEventLoopTimer (GetCurrentEventLoop(), 0, 0.0001, GetTimerUPP (), 0, &gTimer);
1054         }
1055         
1056         //gMidPoint.h = (gRectPort.left + gRectPort.right)/2;
1057         //gMidPoint.v = (gRectPort.top + gRectPort.bottom)/2;
1058         gMidPoint.h = 200;
1059         gMidPoint.v = 200;
1060         GLint swapInt = 1;
1061         //aglSetInteger(gaglContext, AGL_SWAP_INTERVAL, &swapInt);
1062         
1063 #if defined kUseFades
1064         DSpDebugStr (DSpContext_FadeGammaIn (NULL, NULL));
1065 #endif
1066         
1067         
1068         HideCursor();
1069         
1070         
1071     GLint width = gRectPort.right - gRectPort.left;
1072     GLint height = gRectPort.bottom - gRectPort.top;
1073     screenwidth=width;
1074     screenheight=height;
1075      
1076     game.newdetail=detail;
1077         game.newscreenwidth=screenwidth;
1078         game.newscreenheight=screenheight;
1079      
1080         game.InitGame();
1081         
1082         if (gaglContext)
1083                 return true;
1084         else
1085                 return false;
1086         
1087 }
1088
1089 static Boolean RunningOnCarbonX(void)
1090 {
1091         static Boolean first = true;
1092         static Boolean result = false;
1093
1094         if (first)
1095         {
1096                 UInt32 response;
1097
1098                 first = false;
1099
1100                 result = (Gestalt(gestaltSystemVersion, 
1101                     (SInt32 *) &response) == noErr)
1102                 && (response >= 0x01000);
1103         }
1104     return result;
1105 }
1106
1107 static OSStatus LoadFrameworkBundle(CFStringRef pFrameworkCFStrRef, CFBundleRef *pFrameworkCFBndlRef)
1108 {
1109         OSStatus        err;
1110         FSRef           frameworksFolderRef;
1111         CFURLRef        baseURL;
1112         CFURLRef        bundleURL;
1113         
1114         if (nil == pFrameworkCFBndlRef) return paramErr;
1115         
1116         *pFrameworkCFBndlRef = nil;
1117         
1118         baseURL = nil;
1119         bundleURL = nil;
1120         
1121         err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
1122         if (err == noErr) {
1123                 baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
1124                 if (baseURL == nil) {
1125                         err = coreFoundationUnknownErr;
1126                 }
1127         }
1128         if (err == noErr) {
1129                 bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, baseURL, pFrameworkCFStrRef, false);
1130                 if (bundleURL == nil) {
1131                         err = coreFoundationUnknownErr;
1132                 }
1133         }
1134         if (err == noErr) {
1135                 *pFrameworkCFBndlRef = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
1136                 if (*pFrameworkCFBndlRef == nil) {
1137                         err = coreFoundationUnknownErr;
1138                 }
1139         }
1140         if (err == noErr) {
1141             if ( ! CFBundleLoadExecutable( *pFrameworkCFBndlRef ) ) {
1142                         err = coreFoundationUnknownErr;
1143             }
1144         }
1145
1146         // Clean up.
1147         
1148         if (err != noErr && *pFrameworkCFBndlRef != nil) {
1149                 CFRelease(*pFrameworkCFBndlRef);
1150                 *pFrameworkCFBndlRef = nil;
1151         }
1152         if (bundleURL != nil) {
1153                 CFRelease(bundleURL);
1154         }       
1155         if (baseURL != nil) {
1156                 CFRelease(baseURL);
1157         }       
1158         
1159         return err;
1160 }
1161
1162
1163
1164 static CFragConnectionID gCFragConnectionID = 0;
1165
1166 typedef pascal OSErr (*CDM_NewDeviceProcPtr)(CursorDevicePtr * ourDevice);
1167
1168 static OSErr MyCursorDeviceNewDevice(CursorDevicePtr * ourDevice)
1169 {
1170         static CDM_NewDeviceProcPtr sCDM_NewDeviceProcPtr = nil;
1171         OSStatus anErr = noErr;
1172
1173         if (nil == ourDevice) return paramErr;
1174
1175         if (!RunningOnCarbonX())
1176         {
1177                 if (!sCDM_NewDeviceProcPtr)
1178                 {
1179                         if (!gCFragConnectionID)
1180                         {
1181                                 Ptr             mainAddr;
1182                                 Str255  errName;
1183
1184                                 anErr = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch,
1185                                          kFindCFrag, &gCFragConnectionID, &mainAddr, errName);
1186                                 if (noErr != anErr) return anErr;
1187                         }
1188
1189                         if (gCFragConnectionID)
1190                         {
1191                                 CFragSymbolClass symClass;
1192
1193                                 anErr = FindSymbol(gCFragConnectionID, "\pCrsrDevNewDevice",
1194                                         (Ptr*) &sCDM_NewDeviceProcPtr, &symClass);
1195                                 if (noErr != anErr) return anErr;
1196                         }
1197                 }
1198                 if (sCDM_NewDeviceProcPtr)
1199                         anErr = (*sCDM_NewDeviceProcPtr)(ourDevice);
1200                 else
1201                         anErr = paramErr;
1202         }
1203
1204         return anErr;
1205 }
1206
1207 typedef pascal OSErr (*CDM_CursorDeviceMoveToProcPtr)(
1208                                                         CursorDevicePtr   ourDevice,
1209                                                         long              absX,
1210                                                         long              absY);
1211
1212 typedef UInt32 (*CGWarpMouseCursorPositionProcPtr)(CGPoint newCursorPosition);
1213 typedef UInt32 (*CGSetLocalEventsSuppressionIntervalProcPtr)(double pSeconds);
1214
1215 static OSErr MyCursorDeviceMoveTo(      CursorDevicePtr   ourDevice,
1216                                                         long              absX,
1217                                                         long              absY)
1218 {
1219         OSStatus anErr = noErr;
1220
1221         if (RunningOnCarbonX())
1222         {
1223                 static CGWarpMouseCursorPositionProcPtr sCGWarpMouseCursorPositionProcPtr = nil;
1224
1225                 if (nil == sCGWarpMouseCursorPositionProcPtr)
1226                 {
1227                         CFBundleRef tCFBundleRef;
1228
1229                         anErr = LoadFrameworkBundle(CFSTR("ApplicationServices.framework"), &tCFBundleRef);
1230
1231                         if (noErr == anErr)
1232                         {
1233                                 CGSetLocalEventsSuppressionIntervalProcPtr tCGSetLocalEventsSuppressionIntervalProcPtr = nil;
1234
1235                                 sCGWarpMouseCursorPositionProcPtr = (CGWarpMouseCursorPositionProcPtr)
1236                                         CFBundleGetFunctionPointerForName( tCFBundleRef, CFSTR("CGWarpMouseCursorPosition") );
1237                                 if (nil == sCGWarpMouseCursorPositionProcPtr)
1238                                         anErr = cfragNoSymbolErr;
1239
1240                                 tCGSetLocalEventsSuppressionIntervalProcPtr = (CGSetLocalEventsSuppressionIntervalProcPtr)
1241                                         CFBundleGetFunctionPointerForName(tCFBundleRef,CFSTR("CGSetLocalEventsSuppressionInterval"));
1242                                 if (nil != tCGSetLocalEventsSuppressionIntervalProcPtr)
1243                                         (*tCGSetLocalEventsSuppressionIntervalProcPtr)(0.0f);
1244                         }
1245                 }
1246
1247                 if (nil != sCGWarpMouseCursorPositionProcPtr)
1248                 {
1249                         CGPoint tCGPoint;
1250
1251                         tCGPoint.x = absX;
1252                         tCGPoint.y = absY;
1253
1254                         (*sCGWarpMouseCursorPositionProcPtr)(tCGPoint);
1255                 }
1256         }
1257         else
1258         {
1259                 static CDM_CursorDeviceMoveToProcPtr sCDM_CursorDeviceMoveToProcPtr = nil;
1260
1261                 if (!ourDevice) return paramErr;
1262
1263                 if (!sCDM_CursorDeviceMoveToProcPtr)
1264                 {
1265                         if (!gCFragConnectionID)
1266                         {
1267                                 Ptr             mainAddr;
1268                                 Str255  errName;
1269
1270                                 anErr = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch,
1271                                          kFindCFrag, &gCFragConnectionID, &mainAddr, errName);
1272                                 if (noErr != anErr) return anErr;
1273                         }
1274
1275                         if (gCFragConnectionID)
1276                         {
1277                                 CFragSymbolClass symClass;
1278
1279                                 anErr = FindSymbol(gCFragConnectionID, "\pCrsrDevMoveTo",
1280                                         (Ptr*) &sCDM_CursorDeviceMoveToProcPtr, &symClass);
1281                                 if (noErr != anErr) return anErr;
1282                         }
1283                 }
1284                 if (sCDM_CursorDeviceMoveToProcPtr)
1285                         anErr = (*sCDM_CursorDeviceMoveToProcPtr)(ourDevice,absX,absY);
1286                 else
1287                         anErr = paramErr;
1288         }
1289
1290         return anErr;
1291 }
1292
1293 static void DoMouse(void)
1294 {
1295         static CursorDevicePtr virtualCursorDevicePtr = nil;
1296         OSStatus anErr = noErr;
1297
1298          HideCursor();
1299
1300         if (nil == virtualCursorDevicePtr)
1301                 anErr = MyCursorDeviceNewDevice(&virtualCursorDevicePtr);
1302
1303         {
1304                 static Point lastMouse = {-1,-1};
1305                 Point globalMouse;
1306
1307                 GetGlobalMouse(&globalMouse);
1308         
1309                 if (EqualPt(lastMouse, globalMouse))
1310                 {
1311                         game.deltah=0;
1312                         game.deltav=0;
1313                 }
1314
1315                 if (!EqualPt(lastMouse, globalMouse))
1316                 {
1317                         static Point virtualMouse = {0,0};
1318                         delta = globalMouse;
1319
1320                         SubPt(lastMouse, &delta);
1321                         GetGlobalMouse(&lastMouse);
1322                         //AddPt(delta, &virtualMouse);
1323                         
1324                         if(mainmenu||(abs(delta.h)<10*realmultiplier*1000&&abs(delta.v)<10*realmultiplier*1000)){
1325                         game.deltah=delta.h*usermousesensitivity;
1326                         game.deltav=delta.v*usermousesensitivity;
1327                         game.mousecoordh=globalMouse.h;
1328                         game.mousecoordv=globalMouse.v;
1329                         }
1330 #if 1
1331                         //printf("\nMouse Moved: {%d,%d}.",globalMouse.h,globalMouse.v);
1332                         //printf("\tdelta: {%d,%d}.",delta.h,delta.v);
1333                         //printf("\tvirtual: {%d,%d}.",virtualMouse.h,virtualMouse.v);
1334 #endif
1335                         if(!mainmenu)
1336                         if(lastMouse.h>gMidPoint.h+100||lastMouse.h<gMidPoint.h-100||lastMouse.v>gMidPoint.v+100||lastMouse.v<gMidPoint.v-100){
1337                                 MyCursorDeviceMoveTo(virtualCursorDevicePtr,gMidPoint.h,gMidPoint.v);
1338                                 lastMouse = gMidPoint;
1339                         }
1340                 }
1341         }
1342 }
1343
1344
1345 // --------------------------------------------------------------------------
1346
1347 void DoMenu (SInt32 menuResult)
1348 {
1349         SInt16 theMenu;
1350         SInt16 theItem;
1351         MenuRef theMenuHandle;
1352                 
1353         theMenu = HiWord(menuResult);
1354         theItem = LoWord(menuResult);
1355         theMenuHandle = GetMenuHandle(theMenu);
1356
1357         switch (theMenu)
1358         {
1359                 case kMenuApple:
1360                         switch (theItem)
1361                         {
1362                                 case kAppleAbout:
1363                                         break;
1364                                 default:
1365                                         break;
1366                         }
1367                         break;
1368                 case kMenuFile:
1369                         switch (theItem)
1370                         {
1371                                 case kFileQuit:
1372                                         game.quit = true;
1373                                         break;
1374                         }
1375                         break;
1376         }
1377         HiliteMenu(0);
1378         DrawMenuBar();
1379 }
1380
1381 // --------------------------------------------------------------------------
1382
1383 void DoKey (SInt8 theKey, SInt8 theCode)
1384 {
1385         #pragma unused (theCode, theKey)
1386     /*if ((theKey == '=') || (theKey == '+'))
1387         gfScale *= 1.1;
1388     if (theKey == '-')
1389         gfScale /= 1.1;*/
1390         // do nothing
1391 }
1392
1393 // --------------------------------------------------------------------------
1394
1395
1396
1397 /*void DoUpdate (void)
1398 {
1399         static float sps=200;
1400         static int count;
1401         static float oldmult;
1402
1403         DoFrameRate();
1404         
1405         count = multiplier*sps;
1406         if(count<2)count=2;
1407         
1408         oldmult=multiplier;
1409         multiplier/=count;
1410         
1411         for(int i=0;i<count;i++){
1412                 game.Tick();
1413         }
1414         multiplier=oldmult;
1415         
1416         game.TickOnce();
1417         
1418         DoMouse();
1419
1420         DrawGL (&gRectPort);
1421 }*/
1422
1423 void DoUpdate (void)
1424 {
1425         static float sps=200;
1426         static int count;
1427         static float oldmult;
1428         
1429         DoFrameRate(1);
1430         
1431         if(multiplier>.6)multiplier=.6;
1432         
1433         game.fps=1/multiplier;
1434
1435         count = multiplier*sps;
1436         if(count<2)count=2;
1437         //if(count>10)count=10;
1438         
1439         realmultiplier=multiplier;
1440         multiplier*=gamespeed;
1441         if(difficulty==1)multiplier*=.9;
1442         if(difficulty==0)multiplier*=.8;
1443         
1444         if(game.loading==4)multiplier*=.00001;
1445
1446         //multiplier*.9;
1447         if(slomo&&!mainmenu)multiplier*=slomospeed;
1448         //if(freeze)multiplier*=0.00001;
1449         oldmult=multiplier;
1450         multiplier/=(float)count;
1451         
1452         DoMouse();
1453         
1454         game.TickOnce();
1455         
1456         for(int i=0;i<count;i++){
1457                 game.Tick();
1458         }
1459         multiplier=oldmult;
1460         
1461         game.TickOnceAfter();
1462         
1463         DrawGL (&gRectPort);
1464 }
1465
1466 // --------------------------------------------------------------------------
1467
1468 Boolean WaitNextEventWrapper (EventMask eventMask, EventRecord *theEvent, unsigned long sleep,RgnHandle mouseRgn)
1469 {
1470         return WaitNextEvent (eventMask, theEvent, sleep, mouseRgn);
1471 }
1472
1473 // --------------------------------------------------------------------------
1474
1475 OSStatus DSpProcessEventWrapper (EventRecord *inEvent, Boolean *outEventWasProcessed)
1476 {
1477         return DSpProcessEvent (inEvent, outEventWasProcessed);
1478 }
1479
1480 // --------------------------------------------------------------------------
1481
1482 void UpdateWrapper (EventRecord *theEvent)
1483 {
1484         WindowRef whichWindow;
1485         GrafPtr pGrafSave;
1486         
1487         whichWindow = (WindowRef) theEvent->message;
1488         GetPort (&pGrafSave);
1489         SetPort((GrafPtr) GetWindowPort(whichWindow));
1490         BeginUpdate(whichWindow);
1491         DoUpdate();
1492         SetPort((GrafPtr) GetWindowPort(whichWindow));
1493         EndUpdate(whichWindow);
1494         SetPort (pGrafSave);
1495 }
1496
1497 // --------------------------------------------------------------------------
1498
1499 pascal void IdleTimer (EventLoopTimerRef inTimer, void* userData)
1500 {
1501         #pragma unused (inTimer, userData)
1502         if(!stillloading)DoUpdate ();
1503 }
1504
1505 // --------------------------------------------------------------------------
1506
1507 EventLoopTimerUPP GetTimerUPP (void)
1508 {
1509         static EventLoopTimerUPP        sTimerUPP = NULL;
1510         
1511         if (sTimerUPP == NULL)
1512                 sTimerUPP = NewEventLoopTimerUPP (IdleTimer);
1513         
1514         return sTimerUPP;
1515 }
1516
1517 // --------------------------------------------------------------------------
1518
1519 pascal OSStatus mDown (EventHandlerCallRef ref, EventRef e,void * thedata) {
1520         EventMouseButton button;
1521         OSStatus status;
1522         
1523         status = GetEventParameter (e, kEventParamMouseButton, typeMouseButton, NULL, 
1524                 sizeof (button), NULL, &button);
1525         
1526         buttons[button-1] = true;               
1527         
1528         return eventNotHandledErr;
1529 }
1530
1531 pascal OSStatus mUp (EventHandlerCallRef ref, EventRef e,void * thedata) {
1532         EventMouseButton button = 0;
1533         OSStatus status;
1534         
1535         status = GetEventParameter (e, kEventParamMouseButton, typeMouseButton, NULL, 
1536                 sizeof (EventMouseButton), NULL, &button);
1537         
1538         buttons[button-1] = false;      
1539         
1540         return eventNotHandledErr;      
1541 }
1542
1543 void InstallHandlers(void){
1544         OSStatus status;
1545         EventTypeSpec spec;
1546         
1547         spec.eventClass = kEventClassMouse;
1548         spec.eventKind = kEventMouseDown;
1549
1550         status = InstallEventHandler (GetApplicationEventTarget(), 
1551                 NewEventHandlerUPP (mDown), 1, &spec, NULL, NULL);
1552         
1553         
1554         spec.eventKind = kEventMouseUp;
1555         
1556         status = InstallEventHandler (GetApplicationEventTarget(), 
1557                 NewEventHandlerUPP (mUp), 1, &spec, NULL, NULL);
1558
1559 }
1560
1561 void NewEvent(void) {
1562         EventRecord e;
1563         OSStatus s;
1564         
1565         
1566         /*ReceiveNextEvent (0, NULL, 1, true, &er);
1567         
1568         s = SendEventToEventTarget (er, GetEventDispatcherTarget());*/
1569         WaitNextEvent (everyEvent, &e, 0, NULL);
1570         
1571         DoUpdate();
1572 }
1573
1574 void DoEvent (void)
1575 {
1576         EventRecord theEvent;
1577         WindowRef whichWindow;
1578         SInt16 whatPart;
1579         Boolean fProcessed;
1580         
1581 // profile
1582 #if __profile__
1583         if (noErr == gProfErr)
1584                 ProfilerSetStatus(TRUE); // turn on profiling
1585 #endif
1586
1587         if (WaitNextEventWrapper (everyEvent, &theEvent, gSleepTime, NULL))
1588         {
1589                 DSpProcessEventWrapper (&theEvent, &fProcessed);
1590                 if (!fProcessed)
1591                 {
1592                         switch (theEvent.what)
1593                         {
1594                                 case mouseDown:
1595                                         whatPart = FindWindow (theEvent.where, &whichWindow);
1596                                         switch (whatPart)
1597                                         {
1598                                                 case inContent:
1599 //                                                      if (GetWindowFromPort (gpDSpPort) != FrontWindow()) 
1600 //                                                              SelectWindow (GetWindowFromPort (gpDSpPort));
1601                                                         break;
1602                                                 case inMenuBar:
1603                                                 {
1604                                                         SInt32 menuResult = MenuSelect (theEvent.where);
1605                                                         if (HiWord (menuResult) != 0)
1606                                                                 DoMenu (menuResult);
1607                                                 }
1608                                                         break;
1609                                                 case inDrag:
1610                                                         {
1611                                                                 // full screen no drag
1612                                                         }
1613                                                         break;
1614                                                 case inGrow:
1615                                                         {
1616                                                                 // full screen no grow
1617                                                         }
1618                                                         break;
1619                                                 case inGoAway:
1620                                                         {
1621                                                                 // full screen no go away
1622                                                         }
1623                                                         break;
1624                                                 case inZoomIn:
1625                                                 case inZoomOut:
1626                                                         {
1627                                                                 // full screen no zoom
1628                                                         }
1629                                                         break;
1630                                                 case inSysWindow:
1631                                                         break;
1632                                         }
1633                                         break;
1634                                 case keyDown:
1635                                 case autoKey:
1636                                 {
1637                                         SInt8 theKey;
1638                                         SInt8 theCode;
1639                                         theKey = theEvent.message & charCodeMask;
1640                                         theCode = (theEvent.message & keyCodeMask) >> 8;
1641                                         if ((theEvent.modifiers & cmdKey) != 0)
1642                                         {
1643                                                 SInt32 menuResult = MenuKey (theKey);
1644                                                 if (HiWord(menuResult) != 0)
1645                                                         DoMenu (menuResult);
1646                                         }
1647                                         else
1648                                                 DoKey (theKey, theCode);
1649                                 }
1650                                         break;
1651                                 case updateEvt:
1652                                 {
1653                                         UpdateWrapper (&theEvent);
1654                                 }
1655                                         break;
1656                                 case diskEvt:
1657                                         break;
1658                                 /*case osEvt:
1659                                         if (theEvent.message & 0x01000000)              //      Suspend/resume event
1660                                         {
1661                                                 if (theEvent.message & 0x00000001)      //      Resume
1662                                                 {
1663                                                         gSleepTime = kForegroundSleep;  
1664                                                         gfFrontProcess = true;
1665                                                 }
1666                                                 else
1667                                                 {
1668                                                         gSleepTime = kBackgroundSleep;  //      Suspend
1669                                                         gfFrontProcess = false;
1670                                                 }
1671                                         }
1672                                         break;*/
1673
1674                                 case kHighLevelEvent:
1675                                         AEProcessAppleEvent (&theEvent);
1676                                         break;
1677                         }
1678                 }
1679         }
1680 // profile
1681 #if __profile__
1682         if (noErr == gProfErr)
1683                 ProfilerSetStatus(FALSE); // turn profiling off again
1684 #endif
1685 }
1686
1687 // --------------------------------------------------------------------------
1688
1689 void CleanUp (void)
1690 {
1691         MenuHandle hMenu;
1692         
1693 // profile
1694 #if __profile__
1695         if (noErr == gProfErr)
1696         {
1697                 ProfilerDump ("\pGL DSp Carbon.prof");
1698                 ProfilerTerm ();
1699         }
1700 #endif
1701
1702         game.Dispose();
1703         
1704 #if defined kUseFades
1705         DSpDebugStr (DSpContext_FadeGammaOut (NULL, NULL)); // fade display, remove for debug
1706 #endif
1707
1708         RemoveEventLoopTimer(gTimer);
1709         gTimer = NULL;
1710
1711         DeleteFontGL (gFontList);
1712         CleanupAGL (gaglContext); // Cleanup the OpenGL context
1713         gaglContext = 0;
1714         if (gpDSpPort)
1715         {
1716                 ShutdownDSp (gpDSpPort); // DSp shutdown
1717                 gpDSpPort = NULL;
1718         }
1719
1720         
1721         hMenu = GetMenuHandle (kMenuFile);
1722         DeleteMenu (kMenuFile);
1723         DisposeMenu (hMenu);
1724
1725         hMenu = GetMenuHandle (kMenuApple);
1726         DeleteMenu (kMenuApple);
1727         DisposeMenu (hMenu);
1728
1729 #if defined kUseFades
1730         DSpDebugStr (DSpContext_FadeGammaIn (NULL, NULL)); // fade display, remove for debug
1731 #endif
1732         DSpShutdown ();
1733         
1734         ShowCursor();
1735 }
1736
1737 // --------------------------------------------------------------------------
1738 #include <iostream>
1739 #include <InternetConfig.h>
1740
1741 /*void openURL()
1742 {
1743 #ifdef Q_WS_MAC
1744         QString url("http://www.wolfire.com/");
1745         ICInstance icInstance
1746         OSType psiSignature = 'Psi ';
1747         OSStatus error = ::ICStart( &icInstance, psiSignature);
1748         if(error=noErr){
1749                 ConstStr255Param hint( 0x0 );
1750                 const char* data = url.latin1();
1751                 long length = url.length();
1752                 long start( 0 );
1753                 long end( length );
1754                 ::ICLaunchURL( icInstance, hint, data, length, &start, &end);
1755                 ICStop( icInstance);
1756         }
1757         #endif
1758 }*/
1759
1760 void LaunchURL(char *url)
1761 {
1762         ICInstance gICInstance;
1763         ICStart (&gICInstance, 0);
1764         long int start,fin;
1765         start=0;
1766         fin=strlen(url);
1767         ICLaunchURL(gICInstance, "\p" ,url, fin, &start, &fin);
1768 }
1769         
1770         
1771         
1772 int main (void)
1773 {
1774         try { 
1775                 if (SetUp ())   {
1776                         InstallHandlers();
1777                         while (!gDone&&!game.quit&&(!game.tryquit||!game.registered)) {
1778                                 NewEvent ();
1779                         }
1780                 }
1781                 CleanUp ();
1782                 if(game.registernow){
1783                         char url[100];
1784                         sprintf(url,"http://www.wolfire.com/register.html");
1785                         LaunchURL(url);
1786                 }
1787                 return 0;
1788         } catch (const std::exception& error) { 
1789                 ofstream opstream("error.txt"); 
1790         opstream << "Caught exception: " << error.what() << std::endl;
1791             opstream.close();
1792         }       
1793 }