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