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