X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FOpenGL_Windows.cpp;h=27a1c3645727db98c6e6329f5dc1431a9e380ace;hb=3b05abdd90ab43f17da48a79cc0d0348e74b7d97;hp=dcc6c464889c49bc07e556a631d8c0871f49df28;hpb=36cc3af3e5074215817ddee16defde754e2ad67f;p=lugaru.git diff --git a/Source/OpenGL_Windows.cpp b/Source/OpenGL_Windows.cpp index dcc6c46..27a1c36 100644 --- a/Source/OpenGL_Windows.cpp +++ b/Source/OpenGL_Windows.cpp @@ -1,10 +1,69 @@ -#include -#include "Game.h" +/* +Copyright (C) 2003, 2010 - Wolfire Games + +This file is part of Lugaru. + +Lugaru is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifdef WIN32 +#define UINT8 WIN32API_UINT8 +#define UINT16 WIN32API_UINT16 +#define boolean WIN32API_boolean +#include +#undef UINT8 +#undef UINT16 +#undef boolean +#endif + +#define USE_DEVIL 0 + +#ifndef USE_DEVIL +# ifdef WIN32 +# define USE_DEVIL +# endif +#endif + +#if USE_DEVIL + #include "IL/il.h" + #include "IL/ilu.h" + #include "IL/ilut.h" + #include "Game.h" +#else + + #include "Game.h" + extern "C" { + #include "zlib.h" + #include "png.h" + #include "jpeglib.h" + } + + static bool load_image(const char * fname, TGAImageRec & tex); + static bool load_png(const char * fname, TGAImageRec & tex); + static bool load_jpg(const char * fname, TGAImageRec & tex); + static bool save_image(const char * fname); + static bool save_png(const char * fname); +#endif // ADDED GWC +#ifdef _MSC_VER #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glu32.lib") #pragma comment(lib, "glaux.lib") +#endif extern bool buttons[3]; extern float multiplier; @@ -61,7 +120,11 @@ extern float volume; #include #include "gamegl.h" #include "MacCompatibility.h" + +#ifdef WIN32 #include +#endif + #include "fmod.h" #include "res/resource.h" @@ -69,6 +132,20 @@ extern float volume; using namespace std; +#if USE_SDL +SDL_Rect **resolutions = NULL; +static SDL_Rect rect_1024_768 = { 0, 0, 1024, 768 }; +static SDL_Rect rect_800_600 = { 0, 0, 800, 600 }; +static SDL_Rect rect_640_480 = { 0, 0, 640, 480 }; +static SDL_Rect *hardcoded_resolutions[] = { + &rect_1024_768, + &rect_800_600, + &rect_640_480, + NULL +}; +#endif + + unsigned int resolutionDepths[8][2] = {0}; bool selectDetail(int & width, int & height, int & bpp, int & detail); @@ -92,14 +169,79 @@ void CleanUp (void); // statics/globals (internal only) ------------------------------------------ +#ifndef WIN32 +typedef struct tagPOINT { + int x; + int y; +} POINT, *PPOINT; +#endif + +#if USE_SDL + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4273) +#endif + +#define GL_FUNC(ret,fn,params,call,rt) \ + extern "C" { \ + static ret (GLAPIENTRY *p##fn) params = NULL; \ + ret GLAPIENTRY fn params { rt p##fn call; } \ + } +#include "glstubs.h" +#undef GL_FUNC + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +static bool lookup_glsym(const char *funcname, void **func) +{ + *func = SDL_GL_GetProcAddress(funcname); + if (*func == NULL) + { + fprintf(stderr, "Failed to find OpenGL symbol \"%s\"\n", funcname); + return false; + } + return true; +} + +static bool lookup_all_glsyms(void) +{ + bool retval = true; + #define GL_FUNC(ret,fn,params,call,rt) \ + if (!lookup_glsym(#fn, (void **) &p##fn)) retval = false; + #include "glstubs.h" + #undef GL_FUNC + return retval; +} + +static void GLAPIENTRY glDeleteTextures_doNothing(GLsizei n, const GLuint *textures) +{ + // no-op. +} + -Point delta; -static const char g_wndClassName[]={ "LUGARUWINDOWCLASS" }; +void sdlGetCursorPos(POINT *pt) +{ + int x, y; + SDL_GetMouseState(&x, &y); + pt->x = x; + pt->y = y; +} +#define GetCursorPos(x) sdlGetCursorPos(x) +#define SetCursorPos(x, y) SDL_WarpMouse(x, y) +#define ScreenToClient(x, pt) +#define ClientToScreen(x, pt) +#ifdef MessageBox +#undef MessageBox +#endif +#define MessageBox(hwnd,text,title,flags) STUBBED("msgbox") +#endif + +Point delta; -static HINSTANCE g_appInstance; -static HWND g_windowHandle; -static HGLRC hRC; static bool g_button, fullscreen = true; @@ -121,7 +263,6 @@ int kContextHeight; const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 }; -extern HDC hDC; GLuint gFontList; char gcstrMode [256] = ""; @@ -130,11 +271,33 @@ Boolean gDone = false, gfFrontProcess = true; Game * pgame = 0; +#ifndef __MINGW32__ +static int _argc = 0; +static char **_argv = NULL; +#endif + +bool cmdline(const char *cmd) +{ + for (int i = 1; i < _argc; i++) + { + char *arg = _argv[i]; + while (*arg == '-') + arg++; + if (strcasecmp(arg, cmd) == 0) + return true; + } + + return false; +} + + // -------------------------------------------------------------------------- void ReportError (char * strError) { +#ifdef _MSC_VER // !!! FIXME. --ryan. throw std::exception( strError); +#endif /* char errMsgCStr [256]; Str255 strErr; @@ -149,40 +312,11 @@ void ReportError (char * strError) void SetupDSpFullScreen () { - LOGFUNC; - - if (fullscreen) - { - DEVMODE dmScreenSettings; - memset( &dmScreenSettings, 0, sizeof( dmScreenSettings)); - dmScreenSettings.dmSize = sizeof( dmScreenSettings); - dmScreenSettings.dmPelsWidth = kContextWidth; - dmScreenSettings.dmPelsHeight = kContextHeight; - dmScreenSettings.dmBitsPerPel = kBitsPerPixel; - dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - - // set video mode - if (ChangeDisplaySettings( &dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - { - ReportError( "Could not set display mode"); - return; - } - } - - ShowCursor(FALSE); } void ShutdownDSp () { - LOGFUNC; - - if (fullscreen) - { - ChangeDisplaySettings( NULL, 0); - } - - ShowCursor(TRUE); } @@ -192,13 +326,249 @@ void ShutdownDSp () void DrawGL (Game & game) { - if (hDC == 0) - return; - game.DrawGLScene(); } +static KeyMap g_theKeys; + +void SetKey( int key) +{ + g_theKeys[ key >> 3] |= (1 << (key & 7)); +} + +void ClearKey( int key) +{ + g_theKeys[ key >> 3] &= (0xff ^ (1 << (key & 7))); +} + +void GetKeys( unsigned char theKeys[16]) +{ + memcpy( theKeys, &g_theKeys, 16); +} + +Boolean Button() +{ + return g_button; +} + +#if !USE_SDL +static void initSDLKeyTable(void) {} +#else +#define MAX_SDLKEYS SDLK_LAST +static unsigned short KeyTable[MAX_SDLKEYS]; + +static void initSDLKeyTable(void) +{ + memset(KeyTable, 0xFF, sizeof (KeyTable)); + KeyTable[SDLK_BACKSPACE] = MAC_DELETE_KEY; + KeyTable[SDLK_TAB] = MAC_TAB_KEY; + KeyTable[SDLK_RETURN] = MAC_RETURN_KEY; + KeyTable[SDLK_ESCAPE] = MAC_ESCAPE_KEY; + KeyTable[SDLK_SPACE] = MAC_SPACE_KEY; + KeyTable[SDLK_PAGEUP] = MAC_PAGE_UP_KEY; + KeyTable[SDLK_PAGEDOWN] = MAC_PAGE_DOWN_KEY; + KeyTable[SDLK_END] = MAC_END_KEY; + KeyTable[SDLK_HOME] = MAC_HOME_KEY; + KeyTable[SDLK_LEFT] = MAC_ARROW_LEFT_KEY; + KeyTable[SDLK_UP] = MAC_ARROW_UP_KEY; + KeyTable[SDLK_RIGHT] = MAC_ARROW_RIGHT_KEY; + KeyTable[SDLK_DOWN] = MAC_ARROW_DOWN_KEY; + KeyTable[SDLK_INSERT] = MAC_INSERT_KEY; + KeyTable[SDLK_DELETE] = MAC_DEL_KEY; + KeyTable[SDLK_0] = MAC_0_KEY; + KeyTable[SDLK_1] = MAC_1_KEY; + KeyTable[SDLK_2] = MAC_2_KEY; + KeyTable[SDLK_3] = MAC_3_KEY; + KeyTable[SDLK_4] = MAC_4_KEY; + KeyTable[SDLK_5] = MAC_5_KEY; + KeyTable[SDLK_6] = MAC_6_KEY; + KeyTable[SDLK_7] = MAC_7_KEY; + KeyTable[SDLK_8] = MAC_8_KEY; + KeyTable[SDLK_9] = MAC_9_KEY; + KeyTable[SDLK_a] = MAC_A_KEY; + KeyTable[SDLK_b] = MAC_B_KEY; + KeyTable[SDLK_c] = MAC_C_KEY; + KeyTable[SDLK_d] = MAC_D_KEY; + KeyTable[SDLK_e] = MAC_E_KEY; + KeyTable[SDLK_f] = MAC_F_KEY; + KeyTable[SDLK_g] = MAC_G_KEY; + KeyTable[SDLK_h] = MAC_H_KEY; + KeyTable[SDLK_i] = MAC_I_KEY; + KeyTable[SDLK_j] = MAC_J_KEY; + KeyTable[SDLK_k] = MAC_K_KEY; + KeyTable[SDLK_l] = MAC_L_KEY; + KeyTable[SDLK_m] = MAC_M_KEY; + KeyTable[SDLK_n] = MAC_N_KEY; + KeyTable[SDLK_o] = MAC_O_KEY; + KeyTable[SDLK_p] = MAC_P_KEY; + KeyTable[SDLK_q] = MAC_Q_KEY; + KeyTable[SDLK_r] = MAC_R_KEY; + KeyTable[SDLK_s] = MAC_S_KEY; + KeyTable[SDLK_t] = MAC_T_KEY; + KeyTable[SDLK_u] = MAC_U_KEY; + KeyTable[SDLK_v] = MAC_V_KEY; + KeyTable[SDLK_w] = MAC_W_KEY; + KeyTable[SDLK_x] = MAC_X_KEY; + KeyTable[SDLK_y] = MAC_Y_KEY; + KeyTable[SDLK_z] = MAC_Z_KEY; + KeyTable[SDLK_KP0] = MAC_NUMPAD_0_KEY; + KeyTable[SDLK_KP1] = MAC_NUMPAD_1_KEY; + KeyTable[SDLK_KP2] = MAC_NUMPAD_2_KEY; + KeyTable[SDLK_KP3] = MAC_NUMPAD_3_KEY; + KeyTable[SDLK_KP4] = MAC_NUMPAD_4_KEY; + KeyTable[SDLK_KP5] = MAC_NUMPAD_5_KEY; + KeyTable[SDLK_KP6] = MAC_NUMPAD_6_KEY; + KeyTable[SDLK_KP7] = MAC_NUMPAD_7_KEY; + KeyTable[SDLK_KP8] = MAC_NUMPAD_8_KEY; + KeyTable[SDLK_KP9] = MAC_NUMPAD_9_KEY; + KeyTable[SDLK_KP_MULTIPLY] = MAC_NUMPAD_ASTERISK_KEY; + KeyTable[SDLK_KP_PLUS] = MAC_NUMPAD_PLUS_KEY; + KeyTable[SDLK_KP_ENTER] = MAC_NUMPAD_ENTER_KEY; + KeyTable[SDLK_KP_MINUS] = MAC_NUMPAD_MINUS_KEY; + KeyTable[SDLK_KP_PERIOD] = MAC_NUMPAD_PERIOD_KEY; + KeyTable[SDLK_KP_DIVIDE] = MAC_NUMPAD_SLASH_KEY; + KeyTable[SDLK_F1] = MAC_F1_KEY; + KeyTable[SDLK_F2] = MAC_F2_KEY; + KeyTable[SDLK_F3] = MAC_F3_KEY; + KeyTable[SDLK_F4] = MAC_F4_KEY; + KeyTable[SDLK_F5] = MAC_F5_KEY; + KeyTable[SDLK_F6] = MAC_F6_KEY; + KeyTable[SDLK_F7] = MAC_F7_KEY; + KeyTable[SDLK_F8] = MAC_F8_KEY; + KeyTable[SDLK_F9] = MAC_F9_KEY; + KeyTable[SDLK_F10] = MAC_F10_KEY; + KeyTable[SDLK_F11] = MAC_F11_KEY; + KeyTable[SDLK_F12] = MAC_F12_KEY; + KeyTable[SDLK_SEMICOLON] = MAC_SEMICOLON_KEY; + KeyTable[SDLK_PLUS] = MAC_PLUS_KEY; + KeyTable[SDLK_COMMA] = MAC_COMMA_KEY; + KeyTable[SDLK_MINUS] = MAC_MINUS_KEY; + KeyTable[SDLK_PERIOD] = MAC_PERIOD_KEY; + KeyTable[SDLK_SLASH] = MAC_SLASH_KEY; + KeyTable[SDLK_BACKQUOTE] = MAC_TILDE_KEY; + KeyTable[SDLK_LEFTBRACKET] = MAC_LEFTBRACKET_KEY; + KeyTable[SDLK_BACKSLASH] = MAC_BACKSLASH_KEY; + KeyTable[SDLK_RIGHTBRACKET] = MAC_RIGHTBRACKET_KEY; + KeyTable[SDLK_QUOTE] = MAC_APOSTROPHE_KEY; +} + +static inline int clamp_sdl_mouse_button(Uint8 button) +{ + if (button == 2) // right mouse button is button 3 in SDL. + button = 3; + else if (button == 3) + button = 2; + + if ((button >= 1) && (button <= 3)) + return button - 1; + return -1; +} + +static void sdlEventProc(const SDL_Event &e, Game &game) +{ + int val; + bool skipkey = false; + SDLMod mod; + + switch(e.type) + { + case SDL_MOUSEMOTION: + game.deltah += e.motion.xrel; + game.deltav += e.motion.yrel; + return; + + case SDL_MOUSEBUTTONDOWN: + { + val = clamp_sdl_mouse_button(e.button.button); + if ((val >= 0) && (val <= 2)) + { + if (val == 0) + g_button = true; + buttons[val] = true; + } + } + return; + + case SDL_MOUSEBUTTONUP: + { + val = clamp_sdl_mouse_button(e.button.button); + if ((val >= 0) && (val <= 2)) + { + if (val == 0) + g_button = false; + buttons[val] = false; + } + } + return; + + case SDL_KEYDOWN: + if (e.key.keysym.sym == SDLK_g) + { + if (e.key.keysym.mod & KMOD_CTRL) + { + skipkey = true; + SDL_GrabMode mode = SDL_GRAB_ON; + if ((SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) == 0) + { + mode = SDL_WM_GrabInput(SDL_GRAB_QUERY); + mode = (mode==SDL_GRAB_ON) ? SDL_GRAB_OFF:SDL_GRAB_ON; + } + SDL_WM_GrabInput(mode); + } + } + + else if (e.key.keysym.sym == SDLK_RETURN) + { + if (e.key.keysym.mod & KMOD_ALT) + { + skipkey = true; + SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); + } + } + + if ((!skipkey) && (e.key.keysym.sym < SDLK_LAST)) + { + if (KeyTable[e.key.keysym.sym] != 0xffff) + SetKey(KeyTable[e.key.keysym.sym]); + } + + mod = SDL_GetModState(); + if (mod & KMOD_CTRL) + SetKey(MAC_CONTROL_KEY); + if (mod & KMOD_ALT) + SetKey(MAC_OPTION_KEY); + if (mod & KMOD_META) + SetKey(MAC_COMMAND_KEY); + if (mod & KMOD_SHIFT) + SetKey(MAC_SHIFT_KEY); + if (mod & KMOD_CAPS) + SetKey(MAC_CAPS_LOCK_KEY); + + return; + + case SDL_KEYUP: + if (e.key.keysym.sym < SDLK_LAST) + { + if (KeyTable[e.key.keysym.sym] != 0xffff) + ClearKey(KeyTable[e.key.keysym.sym]); + } + + mod = SDL_GetModState(); + if ((mod & KMOD_CTRL) == 0) + ClearKey(MAC_CONTROL_KEY); + if ((mod & KMOD_ALT) == 0) + ClearKey(MAC_OPTION_KEY); + if ((mod & KMOD_META) == 0) + ClearKey(MAC_COMMAND_KEY); + if ((mod & KMOD_SHIFT) == 0) + ClearKey(MAC_SHIFT_KEY); + if ((mod & KMOD_CAPS) == 0) + ClearKey(MAC_CAPS_LOCK_KEY); + return; + } +} +#endif // -------------------------------------------------------------------------- @@ -213,8 +583,7 @@ Boolean SetUp (Game & game) randSeed = UpTime().lo; osx = 0; -// ifstream ipstream(":Data:config.txt", std::ios::in /*| std::ios::nocreate*/); - ifstream ipstream("./Data/config.txt", std::ios::in /*| std::ios::nocreate*/); + ifstream ipstream(ConvertFileName(":Data:config.txt"), std::ios::in /*| std::ios::nocreate*/); detail=1; ismotionblur=0; usermousesensitivity=1; @@ -264,8 +633,7 @@ Boolean SetUp (Game & game) selectDetail(kContextWidth, kContextHeight, kBitsPerPixel, detail); if(!ipstream) { - //ofstream opstream(":Data:config.txt"); - ofstream opstream("./Data/config.txt"); + ofstream opstream(ConvertFileName(":Data:config.txt", "w")); opstream << "Screenwidth:\n"; opstream << kContextWidth; opstream << "\nScreenheight:\n"; @@ -488,10 +856,12 @@ Boolean SetUp (Game & game) if(detail>2)detail=2; if(detail<0)detail=0; - if(screenwidth>3000)screenwidth=640; if(screenwidth<0)screenwidth=640; - if(screenheight>3000)screenheight=480; if(screenheight<0)screenheight=480; +#if !USE_SDL // we'll take anything that works. + if(screenwidth>3000)screenwidth=640; + if(screenheight>3000)screenheight=480; +#endif } if(kBitsPerPixel!=32&&kBitsPerPixel!=16){ kBitsPerPixel=16; @@ -502,117 +872,108 @@ Boolean SetUp (Game & game) SetupDSpFullScreen(); - //------------------------------------------------------------------ - // create window - int x = 0, y = 0; - RECT r = {0, 0, kContextWidth-1, kContextHeight-1}; - DWORD dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE; - DWORD dwExStyle = WS_EX_APPWINDOW; - - if (fullscreen) - { - dwStyle |= WS_POPUP; - } - else - { - - dwStyle |= WS_OVERLAPPEDWINDOW; - dwExStyle |= WS_EX_WINDOWEDGE; - } - - AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle); - - if (!fullscreen) - { - x = (GetSystemMetrics(SM_CXSCREEN) >> 1) - ((r.right - r.left + 1) >> 1); - y = (GetSystemMetrics(SM_CYSCREEN) >> 1) - ((r.bottom - r.top + 1) >> 1); - } - - g_windowHandle=CreateWindowEx( - dwExStyle, - g_wndClassName, "Lugaru", dwStyle, - x, y, -// kContextWidth, kContextHeight, - r.right - r.left + 1, r.bottom - r.top + 1, - NULL,NULL,g_appInstance,NULL ); - if (!g_windowHandle) - { - ReportError("Could not create window"); - return false; - } - - - //------------------------------------------------------------------ - // setup OpenGL - - static PIXELFORMATDESCRIPTOR pfd = - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - kBitsPerPixel, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // No Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 16, // 16Bit Z-Buffer (Depth Buffer) - 0, // No Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - if (!(hDC = GetDC( g_windowHandle))) - ReportError( "Could not get device context"); - - GLuint PixelFormat; - if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) - { - ReportError( "Could not find appropriate pixel format"); - return false; - } - - if (!DescribePixelFormat(hDC, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) - { - ReportError( "Could not retrieve pixel format"); - return false; - } - - if (!SetPixelFormat( hDC, PixelFormat, &pfd)) - { - ReportError( "Could not set pixel format"); - return false; - } - - if (!(hRC = wglCreateContext(hDC))) - { - ReportError( "Could not create rendering context"); - return false; - } - - if (!wglMakeCurrent(hDC, hRC)) - { - ReportError( "Could not activate rendering context"); - return false; - } - - if (fullscreen) - { - // Place the window above all topmost windows - SetWindowPos( g_windowHandle, HWND_TOPMOST, 0,0,0,0, - SWP_NOMOVE | SWP_NOSIZE ); - } - - SetForegroundWindow(g_windowHandle); - SetFocus(g_windowHandle); +#if USE_SDL + if (!SDL_WasInit(SDL_INIT_VIDEO)) + { + if (SDL_Init(SDL_INIT_VIDEO) == -1) + { + fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError()); + return false; + } + + if (SDL_GL_LoadLibrary(NULL) == -1) + { + fprintf(stderr, "SDL_GL_LoadLibrary() failed: %s\n", SDL_GetError()); + SDL_Quit(); + return false; + } + + SDL_Rect **res = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_OPENGL); + if ( (res == NULL) || (res == ((SDL_Rect **)-1)) || (res[0] == NULL) || (res[0]->w < 640) || (res[0]->h < 480) ) + res = hardcoded_resolutions; + + // reverse list (it was sorted biggest to smallest by SDL)... + int count; + for (count = 0; res[count]; count++) + { + if ((res[count]->w < 640) || (res[count]->h < 480)) + break; // sane lower limit. + } + + static SDL_Rect *resolutions_block = NULL; + resolutions_block = (SDL_Rect*) realloc(resolutions_block, sizeof (SDL_Rect) * count); + resolutions = (SDL_Rect**) realloc(resolutions, sizeof (SDL_Rect *) * (count + 1)); + if ((resolutions_block == NULL) || (resolutions == NULL)) + { + SDL_Quit(); + fprintf(stderr, "Out of memory!\n"); + return false; + } + + resolutions[count--] = NULL; + for (int i = 0; count >= 0; i++, count--) + { + memcpy(&resolutions_block[count], res[i], sizeof (SDL_Rect)); + resolutions[count] = &resolutions_block[count]; + } + + if (cmdline("showresolutions")) + { + printf("Resolutions we think are okay:\n"); + for (int i = 0; resolutions[i]; i++) + printf(" %d x %d\n", (int) resolutions[i]->w, (int) resolutions[i]->h); + } + } + + Uint32 sdlflags = SDL_OPENGL; + if (!cmdline("windowed")) + sdlflags |= SDL_FULLSCREEN; + + SDL_WM_SetCaption("Lugaru", "Lugaru"); + + SDL_ShowCursor(0); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) + { + fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + fprintf(stderr, "forcing 640x480...\n"); + kContextWidth = 640; + kContextHeight = 480; + if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) + { + fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + fprintf(stderr, "forcing 640x480 windowed mode...\n"); + sdlflags &= ~SDL_FULLSCREEN; + if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) + { + fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + return false; + } + } + } + + int dblbuf = 0; + if ((SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &dblbuf) == -1) || (!dblbuf)) + { + fprintf(stderr, "Failed to get double buffered GL context!\n"); + SDL_Quit(); + return false; + } + + if (!lookup_all_glsyms()) + { + SDL_Quit(); + return false; + } + + if (!cmdline("nomousegrab")) + SDL_WM_GrabInput(SDL_GRAB_ON); +#endif glClear( GL_COLOR_BUFFER_BIT ); - SwapBuffers( hDC ); + swap_gl_buffers(); // clear all states glDisable( GL_ALPHA_TEST); @@ -653,6 +1014,7 @@ Boolean SetUp (Game & game) glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glAlphaFunc( GL_GREATER, 0.5f); +#if USE_DEVIL if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION || iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION || ilutGetInteger(ILUT_VERSION_NUM) < ILUT_VERSION) @@ -669,6 +1031,7 @@ Boolean SetUp (Game & game) ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); +#endif GLint width = kContextWidth; GLint height = kContextHeight; @@ -689,49 +1052,23 @@ Boolean SetUp (Game & game) static void DoMouse(Game & game) { - static Point lastMouse = {-1,-1}; - Point globalMouse; - - POINT pos; - GetCursorPos(&pos); - ScreenToClient(g_windowHandle, &pos); - globalMouse.h = pos.x; - globalMouse.v = pos.y; - - if (lastMouse.h == globalMouse.h && lastMouse.v == globalMouse.v) +#if USE_SDL + if(mainmenu||(abs(game.deltah)<10*realmultiplier*1000&&abs(game.deltav)<10*realmultiplier*1000)) { - game.deltah=0; - game.deltav=0; - } - else - { - static Point virtualMouse = {0,0}; - delta = globalMouse; - - delta.h -= lastMouse.h; - delta.v -= lastMouse.v; - lastMouse.h = pos.x; - lastMouse.v = pos.y; - - if(mainmenu||(abs(delta.h)<10*realmultiplier*1000&&abs(delta.v)<10*realmultiplier*1000)){ - game.deltah=delta.h*usermousesensitivity; - game.deltav=delta.v*usermousesensitivity; - game.mousecoordh=globalMouse.h; - game.mousecoordv=globalMouse.v; - } - - if(!mainmenu) - { - if(lastMouse.h>gMidPoint.h+100||lastMouse.hgMidPoint.v+100||lastMouse.v= kContextWidth) + game.mousecoordh = kContextWidth - 1; + if (game.mousecoordv < 0) + game.mousecoordv = 0; + else if (game.mousecoordv >= kContextHeight) + game.mousecoordv = kContextHeight - 1; } +#endif } @@ -867,30 +1204,19 @@ void CleanUp (void) // game.Dispose(); +#if USE_DEVIL ilShutDown(); - - if (hRC) - { - wglMakeCurrent( NULL, NULL); - wglDeleteContext( hRC); - hRC = NULL; - } - - if (hDC) - { - ReleaseDC( g_windowHandle, hDC); - hDC = NULL; - } - - if (g_windowHandle) - { - ShowWindow( g_windowHandle, SW_HIDE ); - DestroyWindow( g_windowHandle); - g_windowHandle = NULL; - } - - ShutdownDSp (); - ClipCursor(NULL); +#endif + +#if USE_SDL + SDL_Quit(); + #define GL_FUNC(ret,fn,params,call,rt) p##fn = NULL; + #include "glstubs.h" + #undef GL_FUNC + // cheat here...static destructors are calling glDeleteTexture() after + // the context is destroyed and libGL unloaded by SDL_Quit(). + pglDeleteTextures = glDeleteTextures_doNothing; +#endif } // -------------------------------------------------------------------------- @@ -900,23 +1226,155 @@ static bool g_focused = true; static bool IsFocused() { - if (!g_focused) - return false; + STUBBED("write me"); + return true; +} - if (GetActiveWindow() != g_windowHandle) - return false; - if (IsIconic( g_windowHandle)) - return false; +static void launch_web_browser(const char *url) +{ +#ifdef WIN32 + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + +#elif (defined(__APPLE__) && defined(__MACH__)) + const char *fmt = "open '%s'"; + const size_t len = strlen(fmt) + strlen(url) + 16; + char *buf = new char[len]; + snprintf(buf, len, fmt, url); + system(buf); + delete[] buf; + +#elif PLATFORM_LINUX + const char *fmt = "PATH=$PATH:. xdg-open '%s'"; + const size_t len = strlen(fmt) + strlen(url) + 16; + char *buf = new char[len]; + snprintf(buf, len, fmt, url); + system(buf); + delete[] buf; +#endif +} - return true; + +#ifndef WIN32 +// (code lifted from physfs: http://icculus.org/physfs/ ... zlib license.) +static char *findBinaryInPath(const char *bin, char *envr) +{ + size_t alloc_size = 0; + char *exe = NULL; + char *start = envr; + char *ptr; + + do + { + size_t size; + ptr = strchr(start, ':'); /* find next $PATH separator. */ + if (ptr) + *ptr = '\0'; + + size = strlen(start) + strlen(bin) + 2; + if (size > alloc_size) + { + char *x = (char *) realloc(exe, size); + if (x == NULL) + { + if (exe != NULL) + free(exe); + return(NULL); + } /* if */ + + alloc_size = size; + exe = x; + } /* if */ + + /* build full binary path... */ + strcpy(exe, start); + if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/')) + strcat(exe, "/"); + strcat(exe, bin); + + if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */ + { + strcpy(exe, start); /* i'm lazy. piss off. */ + return(exe); + } /* if */ + + start = ptr + 1; /* start points to beginning of next element. */ + } while (ptr != NULL); + + if (exe != NULL) + free(exe); + + return(NULL); /* doesn't exist in path. */ +} /* findBinaryInPath */ + + +char *calcBaseDir(const char *argv0) +{ + /* If there isn't a path on argv0, then look through the $PATH for it. */ + char *retval; + char *envr; + + char *ptr = strrchr((char *)argv0, '/'); + if (strchr(argv0, '/')) + { + retval = strdup(argv0); + if (retval) + *(strrchr(retval, '/')) = '\0'; + return(retval); + } + + envr = getenv("PATH"); + if (!envr) return NULL; + envr = strdup(envr); + if (!envr) return NULL; + retval = findBinaryInPath(argv0, envr); + free(envr); + return(retval); } +static inline void chdirToAppPath(const char *argv0) +{ + char *dir = calcBaseDir(argv0); + if (dir) + { + #if (defined(__APPLE__) && defined(__MACH__)) + // Chop off /Contents/MacOS if it's at the end of the string, so we + // land in the base of the app bundle. + const size_t len = strlen(dir); + const char *bundledirs = "/Contents/MacOS"; + const size_t bundledirslen = strlen(bundledirs); + if (len > bundledirslen) + { + char *ptr = (dir + len) - bundledirslen; + if (strcasecmp(ptr, bundledirs) == 0) + *ptr = '\0'; + } + #endif + chdir(dir); + free(dir); + } +} +#endif + -int main (void) +int main(int argc, char **argv) { +#ifndef __MINGW32__ + _argc = argc; + _argv = argv; +#endif + + // !!! FIXME: we could use a Win32 API for this. --ryan. +#ifndef WIN32 + chdirToAppPath(argv[0]); +#endif + LOGFUNC; + memset( &g_theKeys, 0, sizeof( KeyMap)); + + initSDLKeyTable(); + try { bool regnow = false; @@ -929,7 +1387,8 @@ int main (void) //ofstream os("log.txt"); //os.close(); - SetUp (game); + if (!SetUp (game)) + return 42; while (!gDone&&!game.quit&&(!game.tryquit||!game.registered)) { @@ -938,21 +1397,21 @@ int main (void) gameFocused = true; // check windows messages - MSG msg; + #if USE_SDL + game.deltah = 0; + game.deltav = 0; + SDL_Event e; // message pump - while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD ) ) + while( SDL_PollEvent( &e ) ) { - if( msg.message == WM_QUIT ) + if( e.type == SDL_QUIT ) { gDone=true; break; } - else - { - TranslateMessage( &msg ); - DispatchMessage( &msg ); - } + sdlEventProc(e, game); } + #endif // game DoUpdate(game); @@ -967,27 +1426,7 @@ int main (void) } // game is not in focus, give CPU time to other apps by waiting for messages instead of 'peeking' - MSG msg; - BOOL bRet; - //if (GetMessage( &msg, g_windowHandle, 0, 0 )) - /*if (GetMessage( &msg, NULL, 0, 0 )) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - }*/ - if ( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0) - { - if (bRet <= 0) - { - // handle the error and possibly exit - gDone=true; - } - else - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } + STUBBED("give up CPU but sniff the event queue"); } } @@ -999,11 +1438,18 @@ int main (void) // if(game.registernow){ if(regnow) { - char url[100]; - sprintf(url,"http://www.wolfire.com/registerpc.html"); - // LaunchURL(url); - ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + #if (defined(__APPLE__) && defined(__MACH__)) + launch_web_browser("http://www.wolfire.com/purchase/lugaru/mac"); + #elif PLATFORM_LINUX + launch_web_browser("http://www.wolfire.com/purchase/lugaru/linux"); + #else + launch_web_browser("http://www.wolfire.com/purchase/lugaru/pc"); + #endif } + + #if PLATFORM_LINUX // (this may not be necessary any more.) + _exit(0); // !!! FIXME: hack...crashes on exit! + #endif return 0; } catch (const std::exception& error) @@ -1013,7 +1459,7 @@ int main (void) std::string e = "Caught exception: "; e += error.what(); - LOG(e, Logger::LOG_ERR); + LOG(e); MessageBox(g_windowHandle, error.what(), "ERROR", MB_OK | MB_ICONEXCLAMATION); } @@ -1027,546 +1473,7 @@ int main (void) // -------------------------------------------------------------------------- - -#define MAX_WINKEYS 256 - static unsigned short KeyTable[MAX_WINKEYS]= - { - 0xffff, // (0) - MAC_MOUSEBUTTON1, // VK_LBUTTON (1) - MAC_MOUSEBUTTON2, // VK_RBUTTON (2) - 0xffff, // VK_CANCEL (3) - 0xffff, // VK_MBUTTON (4) - 0xffff, // (5) - 0xffff, // (6) - 0xffff, // (7) - MAC_DELETE_KEY, // VK_BACK (8) - MAC_TAB_KEY, // VK_TAB (9) - 0xffff, // (10) - 0xffff, // (11) - 0xffff, // VK_CLEAR (12) - MAC_RETURN_KEY, // VK_RETURN (13) - 0xffff, // (14) - 0xffff, // (15) - MAC_SHIFT_KEY, // VK_SHIFT (16) - MAC_CONTROL_KEY, // VK_CONTROL (17) - MAC_OPTION_KEY, // VK_MENU (18) - 0xffff, // VK_PAUSE (19) - MAC_CAPS_LOCK_KEY, // #define VK_CAPITAL (20) - 0xffff, // (21) - 0xffff, // (22) - 0xffff, // (23) - 0xffff, // (24) - 0xffff, // (25) - 0xffff, // (26) - MAC_ESCAPE_KEY, // VK_ESCAPE (27) - 0xffff, // (28) - 0xffff, // (29) - 0xffff, // (30) - 0xffff, // (31) - MAC_SPACE_KEY, // VK_SPACE (32) - MAC_PAGE_UP_KEY, // VK_PRIOR (33) - MAC_PAGE_DOWN_KEY, // VK_NEXT (34) - MAC_END_KEY, // VK_END (35) - MAC_HOME_KEY, // VK_HOME (36) - MAC_ARROW_LEFT_KEY, // VK_LEFT (37) - MAC_ARROW_UP_KEY, // VK_UP (38) - MAC_ARROW_RIGHT_KEY, // VK_RIGHT (39) - MAC_ARROW_DOWN_KEY, // VK_DOWN (40) - 0xffff, // VK_SELECT (41) - 0xffff, // VK_PRINT (42) - 0xffff, // VK_EXECUTE (43) - 0xffff, // VK_SNAPSHOT (44) - MAC_INSERT_KEY, // VK_INSERT (45) - MAC_DEL_KEY, // VK_DELETE (46) - 0xffff, // VK_HELP (47) - MAC_0_KEY, // VK_0 (48) - MAC_1_KEY, // VK_1 (49) - MAC_2_KEY, // VK_2 (50) - MAC_3_KEY, // VK_3 (51) - MAC_4_KEY, // VK_4 (52) - MAC_5_KEY, // VK_5 (53) - MAC_6_KEY, // VK_6 (54) - MAC_7_KEY, // VK_7 (55) - MAC_8_KEY, // VK_8 (56) - MAC_9_KEY, // VK_9 (57) - 0xffff, // (58) - 0xffff, // (59) - 0xffff, // (60) - 0xffff, // (61) - 0xffff, // (62) - 0xffff, // (63) - 0xffff, // (64) - MAC_A_KEY, // VK_A (65) - MAC_B_KEY, // VK_B (66) - MAC_C_KEY, // VK_C (67) - MAC_D_KEY, // VK_D (68) - MAC_E_KEY, // VK_E (69) - MAC_F_KEY, // VK_F (70) - MAC_G_KEY, // VK_G (71) - MAC_H_KEY, // VK_H (72) - MAC_I_KEY, // VK_I (73) - MAC_J_KEY, // VK_J (74) - MAC_K_KEY, // VK_K (75) - MAC_L_KEY, // VK_L (76) - MAC_M_KEY, // VK_M (77) - MAC_N_KEY, // VK_N (78) - MAC_O_KEY, // VK_O (79) - MAC_P_KEY, // VK_P (80) - MAC_Q_KEY, // VK_Q (81) - MAC_R_KEY, // VK_R (82) - MAC_S_KEY, // VK_S (83) - MAC_T_KEY, // VK_T (84) - MAC_U_KEY, // VK_U (85) - MAC_V_KEY, // VK_V (86) - MAC_W_KEY, // VK_W (87) - MAC_X_KEY, // VK_X (88) - MAC_Y_KEY, // VK_Y (89) - MAC_Z_KEY, // VK_Z (90) - 0xffff, // (91) - 0xffff, // (92) - 0xffff, // (93) - 0xffff, // (94) - 0xffff, // (95) - MAC_NUMPAD_0_KEY, // VK_NUMPAD0 (96) - MAC_NUMPAD_1_KEY, // VK_NUMPAD1 (97) - MAC_NUMPAD_2_KEY, // VK_NUMPAD2 (98) - MAC_NUMPAD_3_KEY, // VK_NUMPAD3 (99) - MAC_NUMPAD_4_KEY, // VK_NUMPAD4 (100) - MAC_NUMPAD_5_KEY, // VK_NUMPAD5 (101) - MAC_NUMPAD_6_KEY, // VK_NUMPAD6 (102) - MAC_NUMPAD_7_KEY, // VK_NUMPAD7 (103) - MAC_NUMPAD_8_KEY, // VK_NUMPAD8 (104) - MAC_NUMPAD_9_KEY, // VK_NUMPAD9 (105) - MAC_NUMPAD_ASTERISK_KEY, // VK_MULTIPLY (106) - MAC_NUMPAD_PLUS_KEY, // VK_ADD (107) - MAC_NUMPAD_ENTER_KEY, // VK_SEPARATOR (108) - MAC_NUMPAD_MINUS_KEY, // VK_SUBTRACT (109) - MAC_NUMPAD_PERIOD_KEY, // VK_DECIMAL (110) - MAC_NUMPAD_SLASH_KEY, // VK_DIVIDE (111) - MAC_F1_KEY, // VK_F1 (112) - MAC_F2_KEY, // VK_F2 (113) - MAC_F3_KEY, // VK_F3 (114) - MAC_F4_KEY, // VK_F4 (115) - MAC_F5_KEY, // VK_F5 (116) - MAC_F6_KEY, // VK_F6 (117) - MAC_F7_KEY, // VK_F7 (118) - MAC_F8_KEY, // VK_F8 (119) - MAC_F9_KEY, // VK_F9 (120) - MAC_F10_KEY, // VK_F10 (121) - MAC_F11_KEY, // VK_F11 (122) - MAC_F12_KEY, // VK_F12 (123) - 0xffff, // (124) - 0xffff, // (125) - 0xffff, // (126) - 0xffff, // (127) - 0xffff, // (128) - 0xffff, // (129) - 0xffff, // (130) - 0xffff, // (131) - 0xffff, // (132) - 0xffff, // (133) - 0xffff, // (134) - 0xffff, // (135) - 0xffff, // (136) - 0xffff, // (137) - 0xffff, // (138) - 0xffff, // (139) - 0xffff, // (130) - 0xffff, // (141) - 0xffff, // (142) - 0xffff, // (143) - 0xffff, // VK_NUMLOCK (144) - 0xffff, // VK_SCROLL (145) - 0xffff, // (146) - 0xffff, // (147) - 0xffff, // (148) - 0xffff, // (149) - 0xffff, // (150) - 0xffff, // (151) - 0xffff, // (152) - 0xffff, // (153) - 0xffff, // (154) - 0xffff, // (155) - 0xffff, // (156) - 0xffff, // (157) - 0xffff, // (158) - 0xffff, // (159) - MAC_SHIFT_KEY, // VK_LSHIFT (160) - MAC_SHIFT_KEY, // VK_RSHIFT (161) - MAC_CONTROL_KEY, // VK_LCONTROL (162) - MAC_CONTROL_KEY, // VK_RCONTROL (163) - MAC_OPTION_KEY, // VK_LMENU (164) - MAC_OPTION_KEY, // VK_RMENU (165) - 0xffff, // (166) - 0xffff, // (167) - 0xffff, // (168) - 0xffff, // (169) - 0xffff, // (170) - 0xffff, // (171) - 0xffff, // (172) - 0xffff, // (173) - 0xffff, // (174) - 0xffff, // (175) - 0xffff, // (176) - 0xffff, // (177) - 0xffff, // (178) - 0xffff, // (179) - 0xffff, // (180) - 0xffff, // (181) - 0xffff, // (182) - 0xffff, // (183) - 0xffff, // (184) - 0xffff, // (185) - MAC_SEMICOLON_KEY, // (186) - MAC_PLUS_KEY, // (187) - MAC_COMMA_KEY, // (188) - MAC_MINUS_KEY, // (189) - MAC_PERIOD_KEY, // (190) - MAC_SLASH_KEY, // (191) - MAC_TILDE_KEY, // (192) - 0xffff, // (193) - 0xffff, // (194) - 0xffff, // (195) - 0xffff, // (196) - 0xffff, // (197) - 0xffff, // (198) - 0xffff, // (199) - 0xffff, // (200) - 0xffff, // (201) - 0xffff, // (202) - 0xffff, // (203) - 0xffff, // (204) - 0xffff, // (205) - 0xffff, // (206) - 0xffff, // (207) - 0xffff, // (208) - 0xffff, // (209) - 0xffff, // (210) - 0xffff, // (211) - 0xffff, // (212) - 0xffff, // (213) - 0xffff, // (214) - 0xffff, // (215) - 0xffff, // (216) - 0xffff, // (217) - 0xffff, // (218) - MAC_LEFTBRACKET_KEY, // (219) - MAC_BACKSLASH_KEY, // (220) - MAC_RIGHTBRACKET_KEY, // (221) - MAC_APOSTROPHE_KEY, // (222) - 0xffff, // (223) - 0xffff, // (224) - 0xffff, // (225) - 0xffff, // (226) - 0xffff, // (227) - 0xffff, // (228) - 0xffff, // (229) - 0xffff, // (230) - 0xffff, // (231) - 0xffff, // (232) - 0xffff, // (233) - 0xffff, // (234) - 0xffff, // (235) - 0xffff, // (236) - 0xffff, // (237) - 0xffff, // (238) - 0xffff, // (239) - 0xffff, // (240) - 0xffff, // (241) - 0xffff, // (242) - 0xffff, // (243) - 0xffff, // (244) - 0xffff, // (245) - 0xffff, // (246) - 0xffff, // (247) - 0xffff, // (248) - 0xffff, // (249) - 0xffff, // (250) - 0xffff, // (251) - 0xffff, // (252) - 0xffff, // (253) - 0xffff, // (254) - 0xffff, // (255) - }; - - - static KeyMap g_theKeys; - - void SetKey( int key) - { - g_theKeys[ key >> 3] |= (1 << (key & 7)); - } - - void ClearKey( int key) - { - g_theKeys[ key >> 3] &= (0xff ^ (1 << (key & 7))); - } - - void GetKeys( unsigned char theKeys[16]) - { - memcpy( theKeys, &g_theKeys, 16); - } - - Boolean Button() - { - return g_button; - } - - - void ClipMouseToWindow(HWND window) - { - RECT wRect; - - GetClientRect(window, &wRect); - - ClientToScreen(window, (LPPOINT)&wRect.left); - ClientToScreen(window, (LPPOINT)&wRect.right); - - ClipCursor(&wRect); - - return; - } - - LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) - { - /* this is where we receive all messages concerning this window - * we can either process a message or pass it on to the default - * message handler of windows */ - - static PAINTSTRUCT ps; - - switch(msg) - { - case WM_ACTIVATE: // Watch For Window Activate Message - { - // Check Minimization State - BOOL iconified = HIWORD(wParam) ? TRUE : FALSE; - - if (LOWORD(wParam) == WA_INACTIVE) - { - ClipCursor(NULL); - - if (fullscreen) - { - if( !iconified ) - { - // Minimize window - CloseWindow( hWnd ); - - // The window is now iconified - iconified = GL_TRUE; - } - } - - ShutdownDSp(); - - g_focused=false; // Program Is Active - } - else - { - SetupDSpFullScreen(); - - if( iconified ) - { - // Minimize window - OpenIcon( hWnd ); - - // The window is now iconified - iconified = GL_FALSE; - - // Activate window - ShowWindow( hWnd, SW_SHOW ); - SetForegroundWindow( hWnd ); - SetFocus( hWnd ); - } - - ClipMouseToWindow(hWnd); - g_focused=true; // Program Is No Longer Active - } - - return 0; // Return To The Message Loop - } - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - { - // check for Alt-F4 (exit hotkey) - if (wParam == VK_F4) - { - if (GetKeyState( VK_MENU) & 0x8080) - { - gDone = true; - break; - } - } - if (wParam < MAX_WINKEYS) - { - if (KeyTable[wParam] != 0xffff) - SetKey( KeyTable[wParam]); - } - return (0); - } - - case WM_KEYUP: - case WM_SYSKEYUP: - { - if (wParam < MAX_WINKEYS) - if (KeyTable[wParam] != 0xffff) - ClearKey( KeyTable[wParam]); - return (0); - } - - case WM_CHAR: - case WM_DEADCHAR: - case WM_SYSCHAR: - case WM_SYSDEADCHAR: - return (0); - - case WM_NCLBUTTONDOWN: - case WM_LBUTTONDOWN: - { - g_button = true; - buttons[ 0] = true; - } - return (0); - - case WM_NCRBUTTONDOWN: - case WM_RBUTTONDOWN: - { - buttons[ 1] = true; - } - return (0); - - case WM_NCMBUTTONDOWN: - case WM_MBUTTONDOWN: - { - buttons[ 2] = true; - } - return (0); - - case WM_NCLBUTTONUP: - case WM_LBUTTONUP: - { - g_button = false; - buttons[ 0] = false; - } - return (0); - - case WM_NCRBUTTONUP: - case WM_RBUTTONUP: - { - buttons[ 1] = false; - } - return (0); - - case WM_NCMBUTTONUP: - case WM_MBUTTONUP: - { - buttons[ 2] = false; - } - return (0); - - case WM_NCLBUTTONDBLCLK: - case WM_NCRBUTTONDBLCLK: - case WM_NCMBUTTONDBLCLK: - case WM_LBUTTONDBLCLK: - return (0); - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDBLCLK: - return (0); - - case WM_NCMOUSEMOVE: - case WM_MOUSEMOVE: - /* ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseX = (signed short)(lParam & 0xffff); - ((WindowInfo *)g_lastWindow->GetInfo())->m_mouseY = (signed short)(lParam >> 16); - if (g_lastWindow->m_mouseCallbacksEnabled) g_lastWindow->MouseMoveCallback(); - */// goto winmessage; - return (0); - - case WM_SYSCOMMAND: // Intercept System Commands - { - switch (wParam) // Check System Calls - { - case SC_SCREENSAVE: // Screensaver Trying To Start? - case SC_MONITORPOWER: // Monitor Trying To Enter Powersave? - return 0; // Prevent From Happening - - // User trying to access application menu using ALT? - case SC_KEYMENU: - return 0; - } - } - break; - - case WM_MOVE: -// { -// ReleaseCapture(); -// ClipMouseToWindow(hWnd); -// } - break; - - case WM_SIZE: - break; - - case WM_CLOSE: - { - //gDone = true; - //game.tryquit=1; - } - //return (0); - - case WM_DESTROY: - { - //ClipCursor(NULL); - PostQuitMessage(0); /* Terminate Application */ - } - return (0); - - case WM_ERASEBKGND: - break; - - case WM_PAINT: -// BeginPaint( g_windowHandle,&ps); -// EndPaint( g_windowHandle,&ps); - break; - - default: - break; - } - - /* We processed the message and there - * is no processing by Windows necessary */ - - /* We didn't process the message so let Windows do it */ - return DefWindowProc(hWnd,msg,wParam,lParam); - } - - - static BOOL RegisterWindowClasses(HINSTANCE hFirstInstance) - { - WNDCLASSEX wc; - memset( &wc, 0, sizeof( wc)); - - /* Register the window class. */ - wc.cbSize = sizeof(wc); -#undef style - wc.style = (CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC); /* Combination of Class Styles */ - wc.lpfnWndProc = AppWndProc; /* Adress of Window Procedure */ - wc.cbClsExtra = 0; /* Extra Bytes allocated for this Class */ - wc.cbWndExtra = 0; /* Extra Bytes allocated for each Window */ - wc.hInstance = hFirstInstance; /* Handle of program instance */ - wc.hIcon = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) ); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = g_wndClassName; /* Name of the Window Class */ - wc.hIconSm = LoadIcon( hFirstInstance, MAKEINTRESOURCE(IDI_LUGARU) ); - - if (!RegisterClassEx(&wc)) return FALSE; /* Register Class failed */ - - return TRUE; - } - +#if !USE_SDL int resolutionID(int width, int height) { int whichres; @@ -1579,6 +1486,7 @@ int main (void) if(width==840 && height==524)whichres=5; if(width==1024 && height==640)whichres=6; if(width==1344 && height==840)whichres=7; + if(width==1920 && height==1200)whichres=8; return whichres; } @@ -1595,18 +1503,24 @@ int main (void) if(width==840 && height==524)whichres=5; if(width==1024 && height==640)whichres=6; if(width==1344 && height==840)whichres=7; + if(width>=1920 && height>=1200)whichres=8; return whichres; } +#endif bool selectDetail(int & width, int & height, int & bpp, int & detail) { bool res = true; + + // currently with SDL, we just use whatever is requested + // and don't care. --ryan. + #if !USE_SDL int whichres = closestResolution(width, height); while (true) { - if(whichres<=0 || whichres>7){ + if(whichres<=0 || whichres>8){ whichres = 0; width=640; height=480; @@ -1639,6 +1553,10 @@ int main (void) width=1344; height=840; } + if(whichres==8){ + width=1920; + height=1200; + } if ((detail != 0) && (resolutionDepths[whichres][1] != 0)) { @@ -1654,7 +1572,9 @@ int main (void) detail = 0; break; } - else if (0 == whichres) + else + + if (0 == whichres) { break; } @@ -1663,76 +1583,14 @@ int main (void) } bpp = resolutionDepths[whichres][(detail != 0)]; + #endif return res; } - int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) - { - int argc = 0; - LPWSTR * cl = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argc > 1) - { - if (0 == _wcsicmp(cl[1], L"-windowed")) - { - fullscreen = false; - } - } - - logger.start(true); - - memset( &g_theKeys, 0, sizeof( KeyMap)); - - unsigned int i = 0; - DEVMODE mode; - memset(&mode, 0, sizeof(mode)); - mode.dmSize = sizeof(mode); - while (EnumDisplaySettings(NULL, i++, &mode)) - { - if (mode.dmBitsPerPel < 16) - { - continue; - } - - int res = resolutionID(mode.dmPelsWidth, mode.dmPelsHeight); - - if (res > -1 && res < 8) - { - if (DISP_CHANGE_SUCCESSFUL != ChangeDisplaySettings(&mode, CDS_TEST)) - { - continue; - } - - switch(mode.dmBitsPerPel) - { - case 32: - case 24: - resolutionDepths[res][1] = mode.dmBitsPerPel; - break; - case 16: - resolutionDepths[res][0] = mode.dmBitsPerPel; - break; - } - } - } - - /* if there is no Instance of our program in memory then register the window class */ - if (hPrevInstance == NULL && !RegisterWindowClasses(hInstance)) - return FALSE; /* registration failed! */ - - g_appInstance=hInstance; - - main(); - - UnregisterClass( g_wndClassName, hInstance); - - return TRUE; - - } - extern int channels[100]; extern FSOUND_SAMPLE * samp[100]; - extern FSOUND_STREAM * strm[10]; + extern FSOUND_STREAM * strm[20]; extern "C" void PlaySoundEx(int chan, FSOUND_SAMPLE *sptr, FSOUND_DSPUNIT *dsp, signed char startpaused) { @@ -1795,6 +1653,7 @@ int main (void) return false; } + #if USE_DEVIL ILstring f = strdup(ConvertFileName(fname)); if (!f) { @@ -1851,12 +1710,17 @@ int main (void) } */ free(f); + #else + res = load_image(fname, tex); + //if (!res) printf("failed to load %s\n", fname); + #endif return res; } void ScreenShot(const char * fname) { + #if USE_DEVIL ILstring f = strdup(fname); if (!f) { @@ -1873,5 +1737,259 @@ int main (void) ilDeleteImages(1, &iid); free(f); + #else + save_image(fname); + #endif } + +#if !USE_DEVIL +static bool load_image(const char *file_name, TGAImageRec &tex) +{ + char *ptr = strrchr((char *)file_name, '.'); + if (ptr) + { + if (strcasecmp(ptr+1, "png") == 0) + return load_png(file_name, tex); + else if (strcasecmp(ptr+1, "jpg") == 0) + return load_jpg(file_name, tex); + } + + STUBBED("Unsupported image type"); + return false; +} + + +struct my_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ +}; +typedef struct my_error_mgr * my_error_ptr; + + +static void my_error_exit(j_common_ptr cinfo) +{ + struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err; + longjmp(err->setjmp_buffer, 1); +} + +/* stolen from public domain example.c code in libjpg distribution. */ +static bool load_jpg(const char *file_name, TGAImageRec &tex) +{ + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + JSAMPROW buffer[1]; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + FILE *infile = fopen(file_name, "rb"); + + if (infile == NULL) + return false; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + if (setjmp(jerr.setjmp_buffer)) { + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return false; + } + + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile); + (void) jpeg_read_header(&cinfo, TRUE); + + cinfo.out_color_space = JCS_RGB; + cinfo.quantize_colors = 0; + (void) jpeg_calc_output_dimensions(&cinfo); + (void) jpeg_start_decompress(&cinfo); + + row_stride = cinfo.output_width * cinfo.output_components; + tex.sizeX = cinfo.output_width; + tex.sizeY = cinfo.output_height; + tex.bpp = 24; + + while (cinfo.output_scanline < cinfo.output_height) { + buffer[0] = (JSAMPROW)(char *)tex.data + + ((cinfo.output_height-1) - cinfo.output_scanline) * row_stride; + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + } + + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + fclose(infile); + + return true; +} + + +/* stolen from public domain example.c code in libpng distribution. */ +static bool load_png(const char *file_name, TGAImageRec &tex) +{ + bool hasalpha = false; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + png_byte **rows = NULL; + bool retval = false; + png_byte **row_pointers = NULL; + FILE *fp = fopen(file_name, "rb"); + + if (fp == NULL) + return(NULL); + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + goto png_done; + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + goto png_done; + + if (setjmp(png_jmpbuf(png_ptr))) + goto png_done; + + png_init_io(png_ptr, fp); + png_read_png(png_ptr, info_ptr, + PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING, + NULL); + png_get_IHDR(png_ptr, info_ptr, &width, &height, + &bit_depth, &color_type, &interlace_type, NULL, NULL); + + if (bit_depth != 8) // transform SHOULD handle this... + goto png_done; + + if (color_type & PNG_COLOR_MASK_PALETTE) // !!! FIXME? + goto png_done; + + if ((color_type & PNG_COLOR_MASK_COLOR) == 0) // !!! FIXME? + goto png_done; + + hasalpha = ((color_type & PNG_COLOR_MASK_ALPHA) != 0); + row_pointers = png_get_rows(png_ptr, info_ptr); + if (!row_pointers) + goto png_done; + + if (!hasalpha) + { + png_byte *dst = tex.data; + for (int i = height-1; i >= 0; i--) + { + png_byte *src = row_pointers[i]; + for (int j = 0; j < width; j++) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 0xFF; + src += 3; + dst += 4; + } + } + } + + else + { + png_byte *dst = tex.data; + int pitch = width * 4; + for (int i = height-1; i >= 0; i--, dst += pitch) + memcpy(dst, row_pointers[i], pitch); + } + + tex.sizeX = width; + tex.sizeY = height; + tex.bpp = 32; + retval = true; + +png_done: + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + if (fp) + fclose(fp); + return (retval); +} + + +static bool save_image(const char *file_name) +{ + char *ptr = strrchr((char *)file_name, '.'); + if (ptr) + { + if (strcasecmp(ptr+1, "png") == 0) + return save_png(file_name); + } + + STUBBED("Unsupported image type"); + return false; +} + + +static bool save_png(const char *file_name) +{ + FILE *fp = NULL; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + bool retval = false; + + fp = fopen(file_name, "wb"); + if (fp == NULL) + return false; + + png_bytep *row_pointers = new png_bytep[kContextHeight]; + png_bytep screenshot = new png_byte[kContextWidth * kContextHeight * 3]; + if ((!screenshot) || (!row_pointers)) + goto save_png_done; + + glGetError(); + glReadPixels(0, 0, kContextWidth, kContextHeight, + GL_RGB, GL_UNSIGNED_BYTE, screenshot); + if (glGetError() != GL_NO_ERROR) + goto save_png_done; + + for (int i = 0; i < kContextHeight; i++) + row_pointers[i] = screenshot + ((kContextWidth * ((kContextHeight-1) - i)) * 3); + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + goto save_png_done; + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + goto save_png_done; + + if (setjmp(png_jmpbuf(png_ptr))) + goto save_png_done; + + png_init_io(png_ptr, fp); + + if (setjmp(png_jmpbuf(png_ptr))) + goto save_png_done; + + png_set_IHDR(png_ptr, info_ptr, kContextWidth, kContextHeight, + 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + if (setjmp(png_jmpbuf(png_ptr))) + goto save_png_done; + + png_write_image(png_ptr, row_pointers); + + if (setjmp(png_jmpbuf(png_ptr))) + goto save_png_done; + + png_write_end(png_ptr, NULL); + retval = true; + +save_png_done: + png_destroy_write_struct(&png_ptr, &info_ptr); + delete[] screenshot; + delete[] row_pointers; + if (fp) + fclose(fp); + if (!retval) + unlink(ConvertFileName(file_name)); + return retval; +} + +#endif +