diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c9e4502 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/geecore"] + path = deps/geecore + url = https://github.com/WopsS/GEEcore.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 03d4d1d..5ad79b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ include(ConfigureDefaultOutputDirectories) include(ConfigureResourceRc) include(ConfigureVersionFromGit) -configure_version_from_git() +red3ext_configure_version_from_git() project( RED3ext @@ -17,9 +17,9 @@ project( # ----------------------------------------------------------------------------- # General configuration and variables # ----------------------------------------------------------------------------- -configure_default_output_directories() +red3ext_configure_default_output_directories() -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase") @@ -37,6 +37,23 @@ option(RED3EXT_CI_RELEASE "When ON version metadata will not be appended to GIT_ option(RED3EXT_EXTRA_WARNINGS "Enable extra warnings." ON) option(RED3EXT_TREAT_WARNINGS_AS_ERRORS "Treat compiler warnings as errors." OFF) +# ----------------------------------------------------------------------------- +# Dependencies - Prerequirement +# +# Some of the dependencies are already included in GEEcore with INSTALL or EXPORT +# targets set to ON. Since this is distributed as a packaged application using +# a custom INSTALL target, it is not necessary to include these third-party libs +# in the install directory. Thus, this section disable the INSTALL / EXPORT +# behavior for these libraries. +# ----------------------------------------------------------------------------- +include(deps/ConfigureAndIncludeFmt) +include(deps/ConfigureAndIncludeKangaru) + +# ----------------------------------------------------------------------------- +# Dependencies +# ----------------------------------------------------------------------------- +include(deps/ConfigureAndIncludeGEEcore) + # ----------------------------------------------------------------------------- # Compiler options for all projects # ----------------------------------------------------------------------------- @@ -55,39 +72,23 @@ add_compile_definitions( add_compile_options( # Enable correct reporting of C++ version, see https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus. - $<$:/Zc:__cplusplus> + /Zc:__cplusplus ) add_link_options( # Generate debugging information (PDB) file. - $<$:/DEBUG:FULL> + /DEBUG:FULL ) # ----------------------------------------------------------------------------- # Options / configuration related only to this project # ----------------------------------------------------------------------------- if(RED3EXT_EXTRA_WARNINGS) - if(MSVC) - add_compile_options(/W4) - else() - message( - FATAL_ERROR - "The compiler options to enable extra warnings is not known for \ - '${CMAKE_CXX_COMPILER_ID}'" - ) - endif() + add_compile_options(/W4) endif() if(RED3EXT_TREAT_WARNINGS_AS_ERRORS) - if(MSVC) - add_compile_options(/WX) - else() - message( - FATAL_ERROR - "The compiler option to treat warnings as errors is not known for \ - '${CMAKE_CXX_COMPILER_ID}'" - ) - endif() + add_compile_options(/WX) endif() # ----------------------------------------------------------------------------- diff --git a/cmake/ConfigureDefaultOutputDirectories.cmake b/cmake/ConfigureDefaultOutputDirectories.cmake index ca8a534..c35723a 100644 --- a/cmake/ConfigureDefaultOutputDirectories.cmake +++ b/cmake/ConfigureDefaultOutputDirectories.cmake @@ -1,4 +1,4 @@ -macro(configure_default_output_directories) +macro(red3ext_configure_default_output_directories) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/libs") set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/libs") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") diff --git a/cmake/ConfigureResourceRc.cmake b/cmake/ConfigureResourceRc.cmake index d47e8af..bdfe0e1 100644 --- a/cmake/ConfigureResourceRc.cmake +++ b/cmake/ConfigureResourceRc.cmake @@ -1,4 +1,4 @@ -function(configure_resource_rc TARGET DESCRIPTION) +function(red3ext_configure_resource_rc TARGET DESCRIPTION) get_target_property(RED3EXT_RESOURCE_PRODUCT_NAME "${TARGET}" OUTPUT_NAME) set(RED3EXT_RESOURCE_FILE_DESCRIPTION "${DESCRIPTION}") diff --git a/cmake/ConfigureVersionFromGit.cmake b/cmake/ConfigureVersionFromGit.cmake index 2fc5abf..29937fb 100644 --- a/cmake/ConfigureVersionFromGit.cmake +++ b/cmake/ConfigureVersionFromGit.cmake @@ -1,4 +1,4 @@ -function(configure_version_from_git) +function(red3ext_configure_version_from_git) find_package(Git) __git_set_default_version_variables() diff --git a/cmake/deps/ConfigureAndIncludeFmt.cmake b/cmake/deps/ConfigureAndIncludeFmt.cmake new file mode 100644 index 0000000..ba0ee88 --- /dev/null +++ b/cmake/deps/ConfigureAndIncludeFmt.cmake @@ -0,0 +1,3 @@ +option(FMT_INSTALL "" OFF) + +# The rest is included by GEEcore. diff --git a/cmake/deps/ConfigureAndIncludeGEEcore.cmake b/cmake/deps/ConfigureAndIncludeGEEcore.cmake new file mode 100644 index 0000000..19aa87f --- /dev/null +++ b/cmake/deps/ConfigureAndIncludeGEEcore.cmake @@ -0,0 +1,10 @@ +option(GEECORE_INSTALL "" OFF) + +add_subdirectory(deps/geecore) + +set_target_properties(fmt PROPERTIES FOLDER "Dependencies") +set_target_properties(GEEcore PROPERTIES FOLDER "Dependencies") + +mark_as_advanced( + GEECORE_INSTALL +) diff --git a/cmake/deps/ConfigureAndIncludeKangaru.cmake b/cmake/deps/ConfigureAndIncludeKangaru.cmake new file mode 100644 index 0000000..9881581 --- /dev/null +++ b/cmake/deps/ConfigureAndIncludeKangaru.cmake @@ -0,0 +1,4 @@ +option(KANGARU_EXPORT "" OFF) +option(KANGARU_INSTALL "" OFF) + +# The rest is included by GEEcore. diff --git a/deps/geecore b/deps/geecore new file mode 160000 index 0000000..4ccfacb --- /dev/null +++ b/deps/geecore @@ -0,0 +1 @@ +Subproject commit 4ccfacb49cdc690c248f6f7182eae6fa02b40942 diff --git a/src/dll/CMakeLists.txt b/src/dll/CMakeLists.txt index abbc7a3..925c7bf 100644 --- a/src/dll/CMakeLists.txt +++ b/src/dll/CMakeLists.txt @@ -6,7 +6,7 @@ set_target_properties( OUTPUT_NAME ${PROJECT_NAME} ) -configure_resource_rc( +red3ext_configure_resource_rc( RED3ext.Dll "A script extender for REDengine 3." ) diff --git a/src/loader/AppMetadata.cpp b/src/loader/AppMetadata.cpp new file mode 100644 index 0000000..7dc8c34 --- /dev/null +++ b/src/loader/AppMetadata.cpp @@ -0,0 +1,35 @@ +#include "AppMetadata.hpp" + +#include + +#include +#include + +red3ext::AppMetadata::AppMetadata(const geecore::IHostImage& host_image) + : m_root_directory(compute_root_directory(host_image)) +{ +} + +const std::wstring_view red3ext::AppMetadata::name() const +{ + return L"RED3ext Loader"; +} + +const std::filesystem::path& red3ext::AppMetadata::root_directory() const noexcept +{ + return m_root_directory; +} + +std::filesystem::path red3ext::AppMetadata::module_path() const +{ + return root_directory() / MODULE_NAME; +} + +std::filesystem::path red3ext::AppMetadata::compute_root_directory(const geecore::IHostImage& host_image) +{ + auto game_root = host_image.directory() + .parent_path() // Resolve to "bin" directory. + .parent_path(); // Resolve to game's root directory. + + return game_root / APPLICATION_DIRECTORY; +} diff --git a/src/loader/AppMetadata.hpp b/src/loader/AppMetadata.hpp new file mode 100644 index 0000000..8a59b11 --- /dev/null +++ b/src/loader/AppMetadata.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +#include + +#include +#include +#include + +namespace red3ext +{ +class AppMetadata : public geecore::ILoaderAppMetadata +{ +public: + AppMetadata(const geecore::IHostImage& host_image); + ~AppMetadata() final = default; + + GEECORE_NOEXCEPT_COPYABLE_AND_MOVEABLE(AppMetadata); + + const std::wstring_view name() const final; + const std::filesystem::path& root_directory() const noexcept final; + + std::filesystem::path module_path() const final; + +private: + static constexpr std::wstring_view APPLICATION_DIRECTORY = L"red3ext"; + static constexpr std::wstring_view MODULE_NAME = L"RED3ext.dll"; + + static std::filesystem::path compute_root_directory(const geecore::IHostImage& host_image); + + std::filesystem::path m_root_directory; +}; + +struct AppMetadataService + : kgr::single_service> + , kgr::overrides +{ +}; +} // namespace red3ext diff --git a/src/loader/CMakeLists.txt b/src/loader/CMakeLists.txt index 54da1da..90dfe7d 100644 --- a/src/loader/CMakeLists.txt +++ b/src/loader/CMakeLists.txt @@ -6,20 +6,25 @@ set_target_properties( OUTPUT_NAME winmm ) -configure_resource_rc( +red3ext_configure_resource_rc( RED3ext.Loader "The loader for ${PROJECT_NAME}." ) +geecore_set_target_as_loader(RED3ext.Loader) + set( RED3EXT_LOADER_HEADER_FILES stdafx.hpp Resource.hpp + + AppMetadata.hpp ) set( RED3EXT_LOADER_SRC_FILES Main.cpp + AppMetadata.cpp ) source_group(CMake REGULAR_EXPRESSION cmake_pch.*) @@ -37,7 +42,8 @@ source_group( TREE "${CMAKE_CURRENT_BINARY_DIR}" FILES - ${RED3EXT_RC_FILE} + "${RED3EXT_RC_FILE}" + "${CMAKE_CURRENT_BINARY_DIR}/GEEcore.def" ) target_include_directories( @@ -56,3 +62,10 @@ target_sources( ) target_precompile_headers(RED3ext.Loader PRIVATE stdafx.hpp) + +target_link_libraries( + RED3ext.Loader + PRIVATE + wopss::GEEcore + WIL::WIL +) diff --git a/src/loader/Main.cpp b/src/loader/Main.cpp index 2823350..0627834 100644 --- a/src/loader/Main.cpp +++ b/src/loader/Main.cpp @@ -1,16 +1,78 @@ +#include + +#include + +#include +#include +#include +#include +#include + +#include "AppMetadata.hpp" + BOOL APIENTRY DllMain(HMODULE module, DWORD reason, LPVOID reserved) { - (void)(reserved); + GEECORE_UNUSED(reserved); switch (reason) { case DLL_PROCESS_ATTACH: { DisableThreadLibraryCalls(module); + + try + { + auto host = geecore::HostBuilder() + .add_module_image(module) + .add_service() + .add_loader_lifetime() + .set_as_default() + .build(); + + host->start(); + } + catch (const std::exception& e) + { + geecore::Win32MsgBoxDriverAnsi driver; + geecore::MsgBoxExceptionlessAnsi(driver) + .with_title("RED3ext Loader: Application Exception") + .with_text(e.what()) + .with_icon(geecore::MsgBoxIcon::Error) + .with_buttons(geecore::MsgBoxButtons::Ok) + .show(); + + return FALSE; + } + catch (...) + { + geecore::Win32MsgBoxDriver driver; + geecore::MsgBoxExceptionless(driver) + .with_title(L"RED3ext Loader: Unknown Application Exception") + .with_text(L"An unknown exception has occurred, preventing the application from starting up properly.") + .with_icon(geecore::MsgBoxIcon::Error) + .with_buttons(geecore::MsgBoxButtons::Ok) + .show(); + + return FALSE; + } + break; } case DLL_PROCESS_DETACH: { + try + { + auto host = geecore::Host::instance(); + if (host) + { + host->stop(); + } + } + catch (...) + { + // Unfortunately, there are no specific actions we can take at this point. + } + break; } } diff --git a/src/loader/stdafx.hpp b/src/loader/stdafx.hpp index 81b0aea..1c0b8ea 100644 --- a/src/loader/stdafx.hpp +++ b/src/loader/stdafx.hpp @@ -1,3 +1,12 @@ #pragma once +#include +#include +#include +#include + #include + +#include + +#include