diff options
Diffstat (limited to 'src/PowderToySDL.cpp')
| -rw-r--r-- | src/PowderToySDL.cpp | 337 |
1 files changed, 254 insertions, 83 deletions
diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index c57b3b9..f6ef881 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -5,6 +5,7 @@ #include <time.h> #include "SDL.h" #ifdef WIN +#define _WIN32_WINNT 0x0501 //Necessary for some macros and functions #include "SDL_syswm.h" #include <direct.h> #endif @@ -53,10 +54,6 @@ Atom XA_CLIPBOARD, XA_TARGETS; char *clipboardText = NULL; -#ifdef WIN -extern "C" IMAGE_DOS_HEADER __ImageBase; -#endif - int desktopWidth = 1280, desktopHeight = 1024; SDL_Surface * sdl_scrn; @@ -276,8 +273,11 @@ int SDLOpen() exit(-1); } HWND WindowHandle = SysInfo.window; - HICON hIconSmall = (HICON)LoadImage(reinterpret_cast<HMODULE>(&__ImageBase), MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_SHARED); - HICON hIconBig = (HICON)LoadImage(reinterpret_cast<HMODULE>(&__ImageBase), MAKEINTRESOURCE(101), IMAGE_ICON, 32, 32, LR_SHARED); + + // Use GetModuleHandle to get the Exe HMODULE/HINSTANCE + HMODULE hModExe = GetModuleHandle(NULL); + HICON hIconSmall = (HICON)LoadImage(hModExe, MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, LR_SHARED); + HICON hIconBig = (HICON)LoadImage(hModExe, MAKEINTRESOURCE(101), IMAGE_ICON, 32, 32, LR_SHARED); SendMessage(WindowHandle, WM_SETICON, ICON_SMALL, (LPARAM)hIconSmall); SendMessage(WindowHandle, WM_SETICON, ICON_BIG, (LPARAM)hIconBig); #elif defined(LIN) @@ -543,6 +543,147 @@ int GetModifiers() return SDL_GetModState(); } +#ifdef WIN + +// Returns true if the loaded position was set +// Returns false if something went wrong: SDL_GetWMInfo failed or the loaded position was invalid +bool LoadWindowPosition(int scale) +{ + SDL_SysWMinfo sysInfo; + SDL_VERSION(&sysInfo.version); + if (SDL_GetWMInfo(&sysInfo) > 0) + { + int windowW = (XRES + BARSIZE) * scale; + int windowH = (YRES + MENUSIZE) * scale; + + int savedWindowX = Client::Ref().GetPrefInteger("WindowX", INT_MAX); + int savedWindowY = Client::Ref().GetPrefInteger("WindowY", INT_MAX); + + // Center the window on the primary desktop by default + int newWindowX = (desktopWidth - windowW) / 2; + int newWindowY = (desktopHeight - windowH) / 2; + + bool success = false; + + if (savedWindowX != INT_MAX && savedWindowY != INT_MAX) + { + POINT windowPoints[] = { + {savedWindowX, savedWindowY}, // Top-left + {savedWindowX + windowW, savedWindowY + windowH} // Bottom-right + }; + + MONITORINFO monitor; + monitor.cbSize = sizeof(monitor); + if (GetMonitorInfo(MonitorFromPoint(windowPoints[0], MONITOR_DEFAULTTONEAREST), &monitor) != 0) + { + // Only use the saved window position if it lies inside the visible screen + if (PtInRect(&monitor.rcMonitor, windowPoints[0]) && PtInRect(&monitor.rcMonitor, windowPoints[1])) + { + newWindowX = savedWindowX; + newWindowY = savedWindowY; + + success = true; + } + else + { + // Center the window on the nearest monitor + newWindowX = monitor.rcMonitor.left + (monitor.rcMonitor.right - monitor.rcMonitor.left - windowW) / 2; + newWindowY = monitor.rcMonitor.top + (monitor.rcMonitor.bottom - monitor.rcMonitor.top - windowH) / 2; + } + } + } + + SetWindowPos(sysInfo.window, 0, newWindowX, newWindowY, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); + + // True if we didn't use the default, i.e. the position was valid + return success; + } + + return false; +} + +// Returns true if the window position was saved +bool SaveWindowPosition() +{ + SDL_SysWMinfo sysInfo; + SDL_VERSION(&sysInfo.version); + if (SDL_GetWMInfo(&sysInfo) > 0) + { + WINDOWPLACEMENT placement; + placement.length = sizeof(placement); + GetWindowPlacement(sysInfo.window, &placement); + + Client::Ref().SetPref("WindowX", (int)placement.rcNormalPosition.left); + Client::Ref().SetPref("WindowY", (int)placement.rcNormalPosition.top); + + return true; + } + + return false; +} + +#endif + +void BlueScreen(char * detailMessage){ + ui::Engine * engine = &ui::Engine::Ref(); + engine->g->fillrect(0, 0, engine->GetWidth(), engine->GetHeight(), 17, 114, 169, 210); + + std::string errorTitle = "ERROR"; + std::string errorDetails = "Details: " + std::string(detailMessage); + std::string errorHelp = "An unrecoverable fault has occured, please report the error by visiting the website below\n" + "http://" SERVER; + int currentY = 0, width, height; + int errorWidth = 0; + Graphics::textsize(errorHelp.c_str(), errorWidth, height); + + engine->g->drawtext((engine->GetWidth()/2)-(errorWidth/2), ((engine->GetHeight()/2)-100) + currentY, errorTitle.c_str(), 255, 255, 255, 255); + Graphics::textsize(errorTitle.c_str(), width, height); + currentY += height + 4; + + engine->g->drawtext((engine->GetWidth()/2)-(errorWidth/2), ((engine->GetHeight()/2)-100) + currentY, errorDetails.c_str(), 255, 255, 255, 255); + Graphics::textsize(errorTitle.c_str(), width, height); + currentY += height + 4; + + engine->g->drawtext((engine->GetWidth()/2)-(errorWidth/2), ((engine->GetHeight()/2)-100) + currentY, errorHelp.c_str(), 255, 255, 255, 255); + Graphics::textsize(errorTitle.c_str(), width, height); + currentY += height + 4; + + //Death loop + SDL_Event event; + while(true) + { + while (SDL_PollEvent(&event)) + if(event.type == SDL_QUIT) + exit(-1); +#ifdef OGLI + blit(); +#else + if(engine->Scale==2) + blit2(engine->g->vid, engine->Scale); + else + blit(engine->g->vid); +#endif + } +} + +void SigHandler(int signal) +{ + switch(signal){ + case SIGSEGV: + BlueScreen("Memory read/write error"); + break; + case SIGFPE: + BlueScreen("Floating point exception"); + break; + case SIGILL: + BlueScreen("Program execution exception"); + break; + case SIGABRT: + BlueScreen("Unexpected program abort"); + break; + } +} + int main(int argc, char * argv[]) { currentWidth = XRES+BARSIZE; @@ -602,7 +743,11 @@ int main(int argc, char * argv[]) tempScale = 1; int sdlStatus = SDLOpen(); +#ifdef WIN + LoadWindowPosition(tempScale); +#endif sdl_scrn = SDLSetScreen(tempScale, tempFullscreen); + #ifdef OGLI SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); //glScaled(2.0f, 2.0f, 1.0f); @@ -634,105 +779,131 @@ int main(int argc, char * argv[]) engine->Begin(XRES+BARSIZE, YRES+MENUSIZE); engine->SetFastQuit(Client::Ref().GetPrefBool("FastQuit", true)); - GameController * gameController = new GameController(); - engine->ShowWindow(gameController->GetView()); +#ifndef DEBUG + //Get ready to catch any dodgy errors + signal(SIGSEGV, SigHandler); + signal(SIGFPE, SigHandler); + signal(SIGILL, SigHandler); + signal(SIGABRT, SigHandler); - if(arguments["open"].length()) - { -#ifdef DEBUG - std::cout << "Loading " << arguments["open"] << std::endl; #endif - if(Client::Ref().FileExists(arguments["open"])) + +#ifndef DEBUG + GameController * gameController = NULL; + try { +#endif + + gameController = new GameController(); + engine->ShowWindow(gameController->GetView()); + + if(arguments["open"].length()) { - try + #ifdef DEBUG + std::cout << "Loading " << arguments["open"] << std::endl; + #endif + if(Client::Ref().FileExists(arguments["open"])) { - std::vector<unsigned char> gameSaveData = Client::Ref().ReadFile(arguments["open"]); - if(!gameSaveData.size()) + try { - new ErrorMessage("Error", "Could not read file"); + std::vector<unsigned char> gameSaveData = Client::Ref().ReadFile(arguments["open"]); + if(!gameSaveData.size()) + { + new ErrorMessage("Error", "Could not read file"); + } + else + { + SaveFile * newFile = new SaveFile(arguments["open"]); + GameSave * newSave = new GameSave(gameSaveData); + newFile->SetGameSave(newSave); + gameController->LoadSaveFile(newFile); + delete newFile; + } + } - else + catch(std::exception & e) { - SaveFile * newFile = new SaveFile(arguments["open"]); - GameSave * newSave = new GameSave(gameSaveData); - newFile->SetGameSave(newSave); - gameController->LoadSaveFile(newFile); - delete newFile; + new ErrorMessage("Error", "Could not open save file:\n"+std::string(e.what())) ; } - } - catch(std::exception & e) + else { - new ErrorMessage("Error", "Could not open save file:\n"+std::string(e.what())) ; + new ErrorMessage("Error", "Could not open file"); } } - else - { - new ErrorMessage("Error", "Could not open file"); - } - } - - if(arguments["ptsave"].length()) - { - engine->g->fillrect((engine->GetWidth()/2)-101, (engine->GetHeight()/2)-26, 202, 52, 0, 0, 0, 210); - engine->g->drawrect((engine->GetWidth()/2)-100, (engine->GetHeight()/2)-25, 200, 50, 255, 255, 255, 180); - engine->g->drawtext((engine->GetWidth()/2)-(Graphics::textwidth("Loading save...")/2), (engine->GetHeight()/2)-5, "Loading save...", style::Colour::InformationTitle.Red, style::Colour::InformationTitle.Green, style::Colour::InformationTitle.Blue, 255); -#ifdef OGLI - blit(); -#else - if(engine->Scale==2) - blit2(engine->g->vid, engine->Scale); - else - blit(engine->g->vid); -#endif - std::string ptsaveArg = arguments["ptsave"]; - try - { - if(!ptsaveArg.find("ptsave:")) + if(arguments["ptsave"].length()) { - std::string saveIdPart = ""; - int saveId; - int hashPos = ptsaveArg.find('#'); - if(hashPos != std::string::npos) - { - saveIdPart = ptsaveArg.substr(7, hashPos-7); - } + engine->g->fillrect((engine->GetWidth()/2)-101, (engine->GetHeight()/2)-26, 202, 52, 0, 0, 0, 210); + engine->g->drawrect((engine->GetWidth()/2)-100, (engine->GetHeight()/2)-25, 200, 50, 255, 255, 255, 180); + engine->g->drawtext((engine->GetWidth()/2)-(Graphics::textwidth("Loading save...")/2), (engine->GetHeight()/2)-5, "Loading save...", style::Colour::InformationTitle.Red, style::Colour::InformationTitle.Green, style::Colour::InformationTitle.Blue, 255); + + #ifdef OGLI + blit(); + #else + if(engine->Scale==2) + blit2(engine->g->vid, engine->Scale); else + blit(engine->g->vid); + #endif + std::string ptsaveArg = arguments["ptsave"]; + try { - saveIdPart = ptsaveArg.substr(7); - } - if(saveIdPart.length()) + if(!ptsaveArg.find("ptsave:")) { -#ifdef DEBUG - std::cout << "Got Ptsave: id: " << saveIdPart << std::endl; -#endif - saveId = format::StringToNumber<int>(saveIdPart); - if(!saveId) - throw std::runtime_error("Invalid Save ID"); - - SaveInfo * newSave = Client::Ref().GetSave(saveId, 0); - GameSave * newGameSave = new GameSave(Client::Ref().GetSaveData(saveId, 0)); - newSave->SetGameSave(newGameSave); - if(!newSave) - throw std::runtime_error("Could not load save"); - - gameController->LoadSave(newSave); - delete newSave; + std::string saveIdPart = ""; + int saveId; + int hashPos = ptsaveArg.find('#'); + if(hashPos != std::string::npos) + { + saveIdPart = ptsaveArg.substr(7, hashPos-7); + } + else + { + saveIdPart = ptsaveArg.substr(7); + } + if(saveIdPart.length()) + { + #ifdef DEBUG + std::cout << "Got Ptsave: id: " << saveIdPart << std::endl; + #endif + saveId = format::StringToNumber<int>(saveIdPart); + if(!saveId) + throw std::runtime_error("Invalid Save ID"); + + SaveInfo * newSave = Client::Ref().GetSave(saveId, 0); + GameSave * newGameSave = new GameSave(Client::Ref().GetSaveData(saveId, 0)); + newSave->SetGameSave(newGameSave); + if(!newSave) + throw std::runtime_error("Could not load save"); + + gameController->LoadSave(newSave); + delete newSave; + } + else + { + throw std::runtime_error("No Save ID"); + } } - else + } + catch (std::exception & e) { - throw std::runtime_error("No Save ID"); + new ErrorMessage("Error", "Invalid save link"); } } - } - catch (std::exception & e) - { - new ErrorMessage("Error", "Invalid save link"); - } - } - EngineProcess(); + EngineProcess(); + + #ifdef WIN + SaveWindowPosition(); + #endif + +#ifndef DEBUG + } + catch(...) + { + BlueScreen("Unhandled exception"); + } +#endif ui::Engine::Ref().CloseWindow(); delete gameController; |
