X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FOpenGL_Windows.cpp;h=34c264716534427b0a58eb11bcea292389507432;hb=cbf8f0bfaf3c752f852f0cf87c620305797c73b8;hp=5c70e5fd2c9b9dd69cec14263996e0f8f3628b66;hpb=40a3dd7b76b6b10ae05dbd074f1f80ea7b4aa96d;p=lugaru.git diff --git a/Source/OpenGL_Windows.cpp b/Source/OpenGL_Windows.cpp index 5c70e5f..34c2647 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; @@ -61,7 +91,11 @@ extern float volume; #include #include "gamegl.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] = ""; @@ -134,7 +227,9 @@ Game * pgame = 0; void ReportError (char * strError) { +#ifdef WIN32 // !!! FIXME. --ryan. throw std::exception( strError); +#endif /* char errMsgCStr [256]; Str255 strErr; @@ -149,6 +244,7 @@ void ReportError (char * strError) void SetupDSpFullScreen () { +#ifdef WIN32 LOGFUNC; if (fullscreen) @@ -170,11 +266,13 @@ void SetupDSpFullScreen () } ShowCursor(FALSE); +#endif } void ShutdownDSp () { +#ifdef WIN32 LOGFUNC; if (fullscreen) @@ -183,6 +281,7 @@ void ShutdownDSp () } ShowCursor(TRUE); +#endif } @@ -192,13 +291,255 @@ 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; + 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()); + } + + if (e.key.keysym.sym < SDLK_LAST) + { + if (KeyTable[e.key.keysym.sym] != 0xffff) + SetKey(KeyTable[e.key.keysym.sym]); + } + + if (e.key.keysym.mod & KMOD_CTRL) + SetKey(MAC_CONTROL_KEY); + if (e.key.keysym.mod & KMOD_ALT) + SetKey(MAC_OPTION_KEY); + if (e.key.keysym.mod & KMOD_SHIFT) + SetKey(MAC_SHIFT_KEY); + if (e.key.keysym.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]); + } + + if (e.key.keysym.mod & KMOD_CTRL) + ClearKey(MAC_CONTROL_KEY); + if (e.key.keysym.mod & KMOD_ALT) + ClearKey(MAC_OPTION_KEY); + if (e.key.keysym.mod & KMOD_SHIFT) + ClearKey(MAC_SHIFT_KEY); + if (e.key.keysym.mod & KMOD_CAPS) + ClearKey(MAC_CAPS_LOCK_KEY); + return; + } +} +#endif // -------------------------------------------------------------------------- @@ -213,8 +554,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 +604,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 +841,39 @@ 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; // !!! FIXME: SDL_FULLSCREEN? + SDL_WM_SetCaption("Lugaru", "lugaru"); + 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 +913,6 @@ Boolean SetUp (Game & game) return false; } - //------------------------------------------------------------------ // setup OpenGL @@ -610,9 +981,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 +1025,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 +1042,7 @@ Boolean SetUp (Game & game) ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); +#endif GLint width = kContextWidth; GLint height = kContextHeight; @@ -689,6 +1063,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 +1123,7 @@ static void DoMouse(Game & game) } } } +#endif } @@ -867,8 +1259,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 +1295,7 @@ void CleanUp (void) ShutdownDSp (); ClipCursor(NULL); +#endif } // -------------------------------------------------------------------------- @@ -900,6 +1305,7 @@ static bool g_focused = true; static bool IsFocused() { +#ifdef WIN32 if (!g_focused) return false; @@ -908,15 +1314,104 @@ static bool IsFocused() if (IsIconic( g_windowHandle)) return false; +#endif return true; } +#if PLATFORM_LINUX +#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 +} + int main (void) { 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 +1424,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 +1434,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 +1465,7 @@ int main (void) DispatchMessage( &msg ); } } + #endif // game DoUpdate(game); @@ -967,6 +1480,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 +1502,9 @@ int main (void) DispatchMessage(&msg); } } + #else + STUBBED("give up CPU but sniff the event queue"); + #endif } } @@ -999,10 +1516,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 +1541,7 @@ int main (void) // -------------------------------------------------------------------------- - +#ifdef WIN32 #define MAX_WINKEYS 256 static unsigned short KeyTable[MAX_WINKEYS]= { @@ -1289,30 +1803,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 +2056,7 @@ int main (void) return TRUE; } +#endif int resolutionID(int width, int height) { @@ -1667,6 +2158,7 @@ int main (void) return res; } + #ifdef WIN32 int __stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd) { int argc = 0; @@ -1729,6 +2221,7 @@ int main (void) return TRUE; } + #endif extern int channels[100]; extern FSOUND_SAMPLE * samp[100]; @@ -1795,6 +2288,7 @@ int main (void) return false; } + #if USE_DEVIL ILstring f = strdup(ConvertFileName(fname)); if (!f) { @@ -1851,12 +2345,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 +2372,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 +