diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2414c16..ea57110 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,5 +27,5 @@ SET(BGFX_BUILD_EXAMPLES OFF) add_subdirectory("${CMAKE_SOURCE_DIR}/dependency/bgfx.cmake") target_link_libraries(PuzGame bx bimg bgfx) -target_link_libraries(PuzGameEngine bx) - +target_link_libraries(PuzGameEngine bx bimg bgfx) +set_target_properties(PuzGame PROPERTIES OUTPUT_NAME "PuzGame2") diff --git a/src/build.bat b/src/build.bat index 04d43c0..ce880a2 100644 --- a/src/build.bat +++ b/src/build.bat @@ -1 +1 @@ -cmake --build cmake-build && .\cmake-build\PuzGameEngine.exe +cmake --build cmake-build diff --git a/src/engine/main.cpp b/src/engine/main.cpp index a672c4e..4377f62 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -2,15 +2,44 @@ #include #undef min #undef max + #include -#include #include +#include //#define VISUAL_STUDIO typedef void (*Startup)(void*); typedef void (*Update)(); +constexpr UINT WM_CUSTOM_DLL_CHANGE = WM_USER + 1; + +#ifdef VISUAL_STUDIO + const char* DLLPath = "Debug/PuzGame.dll"; +#else + const char* DLLPath = "libPuzGame.dll"; +#endif + +struct FileWatcherData +{ + bool Change = false; +}; + +struct DevelopmentData +{ + uint8_t FileChangeBuffer[1024]{0}; + HMODULE GameLib = NULL; + HANDLE hDevDir = NULL; + FileWatcherData FileWatcher; +}; + +namespace +{ + DevelopmentData DevData; + Startup StartupFunc; + Update UpdateFunc; +} + LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { LRESULT Res = 0; @@ -50,66 +79,139 @@ HWND InitWindow() DWORD err = GetLastError(); printf("Failed to create window: %#x!\n", err); } + + DevData.hDevDir = CreateFileW(L"cmake-build", FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (DevData.hDevDir == NULL) + { + printf("Failed to monitor dev dir!\n"); + } + return window; } +unsigned long FileWatcherThread(void* data) +{ + DWORD bytesReturned = 0; + bool isRunning = DevData.hDevDir; + while (isRunning) + { + bx::memSet(DevData.FileChangeBuffer, 0, sizeof(DevData.FileChangeBuffer)); + if (ReadDirectoryChangesW(DevData.hDevDir, DevData.FileChangeBuffer, sizeof(DevData.FileChangeBuffer), true, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &bytesReturned, NULL, NULL)) + { + uint32_t offset = 0; + while (true) + { + FILE_NOTIFY_INFORMATION* notifyData = reinterpret_cast(&DevData.FileChangeBuffer[offset]); + wprintf(L"Change: %ls\n", notifyData->FileName); + + if (notifyData->Action == FILE_ACTION_ADDED || notifyData->Action == FILE_ACTION_MODIFIED || notifyData->Action == FILE_ACTION_RENAMED_NEW_NAME) + { + if (wcscmp(notifyData->FileName, L"libPuzGame2.dll") == 0) + { + DevData.FileWatcher.Change = true; + printf("detected dll change!\n"); + } + } + + if (notifyData->NextEntryOffset == 0) break; + offset += notifyData->NextEntryOffset; + } + } + } + printf("File watcher thread ended!\n"); + return 0; +} + +bool ReloadDLL() +{ + if (DevData.GameLib != NULL) + { + FreeLibrary(DevData.GameLib); + } + if (!CopyFile("cmake-build\\libPuzGame2.dll", "cmake-build\\libPuzGame.dll", false)) + { + printf("Failed to copy game DLL!\n"); + } + + HMODULE gameLibReloaded = LoadLibraryEx(DLLPath, NULL, 0); + if (gameLibReloaded == NULL) + { + printf("Failed to load game DLL from %s!\n", DLLPath); + return false; + } + DevData.GameLib = gameLibReloaded; + +#ifdef VISUAL_STUDIO + Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "?Setup@Game@@YAXPEAX@Z"); +#else + Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "_ZN4Game5SetupEPv"); +#endif + if (StartupReloaded == NULL) + { + printf("Failed to load startup function from game DLL!\n"); + return false; + } + +#ifdef VISUAL_STUDIO + Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "?Update@Game@@YAXXZ"); +#else + Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "_ZN4Game6UpdateEv"); +#endif + if (UpdateReloaded == NULL) + { + printf("Failed to load update function from game DLL!\n"); + return false; + } + + StartupFunc = StartupReloaded; + UpdateFunc = UpdateReloaded; + + printf("Loaded Game DLL successfully!\n"); + return true; +} + int main() { HWND window = InitWindow(); if (window == NULL) return 1; - - char Buf[512]; - GetCurrentDirectoryA(sizeof(Buf), Buf); -#ifdef VISUAL_STUDIO - const char* dllPath = "Debug/PuzGame.dll"; -#else - const char* dllPath = "libPuzGame.dll"; -#endif - HMODULE gameLibModule = LoadLibraryEx(dllPath, NULL, 0); - if (gameLibModule == NULL) - { - printf("Failed to load game DLL from %s!", dllPath); - return 1; - } + if (!ReloadDLL()) return 1; -#ifdef VISUAL_STUDIO - Startup StartFunc = (Startup)GetProcAddress(gameLibModule, "?Setup@Game@@YAXPEAX@Z"); -#else - Startup StartFunc = (Startup)GetProcAddress(gameLibModule, "_ZN4Game5SetupEPv"); -#endif - if (StartFunc == NULL) - { - printf("Failed to load startup function from game DLL!\n"); - return 1; - } - -#ifdef VISUAL_STUDIO - Update UpdateFunc = (Update)GetProcAddress(gameLibModule, "?Update@Game@@YAXXZ"); -#else - Update UpdateFunc = (Update)GetProcAddress(gameLibModule, "_ZN4Game6UpdateEv"); -#endif - if (UpdateFunc == NULL) - { - printf("Failed to load update function from game DLL!\n"); - return 1; - } - - printf("Loaded Game DLL successfully!\n"); + bgfx::Init init; + init.platformData.nwh = (void*)window; + init.platformData.ndt = nullptr; + init.platformData.type = bgfx::NativeWindowHandleType::Default; + init.resolution.width = 1920; + init.resolution.height = 1080; + init.resolution.reset = BGFX_RESET_VSYNC; + bgfx::init(init); + + StartupFunc(window); + DWORD fileWatcherThreadId = 0; + CreateThread(NULL, 0, FileWatcherThread, NULL, 0, &fileWatcherThreadId); - StartFunc(window); bool isRunning = true; while (isRunning) { - MSG Message; - BOOL MessageResult = GetMessage(&Message, 0, 0, 0); - if (MessageResult > 0) - { - TranslateMessage(&Message); - DispatchMessageW(&Message); + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + { + + } + + TranslateMessage(&msg); + DispatchMessage(&msg); } - // UpdateFunc(); - // Sleep(1000.0); + + if (DevData.FileWatcher.Change) + { + DevData.FileWatcher.Change = false; + ReloadDLL(); + } + + UpdateFunc(); } return 0; } diff --git a/src/game/Log.cpp b/src/game/Log.cpp index a48d3a3..c128084 100644 --- a/src/game/Log.cpp +++ b/src/game/Log.cpp @@ -1,10 +1,14 @@ #include "Log.h" -#include +#include -namespace Game +namespace { - void Log(const char* text) - { - printf("%s\n", text); - } + char LineBuffer[1024]{0}; +} + +void Log(const char *format, ...) +{ + va_list args; + bx::snprintf(LineBuffer, sizeof(LineBuffer), "%s\n", format); + bx::printf(LineBuffer, args); } diff --git a/src/game/Log.h b/src/game/Log.h index 96cafbe..4d56bc5 100644 --- a/src/game/Log.h +++ b/src/game/Log.h @@ -1,6 +1,3 @@ #pragma once -namespace Game -{ - void Log(const char* text); -} +void Log(const char *format, ...); diff --git a/src/game/Setup.cpp b/src/game/Setup.cpp index e6cf8ef..d4f2841 100644 --- a/src/game/Setup.cpp +++ b/src/game/Setup.cpp @@ -4,22 +4,19 @@ namespace Game { + int32_t FrameCounter = 0; + void Setup(void* window) { - Log("Setup"); - bgfx::Init init; - init.type = bgfx::RendererType::Direct3D12; - init.platformData.nwh = (void*)window; - init.platformData.ndt = nullptr; - init.platformData.type = bgfx::NativeWindowHandleType::Default; - init.resolution.width = 1920; - init.resolution.height = 1080; - init.resolution.reset = BGFX_RESET_VSYNC; - bgfx::init(init); + Log("Game Setup Start!"); } void Update() { - Log("Update"); - } + ++FrameCounter; + if (FrameCounter % 1000000 == 0) + { + Log("Frame!"); + } + } } diff --git a/tools/remedy-session.rdbg b/tools/remedy-session.rdbg index c5b0498..ece0cdb 100644 Binary files a/tools/remedy-session.rdbg and b/tools/remedy-session.rdbg differ