diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index aff0afc..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "extern/CommonLibSSE-NG"] - path = extern/CommonLibSSE-NG - url = https://github.com/alandtse/CommonLibVR - branch = ng diff --git a/README.md b/README.md index 1469dd2..7b5096f 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ ## Dependencies -- [vcpkg v2023.08.09+](https://github.com/microsoft/vcpkg/releases) +- [vcpkg](https://github.com/microsoft/vcpkg) - Create a new Windows environment variable called `VCPKG_ROOT` which points to your vcpkg install directory -- [CMake v3.27+](https://cmake.org/) -- [LLVM v16.0.6+](https://github.com/llvm/llvm-project/releases) +- [CMake](https://cmake.org/) +- [LLVM](https://github.com/llvm/llvm-project/releases) - Visual Studio 2022 with C++ workload ## Resources @@ -34,39 +34,3 @@ - [Address Library Database](https://github.com/meh321/AddressLibraryDatabase) - [Address Library Manager](https://github.com/meh321/AddressLibraryManager/releases) - [Steamless](https://github.com/atom0s/Steamless/releases) - -# Context - -## What you need to know - -- C++ and the tools mentioned in the Dependencies section -- Assembly (specifically, x86-64) -- x64 calling convention - -## What is Skyrim reverse engineering? - -We're all (hopefully) familiar with executables. The process of turning a set of human-readable source code files into machine-readable instructions consists of several layers of translation. Reverse engineering is the process of working back from machine-readable instructions to human-readable source code. Since we don't have the source code for Skyrim, we must use tools like the [Interactive Disassembler (IDA)](https://en.wikipedia.org/wiki/Interactive_Disassembler) to, you guessed it, reverse engineer the source code so that we may "hack into" the game's functionality and do all the interesting things that SKSE plugins do. Thankfully, a bunch of Really Smart People did most of the heavy lifting and went ahead and reverse engineered huge swathes of the game, resulting in [CommonLibSSE](https://github.com/Ryan-rsm-McKenzie/CommonLibSSE) and its various forks. Although these libraries provide a great deal of convenience and significantly speed up development, it is nonetheless often necessary to inspect the disassembled Skyrim executable in IDA or Ghidra. - -## What is CommonLibSSE? - -A library, written in C++, which consists of reverse-engineered classes, functions, etc. found in the disassembled Skyrim executable. Due to its age, there are several different runtime versions of Skyrim. The main versions of interest are v1.5.97, v1.6.640, and VR. Due to differences in struct layouts etc. amongst these runtimes and the resulting difficulty of building DLLs that target different runtimes, [CommonLibSSE-NG](https://github.com/CharmedBaryon/CommonLibSSE-NG) (the basis of this template) was created, which allows building a single DLL that can target every Skyrim runtime using clever tricks like [relocations](). - -## The Address Library:tm: - -The Address Library is a mapping of integer IDs (e.g. 57463) to addresses in different Skyrim runtimes. It allows version-independent targeting of functions etc. using relocations. `REL::Relocation func{RELOCATION_ID(SE_ID, AE_ID), REL::Relocate(se_offset, ae_offset, vr_offset))}` returns a runtime-adjusted pointer to the function mapped by the given SE or AE address library IDs. - -## Some terminology - -- [Hooking](https://en.wikipedia.org/wiki/Hooking): Hooking involves intercepting function/subroutine calls and replacing or extending their logic. There are two types of hooks commonly seen in SKSE plugins: - - Call site hook: These hooks target individual `call` instructions at specific addresses, allowing you to intercept and replace/extend a specific function call. - - See `stl::write_call` in `CommonLibSSE-NG\include\SKSE\Trampoline.h` - - Virtual function hook: These hooks target _every_ invocation of a given function via the virtual function table of its parent class. - - See `stl::write_vfunc` in `CommonLibSSE-NG\include\REL\Relocation.h` - - More about function hooks: [CommonLibSSE NG sample plugin repo](https://gitlab.com/colorglass/commonlibsse-sample-plugin/-/blob/main/README.md#function-hooks) -- [Trampoline](): TODO -- [Thunk](https://en.wikipedia.org/wiki/Thunk): A thin wrapper around a hooked function, allowing the execution of arbitrary logic before or after the hooked code -- [Xbyak](https://github.com/herumi/xbyak): A just-in-time assembler that allows applying assembly patches anywhere in the disassembled executable - -## Events - -Those familiar with Papyrus-based mod development know that the game fires various events for things that occur in game (OnHit, OnCellAttach, etc.). CommonLibSSE-NG exposes various events, allowing you to listen for and execute logic during events relevant to your plugin. Note that events are passed from one loaded SKSE plugin to the next in succession at runtime in alphabetical order of loaded SKSE plugins. Since your plugin is only one of multiple plugins that may be overriding a given event's `ProcessEvent` method, it's important to return `RE::BSEventNotifyControl::kContinue` in all control paths of your `ProcessEvent` override. diff --git a/cmake/version.rc.in b/cmake/version.rc.in index 95029f0..3671c40 100644 --- a/cmake/version.rc.in +++ b/cmake/version.rc.in @@ -1,26 +1,26 @@ -#include +#include 1 VERSIONINFO FILEVERSION @PROJECT_VERSION_MAJOR@, @PROJECT_VERSION_MINOR@, @PROJECT_VERSION_PATCH@, 0 PRODUCTVERSION @PROJECT_VERSION_MAJOR@, @PROJECT_VERSION_MINOR@, @PROJECT_VERSION_PATCH@, 0 FILEFLAGSMASK 0x17L #ifdef _DEBUG - FILEFLAGS 0x1L + FILEFLAGS VS_FF_DEBUG #else - FILEFLAGS 0x0L + FILEFLAGS 0 #endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L + FILEOS VOS_NT + FILETYPE VFT_DLL + FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "040904b0" + BLOCK "040904B0" BEGIN VALUE "FileDescription", "@PROJECT_DESCRIPTION@" VALUE "FileVersion", "@PROJECT_VERSION@" VALUE "InternalName", "@PROJECT_NAME@" - VALUE "LegalCopyright", "Apache License 2.0" + VALUE "LegalCopyright", "GNU General Public License v3.0" VALUE "ProductName", "@PROJECT_FRIENDLY_NAME@" VALUE "ProductVersion", "@PROJECT_VERSION@" END diff --git a/extern/CommonLibSSE-NG b/extern/CommonLibSSE-NG deleted file mode 160000 index e83b23b..0000000 --- a/extern/CommonLibSSE-NG +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e83b23bddb893d44b8f3cf3e6379b9087ad25cc9 diff --git a/project_setup.py b/project_setup.py index bbd90e3..dd76360 100644 --- a/project_setup.py +++ b/project_setup.py @@ -1,36 +1,26 @@ import os import re -import shutil -import stat import subprocess import json cwd = os.path.dirname(os.path.abspath(__file__)) -vcpkg_repo = "https://github.com/microsoft/vcpkg" -stdout, stderr = subprocess.Popen( - ["git", "ls-remote", vcpkg_repo], stdout=subprocess.PIPE -).communicate() -vcpkg_sha = re.split(r"\t+", stdout.decode("ascii"))[0] - -subprocess.Popen(["git", "submodule", "update", "--init"], cwd=cwd).communicate() - - -def onexc(func, path, exc_info): - if not os.access(path, os.W_OK): - os.chmod(path, stat.S_IWUSR) - func(path) - else: - raise - - -if os.path.isdir(os.path.join(cwd, ".git")): - shutil.rmtree(os.path.join(cwd, ".git"), onexc=onexc) os.remove(os.path.join(cwd, "README.md")) project_name = input("Enter project name: ") author = input("Enter author: ") +print() + +from_path = input("Use CommonLibSSE-NG from path? (Y/n): ") +if from_path == "" or from_path.lower() == "y": + print(f"Using CommonLibSSE-NG from path {os.environ["CommonLibSSEPath"]}") +elif from_path.lower() == "n": + print("Using CommonLibSSE-NG as submodule") +else: + print("Invalid input") + exit() + pattern = re.compile(r"(?