X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FOpenGL_Windows.cpp;h=18bb2b90382220146263b122d895ae84139f202b;hb=8fb50ec5e055324deda9c83f74eadfbe88338344;hp=919b1cb612c46cbf5bec42eeeb9a8b119fa8eda6;hpb=8562aa5bebc97ea8a61d056aec3847030c6985b7;p=lugaru.git diff --git a/Source/OpenGL_Windows.cpp b/Source/OpenGL_Windows.cpp index 919b1cb..18bb2b9 100644 --- a/Source/OpenGL_Windows.cpp +++ b/Source/OpenGL_Windows.cpp @@ -1,10 +1,40 @@ + +#ifdef WIN32 #include +#endif + #include "Game.h" +#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" +#else + // just use libpng and libjpg directly; it's lighter-weight and easier + // to manage the dependencies on Linux... + extern "C" { + #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; @@ -60,8 +90,12 @@ extern float volume; #include #include #include "gamegl.h" -#include "WinDefs.h" +#include "MacCompatibility.h" + +#ifdef WIN32 #include +#endif + #include "fmod.h" #include "res/resource.h" @@ -92,14 +126,74 @@ void CleanUp (void); // statics/globals (internal only) ------------------------------------------ +#ifndef WIN32 +typedef struct tagPOINT { + int x; + int y; +} POINT, *PPOINT; +#endif + +#if USE_SDL +#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 + +static bool lookup_glsym(const char *funcname, void **func, const char *libname) +{ + *func = SDL_GL_GetProcAddress(funcname); + if (*func == NULL) + { + fprintf(stderr, "Failed to find OpenGL symbol \"%s\" in \"%s\"\n", + funcname, libname); + return false; + } + return true; +} + +static bool lookup_all_glsyms(const char *libname) +{ + bool retval = true; + #define GL_FUNC(ret,fn,params,call,rt) \ + if (!lookup_glsym(#fn, (void **) &p##fn, libname)) retval = false; + #include "glstubs.h" + #undef GL_FUNC + return retval; +} + +static void GLAPIENTRY glDeleteTextures_doNothing(GLsizei n, const GLuint *textures) +{ + // no-op. +} + + + +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) +#define MessageBox(hwnd,text,title,flags) STUBBED("msgbox") +#endif Point delta; +#ifdef WIN32 static const char g_wndClassName[]={ "LUGARUWINDOWCLASS" }; - static HINSTANCE g_appInstance; static HWND g_windowHandle; static HGLRC hRC; +#endif + static bool g_button, fullscreen = true; @@ -121,7 +215,6 @@ int kContextHeight; const RGBColor rgbBlack = { 0x0000, 0x0000, 0x0000 }; -extern HDC hDC; GLuint gFontList; char gcstrMode [256] = ""; @@ -130,11 +223,32 @@ Boolean gDone = false, gfFrontProcess = true; Game * pgame = 0; + +static int _argc = 0; +static char **_argv = NULL; + +bool cmdline(const char *cmd) +{ + for (int i = 1; i < _argc; i++) + { + char *arg = _argv[i]; + while (*arg == '-') + arg++; + if (stricmp(arg, cmd) == 0) + return true; + } + + return false; +} + + // -------------------------------------------------------------------------- void ReportError (char * strError) { +#ifdef WIN32 // !!! FIXME. --ryan. throw std::exception( strError); +#endif /* char errMsgCStr [256]; Str255 strErr; @@ -149,6 +263,7 @@ void ReportError (char * strError) void SetupDSpFullScreen () { +#ifdef WIN32 LOGFUNC; if (fullscreen) @@ -170,11 +285,13 @@ void SetupDSpFullScreen () } ShowCursor(FALSE); +#endif } void ShutdownDSp () { +#ifdef WIN32 LOGFUNC; if (fullscreen) @@ -183,6 +300,7 @@ void ShutdownDSp () } ShowCursor(TRUE); +#endif } @@ -192,13 +310,259 @@ void ShutdownDSp () void DrawGL (Game & game) { +#ifdef WIN32 if (hDC == 0) return; +#endif 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; + 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) + { + if (val == 0) + { + g_button = true; + SetKey(MAC_MOUSEBUTTON1); + } + + else if (val == 1) + SetKey(MAC_MOUSEBUTTON2); + + buttons[val] = true; + } + } + return; + + case SDL_MOUSEBUTTONUP: + { + val = clamp_sdl_mouse_button(e.button.button); + if (val >= 0) + { + if (val == 0) + { + g_button = false; + ClearKey(MAC_MOUSEBUTTON1); + } + + else if (val == 1) + ClearKey(MAC_MOUSEBUTTON2); + + buttons[val] = false; + } + } + return; + + case SDL_KEYDOWN: + if (e.key.keysym.sym == SDLK_g) + { + if (e.key.keysym.mod & KMOD_CTRL) + { + 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) + SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); + } + + else if (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_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_SHIFT) == 0) + ClearKey(MAC_SHIFT_KEY); + if ((mod & KMOD_CAPS) == 0) + ClearKey(MAC_CAPS_LOCK_KEY); + return; + } +} +#endif // -------------------------------------------------------------------------- @@ -213,8 +577,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 +627,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"; @@ -502,6 +864,46 @@ Boolean SetUp (Game & game) SetupDSpFullScreen(); +#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; + } + + const char *libname = "libGL.so.1"; // !!! FIXME: Linux specific! + if (SDL_GL_LoadLibrary(libname) == -1) + { + fprintf(stderr, "SDL_GL_LoadLibrary(\"%s\") failed: %s\n", + libname, SDL_GetError()); + return false; + } + + if (!lookup_all_glsyms(libname)) + return false; + } + + Uint32 sdlflags = SDL_OPENGL; + if (!cmdline("windowed")) + sdlflags |= SDL_FULLSCREEN; + + SDL_WM_SetCaption("Lugaru", "lugaru"); + + if (!cmdline("nomousegrab")) + SDL_WM_GrabInput(SDL_GRAB_ON); + + SDL_ShowCursor(0); + + if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) + { + fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + return false; + } + + +#elif (defined WIN32) //------------------------------------------------------------------ // create window int x = 0, y = 0; @@ -541,7 +943,6 @@ Boolean SetUp (Game & game) return false; } - //------------------------------------------------------------------ // setup OpenGL @@ -610,9 +1011,10 @@ Boolean SetUp (Game & game) SetForegroundWindow(g_windowHandle); SetFocus(g_windowHandle); +#endif glClear( GL_COLOR_BUFFER_BIT ); - SwapBuffers( hDC ); + swap_gl_buffers(); // clear all states glDisable( GL_ALPHA_TEST); @@ -653,6 +1055,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 +1072,7 @@ Boolean SetUp (Game & game) ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); +#endif GLint width = kContextWidth; GLint height = kContextHeight; @@ -689,6 +1093,23 @@ Boolean SetUp (Game & game) static void DoMouse(Game & game) { +#if USE_SDL + if(mainmenu||(abs(game.deltah)<10*realmultiplier*1000&&abs(game.deltav)<10*realmultiplier*1000)) + { + game.deltah *= usermousesensitivity; + game.deltav *= usermousesensitivity; + game.mousecoordh += game.deltah; + game.mousecoordv += game.deltav; + if (game.mousecoordh < 0) + game.mousecoordh = 0; + else if (game.mousecoordh >= kContextWidth) + game.mousecoordh = kContextWidth - 1; + if (game.mousecoordv < 0) + game.mousecoordv = 0; + else if (game.mousecoordv >= kContextHeight) + game.mousecoordv = kContextHeight - 1; + } +#else static Point lastMouse = {-1,-1}; Point globalMouse; @@ -732,6 +1153,7 @@ static void DoMouse(Game & game) } } } +#endif } @@ -867,8 +1289,20 @@ void CleanUp (void) // game.Dispose(); +#if USE_DEVIL ilShutDown(); - +#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; + +#elif (defined WIN32) if (hRC) { wglMakeCurrent( NULL, NULL); @@ -891,6 +1325,7 @@ void CleanUp (void) ShutdownDSp (); ClipCursor(NULL); +#endif } // -------------------------------------------------------------------------- @@ -900,6 +1335,7 @@ static bool g_focused = true; static bool IsFocused() { +#ifdef WIN32 if (!g_focused) return false; @@ -908,15 +1344,201 @@ static bool IsFocused() if (IsIconic( g_windowHandle)) return false; +#endif return true; } -int main (void) +#if PLATFORM_LINUX +#include +#include +#include +static bool try_launch_browser(const char *browser, const char *url) +{ + // make sure string isn't empty... + while ( (*browser) && (isspace(*browser)) ) browser++; + if (*browser == '\0') return false; + + bool seenurl = false; + char buf[4096]; // !!! FIXME: we aren't checking for overflow here! + char *dst = buf; + while (*browser) + { + char ch = *(browser++); + if (ch == '%') + { + ch = *(browser++); + if (ch == '%') + *(dst++) = '%'; + else if (ch == 's') // "%s" == insert URL here. + { + *(dst++) = '\''; + strcpy(dst, url); + dst += strlen(url); + *(dst++) = '\''; + seenurl = true; + } + // (not %% or %s? Drop the char.) + } + else + { + *(dst++) = ch; + } + } + + *dst = '\0'; + if (!seenurl) + { + strcat(dst, " "); + strcat(dst, url); + } + return(system(buf) == 0); +} +#endif + + +static void launch_web_browser(const char *url) +{ +#ifdef WIN32 + ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); + +// lousy linux doesn't have a clean way to do this, but you can point people +// to docs on the BROWSER variable: +// http://www.catb.org/~esr/BROWSER/ +#elif PLATFORM_LINUX + if (strchr(url, '\'') != NULL) // Prevent simple shell injection. + return; + + const char *envr = getenv("BROWSER"); + if (envr == NULL) // not specified? We'll try a pseudo-sane list... + envr = "opera:mozilla:konqueror:firefox:netscape:xterm -e links:xterm -e lynx:"; + + char *ptr = (char *) alloca(strlen(envr) + 1); + if (ptr == NULL) + return; + strcpy(ptr, envr); + envr = ptr; + + while ((ptr = strchr(envr, ':')) != NULL) + { + *ptr = '\0'; + if (try_launch_browser(envr, url)) + return; + envr = ptr + 1; + } + + try_launch_browser(envr, url); +#endif +} + + +#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(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) + { + chdir(dir); + free(dir); + } +} +#endif + + +int main(int argc, char **argv) +{ + _argc = argc; + _argv = argv; +#ifndef WIN32 + chdirToAppPath(argv[0]); +#endif + LOGFUNC; +#ifndef WIN32 // this is in WinMain, too. + logger.start(true); + memset( &g_theKeys, 0, sizeof( KeyMap)); +#endif + + initSDLKeyTable(); + try { bool regnow = false; @@ -929,7 +1551,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,6 +1561,22 @@ int main (void) gameFocused = true; // check windows messages + #if USE_SDL + game.deltah = 0; + game.deltav = 0; + SDL_Event e; + // message pump + while( SDL_PollEvent( &e ) ) + { + if( e.type == SDL_QUIT ) + { + gDone=true; + break; + } + sdlEventProc(e, game); + } + + #elif (defined WIN32) MSG msg; // message pump while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD ) ) @@ -953,6 +1592,7 @@ int main (void) DispatchMessage( &msg ); } } + #endif // game DoUpdate(game); @@ -967,6 +1607,7 @@ int main (void) } // game is not in focus, give CPU time to other apps by waiting for messages instead of 'peeking' + #ifdef WIN32 MSG msg; BOOL bRet; //if (GetMessage( &msg, g_windowHandle, 0, 0 )) @@ -988,6 +1629,9 @@ int main (void) DispatchMessage(&msg); } } + #else + STUBBED("give up CPU but sniff the event queue"); + #endif } } @@ -999,10 +1643,7 @@ 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); + launch_web_browser("http://www.wolfire.com/registerpc.html"); } return 0; } @@ -1027,7 +1668,7 @@ int main (void) // -------------------------------------------------------------------------- - +#ifdef WIN32 #define MAX_WINKEYS 256 static unsigned short KeyTable[MAX_WINKEYS]= { @@ -1289,30 +1930,6 @@ int main (void) 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; @@ -1566,6 +2183,7 @@ int main (void) return TRUE; } +#endif int resolutionID(int width, int height) { @@ -1579,6 +2197,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,6 +2214,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; } @@ -1606,7 +2226,7 @@ int main (void) while (true) { - if(whichres<=0 || whichres>7){ + if(whichres<=0 || whichres>8){ whichres = 0; width=640; height=480; @@ -1639,6 +2259,16 @@ int main (void) width=1344; height=840; } + if(whichres==8){ + width=1920; + height=1200; + } + + // currently with SDL, we just use whatever the native bitdepth + // of the display is and don't care. + #if USE_SDL + break; + #endif if ((detail != 0) && (resolutionDepths[whichres][1] != 0)) { @@ -1654,7 +2284,9 @@ int main (void) detail = 0; break; } - else if (0 == whichres) + else + + if (0 == whichres) { break; } @@ -1667,6 +2299,7 @@ int main (void) return res; } + #ifdef WIN32 int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { int argc = 0; @@ -1722,13 +2355,14 @@ int main (void) g_appInstance=hInstance; - main(); + main(0, NULL); UnregisterClass( g_wndClassName, hInstance); return TRUE; } + #endif extern int channels[100]; extern FSOUND_SAMPLE * samp[100]; @@ -1795,6 +2429,7 @@ int main (void) return false; } + #if USE_DEVIL ILstring f = strdup(ConvertFileName(fname)); if (!f) { @@ -1851,12 +2486,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,4 +2513,263 @@ 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(file_name, '.'); + if (ptr) + { + if (stricmp(ptr+1, "png") == 0) + return load_png(file_name, tex); + else if (stricmp(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, + png_voidp_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; + + retval = malloc(width * height * 4); + if (!retval) + 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, png_infopp_NULL); + if (fp) + fclose(fp); + return (retval); +} + + +static bool save_image(const char *file_name) +{ + char *ptr = strrchr(file_name, '.'); + if (ptr) + { + if (stricmp(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 +