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