]> git.jsancho.org Git - lugaru.git/blob - Source/OpenGL_Windows.cpp
Game builds and runs...need more input.
[lugaru.git] / Source / OpenGL_Windows.cpp
1
2 #ifdef WIN32
3 #include <vld.h>
4 #endif
5
6 #include "Game.h"
7 #include "IL/il.h"
8 #include "IL/ilu.h"
9 #include "IL/ilut.h"
10
11 // ADDED GWC
12 #ifdef _MSC_VER
13 #pragma comment(lib, "opengl32.lib")
14 #pragma comment(lib, "glu32.lib")
15 #pragma comment(lib, "glaux.lib")
16 #endif
17
18 extern bool buttons[3];
19 extern float multiplier;
20 extern float screenwidth,screenheight;
21 extern float sps;
22 extern float realmultiplier;
23 extern int slomo;
24 extern bool ismotionblur;
25 extern float usermousesensitivity;
26 extern int detail;
27 extern bool floatjump;
28 extern bool cellophane;
29 // MODIFIED GWC
30 //extern int terraindetail;
31 //extern int texdetail;
32 extern float terraindetail;
33 extern float texdetail;
34 extern int bloodtoggle;
35 extern bool osx;
36 extern bool autoslomo;
37 extern bool foliage;
38 extern bool musictoggle;
39 extern bool trilinear;
40 extern float gamespeed;
41 extern int difficulty;
42 extern bool damageeffects;
43 extern int numplayers;
44 extern bool decals;
45 extern bool invertmouse;
46 extern bool texttoggle;
47 extern bool ambientsound;
48 extern bool mousejump;
49 extern bool freeze;
50 extern Person player[maxplayers];
51 extern bool vblsync;
52 extern bool stillloading;
53 extern bool showpoints;
54 extern bool alwaysblur;
55 extern bool immediate;
56 extern bool velocityblur;
57 extern bool debugmode;
58 extern int mainmenu;
59 /*extern*/ bool gameFocused;
60 extern int kBitsPerPixel;
61 extern float slomospeed;
62 extern float slomofreq;
63 extern float oldgamespeed;
64 extern float volume;
65
66 #include <math.h>
67 #include <stdio.h>
68 #include <string.h>
69 #include <fstream>
70 #include <iostream>
71 #include "gamegl.h"
72 #include "MacCompatibility.h"
73
74 #ifdef WIN32
75 #include <shellapi.h>
76 #endif
77
78 #include "fmod.h"
79
80 #include "res/resource.h"
81
82 using namespace std;
83
84
85 unsigned int resolutionDepths[8][2] = {0};
86
87 bool selectDetail(int & width, int & height, int & bpp, int & detail);
88 int closestResolution(int width, int height);
89 int resolutionID(int width, int height);
90
91 void ReportError (char * strError);
92
93 void SetupDSpFullScreen();
94 void ShutdownDSp();
95
96 void DrawGL(Game & game);
97
98 void CreateGLWindow (void);
99 Boolean SetUp (Game & game);
100 void DoKey (SInt8 theKey, SInt8 theCode);
101 void DoUpdate (Game & game);
102
103 void DoEvent (void);
104 void CleanUp (void);
105
106
107 // statics/globals (internal only) ------------------------------------------
108 #ifndef WIN32
109 typedef struct tagPOINT { 
110   int x;
111   int y;
112 } POINT, *PPOINT; 
113 #endif
114
115 #if USE_SDL
116 void sdlGetCursorPos(POINT *pt)
117 {
118     int x, y;
119     SDL_GetMouseState(&x, &y);
120     pt->x = x;
121     pt->y = y;
122 }
123 #define GetCursorPos(x) sdlGetCursorPos(x)
124 #define SetCursorPos(x, y) SDL_WarpMouse(x, y)
125 #define ScreenToClient(x, pt)
126 #define ClientToScreen(x, pt)
127 #define MessageBox(hwnd,text,title,flags) STUBBED("msgbox")
128 #endif
129
130 Point delta;
131
132 #ifdef WIN32
133 static const char g_wndClassName[]={ "LUGARUWINDOWCLASS" };
134 static HINSTANCE g_appInstance;
135 static HWND g_windowHandle;
136 static HGLRC hRC;
137 #endif
138
139 static bool g_button, fullscreen = true;
140
141
142 // Menu defs
143 enum 
144 {
145         kFileQuit = 1
146 };
147
148 enum 
149 {
150         kForegroundSleep = 10,
151         kBackgroundSleep = 10000
152 };
153
154
155 int kContextWidth;
156 int kContextHeight;
157
158 const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 };
159
160 GLuint gFontList;
161 char gcstrMode [256] = "";
162
163 UInt32 gSleepTime = kForegroundSleep;
164 Boolean gDone = false, gfFrontProcess = true;
165
166 Game * pgame = 0;
167
168 // --------------------------------------------------------------------------
169
170 void ReportError (char * strError)
171 {
172 #ifdef WIN32  // !!! FIXME.  --ryan.
173         throw std::exception( strError);
174 #endif
175
176         /*      char errMsgCStr [256];
177         Str255 strErr;
178
179         sprintf (errMsgCStr, "%s", strError); 
180
181         // out as debug string
182         CToPStr (strErr, errMsgCStr);
183         DebugStr (strErr);
184         */
185 }
186
187 void SetupDSpFullScreen ()
188 {
189 #ifdef WIN32
190         LOGFUNC;
191
192         if (fullscreen)
193         {
194                 DEVMODE dmScreenSettings;
195                 memset( &dmScreenSettings, 0, sizeof( dmScreenSettings));
196                 dmScreenSettings.dmSize = sizeof( dmScreenSettings);
197                 dmScreenSettings.dmPelsWidth    = kContextWidth;
198                 dmScreenSettings.dmPelsHeight   = kContextHeight;
199                 dmScreenSettings.dmBitsPerPel   = kBitsPerPixel;
200                 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
201
202                 // set video mode
203                 if (ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
204                 {
205                         ReportError( "Could not set display mode");
206                         return;
207                 }
208         }
209
210         ShowCursor(FALSE);
211 #endif
212 }
213
214
215 void ShutdownDSp ()
216 {
217 #ifdef WIN32
218         LOGFUNC;
219
220         if (fullscreen)
221         {
222                 ChangeDisplaySettings( NULL, 0);
223         }
224
225         ShowCursor(TRUE);
226 #endif
227 }
228
229
230 //-----------------------------------------------------------------------------------------------------------------------
231
232 // OpenGL Drawing
233
234 void DrawGL (Game & game)
235 {
236 #ifdef WIN32
237         if (hDC == 0)
238                 return;
239 #endif
240
241         game.DrawGLScene();
242 }
243
244
245 #if USE_SDL
246 static inline int clamp_sdl_mouse_button(Uint8 button)
247 {
248     if ((button >= 1) && (button <= 3))
249         return button - 1;
250     return -1;
251 }
252
253 static void sdlEventProc(const SDL_Event &e)
254 {
255     int val;
256     switch(e.type)
257         {
258                 case SDL_MOUSEBUTTONDOWN:
259                         {
260                 val = clamp_sdl_mouse_button(e.button.button);
261                 if (val >= 0)
262                 {
263                     if (val == 0)
264                                     g_button = true;
265                                 buttons[val] = true;
266                 }
267                         }
268                         return;
269
270                 case SDL_MOUSEBUTTONUP:
271                         {
272                 val = clamp_sdl_mouse_button(e.button.button);
273                 if (val >= 0)
274                 {
275                     if (val == 0)
276                                     g_button = false;
277                                 buttons[val] = false;
278                 }
279                         }
280             return;
281     }
282 }
283 #endif
284
285 // --------------------------------------------------------------------------
286
287 static Point gMidPoint;
288
289 Boolean SetUp (Game & game)
290 {
291         char string[10];
292
293         LOGFUNC;
294
295         randSeed = UpTime().lo;
296
297         osx = 0;
298 //      ifstream ipstream(":Data:config.txt", std::ios::in /*| std::ios::nocreate*/);
299         ifstream ipstream("./Data/config.txt", std::ios::in /*| std::ios::nocreate*/);
300         detail=1;
301         ismotionblur=0;
302         usermousesensitivity=1;
303         kContextWidth=640;
304         kContextHeight=480;
305         kBitsPerPixel = 32;
306         floatjump=0;
307         cellophane=0;
308         texdetail=4;
309         autoslomo=1;
310         decals=1;
311         invertmouse=0;
312         bloodtoggle=0;
313         terraindetail=2;
314         foliage=1;
315         musictoggle=1;
316         trilinear=1;
317         gamespeed=1;
318         difficulty=1;
319         damageeffects=0;
320         texttoggle=1;
321         alwaysblur=0;
322         showpoints=0;
323         immediate=0;
324         velocityblur=0;
325
326         slomospeed=0.25;
327         slomofreq=8012;
328
329         volume = 0.8f;
330
331         game.crouchkey=MAC_SHIFT_KEY;
332         game.jumpkey=MAC_SPACE_KEY;
333         game.leftkey=MAC_A_KEY;
334         game.forwardkey=MAC_W_KEY;
335         game.backkey=MAC_S_KEY;
336         game.rightkey=MAC_D_KEY;
337         game.drawkey=MAC_E_KEY;
338         game.throwkey=MAC_Q_KEY;
339         game.attackkey=MAC_MOUSEBUTTON1;
340         game.chatkey=MAC_T_KEY;
341         numplayers=1;
342         ambientsound=1;
343         vblsync=0;
344         debugmode=0;
345
346         selectDetail(kContextWidth, kContextHeight, kBitsPerPixel, detail);
347
348         if(!ipstream) {
349                 //ofstream opstream(":Data:config.txt"); 
350                 ofstream opstream("./Data/config.txt"); 
351                 opstream << "Screenwidth:\n";
352                 opstream << kContextWidth;
353                 opstream << "\nScreenheight:\n";
354                 opstream << kContextHeight;
355                 opstream << "\nMouse sensitivity:\n";
356                 opstream << usermousesensitivity;
357                 opstream << "\nBlur(0,1):\n";
358                 opstream << ismotionblur;
359                 opstream << "\nOverall Detail(0,1,2) higher=better:\n";
360                 opstream << detail;
361                 opstream << "\nFloating jump:\n";
362                 opstream << floatjump;
363                 opstream << "\nMouse jump:\n";
364                 opstream << mousejump;
365                 opstream << "\nAmbient sound:\n";
366                 opstream << ambientsound;
367                 opstream << "\nBlood (0,1,2):\n";
368                 opstream << bloodtoggle;
369                 opstream << "\nAuto slomo:\n";
370                 opstream << autoslomo;
371                 opstream << "\nFoliage:\n";
372                 opstream << foliage;
373                 opstream << "\nMusic:\n";
374                 opstream << musictoggle;
375                 opstream << "\nTrilinear:\n";
376                 opstream << trilinear;
377                 opstream << "\nDecals(shadows,blood puddles,etc):\n";
378                 opstream << decals;
379                 opstream << "\nInvert mouse:\n";
380                 opstream << invertmouse;
381                 opstream << "\nGamespeed:\n";
382                 opstream << gamespeed;
383                 opstream << "\nDifficulty(0,1,2) higher=harder:\n";
384                 opstream << difficulty;
385                 opstream << "\nDamage effects(blackout, doublevision):\n";
386                 opstream << damageeffects;
387                 opstream << "\nText:\n";
388                 opstream << texttoggle;
389                 opstream << "\nDebug:\n";
390                 opstream << debugmode;
391                 opstream << "\nVBL Sync:\n";
392                 opstream << vblsync;
393                 opstream << "\nShow Points:\n";
394                 opstream << showpoints;
395                 opstream << "\nAlways Blur:\n";
396                 opstream << alwaysblur;
397                 opstream << "\nImmediate mode (turn on on G5):\n";
398                 opstream << immediate;
399                 opstream << "\nVelocity blur:\n";
400                 opstream << velocityblur;
401                 opstream << "\nVolume:\n";
402                 opstream << volume;
403                 opstream << "\nForward key:\n";
404                 opstream << KeyToChar(game.forwardkey);
405                 opstream << "\nBack key:\n";
406                 opstream << KeyToChar(game.backkey);
407                 opstream << "\nLeft key:\n";
408                 opstream << KeyToChar(game.leftkey);
409                 opstream << "\nRight key:\n";
410                 opstream << KeyToChar(game.rightkey);
411                 opstream << "\nJump key:\n";
412                 opstream << KeyToChar(game.jumpkey);
413                 opstream << "\nCrouch key:\n";
414                 opstream << KeyToChar(game.crouchkey);
415                 opstream << "\nDraw key:\n";
416                 opstream << KeyToChar(game.drawkey);
417                 opstream << "\nThrow key:\n";
418                 opstream << KeyToChar(game.throwkey);
419                 opstream << "\nAttack key:\n";
420                 opstream << KeyToChar(game.attackkey);
421                 opstream << "\nChat key:\n";
422                 opstream << KeyToChar(game.chatkey);
423                 opstream.close();
424         }
425         if(ipstream){
426                 int i;
427                 ipstream.ignore(256,'\n');
428                 ipstream >> kContextWidth;
429                 ipstream.ignore(256,'\n');
430                 ipstream.ignore(256,'\n');
431                 ipstream >> kContextHeight;
432                 ipstream.ignore(256,'\n');
433                 ipstream.ignore(256,'\n');
434                 ipstream >> usermousesensitivity;
435                 ipstream.ignore(256,'\n');
436                 ipstream.ignore(256,'\n');
437                 ipstream >> i;
438                 ismotionblur = (i != 0);
439                 ipstream.ignore(256,'\n');
440                 ipstream.ignore(256,'\n');
441                 ipstream >> detail;
442                 if(detail!=0)kBitsPerPixel=32;
443                 else kBitsPerPixel=16;
444                 ipstream.ignore(256,'\n');
445                 ipstream.ignore(256,'\n');
446                 ipstream >> i;
447                 floatjump = (i != 0);
448                 ipstream.ignore(256,'\n');
449                 ipstream.ignore(256,'\n');
450                 ipstream >> i;
451                 mousejump = (i != 0);
452                 ipstream.ignore(256,'\n');
453                 ipstream.ignore(256,'\n');
454                 ipstream >> i;
455                 ambientsound = (i != 0);
456                 ipstream.ignore(256,'\n');
457                 ipstream.ignore(256,'\n');
458                 ipstream >> bloodtoggle;
459                 ipstream.ignore(256,'\n');
460                 ipstream.ignore(256,'\n');
461                 ipstream >> i;
462                 autoslomo = (i != 0);
463                 ipstream.ignore(256,'\n');
464                 ipstream.ignore(256,'\n');
465                 ipstream >> i;
466                 foliage = (i != 0);
467                 ipstream.ignore(256,'\n');
468                 ipstream.ignore(256,'\n');
469                 ipstream >> i;
470                 musictoggle = (i != 0);
471                 ipstream.ignore(256,'\n');
472                 ipstream.ignore(256,'\n');
473                 ipstream >> i;
474                 trilinear = (i != 0);
475                 ipstream.ignore(256,'\n');
476                 ipstream.ignore(256,'\n');
477                 ipstream >> i;
478                 decals = (i != 0);
479                 ipstream.ignore(256,'\n');
480                 ipstream.ignore(256,'\n');
481                 ipstream >> i;
482                 invertmouse = (i != 0);
483                 ipstream.ignore(256,'\n');
484                 ipstream.ignore(256,'\n');
485                 ipstream >> gamespeed;
486                 oldgamespeed=gamespeed;
487                 if(oldgamespeed==0){
488                         gamespeed=1;
489                         oldgamespeed=1;
490                 }
491                 ipstream.ignore(256,'\n');
492                 ipstream.ignore(256,'\n');
493                 ipstream >> difficulty;
494                 ipstream.ignore(256,'\n');
495                 ipstream.ignore(256,'\n');
496                 ipstream >> i;
497                 damageeffects = (i != 0);
498                 ipstream.ignore(256,'\n');
499                 ipstream.ignore(256,'\n');
500                 ipstream >> i;
501                 texttoggle = (i != 0);
502                 ipstream.ignore(256,'\n');
503                 ipstream.ignore(256,'\n');
504                 ipstream >> i;
505                 debugmode = (i != 0);
506                 ipstream.ignore(256,'\n');
507                 ipstream.ignore(256,'\n');
508                 ipstream >> i;
509                 vblsync = (i != 0);
510                 ipstream.ignore(256,'\n');
511                 ipstream.ignore(256,'\n');
512                 ipstream >> i;
513                 showpoints = (i != 0);
514                 ipstream.ignore(256,'\n');
515                 ipstream.ignore(256,'\n');
516                 ipstream >> i;
517                 alwaysblur = (i != 0);
518                 ipstream.ignore(256,'\n');
519                 ipstream.ignore(256,'\n');
520                 ipstream >> i;
521                 immediate = (i != 0);
522                 ipstream.ignore(256,'\n');
523                 ipstream.ignore(256,'\n');
524                 ipstream >> i;
525                 velocityblur = (i != 0);
526                 ipstream.ignore(256,'\n');
527                 ipstream.ignore(256,'\n'); 
528                 ipstream >> volume;
529                 ipstream.ignore(256,'\n');
530                 ipstream.ignore(256,'\n'); 
531                 ipstream >> string;
532                 game.forwardkey=CharToKey(string);
533                 ipstream.ignore(256,'\n');
534                 ipstream.ignore(256,'\n');
535                 ipstream >> string;
536                 game.backkey=CharToKey(string);
537                 ipstream.ignore(256,'\n');
538                 ipstream.ignore(256,'\n');
539                 ipstream >> string;
540                 game.leftkey=CharToKey(string);
541                 ipstream.ignore(256,'\n');
542                 ipstream.ignore(256,'\n');
543                 ipstream >> string;
544                 game.rightkey=CharToKey(string);
545                 ipstream.ignore(256,'\n');
546                 ipstream.ignore(256,'\n');
547                 ipstream >> string;
548                 game.jumpkey=CharToKey(string);
549                 ipstream.ignore(256,'\n');
550                 ipstream.ignore(256,'\n');
551                 ipstream >> string;
552                 game.crouchkey=CharToKey(string);
553                 ipstream.ignore(256,'\n');
554                 ipstream.ignore(256,'\n');
555                 ipstream >> string;
556                 game.drawkey=CharToKey(string);
557                 ipstream.ignore(256,'\n');
558                 ipstream.ignore(256,'\n');
559                 ipstream >> string;
560                 game.throwkey=CharToKey(string);
561                 ipstream.ignore(256,'\n');
562                 ipstream.ignore(256,'\n');
563                 ipstream >> string;
564                 game.attackkey=CharToKey(string);
565                 ipstream.ignore(256,'\n');
566                 ipstream.ignore(256,'\n');
567                 ipstream >> string;
568                 game.chatkey=CharToKey(string);
569                 ipstream.close();
570
571                 if(detail>2)detail=2;
572                 if(detail<0)detail=0;
573                 if(screenwidth>3000)screenwidth=640;
574                 if(screenwidth<0)screenwidth=640;
575                 if(screenheight>3000)screenheight=480;
576                 if(screenheight<0)screenheight=480;
577         }
578         if(kBitsPerPixel!=32&&kBitsPerPixel!=16){
579                 kBitsPerPixel=16;
580         }
581
582
583         selectDetail(kContextWidth, kContextHeight, kBitsPerPixel, detail);
584
585         SetupDSpFullScreen();
586
587 #if USE_SDL
588     if (!SDL_WasInit(SDL_INIT_VIDEO))
589     {
590         if (SDL_Init(SDL_INIT_VIDEO) == -1)
591         {
592             fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
593             return false;
594         }
595     }
596
597     Uint32 sdlflags = SDL_OPENGL;
598     SDL_WM_SetCaption("Lugaru", "lugaru");
599     SDL_ShowCursor(0);
600     if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL)
601     {
602         fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError());
603         return false;
604     }
605
606 #elif (defined WIN32)
607         //------------------------------------------------------------------
608         // create window
609         int x = 0, y = 0;
610         RECT r = {0, 0, kContextWidth-1, kContextHeight-1};
611         DWORD dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE;
612         DWORD dwExStyle = WS_EX_APPWINDOW;
613
614         if (fullscreen)
615         {
616                 dwStyle |= WS_POPUP;
617         }
618         else
619         {
620
621                 dwStyle |= WS_OVERLAPPEDWINDOW;
622                 dwExStyle |= WS_EX_WINDOWEDGE;
623         }
624
625         AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
626
627         if (!fullscreen)
628         {
629                 x = (GetSystemMetrics(SM_CXSCREEN) >> 1) - ((r.right - r.left + 1) >> 1);
630                 y = (GetSystemMetrics(SM_CYSCREEN) >> 1) - ((r.bottom - r.top + 1) >> 1);
631         }
632
633         g_windowHandle=CreateWindowEx(
634                 dwExStyle,
635                 g_wndClassName, "Lugaru", dwStyle,
636                 x, y,
637 //              kContextWidth, kContextHeight,
638                 r.right - r.left + 1, r.bottom - r.top + 1,
639                 NULL,NULL,g_appInstance,NULL );
640         if (!g_windowHandle)
641         {
642                 ReportError("Could not create window");
643                 return false;
644         }
645
646         //------------------------------------------------------------------
647         // setup OpenGL
648
649         static PIXELFORMATDESCRIPTOR pfd =
650         {
651                 sizeof(PIXELFORMATDESCRIPTOR),                          // Size Of This Pixel Format Descriptor
652                         1,                                                                                      // Version Number
653                         PFD_DRAW_TO_WINDOW |                                            // Format Must Support Window
654                         PFD_SUPPORT_OPENGL |                                            // Format Must Support OpenGL
655                         PFD_DOUBLEBUFFER,                                                       // Must Support Double Buffering
656                         PFD_TYPE_RGBA,                                                          // Request An RGBA Format
657                         kBitsPerPixel,                                                          // Select Our Color Depth
658                         0, 0, 0, 0, 0, 0,                                                       // Color Bits Ignored
659                         0,                                                                                      // No Alpha Buffer
660                         0,                                                                                      // Shift Bit Ignored
661                         0,                                                                                      // No Accumulation Buffer
662                         0, 0, 0, 0,                                                                     // Accumulation Bits Ignored
663                         16,                                                                                     // 16Bit Z-Buffer (Depth Buffer)  
664                         0,                                                                                      // No Stencil Buffer
665                         0,                                                                                      // No Auxiliary Buffer
666                         PFD_MAIN_PLANE,                                                         // Main Drawing Layer
667                         0,                                                                                      // Reserved
668                         0, 0, 0                                                                         // Layer Masks Ignored
669         };
670
671         if (!(hDC = GetDC( g_windowHandle)))
672                 ReportError( "Could not get device context");
673
674         GLuint PixelFormat;
675         if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd)))
676         {
677                 ReportError( "Could not find appropriate pixel format");
678                 return false;
679         }
680
681         if (!DescribePixelFormat(hDC, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
682         {
683                 ReportError( "Could not retrieve pixel format");
684                 return false;
685         }
686
687         if (!SetPixelFormat( hDC, PixelFormat, &pfd))
688         {
689                 ReportError( "Could not set pixel format");
690                 return false;
691         }
692
693         if (!(hRC = wglCreateContext(hDC)))
694         {
695                 ReportError( "Could not create rendering context");
696                 return false;
697         }
698
699         if (!wglMakeCurrent(hDC, hRC))
700         {
701                 ReportError( "Could not activate rendering context");
702                 return false;
703         }
704
705         if (fullscreen)
706         {
707                 // Place the window above all topmost windows
708                 SetWindowPos( g_windowHandle, HWND_TOPMOST, 0,0,0,0,
709                         SWP_NOMOVE | SWP_NOSIZE );
710         }
711
712         SetForegroundWindow(g_windowHandle);
713         SetFocus(g_windowHandle);
714 #endif
715
716         glClear( GL_COLOR_BUFFER_BIT );
717         swap_gl_buffers();
718
719         // clear all states
720         glDisable( GL_ALPHA_TEST);
721         glDisable( GL_BLEND);
722         glDisable( GL_DEPTH_TEST);
723         //      glDisable( GL_DITHER);
724         glDisable( GL_FOG);
725         glDisable( GL_LIGHTING);
726         glDisable( GL_LOGIC_OP);
727         glDisable( GL_STENCIL_TEST);
728         glDisable( GL_TEXTURE_1D);
729         glDisable( GL_TEXTURE_2D);
730         glPixelTransferi( GL_MAP_COLOR, GL_FALSE);
731         glPixelTransferi( GL_RED_SCALE, 1);
732         glPixelTransferi( GL_RED_BIAS, 0);
733         glPixelTransferi( GL_GREEN_SCALE, 1);
734         glPixelTransferi( GL_GREEN_BIAS, 0);
735         glPixelTransferi( GL_BLUE_SCALE, 1);
736         glPixelTransferi( GL_BLUE_BIAS, 0);
737         glPixelTransferi( GL_ALPHA_SCALE, 1);
738         glPixelTransferi( GL_ALPHA_BIAS, 0);
739
740         // set initial rendering states
741         glShadeModel( GL_SMOOTH);
742         glClearDepth( 1.0f);
743         glDepthFunc( GL_LEQUAL);
744         glDepthMask( GL_TRUE);
745         //      glDepthRange( FRONT_CLIP, BACK_CLIP);
746         glEnable( GL_DEPTH_TEST);
747         glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
748         glCullFace( GL_FRONT);
749         glEnable( GL_CULL_FACE);
750         glEnable( GL_LIGHTING);
751 //      glEnable( GL_LIGHT_MODEL_AMBIENT);
752         glEnable( GL_DITHER);
753         glEnable( GL_COLOR_MATERIAL);
754         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
755         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
756         glAlphaFunc( GL_GREATER, 0.5f);
757
758         if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION ||
759                 iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION ||
760                 ilutGetInteger(ILUT_VERSION_NUM) < ILUT_VERSION)
761         {
762                 ReportError("DevIL version is different...exiting!\n");
763                 return false;
764         }
765
766         ilInit();
767         iluInit();
768         ilutInit();
769
770         ilutRenderer(ILUT_OPENGL);
771
772         ilEnable(IL_ORIGIN_SET);
773         ilOriginFunc(IL_ORIGIN_LOWER_LEFT);
774
775         GLint width = kContextWidth;
776         GLint height = kContextHeight;
777         gMidPoint.h = width / 2;
778         gMidPoint.v = height / 2;
779         screenwidth=width;
780         screenheight=height;
781
782         game.newdetail=detail;
783         game.newscreenwidth=screenwidth;
784         game.newscreenheight=screenheight;
785
786         game.InitGame();
787
788         return true;
789 }
790
791
792 static void DoMouse(Game & game)
793 {
794         static Point lastMouse = {-1,-1};
795         Point globalMouse;
796
797         POINT pos;
798         GetCursorPos(&pos);
799         ScreenToClient(g_windowHandle, &pos);
800         globalMouse.h = pos.x;
801         globalMouse.v = pos.y;
802
803         if (lastMouse.h == globalMouse.h && lastMouse.v == globalMouse.v)
804         {
805                 game.deltah=0;
806                 game.deltav=0;
807         }
808         else
809         {
810                 static Point virtualMouse = {0,0};
811                 delta = globalMouse;
812
813                 delta.h -= lastMouse.h;
814                 delta.v -= lastMouse.v;
815                 lastMouse.h = pos.x;
816                 lastMouse.v = pos.y;
817
818                 if(mainmenu||(abs(delta.h)<10*realmultiplier*1000&&abs(delta.v)<10*realmultiplier*1000)){
819                         game.deltah=delta.h*usermousesensitivity;
820                         game.deltav=delta.v*usermousesensitivity;
821                         game.mousecoordh=globalMouse.h;
822                         game.mousecoordv=globalMouse.v;
823                 }
824
825                 if(!mainmenu)
826                 {
827                         if(lastMouse.h>gMidPoint.h+100||lastMouse.h<gMidPoint.h-100||lastMouse.v>gMidPoint.v+100||lastMouse.v<gMidPoint.v-100){
828                                 pos.x = gMidPoint.h;
829                                 pos.y = gMidPoint.v;
830                                 ClientToScreen(g_windowHandle, &pos);
831                                 //SetCursorPos( gMidPoint.h,gMidPoint.v);
832                                 SetCursorPos(pos.x, pos.y);
833                                 lastMouse = gMidPoint;
834                         }
835                 }
836         }
837 }
838
839
840
841 // --------------------------------------------------------------------------
842
843 void DoKey (SInt8 theKey, SInt8 theCode)
844 {
845         // do nothing
846 }
847
848 // --------------------------------------------------------------------------
849
850
851
852 void DoFrameRate (int update)
853 {       
854         static long frames = 0;
855
856         static AbsoluteTime time = {0,0};
857         static AbsoluteTime frametime = {0,0};
858         AbsoluteTime currTime = UpTime ();
859         double deltaTime = (float) AbsoluteDeltaToDuration (currTime, frametime);
860
861         if (0 > deltaTime)      // if negative microseconds
862                 deltaTime /= -1000000.0;
863         else                            // else milliseconds
864                 deltaTime /= 1000.0;
865
866         multiplier=deltaTime;
867         if(multiplier<.001)multiplier=.001;
868         if(multiplier>10)multiplier=10;
869         if(update)frametime = currTime; // reset for next time interval
870
871         deltaTime = (float) AbsoluteDeltaToDuration (currTime, time);
872
873         if (0 > deltaTime)      // if negative microseconds
874                 deltaTime /= -1000000.0;
875         else                            // else milliseconds
876                 deltaTime /= 1000.0;
877         frames++;
878         if (0.001 <= deltaTime) // has update interval passed
879         {
880                 if(update){
881                         time = currTime;        // reset for next time interval
882                         frames = 0;
883                 }
884         }
885 }
886
887
888 void DoUpdate (Game & game)
889 {
890         static float sps=200;
891         static int count;
892         static float oldmult;
893
894         DoFrameRate(1);
895         if(multiplier>.6)multiplier=.6;
896
897         game.fps=1/multiplier;
898
899         count = multiplier*sps;
900         if(count<2)count=2;
901         //if(count>10)count=10;
902
903         realmultiplier=multiplier;
904         multiplier*=gamespeed;
905         if(difficulty==1)multiplier*=.9;
906         if(difficulty==0)multiplier*=.8;
907
908         if(game.loading==4)multiplier*=.00001;
909         //multiplier*.9;
910         if(slomo&&!mainmenu)multiplier*=slomospeed;
911         //if(freeze)multiplier*=0.00001;
912         oldmult=multiplier;
913         multiplier/=(float)count;
914
915         DoMouse(game);
916
917         game.TickOnce();
918
919         for(int i=0;i<count;i++)
920         {
921                 game.Tick();
922         }
923         multiplier=oldmult;
924
925         game.TickOnceAfter();
926 /* - Debug code to test how many channels were active on average per frame
927         static long frames = 0;
928
929         static AbsoluteTime start = {0,0};
930         AbsoluteTime currTime = UpTime ();
931         static int num_channels = 0;
932         
933         num_channels += FSOUND_GetChannelsPlaying();
934         double deltaTime = (float) AbsoluteDeltaToDuration (currTime, start);
935
936         if (0 > deltaTime)      // if negative microseconds
937                 deltaTime /= -1000000.0;
938         else                            // else milliseconds
939                 deltaTime /= 1000.0;
940
941         ++frames;
942
943         if (deltaTime >= 1)
944         {
945                 start = currTime;
946                 float avg_channels = (float)num_channels / (float)frames;
947
948                 ofstream opstream("log.txt",ios::app); 
949                 opstream << "Average frame count: ";
950                 opstream << frames;
951                 opstream << " frames - ";
952                 opstream << avg_channels;
953                 opstream << " per frame.\n";
954                 opstream.close();
955
956                 frames = 0;
957                 num_channels = 0;
958         }
959 */
960         DrawGL (game);
961 }
962
963 // --------------------------------------------------------------------------
964
965
966 void CleanUp (void)
967 {
968         LOGFUNC;
969
970 //      game.Dispose();
971
972         ilShutDown();
973
974 #if USE_SDL
975     SDL_Quit();
976
977 #elif (defined WIN32)
978         if (hRC)
979         {
980                 wglMakeCurrent( NULL, NULL);
981                 wglDeleteContext( hRC);
982                 hRC = NULL;
983         }
984
985         if (hDC)
986         {
987                 ReleaseDC( g_windowHandle, hDC);
988                 hDC = NULL;
989         }
990
991         if (g_windowHandle)
992         {
993                 ShowWindow( g_windowHandle, SW_HIDE );
994                 DestroyWindow( g_windowHandle);
995                 g_windowHandle = NULL;
996         }
997
998         ShutdownDSp ();
999         ClipCursor(NULL);
1000 #endif
1001 }
1002
1003 // --------------------------------------------------------------------------
1004
1005 static bool g_focused = true;
1006
1007
1008 static bool IsFocused()
1009 {
1010 #ifdef WIN32
1011         if (!g_focused)
1012                 return false;
1013
1014         if (GetActiveWindow() != g_windowHandle)
1015                 return false;
1016
1017         if (IsIconic( g_windowHandle))
1018                 return false;
1019 #endif
1020
1021         return true;
1022 }
1023
1024
1025 int main (void)
1026 {
1027         LOGFUNC;
1028
1029         try
1030         {
1031                 bool regnow = false;
1032                 {
1033                         Game game;
1034                         pgame = &game;
1035
1036                         //ofstream os("error.txt");
1037                         //os.close();
1038                         //ofstream os("log.txt");
1039                         //os.close();
1040
1041                         SetUp (game);
1042
1043                         while (!gDone&&!game.quit&&(!game.tryquit||!game.registered))
1044                         {
1045                                 if (IsFocused())
1046                                 {
1047                                         gameFocused = true;
1048
1049                                         // check windows messages
1050                     #if USE_SDL
1051                                         SDL_Event e;
1052                                         // message pump
1053                                         while( SDL_PollEvent( &e ) )
1054                                         {
1055                                                 if( e.type == SDL_QUIT )
1056                                                 {
1057                                                         gDone=true;
1058                                                         break;
1059                                                 }
1060                         sdlEventProc(e);
1061                                         }
1062                     #elif (defined WIN32)
1063                                         MSG msg;
1064                                         // message pump
1065                                         while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD ) )
1066                                         {
1067                                                 if( msg.message == WM_QUIT )
1068                                                 {
1069                                                         gDone=true;
1070                                                         break;
1071                                                 }
1072                                                 else
1073                                                 {
1074                                                         TranslateMessage( &msg );
1075                                                         DispatchMessage( &msg );
1076                                                 }
1077                                         }
1078                     #endif
1079
1080                                         // game
1081                                         DoUpdate(game);
1082                                 }
1083                                 else
1084                                 {
1085                                         if (gameFocused)
1086                                         {
1087                                                 // allow game chance to pause
1088                                                 gameFocused = false;
1089                                                 DoUpdate(game);
1090                                         }
1091
1092                                         // game is not in focus, give CPU time to other apps by waiting for messages instead of 'peeking'
1093                     #ifdef WIN32
1094                                         MSG msg;
1095                                         BOOL bRet;
1096                                         //if (GetMessage( &msg, g_windowHandle, 0, 0 ))
1097                                         /*if (GetMessage( &msg, NULL, 0, 0 ))
1098                                         {
1099                                                 TranslateMessage(&msg);
1100                                                 DispatchMessage(&msg);
1101                                         }*/
1102                                         if ( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
1103                                         { 
1104                                                 if (bRet <= 0)
1105                                                 {
1106                                                         // handle the error and possibly exit
1107                                                         gDone=true;
1108                                                 }
1109                                                 else
1110                                                 {
1111                                                         TranslateMessage(&msg); 
1112                                                         DispatchMessage(&msg); 
1113                                                 }
1114                                         }
1115                     #else
1116                     STUBBED("give up CPU but sniff the event queue");
1117                     #endif
1118                                 }
1119                         }
1120
1121                         regnow = game.registernow;
1122                 }
1123                 pgame = 0;
1124
1125                 CleanUp ();
1126 //              if(game.registernow){
1127                 if(regnow)
1128                 {
1129             #ifndef WIN32
1130             STUBBED("launch a web browser");
1131             #else
1132                         char url[100];
1133                         sprintf(url,"http://www.wolfire.com/registerpc.html");
1134                         //                      LaunchURL(url);
1135                         ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
1136             #endif
1137                 }
1138                 return 0;
1139         }
1140         catch (const std::exception& error)
1141         {
1142                 CleanUp();
1143
1144                 std::string e = "Caught exception: ";
1145                 e += error.what();
1146
1147                 LOG(e, Logger::LOG_ERR);
1148
1149                 MessageBox(g_windowHandle, error.what(), "ERROR", MB_OK | MB_ICONEXCLAMATION);
1150         }
1151
1152         CleanUp();
1153
1154         return -1;
1155 }
1156
1157
1158
1159         // --------------------------------------------------------------------------
1160
1161
1162 #define MAX_WINKEYS 256
1163         static unsigned short KeyTable[MAX_WINKEYS]=
1164         {
1165                 0xffff,  // (0)
1166                         MAC_MOUSEBUTTON1,  // VK_LBUTTON        (1)
1167                         MAC_MOUSEBUTTON2,  // VK_RBUTTON        (2)
1168                         0xffff,  // VK_CANCEL   (3)
1169                         0xffff,  // VK_MBUTTON  (4)
1170                         0xffff,  // (5)
1171                         0xffff,  // (6)
1172                         0xffff,  // (7)
1173                         MAC_DELETE_KEY,  // VK_BACK     (8)
1174                         MAC_TAB_KEY,  // VK_TAB (9)
1175                         0xffff,  // (10)
1176                         0xffff,  // (11)
1177                         0xffff,  // VK_CLEAR    (12)
1178                         MAC_RETURN_KEY,  // VK_RETURN   (13)
1179                         0xffff,  // (14)
1180                         0xffff,  // (15)
1181                         MAC_SHIFT_KEY,  // VK_SHIFT     (16)
1182                         MAC_CONTROL_KEY,  // VK_CONTROL (17)
1183                         MAC_OPTION_KEY,  // VK_MENU     (18)
1184                         0xffff,  // VK_PAUSE    (19)
1185                         MAC_CAPS_LOCK_KEY,  // #define VK_CAPITAL       (20)
1186                         0xffff,  // (21)
1187                         0xffff,  // (22)
1188                         0xffff,  // (23)
1189                         0xffff,  // (24)
1190                         0xffff,  // (25)
1191                         0xffff,  // (26)
1192                         MAC_ESCAPE_KEY,  // VK_ESCAPE   (27)
1193                         0xffff,  // (28)
1194                         0xffff,  // (29)
1195                         0xffff,  // (30)
1196                         0xffff,  // (31)
1197                         MAC_SPACE_KEY,  // VK_SPACE     (32)
1198                         MAC_PAGE_UP_KEY,  // VK_PRIOR   (33)
1199                         MAC_PAGE_DOWN_KEY,  // VK_NEXT  (34)
1200                         MAC_END_KEY,  // VK_END (35)
1201                         MAC_HOME_KEY,  // VK_HOME       (36)
1202                         MAC_ARROW_LEFT_KEY,  // VK_LEFT (37)
1203                         MAC_ARROW_UP_KEY,  // VK_UP     (38)
1204                         MAC_ARROW_RIGHT_KEY,  // VK_RIGHT       (39)
1205                         MAC_ARROW_DOWN_KEY,  // VK_DOWN (40)
1206                         0xffff,  // VK_SELECT   (41)
1207                         0xffff,  // VK_PRINT    (42)
1208                         0xffff,  // VK_EXECUTE  (43)
1209                         0xffff,  // VK_SNAPSHOT (44)
1210                         MAC_INSERT_KEY,  // VK_INSERT   (45)
1211                         MAC_DEL_KEY,  // VK_DELETE      (46)
1212                         0xffff,  // VK_HELP     (47)
1213                         MAC_0_KEY,  // VK_0     (48)
1214                         MAC_1_KEY,  // VK_1     (49)
1215                         MAC_2_KEY,  // VK_2     (50)
1216                         MAC_3_KEY,  // VK_3     (51)
1217                         MAC_4_KEY,  // VK_4     (52)
1218                         MAC_5_KEY,  // VK_5     (53)
1219                         MAC_6_KEY,  // VK_6     (54)
1220                         MAC_7_KEY,  // VK_7     (55)
1221                         MAC_8_KEY,  // VK_8     (56)
1222                         MAC_9_KEY,  // VK_9     (57)
1223                         0xffff,  // (58)
1224                         0xffff,  // (59)
1225                         0xffff,  // (60)
1226                         0xffff,  // (61)
1227                         0xffff,  // (62)
1228                         0xffff,  // (63)
1229                         0xffff,  // (64)
1230                         MAC_A_KEY,  // VK_A     (65)
1231                         MAC_B_KEY,  // VK_B     (66)
1232                         MAC_C_KEY,  // VK_C     (67)
1233                         MAC_D_KEY,  // VK_D     (68)
1234                         MAC_E_KEY,  // VK_E     (69)
1235                         MAC_F_KEY,  // VK_F     (70)
1236                         MAC_G_KEY,  // VK_G     (71)
1237                         MAC_H_KEY,  // VK_H     (72)
1238                         MAC_I_KEY,  // VK_I     (73)
1239                         MAC_J_KEY,  // VK_J     (74)
1240                         MAC_K_KEY,  // VK_K     (75)
1241                         MAC_L_KEY,  // VK_L     (76)
1242                         MAC_M_KEY,  // VK_M     (77)
1243                         MAC_N_KEY,  // VK_N     (78)
1244                         MAC_O_KEY,  // VK_O     (79)
1245                         MAC_P_KEY,  // VK_P     (80)
1246                         MAC_Q_KEY,  // VK_Q     (81)
1247                         MAC_R_KEY,  // VK_R     (82)
1248                         MAC_S_KEY,  // VK_S     (83)
1249                         MAC_T_KEY,  // VK_T     (84)
1250                         MAC_U_KEY,  // VK_U     (85)
1251                         MAC_V_KEY,  // VK_V     (86)
1252                         MAC_W_KEY,  // VK_W     (87)
1253                         MAC_X_KEY,  // VK_X     (88)
1254                         MAC_Y_KEY,  // VK_Y     (89)
1255                         MAC_Z_KEY,  // VK_Z     (90)
1256                         0xffff,  // (91)
1257                         0xffff,  // (92)
1258                         0xffff,  // (93)
1259                         0xffff,  // (94)
1260                         0xffff,  // (95)
1261                         MAC_NUMPAD_0_KEY,  // VK_NUMPAD0        (96)
1262                         MAC_NUMPAD_1_KEY,  // VK_NUMPAD1        (97)
1263                         MAC_NUMPAD_2_KEY,  // VK_NUMPAD2        (98)
1264                         MAC_NUMPAD_3_KEY,  // VK_NUMPAD3        (99)
1265                         MAC_NUMPAD_4_KEY,  // VK_NUMPAD4        (100)
1266                         MAC_NUMPAD_5_KEY,  // VK_NUMPAD5        (101)
1267                         MAC_NUMPAD_6_KEY,  // VK_NUMPAD6        (102)
1268                         MAC_NUMPAD_7_KEY,  // VK_NUMPAD7        (103)
1269                         MAC_NUMPAD_8_KEY,  // VK_NUMPAD8        (104)
1270                         MAC_NUMPAD_9_KEY,  // VK_NUMPAD9        (105)
1271                         MAC_NUMPAD_ASTERISK_KEY,  // VK_MULTIPLY        (106)
1272                         MAC_NUMPAD_PLUS_KEY,  // VK_ADD (107)
1273                         MAC_NUMPAD_ENTER_KEY,  // VK_SEPARATOR  (108)
1274                         MAC_NUMPAD_MINUS_KEY,  // VK_SUBTRACT   (109)
1275                         MAC_NUMPAD_PERIOD_KEY,  // VK_DECIMAL   (110)
1276                         MAC_NUMPAD_SLASH_KEY,  // VK_DIVIDE     (111)
1277                         MAC_F1_KEY,  // VK_F1   (112)
1278                         MAC_F2_KEY,  // VK_F2   (113)
1279                         MAC_F3_KEY,  // VK_F3   (114)
1280                         MAC_F4_KEY,  // VK_F4   (115)
1281                         MAC_F5_KEY,  // VK_F5   (116)
1282                         MAC_F6_KEY,  // VK_F6   (117)
1283                         MAC_F7_KEY,  // VK_F7   (118)
1284                         MAC_F8_KEY,  // VK_F8   (119)
1285                         MAC_F9_KEY,  // VK_F9   (120)
1286                         MAC_F10_KEY,  // VK_F10 (121)
1287                         MAC_F11_KEY,  // VK_F11 (122)
1288                         MAC_F12_KEY,  // VK_F12 (123)
1289                         0xffff,  // (124)
1290                         0xffff,  // (125)
1291                         0xffff,  // (126)
1292                         0xffff,  // (127)
1293                         0xffff,  // (128)
1294                         0xffff,  // (129)
1295                         0xffff,  // (130)
1296                         0xffff,  // (131)
1297                         0xffff,  // (132)
1298                         0xffff,  // (133)
1299                         0xffff,  // (134)
1300                         0xffff,  // (135)
1301                         0xffff,  // (136)
1302                         0xffff,  // (137)
1303                         0xffff,  // (138)
1304                         0xffff,  // (139)
1305                         0xffff,  // (130)
1306                         0xffff,  // (141)
1307                         0xffff,  // (142)
1308                         0xffff,  // (143)
1309                         0xffff,  // VK_NUMLOCK  (144)
1310                         0xffff,  // VK_SCROLL   (145)
1311                         0xffff,  // (146)
1312                         0xffff,  // (147)
1313                         0xffff,  // (148)
1314                         0xffff,  // (149)
1315                         0xffff,  // (150)
1316                         0xffff,  // (151)
1317                         0xffff,  // (152)
1318                         0xffff,  // (153)
1319                         0xffff,  // (154)
1320                         0xffff,  // (155)
1321                         0xffff,  // (156)
1322                         0xffff,  // (157)
1323                         0xffff,  // (158)
1324                         0xffff,  // (159)
1325                         MAC_SHIFT_KEY,  // VK_LSHIFT    (160)
1326                         MAC_SHIFT_KEY,  // VK_RSHIFT    (161)
1327                         MAC_CONTROL_KEY,  // VK_LCONTROL        (162)
1328                         MAC_CONTROL_KEY,  // VK_RCONTROL        (163)
1329                         MAC_OPTION_KEY,  // VK_LMENU    (164)
1330                         MAC_OPTION_KEY,  // VK_RMENU    (165)
1331                         0xffff,  // (166)
1332                         0xffff,  // (167)
1333                         0xffff,  // (168)
1334                         0xffff,  // (169)
1335                         0xffff,  // (170)
1336                         0xffff,  // (171)
1337                         0xffff,  // (172)
1338                         0xffff,  // (173)
1339                         0xffff,  // (174)
1340                         0xffff,  // (175)
1341                         0xffff,  // (176)
1342                         0xffff,  // (177)
1343                         0xffff,  // (178)
1344                         0xffff,  // (179)
1345                         0xffff,  // (180)
1346                         0xffff,  // (181)
1347                         0xffff,  // (182)
1348                         0xffff,  // (183)
1349                         0xffff,  // (184)
1350                         0xffff,  // (185)
1351                         MAC_SEMICOLON_KEY,  // (186)
1352                         MAC_PLUS_KEY,  // (187)
1353                         MAC_COMMA_KEY,  // (188)
1354                         MAC_MINUS_KEY,  // (189)
1355                         MAC_PERIOD_KEY,  // (190)
1356                         MAC_SLASH_KEY,  // (191)
1357                         MAC_TILDE_KEY,  // (192)
1358                         0xffff,  // (193)
1359                         0xffff,  // (194)
1360                         0xffff,  // (195)
1361                         0xffff,  // (196)
1362                         0xffff,  // (197)
1363                         0xffff,  // (198)
1364                         0xffff,  // (199)
1365                         0xffff,  // (200)
1366                         0xffff,  // (201)
1367                         0xffff,  // (202)
1368                         0xffff,  // (203)
1369                         0xffff,  // (204)
1370                         0xffff,  // (205)
1371                         0xffff,  // (206)
1372                         0xffff,  // (207)
1373                         0xffff,  // (208)
1374                         0xffff,  // (209)
1375                         0xffff,  // (210)
1376                         0xffff,  // (211)
1377                         0xffff,  // (212)
1378                         0xffff,  // (213)
1379                         0xffff,  // (214)
1380                         0xffff,  // (215)
1381                         0xffff,  // (216)
1382                         0xffff,  // (217)
1383                         0xffff,  // (218)
1384                         MAC_LEFTBRACKET_KEY,  // (219)
1385                         MAC_BACKSLASH_KEY,  // (220)
1386                         MAC_RIGHTBRACKET_KEY,  // (221)
1387                         MAC_APOSTROPHE_KEY,  // (222)
1388                         0xffff,  // (223)
1389                         0xffff,  // (224)
1390                         0xffff,  // (225)
1391                         0xffff,  // (226)
1392                         0xffff,  // (227)
1393                         0xffff,  // (228)
1394                         0xffff,  // (229)
1395                         0xffff,  // (230)
1396                         0xffff,  // (231)
1397                         0xffff,  // (232)
1398                         0xffff,  // (233)
1399                         0xffff,  // (234)
1400                         0xffff,  // (235)
1401                         0xffff,  // (236)
1402                         0xffff,  // (237)
1403                         0xffff,  // (238)
1404                         0xffff,  // (239)
1405                         0xffff,  // (240)
1406                         0xffff,  // (241)
1407                         0xffff,  // (242)
1408                         0xffff,  // (243)
1409                         0xffff,  // (244)
1410                         0xffff,  // (245)
1411                         0xffff,  // (246)
1412                         0xffff,  // (247)
1413                         0xffff,  // (248)
1414                         0xffff,  // (249)
1415                         0xffff,  // (250)
1416                         0xffff,  // (251)
1417                         0xffff,  // (252)
1418                         0xffff,  // (253)
1419                         0xffff,  // (254)
1420                         0xffff,  // (255)
1421         };
1422
1423
1424         static KeyMap g_theKeys;
1425
1426         void SetKey( int key)
1427         {
1428                 g_theKeys[ key >> 3] |= (1 << (key & 7));
1429         }
1430
1431         void ClearKey( int key)
1432         {
1433                 g_theKeys[ key >> 3] &= (0xff ^ (1 << (key & 7)));
1434         }
1435
1436         void GetKeys(  unsigned char theKeys[16])
1437         {
1438                 memcpy( theKeys, &g_theKeys, 16);
1439         }
1440
1441         Boolean Button()
1442         {
1443                 return g_button;
1444         }
1445
1446
1447 #ifdef WIN32
1448         void ClipMouseToWindow(HWND window)
1449         {
1450                 RECT wRect;
1451
1452                 GetClientRect(window, &wRect);
1453
1454                 ClientToScreen(window, (LPPOINT)&wRect.left);
1455                 ClientToScreen(window, (LPPOINT)&wRect.right);
1456
1457                 ClipCursor(&wRect);
1458
1459                 return;
1460         }
1461
1462         LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
1463         {
1464                 /* this is where we receive all messages concerning this window
1465                 * we can either process a message or pass it on to the default
1466                 * message handler of windows */
1467
1468                 static PAINTSTRUCT ps;
1469
1470                 switch(msg)
1471                 {
1472                 case WM_ACTIVATE:       // Watch For Window Activate Message
1473                         {
1474                                 // Check Minimization State
1475                                 BOOL iconified = HIWORD(wParam) ? TRUE : FALSE;
1476
1477                                 if (LOWORD(wParam) == WA_INACTIVE)
1478                                 {
1479                                         ClipCursor(NULL);
1480
1481                                         if (fullscreen)
1482                                         {
1483                                                 if( !iconified )
1484                                                 {
1485                                                         // Minimize window
1486                                                         CloseWindow( hWnd );
1487
1488                                                         // The window is now iconified
1489                                                         iconified = GL_TRUE;
1490                                                 }
1491                                         }
1492
1493                                         ShutdownDSp();
1494
1495                                         g_focused=false;                                // Program Is Active
1496                                 }
1497                                 else
1498                                 {
1499                                         SetupDSpFullScreen();
1500
1501                                         if( iconified )
1502                                         {
1503                                                 // Minimize window
1504                                                 OpenIcon( hWnd );
1505
1506                                                 // The window is now iconified
1507                                                 iconified = GL_FALSE;
1508
1509                                                 // Activate window
1510                                                 ShowWindow( hWnd, SW_SHOW );
1511                                                 SetForegroundWindow( hWnd );
1512                                                 SetFocus( hWnd );
1513                                         }
1514
1515                                         ClipMouseToWindow(hWnd);
1516                                         g_focused=true;                 // Program Is No Longer Active
1517                                 }
1518
1519                                 return 0;                                               // Return To The Message Loop
1520                         }
1521
1522                 case WM_KEYDOWN:
1523                 case WM_SYSKEYDOWN:
1524                         {
1525                                 // check for Alt-F4 (exit hotkey)
1526                                 if (wParam == VK_F4)
1527                                 {
1528                                         if (GetKeyState( VK_MENU) & 0x8080)
1529                                         {
1530                                                 gDone = true;
1531                                                 break;
1532                                         }
1533                                 }
1534                                 if (wParam < MAX_WINKEYS)
1535                                 {
1536                                         if (KeyTable[wParam] != 0xffff)
1537                                                 SetKey( KeyTable[wParam]);
1538                                 }
1539                                 return (0);
1540                         }
1541
1542                 case WM_KEYUP:
1543                 case WM_SYSKEYUP:
1544                         {
1545                                 if (wParam < MAX_WINKEYS)
1546                                         if (KeyTable[wParam] != 0xffff)
1547                                                 ClearKey( KeyTable[wParam]);
1548                                 return (0);
1549                         }
1550
1551                 case WM_CHAR:
1552                 case WM_DEADCHAR:
1553                 case WM_SYSCHAR:
1554                 case WM_SYSDEADCHAR:
1555                         return (0);
1556
1557                 case WM_NCLBUTTONDOWN:
1558                 case WM_LBUTTONDOWN:
1559                         {
1560                                 g_button = true;
1561                                 buttons[ 0] = true;
1562                         }
1563                         return (0);
1564
1565                 case WM_NCRBUTTONDOWN:
1566                 case WM_RBUTTONDOWN:
1567                         {
1568                                 buttons[ 1] = true;
1569                         }
1570                         return (0);
1571
1572                 case WM_NCMBUTTONDOWN:
1573                 case WM_MBUTTONDOWN:
1574                         {
1575                                 buttons[ 2] = true;
1576                         }
1577                         return (0);
1578
1579                 case WM_NCLBUTTONUP:
1580                 case WM_LBUTTONUP:
1581                         {
1582                                 g_button = false;
1583                                 buttons[ 0] = false;
1584                         }
1585                         return (0);
1586
1587                 case WM_NCRBUTTONUP:
1588                 case WM_RBUTTONUP:
1589                         {
1590                                 buttons[ 1] = false;
1591                         }
1592                         return (0);
1593
1594                 case WM_NCMBUTTONUP:
1595                 case WM_MBUTTONUP:
1596                         {
1597                                 buttons[ 2] = false;
1598                         }
1599                         return (0);
1600
1601                 case WM_NCLBUTTONDBLCLK:
1602                 case WM_NCRBUTTONDBLCLK:
1603                 case WM_NCMBUTTONDBLCLK:
1604                 case WM_LBUTTONDBLCLK:
1605                         return (0);
1606                 case WM_RBUTTONDBLCLK:
1607                 case WM_MBUTTONDBLCLK:
1608                         return (0);
1609
1610                 case WM_NCMOUSEMOVE:
1611                 case WM_MOUSEMOVE:
1612                         /*                      ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseX = (signed short)(lParam & 0xffff);
1613                         ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseY = (signed short)(lParam >> 16);
1614                         if (g_lastWindow->m_mouseCallbacksEnabled) g_lastWindow->MouseMoveCallback();
1615                         *///                    goto winmessage;
1616                         return (0);
1617
1618                 case WM_SYSCOMMAND:                                             // Intercept System Commands
1619                         {
1620                                 switch (wParam)                                         // Check System Calls
1621                                 {
1622                                 case SC_SCREENSAVE:                             // Screensaver Trying To Start?
1623                                 case SC_MONITORPOWER:                   // Monitor Trying To Enter Powersave?
1624                                         return 0;                                       // Prevent From Happening
1625
1626                                         // User trying to access application menu using ALT?
1627                                 case SC_KEYMENU:
1628                                         return 0;
1629                                 }
1630                         }
1631                         break;
1632
1633                 case WM_MOVE:
1634 //                      {
1635 //                              ReleaseCapture();
1636 //                              ClipMouseToWindow(hWnd);
1637 //                      }
1638                         break;
1639
1640                 case WM_SIZE:
1641                         break;
1642
1643                 case WM_CLOSE:
1644                         {
1645                                 //gDone =  true;
1646                                 //game.tryquit=1;
1647                         }
1648                         //return (0);
1649
1650                 case WM_DESTROY:
1651                         {
1652                                 //ClipCursor(NULL);
1653                                 PostQuitMessage(0);  /* Terminate Application */
1654                         }
1655                         return (0);
1656
1657                 case WM_ERASEBKGND:
1658                         break;
1659
1660                 case WM_PAINT:
1661 //                      BeginPaint( g_windowHandle,&ps);
1662 //                      EndPaint( g_windowHandle,&ps);
1663                         break;
1664
1665                 default:
1666                         break;
1667                 }
1668
1669                 /* We processed the message and there
1670                 * is no processing by Windows necessary */
1671
1672                 /* We didn't process the message so let Windows do it */
1673                 return DefWindowProc(hWnd,msg,wParam,lParam);
1674         }
1675
1676
1677         static BOOL RegisterWindowClasses(HINSTANCE hFirstInstance)
1678         {
1679                 WNDCLASSEX wc;
1680                 memset( &wc, 0, sizeof( wc));
1681
1682                 /* Register the window class. */
1683                 wc.cbSize = sizeof(wc);
1684 #undef style
1685                 wc.style = (CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC);  /* Combination of Class Styles */
1686                 wc.lpfnWndProc = AppWndProc;       /* Adress of Window Procedure */
1687                 wc.cbClsExtra = 0;                 /* Extra Bytes allocated for this Class */
1688                 wc.cbWndExtra = 0;                 /* Extra Bytes allocated for each Window */
1689                 wc.hInstance = hFirstInstance;     /* Handle of program instance */
1690                 wc.hIcon = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) );
1691                 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1692                 wc.hbrBackground = NULL;
1693                 wc.lpszMenuName  = NULL;
1694                 wc.lpszClassName = g_wndClassName; /* Name of the Window Class */
1695                 wc.hIconSm = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) );
1696
1697                 if (!RegisterClassEx(&wc)) return FALSE;  /* Register Class failed */
1698
1699                 return TRUE;
1700         }
1701 #endif
1702
1703         int resolutionID(int width, int height)
1704         {
1705                 int whichres;
1706                 whichres=-1;
1707                 if(width==640 && height==480)whichres=0;
1708                 if(width==800 && height==600)whichres=1;
1709                 if(width==1024 && height==768)whichres=2;
1710                 if(width==1280 && height==1024)whichres=3;
1711                 if(width==1600 && height==1200)whichres=4;
1712                 if(width==840 && height==524)whichres=5;
1713                 if(width==1024 && height==640)whichres=6;
1714                 if(width==1344 && height==840)whichres=7;
1715
1716                 return whichres;
1717         }
1718
1719         int closestResolution(int width, int height)
1720         {
1721                 int whichres;
1722                 whichres=-1;
1723                 if(width>=640 && height>=480)whichres=0;
1724                 if(width>=800 && height>=600)whichres=1;
1725                 if(width>=1024 && height>=768)whichres=2;
1726                 if(width>=1280 && height>=1024)whichres=3;
1727                 if(width>=1600 && height>=1200)whichres=4;
1728                 if(width==840 && height==524)whichres=5;
1729                 if(width==1024 && height==640)whichres=6;
1730                 if(width==1344 && height==840)whichres=7;
1731
1732                 return whichres;
1733         }
1734
1735         bool selectDetail(int & width, int & height, int & bpp, int & detail)
1736         {
1737                 bool res = true;
1738                 int whichres = closestResolution(width, height);
1739
1740                 while (true)
1741                 {
1742                         if(whichres<=0 || whichres>7){
1743                                 whichres = 0;
1744                                 width=640;
1745                                 height=480;
1746                         }
1747                         if(whichres==1){
1748                                 width=800;
1749                                 height=600;
1750                         }
1751                         if(whichres==2){
1752                                 width=1024;
1753                                 height=768;
1754                         }
1755                         if(whichres==3){
1756                                 width=1280;
1757                                 height=1024;
1758                         }
1759                         if(whichres==4){
1760                                 width=1600;
1761                                 height=1200;
1762                         }
1763                         if(whichres==5){
1764                                 width=840;
1765                                 height=524;
1766                         }
1767                         if(whichres==6){
1768                                 width=1024;
1769                                 height=640;
1770                         }
1771                         if(whichres==7){
1772                                 width=1344;
1773                                 height=840;
1774                         }
1775
1776                         if ((detail != 0) && (resolutionDepths[whichres][1] != 0))
1777                         {
1778                                 break;
1779                         }
1780                         else if ((detail == 0) && (resolutionDepths[whichres][0] != 0))
1781                         {
1782                                 break;
1783                         }
1784                         else if ((detail != 0) && (resolutionDepths[whichres][0] != 0))
1785                         {
1786                                 res = false;
1787                                 detail = 0;
1788                                 break;
1789                         }
1790                         else if (0 == whichres)
1791                         {
1792                                 break;
1793                         }
1794
1795                         --whichres;
1796                 }
1797
1798                 bpp = resolutionDepths[whichres][(detail != 0)];
1799
1800                 return res;
1801         }
1802
1803     #ifdef WIN32
1804         int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
1805         {
1806                 int argc = 0;
1807                 LPWSTR * cl = CommandLineToArgvW(GetCommandLineW(), &argc);
1808                 if (argc > 1)
1809                 {
1810                         if (0 == _wcsicmp(cl[1], L"-windowed"))
1811                         {
1812                                 fullscreen = false;
1813                         }
1814                 }
1815
1816                 logger.start(true);
1817
1818                 memset( &g_theKeys, 0, sizeof( KeyMap));
1819
1820                 unsigned int i = 0;
1821                 DEVMODE mode;
1822                 memset(&mode, 0, sizeof(mode));
1823                 mode.dmSize = sizeof(mode);
1824                 while (EnumDisplaySettings(NULL, i++, &mode))
1825                 {
1826                         if (mode.dmBitsPerPel < 16)
1827                         {
1828                                 continue;
1829                         }
1830
1831                         int res = resolutionID(mode.dmPelsWidth, mode.dmPelsHeight);
1832
1833                         if (res > -1 && res < 8)
1834                         {
1835                                 if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&mode, CDS_TEST))
1836                                 {
1837                                         continue;
1838                                 }
1839
1840                                 switch(mode.dmBitsPerPel)
1841                                 {
1842                                 case 32:
1843                                 case 24:
1844                                         resolutionDepths[res][1] = mode.dmBitsPerPel;
1845                                         break;
1846                                 case 16:
1847                                         resolutionDepths[res][0] = mode.dmBitsPerPel;
1848                                         break;
1849                                 }
1850                         }
1851                 }
1852
1853                 /* if there is no Instance of our program in memory then register the window class */
1854                 if (hPrevInstance == NULL && !RegisterWindowClasses(hInstance))
1855                         return FALSE;  /* registration failed! */
1856
1857                 g_appInstance=hInstance;
1858
1859                 main();
1860
1861                 UnregisterClass( g_wndClassName, hInstance);
1862
1863                 return TRUE;
1864
1865         }
1866     #endif
1867
1868         extern int channels[100];
1869         extern FSOUND_SAMPLE * samp[100];
1870         extern FSOUND_STREAM * strm[10];
1871
1872         extern "C" void PlaySoundEx(int chan, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused)
1873         {
1874                 const FSOUND_SAMPLE * currSample = FSOUND_GetCurrentSample(channels[chan]);
1875                 if (currSample && currSample == samp[chan])
1876                 {
1877                         if (FSOUND_GetPaused(channels[chan]))
1878                         {
1879                                 FSOUND_StopSound(channels[chan]);
1880                                 channels[chan] = FSOUND_FREE;
1881                         }
1882                         else if (FSOUND_IsPlaying(channels[chan]))
1883                         {
1884                                 int loop_mode = FSOUND_GetLoopMode(channels[chan]);
1885                                 if (loop_mode & FSOUND_LOOP_OFF)
1886                                 {
1887                                         channels[chan] = FSOUND_FREE;
1888                                 }
1889                         }
1890                 }
1891                 else
1892                 {
1893                         channels[chan] = FSOUND_FREE;
1894                 }
1895
1896                 channels[chan] = FSOUND_PlaySoundEx(channels[chan], sptr, dsp, startpaused);
1897                 if (channels[chan] < 0)
1898                 {
1899                         channels[chan] = FSOUND_PlaySoundEx(FSOUND_FREE, sptr, dsp, startpaused);
1900                 }
1901         }
1902
1903         extern "C" void PlayStreamEx(int chan, FSOUND_STREAM *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused)
1904         {
1905                 const FSOUND_SAMPLE * currSample = FSOUND_GetCurrentSample(channels[chan]);
1906                 if (currSample && currSample == FSOUND_Stream_GetSample(sptr))
1907                 {
1908                                 FSOUND_StopSound(channels[chan]);
1909                                 FSOUND_Stream_Stop(sptr);
1910                 }
1911                 else
1912                 {
1913                         FSOUND_Stream_Stop(sptr);
1914                         channels[chan] = FSOUND_FREE;
1915                 }
1916
1917                 channels[chan] = FSOUND_Stream_PlayEx(channels[chan], sptr, dsp, startpaused);
1918                 if (channels[chan] < 0)
1919                 {
1920                         channels[chan] = FSOUND_Stream_PlayEx(FSOUND_FREE, sptr, dsp, startpaused);
1921                 }
1922         }
1923
1924         bool LoadImage(const char * fname, TGAImageRec & tex)
1925         {
1926                 bool res = true;
1927
1928                 if ( tex.data == NULL )
1929                 {
1930                         return false;
1931                 }
1932
1933                 ILstring f = strdup(ConvertFileName(fname));
1934                 if (!f)
1935                 {
1936                         return false;
1937                 }
1938
1939                 ILuint iid=0;
1940                 ilGenImages(1, &iid);
1941                 ilBindImage(iid);
1942                 if (ilLoadImage(f))
1943                 {
1944                         //iluFlipImage();
1945                         tex.sizeX = ilGetInteger(IL_IMAGE_WIDTH);
1946                         tex.sizeY = ilGetInteger(IL_IMAGE_HEIGHT);
1947                         tex.bpp = ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
1948                         ILuint Bpp = ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL),
1949                                 imageSize = tex.sizeX * tex.sizeY * Bpp;
1950                         ILubyte *Data = ilGetData();
1951                         memcpy(tex.data, Data, imageSize);
1952
1953                         // Truvision Targa files are stored as BGR colors
1954                         // We want RGB so Blue and Red bytes are switched
1955                         if (IL_TGA == ilGetInteger(IL_IMAGE_FORMAT))
1956                         {
1957                                 // Loop Through The Image Data
1958                                 for (GLuint i = 0; i < int(imageSize); i += Bpp)
1959                                 {
1960                                         // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
1961                                         GLbyte temp;                                            // Temporary Variable
1962                                         temp = tex.data[i];                                     // Temporarily Store The Value At Image Data 'i'
1963                                         tex.data[i] = tex.data[i + 2];          // Set The 1st Byte To The Value Of The 3rd Byte
1964                                         tex.data[i + 2] = temp;                         // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
1965                                 }
1966                         }
1967                 }
1968                 else
1969                 {
1970                         res = false;
1971                 }
1972                 ilDeleteImages(1, &iid);
1973 /*
1974                 if (tid)
1975                 {
1976                         GLuint texid = ilutGLLoadImage(f);
1977                         *tid = texid;
1978                 }
1979                 else if (mip)
1980                 {
1981                         ilutGLBuildMipmaps()
1982                 }
1983                 else
1984                 {
1985                         ilutGLTexImage(0);
1986                 }
1987 */
1988                 free(f);
1989
1990                 return res;
1991         }
1992
1993         void ScreenShot(const char * fname)
1994         {
1995                 ILstring f = strdup(fname);
1996                 if (!f)
1997                 {
1998                         return;
1999                 }
2000
2001                 ILuint iid;
2002                 ilGenImages(1, &iid);
2003                 ilBindImage(iid);
2004                 if (ilutGLScreen())
2005                 {
2006                         ilSaveImage(f);
2007                 }
2008                 ilDeleteImages(1, &iid);
2009
2010                 free(f);
2011         }
2012
2013