#include "framework.h" #include "winmain.h" #include "resource.h" #include "Sound/sound.h" #ifndef NEW_INV #include "inventory.h" #endif #include "control.h" #include "gameflow.h" #include "savegame.h" #include "level.h" #include "configuration.h" #include "Renderer11.h" #include "Scripting/GameFlowScript.h" #include "Scripting/GameLogicScript.h" #include #include #include using namespace TEN::Renderer; using std::exception; using std::string; using std::cout; using std::endl; WINAPP App; unsigned int ThreadID; uintptr_t ThreadHandle; HACCEL hAccTable; byte receivedWmClose = false; bool Debug = false; HWND WindowsHandle; DWORD MainThreadID; #if _DEBUG string commit; #endif int lua_exception_handler(lua_State* L, sol::optional maybe_exception, sol::string_view description) { return luaL_error(L, description.data()); } void WinProcMsg() { MSG Msg; do { GetMessage(&Msg, 0, 0, 0); if (!TranslateAccelerator(WindowsHandle, hAccTable, &Msg)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } } while (!ThreadEnded && Msg.message != WM_QUIT); } void CALLBACK HandleWmCommand(unsigned short wParam) { if (wParam == 8) { if (!IsLevelLoading) { SuspendThread((HANDLE)ThreadHandle); g_Renderer.toggleFullScreen(); ResumeThread((HANDLE)ThreadHandle); if (g_Renderer.isFullsScreen()) { SetCursor(0); ShowCursor(false); } else { SetCursor(LoadCursorA(App.hInstance, (LPCSTR)0x68)); ShowCursor(true); } } } } LRESULT CALLBACK WinAppProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { // Disables ALT + SPACE if (msg == WM_SYSCOMMAND && wParam == SC_KEYMENU) return 0; if (msg > 0x10) { if (msg == WM_COMMAND) HandleWmCommand((unsigned short)wParam); return DefWindowProcA(hWnd, msg, wParam, (LPARAM)lParam); } if (msg == WM_CLOSE) { receivedWmClose = true; PostQuitMessage(0); DoTheGame = false; return DefWindowProcA(hWnd, 0x10u, wParam, (LPARAM)lParam); } if (msg != WM_ACTIVATE) return DefWindowProcA(hWnd, msg, wParam, (LPARAM)lParam); if (receivedWmClose) { return DefWindowProcA(hWnd, msg, wParam, (LPARAM)lParam); } if ((short)wParam) { if ((signed int)(unsigned short)wParam > 0 && (signed int)(unsigned short)wParam <= 2) { //DB_Log(6, "WM_ACTIVE"); if (!Debug) ResumeThread((HANDLE)ThreadHandle); return 0; } } else { //DB_Log(6, "WM_INACTIVE"); //DB_Log(5, "HangGameThread"); if (!Debug) SuspendThread((HANDLE)ThreadHandle); } return 0; } int main() { return WinMain(GetModuleHandle(nullptr), nullptr, GetCommandLine(), SW_SHOW); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { int RetVal; int n; // Process the command line bool setup = false; LPWSTR* argv; int argc; argv = CommandLineToArgvW(GetCommandLineW(), &argc); for (int i = 1; i < argc; i++) { if (wcscmp(argv[i], L"/setup") == 0) setup = true; if (wcscmp(argv[i], L"/debug") == 0) Debug = true; } LocalFree(argv); // Clear Application Structure memset(&App, 0, sizeof(WINAPP)); InitTENLog(); // Initialise the new scripting system sol::state luaState; luaState.open_libraries(sol::lib::base, sol::lib::math); luaState.set_exception_handler(lua_exception_handler); try { g_GameFlow = new GameFlow(&luaState); g_GameFlow->LoadGameFlowScript(); g_GameScript = new GameScript(&luaState); } catch (TENScriptException const& e) { std::string msg = std::string{ "An unrecoverable error occurred in " } + __func__ + ": " + e.what(); TENLog(msg, LogLevel::Error, LogConfig::All); ShutdownTENLog(); throw; } // Initialise chunks for savegames SaveGame::Start(); INITCOMMONCONTROLSEX commCtrlInit; commCtrlInit.dwSize = sizeof(INITCOMMONCONTROLSEX); commCtrlInit.dwICC = ICC_USEREX_CLASSES | ICC_STANDARD_CLASSES; InitCommonControlsEx(&commCtrlInit); // Initialise main window App.hInstance = hInstance; App.WindowClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1)); App.WindowClass.lpszMenuName = NULL; App.WindowClass.lpszClassName = "TombEngine"; App.WindowClass.hbrBackground = reinterpret_cast(GetStockObject(BLACK_BRUSH)); App.WindowClass.hInstance = hInstance; App.WindowClass.style = CS_VREDRAW | CS_HREDRAW; App.WindowClass.lpfnWndProc = WinAppProc; App.WindowClass.cbClsExtra = 0; App.WindowClass.cbWndExtra = 0; App.WindowClass.hCursor = LoadCursor(App.hInstance, IDC_ARROW); if (!RegisterClass(&App.WindowClass)) { printf("Unable To Register Window Class\n"); return false; } // Create the renderer and enumerate adapters and video modes g_Renderer.Create(); g_Renderer.EnumerateVideoModes(); // Load configuration and optionally show the setup dialog InitDefaultConfiguration(); if (setup || !LoadConfiguration()) { if (!SetupDialog()) { WinClose(); return 0; } LoadConfiguration(); } RECT Rect; Rect.left = 0; Rect.top = 0; Rect.right = g_Configuration.Width; Rect.bottom = g_Configuration.Height; AdjustWindowRect(&Rect, WS_CAPTION, false); App.WindowHandle = CreateWindowEx( 0, "TombEngine", g_GameFlow->GetString(STRING_WINDOW_TITLE), WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX, CW_USEDEFAULT, // TODO: change this to center of screen !!! CW_USEDEFAULT, Rect.right - Rect.left, Rect.bottom - Rect.top, NULL, NULL, App.hInstance, NULL ); if (!App.WindowHandle) { printf("Unable To Create Window: %d\n", GetLastError()); return false; } WindowsHandle = App.WindowHandle; // Initialise the renderer g_Renderer.Initialise(g_Configuration.Width, g_Configuration.Height, g_Configuration.RefreshRate, g_Configuration.Windowed, App.WindowHandle); // Initialize audio if (g_Configuration.EnableSound) Sound_Init(); // Initialise the new inventory //g_Inventory = Inventory(); App.bNoFocus = false; App.isInScene = false; UpdateWindow(WindowsHandle); ShowWindow(WindowsHandle, nShowCmd); SetCursor(NULL); ShowCursor(FALSE); hAccTable = LoadAccelerators(hInstance, (LPCSTR)0x65); //g_Renderer->Test(); DoTheGame = true; ThreadEnded = false; ThreadHandle = BeginThread(GameMain, ThreadID); WinProcMsg(); ThreadEnded = true; while (DoTheGame); WinClose(); exit(EXIT_SUCCESS); } void WinClose() { DestroyAcceleratorTable(hAccTable); if (g_Configuration.EnableSound) Sound_DeInit(); delete g_GameScript; delete g_GameFlow; ShutdownTENLog(); SaveGame::End(); }