2013-08-29 11:45:22 +09:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 yvt
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-08-29 11:45:22 +09:00
|
|
|
This file is part of OpenSpades.
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-08-29 11:45:22 +09:00
|
|
|
OpenSpades 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 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-08-29 11:45:22 +09:00
|
|
|
OpenSpades 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.
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-08-29 11:45:22 +09:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OpenSpades. If not, see <http://www.gnu.org/licenses/>.
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-08-29 11:45:22 +09:00
|
|
|
*/
|
2013-08-18 16:18:06 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <algorithm> //std::sort
|
|
|
|
#include <memory>
|
|
|
|
|
2016-12-04 20:01:37 +00:00
|
|
|
#if !defined(__APPLE__) && (__unix || __unix__)
|
2016-12-03 19:04:58 +09:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
#include <Imports/SDL.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <zlib.h>
|
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
#include "Main.h"
|
|
|
|
#include "MainScreen.h"
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "Runner.h"
|
|
|
|
#include <Client/Client.h>
|
|
|
|
#include <Client/GameMap.h>
|
|
|
|
#include <Core/ConcurrentDispatch.h>
|
|
|
|
#include <Core/CpuID.h>
|
2013-09-13 23:07:49 +02:00
|
|
|
#include <Core/Debug.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <Core/DirectoryFileSystem.h>
|
|
|
|
#include <Core/FileManager.h>
|
|
|
|
#include <Core/ServerAddress.h>
|
2013-09-13 23:07:49 +02:00
|
|
|
#include <Core/Settings.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <Core/Strings.h>
|
2013-11-27 00:46:12 +09:00
|
|
|
#include <Core/Thread.h>
|
2013-09-13 23:07:49 +02:00
|
|
|
#include <Core/ZipFileSystem.h>
|
2014-02-07 00:09:26 +09:00
|
|
|
#include <Gui/StartupScreen.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <OpenSpades.h>
|
2013-08-18 16:18:06 +09:00
|
|
|
|
2013-09-13 23:07:49 +02:00
|
|
|
#include <Core/VoxelModel.h>
|
|
|
|
#include <Draw/GLOptimizedVoxelModel.h>
|
2013-08-18 16:18:06 +09:00
|
|
|
|
2013-09-14 02:05:05 +02:00
|
|
|
#include <ScriptBindings/ScriptManager.h>
|
2013-09-12 02:10:44 +09:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
#include <Core/Bitmap.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <Core/MemoryStream.h>
|
2014-03-31 20:37:23 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
#if _MSC_VER >= 1900 // Visual Studio 2015 or higher
|
|
|
|
extern "C" {
|
|
|
|
FILE __iob_func[3] = {*stdin, *stdout, *stderr};
|
|
|
|
}
|
2016-03-01 16:35:36 +02:00
|
|
|
#endif
|
2016-02-17 21:47:55 +02:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
static const unsigned char splashImage[] = {
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "SplashImage.inc"
|
2014-03-31 20:37:23 +09:00
|
|
|
};
|
2016-07-15 19:35:09 +09:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
#if !defined(__APPLE__) && __unix
|
2014-05-06 00:22:01 +11:00
|
|
|
static const unsigned char Icon[] = {
|
2016-12-03 18:23:47 +09:00
|
|
|
#include "Icon.inc"
|
2014-05-06 00:22:01 +11:00
|
|
|
};
|
2016-07-15 19:35:09 +09:00
|
|
|
#endif
|
2014-05-06 00:22:01 +11:00
|
|
|
|
2016-11-19 21:03:51 +09:00
|
|
|
DEFINE_SPADES_SETTING(cl_showStartupWindow, "1");
|
2013-11-27 00:48:58 +09:00
|
|
|
|
2013-08-18 16:18:06 +09:00
|
|
|
#ifdef WIN32
|
|
|
|
#include <shlobj.h>
|
2016-12-03 18:23:47 +09:00
|
|
|
#include <windows.h>
|
|
|
|
#define strncasecmp(x, y, z) _strnicmp(x, y, z)
|
|
|
|
#define strcasecmp(x, y) _stricmp(x, y)
|
2013-11-01 22:08:03 +01:00
|
|
|
|
2016-11-19 21:03:51 +09:00
|
|
|
DEFINE_SPADES_SETTING(core_win32BeginPeriod, "1");
|
2014-01-01 20:43:46 +09:00
|
|
|
|
|
|
|
class ThreadQuantumSetter {
|
|
|
|
public:
|
|
|
|
ThreadQuantumSetter() {
|
2016-12-03 18:23:47 +09:00
|
|
|
if (core_win32BeginPeriod) {
|
2014-01-01 20:43:46 +09:00
|
|
|
timeBeginPeriod(1);
|
|
|
|
SPLog("Thread quantum was modified to 1ms by timeBeginPeriod");
|
|
|
|
SPLog("(to disable this behavior, set core_win32BeginPeriod to 0)");
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2014-01-01 20:43:46 +09:00
|
|
|
SPLog("Thread quantum is not modified");
|
|
|
|
SPLog("(to enable this behavior, set core_win32BeginPeriod to 1)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
~ThreadQuantumSetter() {
|
2016-12-03 18:23:47 +09:00
|
|
|
if (core_win32BeginPeriod) {
|
2014-01-01 20:43:46 +09:00
|
|
|
timeEndPeriod(1);
|
|
|
|
SPLog("Thread quantum was restored");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
// lm: without doing it this way, we will get a low-res icon or an ugly resampled icon in our
|
|
|
|
// window.
|
|
|
|
// we cannot use the fltk function on the console window, because it's not an Fl_Window...
|
|
|
|
void setIcon(HWND hWnd) {
|
2013-11-01 22:08:03 +01:00
|
|
|
HINSTANCE hInstance = GetModuleHandle(NULL);
|
2016-12-03 18:23:47 +09:00
|
|
|
HICON hIcon = (HICON)LoadImageA(hInstance, "AppIcon", IMAGE_ICON, GetSystemMetrics(SM_CXICON),
|
|
|
|
GetSystemMetrics(SM_CYICON), 0);
|
|
|
|
if (hIcon) {
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
|
2013-11-01 22:08:03 +01:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
hIcon = (HICON)LoadImageA(hInstance, "AppIcon", IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
|
|
|
|
GetSystemMetrics(SM_CYSMICON), 0);
|
|
|
|
if (hIcon) {
|
|
|
|
SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
|
2013-11-01 22:08:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-24 00:31:51 +01:00
|
|
|
#include <DbgHelp.h>
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
LONG WINAPI UnhandledExceptionProc(LPEXCEPTION_POINTERS lpEx) {
|
|
|
|
typedef BOOL(WINAPI * PDUMPFN)(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
|
|
|
|
MINIDUMP_TYPE DumpType,
|
|
|
|
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
|
|
|
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
|
|
|
PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
|
|
|
|
HMODULE hLib = LoadLibrary("DbgHelp.dll");
|
2013-12-24 00:31:51 +01:00
|
|
|
PDUMPFN pMiniDumpWriteDump = (PDUMPFN)GetProcAddress(hLib, "MiniDumpWriteDump");
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
static char buf[MAX_PATH + 120] = {0}; // this is our display buffer.
|
|
|
|
if (pMiniDumpWriteDump) {
|
|
|
|
static char fullBuf[MAX_PATH + 120] = {0};
|
|
|
|
if (SUCCEEDED(
|
|
|
|
SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0,
|
|
|
|
buf))) { // max length = MAX_PATH (temp abuse this buffer space)
|
|
|
|
strcat_s(buf, "\\"); // ensure we end with a slash.
|
2013-12-24 00:31:51 +01:00
|
|
|
} else {
|
2016-12-03 18:23:47 +09:00
|
|
|
buf[0] = 0; // empty it, the file will now end up in the working directory :(
|
2013-12-24 00:31:51 +01:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
sprintf(fullBuf, "%sOpenSpadesCrash%d.dmp", buf,
|
|
|
|
GetTickCount()); // some sort of randomization.
|
|
|
|
HANDLE hFile = CreateFile(fullBuf, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
|
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE) {
|
2013-12-24 00:31:51 +01:00
|
|
|
MINIDUMP_EXCEPTION_INFORMATION mdei = {0};
|
|
|
|
mdei.ThreadId = GetCurrentThreadId();
|
|
|
|
mdei.ExceptionPointers = lpEx;
|
|
|
|
mdei.ClientPointers = TRUE;
|
|
|
|
MINIDUMP_TYPE mdt = MiniDumpNormal;
|
2016-12-03 18:23:47 +09:00
|
|
|
BOOL rv = pMiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, mdt,
|
|
|
|
(lpEx != 0) ? &mdei : 0, 0, 0);
|
|
|
|
CloseHandle(hFile);
|
|
|
|
sprintf_s(buf,
|
|
|
|
"Something went horribly wrong, please send the file \n%s\nfor analysis.",
|
|
|
|
fullBuf);
|
2013-12-24 00:31:51 +01:00
|
|
|
} else {
|
2016-12-03 18:23:47 +09:00
|
|
|
sprintf_s(buf, "Something went horribly wrong,\ni even failed to store information "
|
|
|
|
"about the problem... (0x%08x)",
|
|
|
|
lpEx ? lpEx->ExceptionRecord->ExceptionCode : 0xffffffff);
|
2013-12-24 00:31:51 +01:00
|
|
|
}
|
|
|
|
} else {
|
2016-12-03 18:23:47 +09:00
|
|
|
sprintf_s(buf, "Something went horribly wrong,\ni even failed to retrieve information "
|
|
|
|
"about the problem... (0x%08x)",
|
|
|
|
lpEx ? lpEx->ExceptionRecord->ExceptionCode : 0xffffffff);
|
2013-12-24 00:31:51 +01:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
MessageBoxA(NULL, buf, "Oops, we crashed...", MB_OK | MB_ICONERROR);
|
|
|
|
ExitProcess(-1);
|
|
|
|
// return EXCEPTION_EXECUTE_HANDLER;
|
2013-12-24 00:31:51 +01:00
|
|
|
}
|
2014-01-01 20:43:46 +09:00
|
|
|
#else
|
2016-12-03 18:23:47 +09:00
|
|
|
class ThreadQuantumSetter {};
|
2013-08-18 16:18:06 +09:00
|
|
|
#endif
|
|
|
|
|
2016-11-19 21:03:51 +09:00
|
|
|
SPADES_SETTING(cg_lastQuickConnectHost);
|
|
|
|
SPADES_SETTING(cg_protocolVersion);
|
|
|
|
SPADES_SETTING(cg_playerName);
|
2013-10-09 23:18:13 +02:00
|
|
|
int cg_autoConnect = 0;
|
2014-05-08 16:40:44 +03:00
|
|
|
bool cg_printVersion = false;
|
|
|
|
bool cg_printHelp = false;
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
void printHelp(char *binaryName) {
|
|
|
|
printf("usage: %s [server_address] [v=protocol_version] [-h|--help] [-v|--version] \n",
|
|
|
|
binaryName);
|
2014-05-08 16:40:44 +03:00
|
|
|
}
|
2013-10-09 23:18:13 +02:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
int argsHandler(int argc, char **argv, int &i) {
|
|
|
|
if (char *a = argv[i]) {
|
|
|
|
if (!strncasecmp(a, "aos://", 6)) {
|
2013-10-09 23:18:13 +02:00
|
|
|
cg_lastQuickConnectHost = a;
|
|
|
|
cg_autoConnect = 1;
|
|
|
|
return ++i;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
// lm: we attempt to detect protocol version, allowing with or without a prefix 'v='
|
|
|
|
// we set proto, but without url we will not auto-connect
|
|
|
|
if (a[0] == 'v' && a[1] == '=') {
|
|
|
|
a += 2;
|
|
|
|
}
|
|
|
|
if (!strcasecmp(a, "75") || !strcasecmp(a, "075") || !strcasecmp(a, "0.75")) {
|
2013-10-09 23:18:13 +02:00
|
|
|
cg_protocolVersion = 3;
|
|
|
|
return ++i;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!strcasecmp(a, "76") || !strcasecmp(a, "076") || !strcasecmp(a, "0.76")) {
|
2013-10-09 23:18:13 +02:00
|
|
|
cg_protocolVersion = 4;
|
|
|
|
return ++i;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!strcasecmp(a, "--version") || !strcasecmp(a, "-v")) {
|
2014-05-08 16:40:44 +03:00
|
|
|
cg_printVersion = true;
|
|
|
|
return ++i;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!strcasecmp(a, "--help") || !strcasecmp(a, "-h")) {
|
2014-05-08 16:40:44 +03:00
|
|
|
cg_printHelp = true;
|
|
|
|
return ++i;
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
}
|
2014-05-08 16:40:44 +03:00
|
|
|
|
2013-10-09 23:18:13 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
namespace spades {
|
2016-12-03 18:23:47 +09:00
|
|
|
void StartClient(const spades::ServerAddress &addr, const std::string &playerName) {
|
|
|
|
class ConcreteRunner : public spades::gui::Runner {
|
2013-11-22 22:50:14 +09:00
|
|
|
spades::ServerAddress addr;
|
|
|
|
std::string playerName;
|
2016-12-03 18:23:47 +09:00
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
protected:
|
2016-12-03 18:23:47 +09:00
|
|
|
virtual spades::gui::View *CreateView(spades::client::IRenderer *renderer,
|
|
|
|
spades::client::IAudioDevice *audio) {
|
2013-11-22 22:50:14 +09:00
|
|
|
return new spades::client::Client(renderer, audio, addr, playerName);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
public:
|
2016-12-03 18:23:47 +09:00
|
|
|
ConcreteRunner(const spades::ServerAddress &addr, const std::string &playerName)
|
|
|
|
: addr(addr), playerName(playerName) {}
|
2013-11-22 22:50:14 +09:00
|
|
|
};
|
|
|
|
ConcreteRunner runner(addr, playerName);
|
|
|
|
runner.RunProtected();
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
void StartMainScreen() {
|
|
|
|
class ConcreteRunner : public spades::gui::Runner {
|
2013-11-22 22:50:14 +09:00
|
|
|
protected:
|
2016-12-03 18:23:47 +09:00
|
|
|
virtual spades::gui::View *CreateView(spades::client::IRenderer *renderer,
|
|
|
|
spades::client::IAudioDevice *audio) {
|
2013-11-22 22:50:14 +09:00
|
|
|
return new spades::gui::MainScreen(renderer, audio);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
public:
|
|
|
|
};
|
|
|
|
ConcreteRunner runner;
|
|
|
|
runner.RunProtected();
|
|
|
|
}
|
|
|
|
}
|
2013-11-28 17:39:00 +01:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
/** Thrown when user wants to exit the program while its initialization. */
|
2016-12-03 18:23:47 +09:00
|
|
|
class ExitRequestException : public std::exception {
|
2014-03-31 20:37:23 +09:00
|
|
|
public:
|
|
|
|
ExitRequestException() throw() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SplashWindow {
|
|
|
|
SDL_Window *window;
|
|
|
|
SDL_Surface *surface;
|
|
|
|
spades::Handle<spades::Bitmap> bmp;
|
|
|
|
bool startupScreenRequested;
|
2016-12-03 18:23:47 +09:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
public:
|
2016-12-03 18:23:47 +09:00
|
|
|
SplashWindow() : window(nullptr), surface(nullptr), startupScreenRequested(false) {
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::MemoryStream stream(reinterpret_cast<const char *>(splashImage),
|
|
|
|
sizeof(splashImage));
|
2014-03-31 20:37:23 +09:00
|
|
|
bmp.Set(spades::Bitmap::Load(&stream), false);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
|
|
|
window = SDL_CreateWindow("OpenSpades Splash Window", SDL_WINDOWPOS_CENTERED,
|
|
|
|
SDL_WINDOWPOS_CENTERED, bmp->GetWidth(), bmp->GetHeight(),
|
|
|
|
SDL_WINDOW_BORDERLESS);
|
|
|
|
if (window == nullptr) {
|
2014-03-31 20:37:23 +09:00
|
|
|
SPLog("Creation of splash window failed.");
|
|
|
|
return;
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
surface = SDL_GetWindowSurface(window);
|
2016-12-03 18:23:47 +09:00
|
|
|
if (surface == nullptr) {
|
2014-03-31 20:37:23 +09:00
|
|
|
SPLog("Creation of splash window surface failed.");
|
|
|
|
SDL_DestroyWindow(window);
|
|
|
|
return;
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-04-24 11:42:57 +11:00
|
|
|
#ifdef __APPLE__
|
|
|
|
#elif __unix
|
|
|
|
SDL_Surface *icon = nullptr;
|
|
|
|
SDL_RWops *icon_rw = nullptr;
|
2014-05-06 00:22:01 +11:00
|
|
|
icon_rw = SDL_RWFromConstMem(Icon, sizeof(Icon));
|
2014-04-24 11:42:57 +11:00
|
|
|
if (icon_rw != nullptr) {
|
|
|
|
icon = IMG_LoadPNG_RW(icon_rw);
|
|
|
|
SDL_FreeRW(icon_rw);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
if (icon == nullptr) {
|
2014-04-24 11:42:57 +11:00
|
|
|
std::string msg = SDL_GetError();
|
|
|
|
SPLog("Failed to load icon: %s", msg.c_str());
|
|
|
|
} else {
|
|
|
|
SDL_SetWindowIcon(window, icon);
|
|
|
|
SDL_FreeSurface(icon);
|
|
|
|
}
|
|
|
|
#endif
|
2014-03-31 20:37:23 +09:00
|
|
|
// put splash image
|
2016-12-03 18:23:47 +09:00
|
|
|
auto *s = SDL_CreateRGBSurfaceFrom(bmp->GetPixels(), bmp->GetWidth(), bmp->GetHeight(), 32,
|
|
|
|
bmp->GetWidth() * 4, 0xff, 0xff00, 0xff0000, 0);
|
2014-03-31 20:37:23 +09:00
|
|
|
SDL_BlitSurface(s, nullptr, surface, nullptr);
|
|
|
|
SDL_FreeSurface(s);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
SDL_UpdateWindowSurface(window);
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
SDL_Window *GetWindow() { return window; }
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
void PumpEvents() {
|
|
|
|
SDL_PumpEvents();
|
|
|
|
SDL_Event e;
|
2016-12-03 18:23:47 +09:00
|
|
|
while (SDL_PollEvent(&e)) {
|
|
|
|
switch (e.type) {
|
2014-03-31 20:37:23 +09:00
|
|
|
case SDL_KEYDOWN:
|
2016-12-03 18:23:47 +09:00
|
|
|
switch (e.key.keysym.sym) {
|
2014-03-31 20:37:23 +09:00
|
|
|
case SDLK_ESCAPE: throw ExitRequestException();
|
2016-12-03 18:23:47 +09:00
|
|
|
case SDLK_SPACE: startupScreenRequested = true; break;
|
2014-03-31 20:37:23 +09:00
|
|
|
}
|
|
|
|
break;
|
2016-12-03 18:23:47 +09:00
|
|
|
case SDL_QUIT: throw ExitRequestException();
|
2014-03-31 20:37:23 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
bool IsStartupScreenRequested() { return startupScreenRequested; }
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
~SplashWindow() {
|
2016-12-03 18:23:47 +09:00
|
|
|
if (window)
|
|
|
|
SDL_DestroyWindow(window);
|
2014-03-31 20:37:23 +09:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
static uLong computeCrc32ForStream(spades::IStream *s) {
|
|
|
|
uLong crc = crc32(0L, Z_NULL, 0);
|
|
|
|
|
|
|
|
char buf[16384];
|
|
|
|
size_t sz;
|
|
|
|
|
|
|
|
while ((sz = s->Read(buf, 16384)) != 0) {
|
|
|
|
crc = crc32(crc, reinterpret_cast<const Bytef *>(buf), static_cast<uInt>(sz));
|
|
|
|
}
|
|
|
|
|
|
|
|
return crc;
|
2016-07-16 00:14:59 +09:00
|
|
|
}
|
2014-03-31 20:37:23 +09:00
|
|
|
|
2014-04-04 16:46:01 +09:00
|
|
|
#ifdef WIN32
|
|
|
|
static std::string Utf8FromWString(const wchar_t *ws) {
|
2016-12-03 18:23:47 +09:00
|
|
|
auto *s = (char *)SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)(ws), wcslen(ws) * 2 + 2);
|
|
|
|
if (!s)
|
|
|
|
return "";
|
2014-04-04 16:46:01 +09:00
|
|
|
std::string ss(s);
|
|
|
|
SDL_free(s);
|
|
|
|
return ss;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
int main(int argc, char **argv) {
|
2013-12-24 00:31:51 +01:00
|
|
|
#ifdef WIN32
|
2016-12-03 18:23:47 +09:00
|
|
|
SetUnhandledExceptionFilter(UnhandledExceptionProc);
|
2013-12-24 00:31:51 +01:00
|
|
|
#endif
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
for (int i = 1; i < argc;) {
|
|
|
|
int ret = argsHandler(argc, argv, i);
|
|
|
|
if (!ret) {
|
|
|
|
// ignore unknown arg
|
|
|
|
i++;
|
2014-05-08 16:40:44 +03:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
}
|
2014-05-08 16:40:44 +03:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (cg_printVersion) {
|
|
|
|
printf("%s\n", PACKAGE_STRING);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-05-08 16:40:44 +03:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (cg_printHelp) {
|
|
|
|
printHelp(argv[0]);
|
|
|
|
return 0;
|
|
|
|
}
|
2014-05-08 16:40:44 +03:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
std::unique_ptr<SplashWindow> splashWindow;
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
try {
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// start recording backtrace
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::reflection::Backtrace::StartBacktrace();
|
|
|
|
SPADES_MARK_FUNCTION();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// show splash window
|
|
|
|
// NOTE: splash window uses image loader, which assumes backtrace is already initialized.
|
|
|
|
splashWindow.reset(new SplashWindow());
|
|
|
|
auto showSplashWindowTime = SDL_GetTicks();
|
|
|
|
auto pumpEvents = [&splashWindow] { splashWindow->PumpEvents(); };
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// initialize threads
|
2013-11-27 00:46:12 +09:00
|
|
|
spades::Thread::InitThreadSystem();
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::DispatchQueue::GetThreadQueue()->MarkSDLVideoThread();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
SPLog("Package: " PACKAGE_STRING);
|
2016-12-03 18:23:47 +09:00
|
|
|
// setup user-specific default resource directories
|
2013-09-12 02:10:44 +09:00
|
|
|
#ifdef WIN32
|
2014-04-04 16:46:01 +09:00
|
|
|
static wchar_t buf[4096];
|
|
|
|
GetModuleFileNameW(NULL, buf, 4096);
|
|
|
|
std::wstring appdir = buf;
|
2016-12-03 18:23:47 +09:00
|
|
|
appdir = appdir.substr(0, appdir.find_last_of(L'\\') + 1);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, buf))) {
|
2014-04-04 16:46:01 +09:00
|
|
|
std::wstring datadir = buf;
|
|
|
|
datadir += L"\\OpenSpades\\Resources";
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(
|
|
|
|
new spades::DirectoryFileSystem(Utf8FromWString(datadir.c_str()), true));
|
2013-11-01 22:08:03 +01:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
|
|
|
|
spades::FileManager::AddFileSystem(
|
|
|
|
new spades::DirectoryFileSystem(Utf8FromWString((appdir + L"Resources").c_str()), false));
|
|
|
|
|
|
|
|
// fltk has a console window on windows (can disable while building, maybe use a builtin
|
|
|
|
// console for a later release?)
|
2013-11-01 22:08:03 +01:00
|
|
|
HWND hCon = GetConsoleWindow();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (NULL != hCon) {
|
|
|
|
setIcon(hCon);
|
2013-09-12 02:10:44 +09:00
|
|
|
}
|
2013-11-01 22:08:03 +01:00
|
|
|
|
2013-08-18 16:18:06 +09:00
|
|
|
#elif defined(__APPLE__)
|
2013-09-12 02:10:44 +09:00
|
|
|
std::string home = getenv("HOME");
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem("./Resources", false));
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-04-01 15:52:40 +09:00
|
|
|
// OS X application is made of Bundle, which contains its own Resources directory.
|
|
|
|
{
|
|
|
|
char *baseDir = SDL_GetBasePath();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (baseDir) {
|
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(baseDir, false));
|
2014-04-01 15:52:40 +09:00
|
|
|
SDL_free(baseDir);
|
|
|
|
}
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(
|
|
|
|
home + "/Library/Application Support/OpenSpades/Resources", true));
|
2013-08-18 16:18:06 +09:00
|
|
|
#else
|
2013-09-12 02:10:44 +09:00
|
|
|
std::string home = getenv("HOME");
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem("./Resources", false));
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(
|
|
|
|
CMAKE_INSTALL_PREFIX "/" OPENSPADES_INSTALL_RESOURCES, false));
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
std::string xdg_data_home = home + "/.local/share";
|
2014-04-07 19:58:10 +11:00
|
|
|
|
|
|
|
if (getenv("XDG_DATA_HOME") == NULL) {
|
|
|
|
SPLog("XDG_DATA_HOME not defined. Assuming that XDG_DATA_HOME is ~/.local/share");
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2014-04-06 20:10:13 +11:00
|
|
|
std::string xdg_data_home = getenv("XDG_DATA_HOME");
|
|
|
|
SPLog("XDG_DATA_HOME is %s", xdg_data_home.c_str());
|
2014-04-07 19:58:10 +11:00
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-04-07 19:58:10 +11:00
|
|
|
struct stat info;
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (stat((xdg_data_home + "/openspades").c_str(), &info) != 0) {
|
|
|
|
if (stat((home + "/.openspades").c_str(), &info) != 0) {
|
|
|
|
} else if (info.st_mode & S_IFDIR) {
|
|
|
|
SPLog("Openspades directory in XDG_DATA_HOME not found, though old directory "
|
|
|
|
"exists. Trying to resolve compatibility problem.");
|
2014-04-07 19:58:10 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (rename((home + "/.openspades").c_str(),
|
|
|
|
(xdg_data_home + "/openspades").c_str()) != 0) {
|
2014-04-07 19:58:10 +11:00
|
|
|
SPLog("Failed to move old directory to new.");
|
|
|
|
} else {
|
|
|
|
SPLog("Successfully moved old directory.");
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (mkdir((home + "/.openspades").c_str(),
|
|
|
|
S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0) {
|
|
|
|
SDL_RWops *io = SDL_RWFromFile(
|
|
|
|
(home + "/.openspades/CONTENT_MOVED_TO_NEW_DIR").c_str(), "wb");
|
2014-04-07 19:58:10 +11:00
|
|
|
if (io != NULL) {
|
2016-12-03 18:23:47 +09:00
|
|
|
const char *text = ("Content of this directory moved to " +
|
|
|
|
xdg_data_home + "/openspades")
|
|
|
|
.c_str();
|
2014-04-07 19:58:10 +11:00
|
|
|
io->write(io, text, strlen(text), 1);
|
|
|
|
io->close(io);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
}
|
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::FileManager::AddFileSystem(
|
|
|
|
new spades::DirectoryFileSystem(xdg_data_home + "/openspades/Resources", true));
|
2014-04-07 19:58:10 +11:00
|
|
|
|
2013-08-18 16:18:06 +09:00
|
|
|
#endif
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// start log output to SystemMessages.log
|
2016-12-03 18:23:47 +09:00
|
|
|
try {
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::StartLog();
|
2016-12-03 18:23:47 +09:00
|
|
|
} catch (const std::exception &ex) {
|
2014-03-15 21:57:31 +09:00
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
2016-12-03 18:23:47 +09:00
|
|
|
auto msg = spades::Format(
|
|
|
|
"Failed to start recording log because of the following error:\n{0}\n\n"
|
|
|
|
"OpenSpades will continue to run, but any critical events are not logged.",
|
|
|
|
ex.what());
|
|
|
|
if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "OpenSpades Log System Failure",
|
|
|
|
msg.c_str(), splashWindow->GetWindow())) {
|
2014-03-15 21:57:31 +09:00
|
|
|
// showing dialog failed.
|
|
|
|
}
|
2013-09-12 02:10:44 +09:00
|
|
|
}
|
|
|
|
SPLog("Log Started.");
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// load preferences.
|
2014-03-31 19:20:28 +09:00
|
|
|
spades::Settings::GetInstance()->Load();
|
2014-03-31 20:37:23 +09:00
|
|
|
pumpEvents();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// dump CPU info (for debugging?)
|
2013-12-25 14:21:21 +09:00
|
|
|
{
|
|
|
|
spades::CpuID cpuid;
|
|
|
|
SPLog("---- CPU Information ----");
|
|
|
|
SPLog("Vendor ID: %s", cpuid.GetVendorId().c_str());
|
|
|
|
SPLog("Brand ID: %s", cpuid.GetBrand().c_str());
|
2016-12-03 18:23:47 +09:00
|
|
|
SPLog("Supports MMX: %s", cpuid.Supports(spades::CpuFeature::MMX) ? "YES" : "NO");
|
|
|
|
SPLog("Supports SSE: %s", cpuid.Supports(spades::CpuFeature::SSE) ? "YES" : "NO");
|
|
|
|
SPLog("Supports SSE2: %s", cpuid.Supports(spades::CpuFeature::SSE2) ? "YES" : "NO");
|
|
|
|
SPLog("Supports SSE3: %s", cpuid.Supports(spades::CpuFeature::SSE3) ? "YES" : "NO");
|
|
|
|
SPLog("Supports SSSE3: %s", cpuid.Supports(spades::CpuFeature::SSSE3) ? "YES" : "NO");
|
|
|
|
SPLog("Supports FMA: %s", cpuid.Supports(spades::CpuFeature::FMA) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX: %s", cpuid.Supports(spades::CpuFeature::AVX) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX2: %s", cpuid.Supports(spades::CpuFeature::AVX2) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX512F: %s",
|
|
|
|
cpuid.Supports(spades::CpuFeature::AVX512F) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX512CD: %s",
|
|
|
|
cpuid.Supports(spades::CpuFeature::AVX512CD) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX512ER: %s",
|
|
|
|
cpuid.Supports(spades::CpuFeature::AVX512ER) ? "YES" : "NO");
|
|
|
|
SPLog("Supports AVX512PF: %s",
|
|
|
|
cpuid.Supports(spades::CpuFeature::AVX512PF) ? "YES" : "NO");
|
|
|
|
SPLog("Simultaneous Multithreading: %s",
|
|
|
|
cpuid.Supports(spades::CpuFeature::SimultaneousMT) ? "YES" : "NO");
|
2013-12-25 14:21:21 +09:00
|
|
|
SPLog("Misc:");
|
|
|
|
SPLog("%s", cpuid.GetMiscInfo().c_str());
|
|
|
|
SPLog("-------------------------");
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
// register resource directory specified by Makefile (or something)
|
2014-05-09 02:59:35 +11:00
|
|
|
#if defined(RESDIR_DEFINED)
|
2013-11-01 22:08:03 +01:00
|
|
|
spades::FileManager::AddFileSystem(new spades::DirectoryFileSystem(RESDIR, false));
|
2013-08-18 18:49:41 +09:00
|
|
|
#endif
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// search current file system for .pak files
|
2013-09-12 02:10:44 +09:00
|
|
|
{
|
2016-12-03 18:23:47 +09:00
|
|
|
std::vector<spades::IFileSystem *> fss;
|
|
|
|
std::vector<spades::IFileSystem *> fssImportant;
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
std::vector<std::string> files = spades::FileManager::EnumFiles("");
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
struct Comparator {
|
2016-12-03 18:23:47 +09:00
|
|
|
static int GetPakId(const std::string &str) {
|
|
|
|
if (str.size() >= 4 && str[0] == 'p' && str[1] == 'a' && str[2] == 'k' &&
|
|
|
|
(str[3] >= '0' && str[3] <= '9')) {
|
2013-09-12 02:10:44 +09:00
|
|
|
return atoi(str.c_str() + 3);
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-12 02:10:44 +09:00
|
|
|
return 32767;
|
|
|
|
}
|
2013-09-11 19:46:08 +09:00
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
static bool Compare(const std::string &a, const std::string &b) {
|
2013-09-12 02:10:44 +09:00
|
|
|
int pa = GetPakId(a);
|
|
|
|
int pb = GetPakId(b);
|
2016-12-03 18:23:47 +09:00
|
|
|
if (pa == pb) {
|
2013-09-12 02:10:44 +09:00
|
|
|
return a < b;
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2013-09-12 02:10:44 +09:00
|
|
|
return pa < pb;
|
|
|
|
}
|
2013-09-11 19:46:08 +09:00
|
|
|
}
|
2013-09-12 02:10:44 +09:00
|
|
|
};
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
std::sort(files.begin(), files.end(), Comparator::Compare);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
for (size_t i = 0; i < files.size(); i++) {
|
2013-09-12 02:10:44 +09:00
|
|
|
std::string name = files[i];
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
// check extension
|
2016-12-03 18:23:47 +09:00
|
|
|
if (name.size() < 4 || (name.rfind(".pak") != name.size() - 4 &&
|
|
|
|
name.rfind(".zip") != name.size() - 4)) {
|
|
|
|
SPLog("Ignored loose file: %s", name.c_str());
|
2013-09-12 02:10:44 +09:00
|
|
|
continue;
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
if (spades::FileManager::FileExists(name.c_str())) {
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::IStream *stream = spades::FileManager::OpenForReading(name.c_str());
|
2016-12-03 18:23:47 +09:00
|
|
|
uLong crc = computeCrc32ForStream(stream);
|
|
|
|
|
|
|
|
stream->SetPosition(0);
|
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::ZipFileSystem *fs = new spades::ZipFileSystem(stream);
|
2016-12-03 18:23:47 +09:00
|
|
|
if (name[0] == '_' && false) { // last resort for #198
|
2016-07-16 00:14:59 +09:00
|
|
|
SPLog("Pak registered: %s: %08lx (marked as 'important')", name.c_str(),
|
2016-12-03 18:23:47 +09:00
|
|
|
static_cast<unsigned long>(crc));
|
2014-03-16 00:53:28 +09:00
|
|
|
fssImportant.push_back(fs);
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
|
|
|
SPLog("Pak registered: %s: %08lx", name.c_str(),
|
|
|
|
static_cast<unsigned long>(crc));
|
2014-03-16 00:53:28 +09:00
|
|
|
fss.push_back(fs);
|
|
|
|
}
|
2013-09-12 02:10:44 +09:00
|
|
|
}
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
for (size_t i = fss.size(); i > 0; i--) {
|
2014-03-16 00:53:28 +09:00
|
|
|
spades::FileManager::AppendFileSystem(fss[i - 1]);
|
|
|
|
}
|
2016-12-03 18:23:47 +09:00
|
|
|
for (size_t i = 0; i < fssImportant.size(); i++) {
|
2014-03-16 00:53:28 +09:00
|
|
|
spades::FileManager::PrependFileSystem(fssImportant[i]);
|
2013-08-18 16:18:06 +09:00
|
|
|
}
|
|
|
|
}
|
2014-03-31 20:37:23 +09:00
|
|
|
pumpEvents();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// initialize localization system
|
2014-02-14 16:20:42 +09:00
|
|
|
SPLog("Initializing localization system");
|
|
|
|
spades::LoadCurrentLocale();
|
|
|
|
_Tr("Main", "Localization System Loaded");
|
2014-03-31 20:37:23 +09:00
|
|
|
pumpEvents();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 21:15:56 +09:00
|
|
|
// parse args
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// initialize AngelScript
|
2013-09-12 02:10:44 +09:00
|
|
|
SPLog("Initializing script engine");
|
|
|
|
spades::ScriptManager::GetInstance();
|
2014-03-31 20:37:23 +09:00
|
|
|
pumpEvents();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-01-01 20:43:46 +09:00
|
|
|
ThreadQuantumSetter quantumSetter;
|
2014-02-24 19:02:13 +09:00
|
|
|
(void)quantumSetter; // suppress "unused variable" warning
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// we want to show splash window at least for some time...
|
|
|
|
pumpEvents();
|
|
|
|
auto ticks = SDL_GetTicks();
|
2016-12-03 18:23:47 +09:00
|
|
|
if (ticks < showSplashWindowTime + 1500) {
|
2014-03-31 20:37:23 +09:00
|
|
|
SDL_Delay(showSplashWindowTime + 1500 - ticks);
|
|
|
|
}
|
|
|
|
pumpEvents();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
// everything is now ready!
|
2016-12-03 18:23:47 +09:00
|
|
|
if (!cg_autoConnect) {
|
|
|
|
if (!((int)cl_showStartupWindow != 0 || splashWindow->IsStartupScreenRequested())) {
|
2014-03-31 20:37:23 +09:00
|
|
|
splashWindow.reset();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-11-22 22:50:14 +09:00
|
|
|
SPLog("Starting main screen");
|
|
|
|
spades::StartMainScreen();
|
2016-12-03 18:23:47 +09:00
|
|
|
} else {
|
2014-03-31 20:37:23 +09:00
|
|
|
splashWindow.reset();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-02-07 00:09:26 +09:00
|
|
|
SPLog("Starting startup window");
|
|
|
|
::spades::gui::StartupScreen::Run();
|
2013-11-22 22:50:14 +09:00
|
|
|
}
|
2013-10-09 23:18:13 +02:00
|
|
|
} else {
|
2014-03-31 20:37:23 +09:00
|
|
|
splashWindow.reset();
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
spades::ServerAddress host(cg_lastQuickConnectHost.CString(),
|
|
|
|
(int)cg_protocolVersion == 3
|
|
|
|
? spades::ProtocolVersion::v075
|
|
|
|
: spades::ProtocolVersion::v076);
|
|
|
|
spades::StartClient(host, std::string(cg_playerName).substr(0, 15));
|
2013-10-09 23:18:13 +02:00
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2013-09-12 02:10:44 +09:00
|
|
|
spades::Settings::GetInstance()->Flush();
|
2013-10-10 20:16:29 +02:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
} catch (const ExitRequestException &) {
|
2014-03-31 20:37:23 +09:00
|
|
|
// user changed his mind.
|
2016-12-03 18:23:47 +09:00
|
|
|
} catch (const std::exception &ex) {
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-03-31 20:37:23 +09:00
|
|
|
try {
|
|
|
|
splashWindow.reset(nullptr);
|
2016-12-03 18:23:47 +09:00
|
|
|
} catch (...) {
|
2014-03-31 20:37:23 +09:00
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-02-24 19:02:13 +09:00
|
|
|
std::string msg = ex.what();
|
2016-12-03 18:23:47 +09:00
|
|
|
msg = _Tr("Main", "A serious error caused OpenSpades to stop working:\n\n{0}\n\nSee "
|
|
|
|
"SystemMessages.log for more details.",
|
|
|
|
msg);
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-02-24 19:02:13 +09:00
|
|
|
SPLog("[!] Terminating due to the fatal error: %s", ex.what());
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2014-02-24 19:02:13 +09:00
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
2016-12-03 18:23:47 +09:00
|
|
|
if (SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
|
|
|
_Tr("Main", "OpenSpades Fatal Error").c_str(), msg.c_str(),
|
|
|
|
nullptr)) {
|
2014-02-24 19:02:13 +09:00
|
|
|
// showing dialog failed.
|
|
|
|
// TODO: do appropriate action
|
2013-08-18 16:18:06 +09:00
|
|
|
}
|
|
|
|
}
|
2014-04-06 20:10:13 +11:00
|
|
|
|
2016-12-03 18:23:47 +09:00
|
|
|
return 0;
|
2013-08-18 16:18:06 +09:00
|
|
|
}
|