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