diff --git a/.clang-format b/.clang-format deleted file mode 100644 index ec370f5..0000000 --- a/.clang-format +++ /dev/null @@ -1,100 +0,0 @@ -AccessModifierOffset: -4 -AlignAfterOpenBracket: AlwaysBreak -AlignArrayOfStructures: Left -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: Consecutive -AlignConsecutiveDeclarations: None -AlignConsecutiveMacros: None -AlignEscapedNewlines: Right -AlignOperands: Align -AllowAllArgumentsOnNextLine: False -AllowAllParametersOfDeclarationOnNextLine: False -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: False -AllowShortEnumsOnASingleLine: False -AllowShortFunctionsOnASingleLine: Inline -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Inline -AllowShortLoopsOnASingleLine: False -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: False -AlwaysBreakTemplateDeclarations: Yes -BinPackArguments: False -BinPackParameters: False -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: True - AfterClass: True - AfterControlStatement: Always - AfterEnum: True - AfterFunction: True - AfterNamespace: True - AfterStruct: True - AfterUnion: True - AfterExternBlock: True - BeforeCatch: True - BeforeElse: True - BeforeLambdaBody: True - BeforeWhile: True - IndentBraces: False - SplitEmptyFunction: False - SplitEmptyRecord: False - SplitEmptyNamespace: False -BreakBeforeBinaryOperators: NonAssignment -BreakBeforeBraces: Custom -BreakBeforeTernaryOperators: True -BreakConstructorInitializers: AfterColon -BreakInheritanceList: AfterColon -BreakStringLiterals: False -ColumnLimit: 0 -CompactNamespaces: False -Cpp11BracedListStyle: False -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: Always -FixNamespaceComments: False -IncludeBlocks: Preserve -IndentAccessModifiers: False -IndentCaseBlocks: True -IndentCaseLabels: True -IndentExternBlock: AfterExternBlock -IndentGotoLabels: False -IndentPPDirectives: AfterHash -IndentWidth: 4 -IndentWrappedFunctionNames: True -KeepEmptyLinesAtTheStartOfBlocks: False -LambdaBodyIndentation: Signature -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: All -PPIndentWidth: 1 -PackConstructorInitializers: NextLine -PointerAlignment: Left -QualifierAlignment: Custom -QualifierOrder: ['inline', 'static', 'const', 'type'] -ReferenceAlignment: Left -ReflowComments: False -SeparateDefinitionBlocks: Always -SortIncludes: CaseInsensitive -SpaceAfterCStyleCast: False -SpaceAfterLogicalNot: False -SpaceAfterTemplateKeyword: False -SpaceBeforeAssignmentOperators: True -SpaceBeforeCaseColon: False -SpaceBeforeCpp11BracedList: False -SpaceBeforeCtorInitializerColon: True -SpaceBeforeInheritanceColon: True -SpaceBeforeParens: ControlStatements -SpaceBeforeRangeBasedForLoopColon: True -SpaceBeforeSquareBrackets: False -SpaceInEmptyBlock: False -SpaceInEmptyParentheses: False -SpacesBeforeTrailingComments: 2 -SpacesInAngles: Never -SpacesInCStyleCastParentheses: False -SpacesInConditionalStatement: False -SpacesInContainerLiterals: True -SpacesInParentheses: False -SpacesInSquareBrackets: False -Standard: Latest -TabWidth: 4 -UseCRLF: True -UseTab: AlignWithSpaces diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index fb7e6e3..0000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -[*] -charset = utf-8 -insert_final_newline = true - -[*.{hpp,cpp}] -indent_style = tab -indent_size = 4 - -[{CMakeLists.txt,*.cmake,*.cmake.in}] -indent_style = tab -indent_size = 4 - -[*.{json,yml}] -indent_style = space -indent_size = 2 diff --git a/.gitattributes b/.gitattributes index dfe0770..cc864ad 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1 @@ -# Auto detect text files and perform LF normalization -* text=auto +*.ps1 linguist-vendored \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3f65f13 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +name: CI + +on: + push: + paths: + - "Plugin/**" + workflow_dispatch: + +jobs: + run-build: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Dependencies + run: | + git submodule update --init --recursive; + vcpkg integrate install + + - name: Build + run: | + Remove-Item build -Recurse -Force -ErrorAction:SilentlyContinue -Confirm:$False | Out-Null; + cmake -B build -S Plugin --preset=build-release-msvc-msvc -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake; + cmake --build build + + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: Release + path: build/Release + retention-days: 30 diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml new file mode 100644 index 0000000..6b2ed65 --- /dev/null +++ b/.github/workflows/clang-format.yml @@ -0,0 +1,21 @@ +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: DoozyX/clang-format-lint-action@v0.16.2 + with: + source: '.' + exclude: './docs' + extensions: 'c,cc,cpp,cxx,h,hpp,hxx,inl,inc,ixx' + clangFormatVersion: 16 + inplace: True + - uses: EndBug/add-and-commit@v9 + with: + author_name: clang-format + message: 'chore: style formatting' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml index 9fed75d..24bd4ed 100644 --- a/.github/workflows/maintenance.yml +++ b/.github/workflows/maintenance.yml @@ -1,33 +1,24 @@ -name: Scripted maintenance +name: Maintenance -on: [ push, pull_request_target ] +on: [push] jobs: maintenance: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + + - uses: DoozyX/clang-format-lint-action@v0.16.2 with: - ref: ${{ github.head_ref }} + source: '.' + exclude: './docs' + extensions: 'c,cc,cpp,cppm,cxx,h,hpp,hxx,inl,inc,ixx,mxx' + clangFormatVersion: 16 + inplace: True - - name: Cache LLVM and Clang - id: cache-llvm - uses: actions/cache@v2 + - uses: EndBug/add-and-commit@v9 with: - path: ${{ runner.temp }}/llvm - key: llvm-14 - - - name: Install LLVM and Clang - uses: KyleMayes/install-llvm-action@v1 - with: - version: "14" - directory: ${{ runner.temp }}/llvm - cached: ${{ steps.cache-llvm.outputs.cache-hit }} - - - name: Run clang-format - run: find -type f \( -name *.h -o -name *.cpp \) | xargs clang-format -style=file -i - - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: maintenance + committer_name: clang-format + committer_email: 41898282+github-actions[bot]@users.noreply.github.com + message: 'chore: style formatting' diff --git a/.gitignore b/.gitignore index d163863..5c96cd0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ -build/ \ No newline at end of file +[Bb]uild/ +.vs/ +.vscode/ +*.zip +*.timestamp +deploy-*.ps1 diff --git a/.gitmodules b/.gitmodules index b30655b..350cfcd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ -[submodule "extern/BethesdaCMakeModules"] - path = extern/BethesdaCMakeModules - url = https://github.com/shad0wshayd3/BethesdaCMakeModules.git [submodule "extern/CommonLibF4"] path = extern/CommonLibF4 url = https://github.com/shad0wshayd3/CommonLibF4.git +[submodule "extern/DKUtil"] + path = extern/DKUtil + url = https://github.com/gottyduke/DKUtil.git diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index 5a62af7..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -cmake_minimum_required(VERSION 3.22) -set(NAME "BakaMaxPapyrusOps") -set(VERSION 1.1.0) - -# ---- Options ---- - -option(COPY_BUILD "Copy the build output to the Fallout 4 directory." OFF) - -# ---- Cache build vars ---- - -macro(set_from_environment VARIABLE) - if (NOT DEFINED ${VARIABLE} AND DEFINED ENV{${VARIABLE}}) - set(${VARIABLE} $ENV{${VARIABLE}}) - endif() -endmacro() - -macro(find_commonlib_path) - if (CommonLibName AND NOT ${CommonLibName} STREQUAL "") - # Check extern - find_path(CommonLibPath - NAMES - include/REL/Relocation.h - PATHS - extern/${CommonLibName} - extern/${CommonLibName}/${CommonLibName} - ) - if (${CommonLibName} STREQUAL "CommonLibName-NOTFOUND") - #Check path - set_from_environment(${CommonLibName}Path) - set(CommonLibName ${${CommonLibName}Path}) - endif() - endif() -endmacro() - -set_from_environment(VCPKG_ROOT) -if (NOT DEFINED VCPKG_ROOT) - message( - WARNING - "Variable VCPKG_ROOT is not set. Continuing without vcpkg." - ) -endif() - -set_from_environment(Fallout4Path) -set(CommonLibName "CommonLibF4") -find_commonlib_path("CommonLibF4") - -message( - STATUS - "Building for Fallout 4 at ${Fallout4Path} with ${CommonLibName} at ${CommonLibPath}." -) - -set(Boost_USE_STATIC_RUNTIME OFF CACHE BOOL "") -set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" CACHE STRING "") - -# ---- Project ---- - -project( - ${NAME} - VERSION ${VERSION} - LANGUAGES CXX -) - -# ---- Include guards ---- - -if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) - message( - FATAL_ERROR - "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there." - ) -endif() - -# ---- Subdirectories ---- - -add_subdirectory(src) diff --git a/CMakePresets.json b/CMakePresets.json deleted file mode 100644 index 00350b9..0000000 --- a/CMakePresets.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "configurePresets": [ - { - "binaryDir": "${sourceDir}/build", - "cacheVariables": { - "CMAKE_BUILD_TYPE": { - "type": "STRING", - "value": "Release" - } - }, - "errors": { - "deprecated": true - }, - "hidden": true, - "name": "cmake-dev", - "warnings": { - "deprecated": true, - "dev": true - } - }, - { - "cacheVariables": { - "CMAKE_TOOLCHAIN_FILE": { - "type": "STRING", - "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - }, - "VCPKG_OVERLAY_PORTS": { - "type": "STRING", - "value": "${sourceDir}/cmake/ports/" - } - }, - "hidden": true, - "name": "vcpkg" - }, - { - "cacheVariables": { - "CMAKE_MSVC_RUNTIME_LIBRARY": { - "type": "STRING", - "value": "MultiThreaded$<$:Debug>" - }, - "VCPKG_TARGET_TRIPLET": { - "type": "STRING", - "value": "x64-windows-static" - } - }, - "hidden": true, - "name": "windows" - }, - { - "cacheVariables": { - "CMAKE_CXX_FLAGS": "/EHsc /MP /W4 /WX", - "CMAKE_CXX_FLAGS_RELEASE": "/O2 /DNDEBUG" - }, - "generator": "Visual Studio 17 2022", - "inherits": [ - "cmake-dev", - "vcpkg", - "windows" - ], - "name": "vs2022-windows-vcpkg", - "toolset": "v143" - } - ], - "version": 2 -} diff --git a/LICENSE b/LICENSE index 5337fdb..f288702 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,674 @@ -MIT License - -Copyright (c) 2022 shad0wshayd3 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program 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. + + This program 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Plugin/!update.ps1 b/Plugin/!update.ps1 new file mode 100644 index 0000000..1cbb5df --- /dev/null +++ b/Plugin/!update.ps1 @@ -0,0 +1,263 @@ +#Requires -Version 5 + +# args +param ( + [Parameter(Mandatory)][ValidateSet('SOURCEGEN', 'DISTRIBUTE')][string]$Mode = 'SOURCEGEN', + [string]$Version, + [string]$Path, + [string]$Payload +) + + +$ErrorActionPreference = "Stop" + +$Folder = $PSScriptRoot | Split-Path -Leaf +$SourceExt = @('.asm', '.c', '.cc', '.cpp', '.cxx', '.h', '.hpp', '.hxx', 'inc', '.inl', '.ixx') +$ConfigExt = @('.ini', '.json', '.toml', '.xml') +$DocsExt = @('.md') + +function Normalize-Path { + param ( + [string]$in + ) + + $out = $in -replace '\\', '/' + while ($out.Contains('//')) { + $out = $out -replace '//', '/' + } + return $out +} + +function Resolve-Files { + param ( + [Parameter(ValueFromPipeline)][string]$parent = $PSScriptRoot, + [string[]]$range = @('include', 'src', 'test') + ) + + process { + Push-Location $PSScriptRoot + $_generated = [System.Collections.ArrayList]::new() + + try { + foreach ($directory in $range) { + if (!$env:RebuildInvoke) { + Write-Host "`t[$parent/$directory]" + } + + Get-ChildItem "$parent/$directory" -Recurse -File -ErrorAction SilentlyContinue | Where-Object { + ($_.Extension -in ($SourceExt + $DocsExt)) -and + ($_.Name -notmatch 'Plugin.h|Version.h') + } | Resolve-Path -Relative | ForEach-Object { + if (!$env:RebuildInvoke) { + Write-Host "`t`t<$_>" + } + $_generated.Add("`n`t`"$(Normalize-Path $_.Substring(2))`"") | Out-Null + } + } + + Get-ChildItem "$parent/dist" -Exclude "rules" | Get-ChildItem -File -Recurse -ErrorAction SilentlyContinue | Where-Object { + ($_.Extension -in ($ConfigExt + $DocsExt)) -and + ($_.Name -notmatch 'cmake|vcpkg') + } | Resolve-Path -Relative | ForEach-Object { + if (!$env:RebuildInvoke) { + Write-Host "`t`t<$_>" + } + $_generated.Add("`n`t`"$(Normalize-Path $_.Substring(2))`"") | Out-Null + } + } + finally { + Pop-Location + } + + return $_generated + } +} + + +Write-Host "`n`t<$Folder> [$Mode]" + + +# @@SOURCEGEN +if ($Mode.ToUpper() -eq 'SOURCEGEN') { + Write-Host "`tGenerating CMake sourcelist..." + Remove-Item "$Path/sourcelist.cmake" -Force -Confirm:$false -ErrorAction Ignore + + $generated = 'set(SOURCES' + $generated += $PSScriptRoot | Resolve-Files + if ($Path) { + $generated += $Path | Resolve-Files + } + $generated += "`n)" + [IO.File]::WriteAllText("$Path/sourcelist.cmake", $generated) +} + +$RuleVarTbl = @{ + config = 'debug'; + cmake_output = Normalize-Path ($Path + '/'); + dist = Normalize-Path "$PSScriptRoot/dist/"; + project_name = $Payload; + project_version = $Version; +} +$RuleCmds = @() + +function Resolve-RuleVar { + param ( + [string]$Path + ) + + $Path = $Path.Trim(' ') + $any = [regex]::Matches($Path, '\{.*?\}').Value + $Resolved = $Path + + # env: + foreach ($unset in $any) { + $inner = $unset.Trim('{', '}') + if ($inner.StartsWith('env:')) { + $Resolved = $Resolved -replace $unset, [System.Environment]::GetEnvironmentVariable($inner.TrimStart('env:')) + } + else { + $Resolved = if ($script:RuleVarTbl.Contains($inner)) { + $Resolved -replace $unset, $script:RuleVarTbl[$inner] + } + else { + $Resolved -replace $unset, $inner + } + } + } + + return Normalize-Path $Resolved.Trim('{', '}') +} + +function Resolve-Rules { + param ( + [Object]$Deployee + ) + + switch ($Deployee.action) { + "base" { + $script:RuleVarTbl[($Deployee.params[0].Trim('{', '}'))] = Resolve-RuleVar $Deployee.params[1] + #"setting $($Deployee.params[0]) to $(Resolve-RuleVar $Deployee.params[1])" + break + } + "copy" { + $source = $(Resolve-RuleVar $Deployee.params[0]) + $destination = $(Resolve-RuleVar $Deployee.params[1]) + $dest_path = $destination.Substring(0, $destination.LastIndexOf('/') + 1) + $script:RuleCmds += "New-Item `'$dest_path`' -ItemType Directory -Force -ErrorAction:SilentlyContinue" + $script:RuleCmds += "Copy-Item `'$source`' `'$destination`' -Force -Recurse -ErrorAction:SilentlyContinue" + break + } + "copy_if" { + $source = $(Resolve-RuleVar $Deployee.params[0]) + $destination = $(Resolve-RuleVar $Deployee.params[1]) + $dest_path = $destination.Substring(0, $destination.LastIndexOf('/') + 1) + $script:RuleCmds += "if (Test-Path `'$source`') {" + $script:RuleCmds += "New-Item `'$dest_path`' -ItemType Directory -Force -ErrorAction:SilentlyContinue" + $script:RuleCmds += "Copy-Item `'$source`' `'$destination`' -Force -Recurse -ErrorAction:SilentlyContinue }" + break + } + "package" { + $source_tree = @() + foreach ($source in $Deployee.params[0..($Deployee.params.Length - 2)]) { + $source_tree += , "`'$(Resolve-RuleVar $source)`'" + } + $script:RuleCmds += "Compress-Archive -Path $($source_tree -join ',') -DestinationPath `'$(Resolve-RuleVar $Deployee.params[-1])`' -Force -ErrorAction:SilentlyContinue" + break + } + "remove" { + foreach ($to_remove in $Deployee.params) { + $script:RuleCmds += "Remove-Item `'$(Resolve-RuleVar $to_remove)`' -Force -Recurse -ErrorAction:SilentlyContinue" + } + break + } + "script" { + foreach ($raw_script in $Deployee.params) { + $script:RuleCmds += $raw_script + } + break + } + default { + break + } + } +} + + +# @@DISTRIBUTE +if ($Mode.ToUpper() -eq 'DISTRIBUTE') { + if ($Version.ToUpper() -eq '-1') { + # update script to every project + Get-ChildItem "$PSScriptRoot/$Path" -Directory -Recurse | Where-Object { + $_.Name -notin @('vcpkg', 'build', '.git', '.vs') -and + (Test-Path "$_/CMakeLists.txt" -PathType Leaf) -and + (Test-Path "$_/vcpkg.json" -PathType Leaf) + } | ForEach-Object { + Write-Host "`tUpdated <$_>" + Robocopy.exe "$PSScriptRoot" "$_" '!Update.ps1' /MT /NJS /NFL /NDL /NJH | Out-Null + } + exit + } + + $Path = Normalize-Path $Path + $RuleVarTbl.config = $Path.Split('/')[-1].ToLower() + + $rules = Get-ChildItem "$($RuleVarTbl.dist)/rules" -File *.json + $rule_timestamp = @( "!update : $((Get-Item $MyInvocation.MyCommand.Path).LastWriteTime.Ticks)" ) + + # generate timestamp & distribution step + foreach ($rule in $rules) { + $rule_timestamp += , "$($rule.BaseName) : $($rule.LastWriteTime.Ticks)" + } + + $regenerate = $true + $timestamp = "$($RuleVarTbl.dist)/rules/$($RuleVarTbl.project_version).timestamp" + Write-Host "`tChecking deploy rules..." + + if (Test-Path "$($RuleVarTbl.dist)/deploy.ps1") { + $rule_timestamp += , "deployer : $((Get-Item "$($RuleVarTbl.dist)/deploy.ps1").LastWriteTime.Ticks)" + } + + if (Test-Path $timestamp) { + $old_timestamp = [IO.File]::ReadAllText($timestamp) + + if ($old_timestamp -eq ($rule_timestamp | Out-String)) { + $regenerate = $false + Write-Host "`t...No changes" + } + else { + Write-Host "`t...Pending changes" + } + } + + # parse all rules + if ($regenerate) { + Write-Host "`tRegenerating deploy rules..." + + foreach ($rule in $rules) { + $deployer = [IO.File]::ReadAllText($rule.FullName) | ConvertFrom-Json + + foreach ($deployee in $deployer) { + if (("config" -in $deployee.PSObject.Properties.Name) -and ($deployee.config -ne $RuleVarTbl.config)) { + continue + } + else { + Resolve-Rules $deployee + } + } + } + + $RuleCmds | Out-File "$($RuleVarTbl.dist)/deploy-$($RuleVarTbl.config.ToLower()).ps1" utf8 + + $rule_timestamp[-1] = "deployer : $((Get-Item "$($RuleVarTbl.dist)/deploy-$($RuleVarTbl.config.ToLower()).ps1").LastWriteTime.Ticks)" + Remove-Item "$($RuleVarTbl.dist)/rules/*.timestamp" -Force -ErrorAction:SilentlyContinue | Out-Null + $rule_timestamp | Out-File $timestamp utf8 + + Write-Host "`t...Ok" + } + + # deploy + Write-Host "`tExecuting deploy rules..." + & "$($RuleVarTbl.dist)/deploy-$($RuleVarTbl.config.ToLower()).ps1" + + Write-Host "`t...Ok" +} diff --git a/Plugin/.clang-format b/Plugin/.clang-format new file mode 100644 index 0000000..e1170b2 --- /dev/null +++ b/Plugin/.clang-format @@ -0,0 +1,97 @@ +--- +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignConsecutiveMacros: false +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BitFieldColonSpacing: After +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +BreakInheritanceList: AfterColon +BreakStringLiterals: true +ColumnLimit: 0 +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +FixNamespaceComments: false +IncludeBlocks: Preserve +IndentCaseBlocks: true +IndentCaseLabels: false +IndentExternBlock: Indent +IndentGotoLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +PointerAlignment: Left +ReflowComments: false +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Latest +TabWidth: 4 +UseTab: AlignWithSpaces +LineEnding: CRLF +PackConstructorInitializers: BinPack diff --git a/Plugin/CMakeLists.txt b/Plugin/CMakeLists.txt new file mode 100644 index 0000000..3b40b46 --- /dev/null +++ b/Plugin/CMakeLists.txt @@ -0,0 +1,132 @@ +cmake_minimum_required(VERSION 3.21) + +# info +project( + BakaMaxPapyrusOps + VERSION 2.0.0 + LANGUAGES CXX +) + +# boiler +include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common.cmake) + +# in-place configuration +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Plugin.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/Plugin.h + @ONLY +) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/version.rc + @ONLY +) + +# source files +execute_process(COMMAND powershell -ExecutionPolicy Bypass -File "${CMAKE_CURRENT_SOURCE_DIR}/!update.ps1" "SOURCEGEN" "${PROJECT_VERSION}" "${CMAKE_CURRENT_BINARY_DIR}") +include(${CMAKE_CURRENT_BINARY_DIR}/sourcelist.cmake) +source_group( + TREE ${CMAKE_CURRENT_SOURCE_DIR} + FILES ${SOURCES} +) + +source_group( + TREE ${CMAKE_CURRENT_BINARY_DIR} + FILES ${CMAKE_CURRENT_BINARY_DIR}/include/Plugin.h +) + +# dependencies +find_package(spdlog CONFIG REQUIRED) +find_dependency_path(DKUtil include/DKUtil/Logger.hpp) +find_dependency_path(CommonLibF4/CommonLibF4 include/F4SE/F4SE.h) + +# cmake target +# runtime +add_library( + ${PROJECT_NAME} + SHARED + ${SOURCES} + ${CMAKE_CURRENT_BINARY_DIR}/include/Plugin.h + ${CMAKE_CURRENT_BINARY_DIR}/version.rc + .clang-format + vcpkg.json +) + +# include dir +target_include_directories( + ${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/src +) + +# linkage +target_link_libraries( + ${PROJECT_NAME} + PRIVATE + DKUtil::DKUtil + CommonLibF4::CommonLibF4 + spdlog::spdlog +) + +# compiler def +if (MSVC) + add_compile_definitions(_UNICODE) + + target_compile_options( + ${PROJECT_NAME} + PRIVATE + /MP + /await + /W0 + /WX + /permissive- + /utf-8 + /Zc:alignedNew + /Zc:auto + /Zc:__cplusplus + /Zc:externC + /Zc:externConstexpr + /Zc:forScope + /Zc:hiddenFriend + /Zc:implicitNoexcept + /Zc:lambda + /Zc:noexceptTypes + /Zc:preprocessor + /Zc:referenceBinding + /Zc:rvalueCast + /Zc:sizedDealloc + /Zc:strictStrings + /Zc:ternary + /Zc:threadSafeInit + /Zc:trigraphs + /Zc:wchar_t + /wd4200 # nonstandard extension used : zero-sized array in struct/union + /FI${CMAKE_CURRENT_SOURCE_DIR}/src/PCH.h + ) +endif() + +# PCH +target_precompile_headers( + ${PROJECT_NAME} + PRIVATE + src/PCH.h +) + +set_property( + TARGET + ${PROJECT_NAME} + PROPERTY VS_USER_PROPS + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/build_stl_modules.props" +) + +# update deployments + add_custom_command( + TARGET + ${PROJECT_NAME} + POST_BUILD + COMMAND powershell -NoProfile -ExecutionPolicy Bypass -File + "${CMAKE_CURRENT_SOURCE_DIR}/!update.ps1" "DISTRIBUTE" "${PROJECT_VERSION}" "${CMAKE_CURRENT_BINARY_DIR}/$(ConfigurationName)" "${PROJECT_NAME}" + ) diff --git a/Plugin/CMakePresets.json b/Plugin/CMakePresets.json new file mode 100644 index 0000000..4333c1a --- /dev/null +++ b/Plugin/CMakePresets.json @@ -0,0 +1,233 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 26, + "patch": 0 + }, + "configurePresets": [ + { + "name": "common", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "$env{PROJECT_PLATFORM_FLAGS} $env{PROJECT_TEXT_FLAGS} $env{PROJECT_COMPILER_FLAGS} $penv{CXXFLAGS}", + "F4SE_SUPPORT_XBYAK": "ON", + "USING_VCPKG": true + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-msvc-x64", + "enableMicrosoftCodeAnalysis": true, + "enableClangTidyCodeAnalysis": true + } + } + }, + { + "name": "packaging-vcpkg", + "hidden": true, + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": { + "type": "STRING", + "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + }, + "VCPKG_TARGET_TRIPLET": "x64-windows-static-md" + } + }, + { + "name": "buildtype-debug", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "buildtype-release", + "hidden": true, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "x64", + "hidden": true, + "architecture": "x64", + "cacheVariables": { + "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$:Debug>DLL" + } + }, + { + "name": "generator-msvc", + "hidden": true, + "inherits": "x64", + "generator": "Visual Studio 17 2022" + }, + { + "name": "generator-ninja", + "hidden": true, + "generator": "Ninja" + }, + { + "name": "compiler-msvc", + "hidden": true, + "environment": { + "PROJECT_COMPILER_FLAGS": "/cgthreads8 /diagnostics:caret /fp:contract /fp:except- /guard:cf- /permissive- /Zc:__cplusplus /Zc:enumTypes /Zc:lambda /Zc:preprocessor /Zc:referenceBinding /Zc:rvalueCast /Zc:templateScope /Zc:ternary /Zc:preprocessor /EHsc /MP /W4 /WX /external:anglebrackets /external:W0", + "PROJECT_COMPILER": "msvc" + } + }, + { + "name": "compiler-clang", + "hidden": true, + "cacheVariables": { + "CMAKE_C_COMPILER": "clang", + "CMAKE_CXX_COMPILER": "clang++" + }, + "environment": { + "PROJECT_COMPILER": "clang", + "PROJECT_COMPILER_FLAGS": "-Wno-overloaded-virtual -Wno-delete-non-abstract-non-virtual-dtor -Wno-inconsistent-missing-override -Wno-reinterpret-base-class" + }, + "vendor": { + "microsoft.com/VisualStudioSettings/CMake/1.0": { + "intelliSenseMode": "windows-clang-x64" + } + } + }, + { + "name": "compiler-clang-cl", + "hidden": true, + "inherits": "compiler-clang", + "cacheVariables": { + "CMAKE_C_COMPILER": "clang-cl", + "CMAKE_CXX_COMPILER": "clang-cl" + }, + "environment": { + "CC": "clang-cl", + "CXX": "clang-cl", + "PROJECT_COMPILER_FLAGS": "/permissive- /EHsc /W4 /WX -Wno-overloaded-virtual -Wno-delete-non-abstract-non-virtual-dtor -Wno-inconsistent-missing-override -Wno-reinterpret-base-class -D__cpp_consteval" + } + }, + { + "name": "build-debug-msvc-msvc", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-debug", + "generator-msvc", + "compiler-msvc" + ] + }, + { + "name": "build-debug-msvc-ninja", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-debug", + "generator-ninja", + "compiler-msvc" + ] + }, + { + "name": "build-debug-clang-cl-msvc", + "toolset": "ClangCL", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-debug", + "generator-msvc", + "compiler-clang-cl" + ] + }, + { + "name": "build-debug-clang-cl-ninja", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-debug", + "generator-ninja", + "compiler-clang-cl" + ] + }, + { + "name": "build-release-msvc-msvc", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-release", + "generator-msvc", + "compiler-msvc" + ] + }, + { + "name": "build-release-msvc-ninja", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-release", + "generator-ninja", + "compiler-msvc" + ] + }, + { + "name": "build-release-clang-cl-msvc", + "toolset": "ClangCL", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-release", + "generator-msvc", + "compiler-clang-cl" + ] + }, + { + "name": "build-release-clang-cl-ninja", + "inherits": [ + "common", + "packaging-vcpkg", + "buildtype-release", + "generator-ninja", + "compiler-clang-cl" + ] + } + ], + "buildPresets": [ + { + "name": "debug-msvc-ninja", + "configurePreset": "build-debug-msvc-ninja", + "displayName": "1. (Debug) MSVC - Ninja" + }, + { + "name": "release-msvc-ninja", + "configurePreset": "build-release-msvc-ninja", + "displayName": "2. (Release) MSVC - Ninja" + }, + { + "name": "debug-msvc-msvc", + "configurePreset": "build-debug-msvc-msvc", + "displayName": "3. (Debug) MSVC - MSVC" + }, + { + "name": "release-msvc-msvc", + "configurePreset": "build-release-msvc-msvc", + "displayName": "4. (Release) MSVC - MSVC" + }, + { + "name": "debug-clang-cl-ninja", + "configurePreset": "build-debug-clang-cl-ninja", + "displayName": "5. (Debug) Clang - Ninja" + }, + { + "name": "release-clang-cl-ninja", + "configurePreset": "build-release-clang-cl-ninja", + "displayName": "6. (Release) Clang - Ninja" + }, + { + "name": "debug-clang-cl-msvc", + "configurePreset": "build-debug-clang-cl-msvc", + "displayName": "7. (Debug) Clang - MSVC" + }, + { + "name": "release-clang-cl-msvc", + "configurePreset": "build-release-clang-cl-msvc", + "displayName": "8. (Release) Clang - MSVC" + } + ] +} diff --git a/Plugin/cmake/Plugin.h.in b/Plugin/cmake/Plugin.h.in new file mode 100644 index 0000000..d3bc623 --- /dev/null +++ b/Plugin/cmake/Plugin.h.in @@ -0,0 +1,12 @@ +#pragma once + + +namespace Plugin +{ + inline constexpr auto NAME = "@PROJECT_NAME@"sv; + inline constexpr auto AUTHOR = "shad0wshayd3"sv; + inline constexpr auto Version = + @PROJECT_VERSION_MAJOR@u * 10000 + + @PROJECT_VERSION_MINOR@u * 100 + + @PROJECT_VERSION_PATCH@u; +} diff --git a/Plugin/cmake/build_stl_modules.props b/Plugin/cmake/build_stl_modules.props new file mode 100644 index 0000000..a8184de --- /dev/null +++ b/Plugin/cmake/build_stl_modules.props @@ -0,0 +1,8 @@ + + + + + false + + + \ No newline at end of file diff --git a/Plugin/cmake/common.cmake b/Plugin/cmake/common.cmake new file mode 100644 index 0000000..22ece50 --- /dev/null +++ b/Plugin/cmake/common.cmake @@ -0,0 +1,44 @@ +# dependency macros +macro(find_dependency_path DEPENDENCY FILE) + # searches extern for dependencies and if not checks the environment variable + if(NOT ${DEPENDENCY} STREQUAL "") + # Check extern + message( + STATUS + "Searching for ${DEPENDENCY} using file ${FILE}" + ) + find_path("${DEPENDENCY}Path" + ${FILE} + PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../extern/${DEPENDENCY}") + + if("${${DEPENDENCY}Path}" STREQUAL "${DEPENDENCY}Path-NOTFOUND") + # Check path + message( + STATUS + "Getting environment for ${DEPENDENCY}Path: $ENV{${DEPENDENCY}Path}" + ) + set("${DEPENDENCY}Path" "$ENV{${DEPENDENCY}Path}") + endif() + + message( + STATUS + "Found ${DEPENDENCY} in ${${DEPENDENCY}Path}; adding" + ) + add_subdirectory("${${DEPENDENCY}Path}" ${DEPENDENCY}) + endif() +endmacro() + + +# standards & flags +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DEBUG OFF) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) +set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE FILEPATH "") + + +# out-of-source builds only +if(${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR}) + message(FATAL_ERROR "In-source builds are not allowed.") +endif() diff --git a/cmake/version.rc.in b/Plugin/cmake/version.rc.in similarity index 94% rename from cmake/version.rc.in rename to Plugin/cmake/version.rc.in index efbb756..b285c31 100644 --- a/cmake/version.rc.in +++ b/Plugin/cmake/version.rc.in @@ -20,7 +20,7 @@ BEGIN VALUE "FileDescription", "@PROJECT_NAME@" VALUE "FileVersion", "@PROJECT_VERSION@.0" VALUE "InternalName", "@PROJECT_NAME@" - VALUE "LegalCopyright", "MIT License" + VALUE "LegalCopyright", "GPLv3 License" VALUE "ProductName", "@PROJECT_NAME@" VALUE "ProductVersion", "@PROJECT_VERSION@.0" END diff --git a/res/settings.toml b/Plugin/dist/BakaMaxPapyrusOps.ini similarity index 76% rename from res/settings.toml rename to Plugin/dist/BakaMaxPapyrusOps.ini index 3e73246..96d4be7 100644 --- a/res/settings.toml +++ b/Plugin/dist/BakaMaxPapyrusOps.ini @@ -1,16 +1,12 @@ -[General] -# Enable Debug message output -EnableDebugLogging = false - [Fixes] # Fix unintentionally allocating script pages when getting largest available page, but out of memory. -FixScriptPageAllocation = true +bFixScriptPageAllocation = 1 # Fixes ToggleScripts command not persisting when saving/stack dumping # Scripts will now stay turned off when toggled off, and on when toggled on. -FixToggleScriptsCommand = true +bFixToggleScriptsCommand = 1 [Tweaks] # Maximum papyrus operations per frame. Higher number means better script performance on average # Has a very minor impact on framerate, and varies from script to script. (Default: 500, Vanilla value: 100). Recommended Range: 100-2000. -MaxPapyrusOpsPerFrame = 500 +iMaxPapyrusOpsPerFrame = 500 \ No newline at end of file diff --git a/Plugin/dist/rules/!base.json b/Plugin/dist/rules/!base.json new file mode 100644 index 0000000..34490f7 --- /dev/null +++ b/Plugin/dist/rules/!base.json @@ -0,0 +1,16 @@ +[ + { + "action": "base", + "params": [ + "{target_base}", + "{env:Fallout4Path}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "copy", + "params": [ + "{cmake_output}\\*", + "{dist}\\" + ] + } +] \ No newline at end of file diff --git a/Plugin/dist/rules/bin_copy.json b/Plugin/dist/rules/bin_copy.json new file mode 100644 index 0000000..a78daf1 --- /dev/null +++ b/Plugin/dist/rules/bin_copy.json @@ -0,0 +1,16 @@ +[ + { + "action": "copy", + "params": [ + "{dist}\\*.dll", + "{target_base}" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.pdb", + "{target_base}" + ] + } +] \ No newline at end of file diff --git a/Plugin/dist/rules/config_copy.json b/Plugin/dist/rules/config_copy.json new file mode 100644 index 0000000..16e0de0 --- /dev/null +++ b/Plugin/dist/rules/config_copy.json @@ -0,0 +1,23 @@ +[ + { + "action": "copy_if", + "params": [ + "{dist}\\*.ini", + "{target_base}" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.toml", + "{target_base}" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.json", + "{target_base}" + ] + } +] \ No newline at end of file diff --git a/Plugin/dist/rules/publish_package.json b/Plugin/dist/rules/publish_package.json new file mode 100644 index 0000000..0150c3e --- /dev/null +++ b/Plugin/dist/rules/publish_package.json @@ -0,0 +1,54 @@ +[ + { + "action": "copy", + "params": [ + "{dist}\\*.dll", + "{dist}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "copy_if", + "config": "RelWithDebInfo", + "params": [ + "{dist}\\*.pdb", + "{dist}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.ini", + "{dist}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.toml", + "{dist}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "copy_if", + "params": [ + "{dist}\\*.json", + "{dist}\\Data\\F4SE\\Plugins\\" + ] + }, + { + "action": "package", + "config": "Release", + "params": [ + "{dist}\\Data\\", + "{dist}\\{project_name}.v{project_version}.zip" + ] + }, + { + "action": "package", + "config": "RelWithDebInfo", + "params": [ + "{dist}\\Data\\", + "{dist}\\{project_name}.v{project_version}.zip" + ] + } +] \ No newline at end of file diff --git a/Plugin/src/PCH.h b/Plugin/src/PCH.h new file mode 100644 index 0000000..74fa66a --- /dev/null +++ b/Plugin/src/PCH.h @@ -0,0 +1,136 @@ +#pragma once + +// c +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// cxx +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Clib +#include "F4SE/F4SE.h" +#include "RE/Fallout.h" + +// winnt +#include + +#undef min +#undef max + +using namespace std::literals; + +#define DLLEXPORT extern "C" [[maybe_unused]] __declspec(dllexport) + +// Plugin +#include "Plugin.h" + +// DKUtil +#include "DKUtil/Config.hpp" +#include "DKUtil/Hook.hpp" +#include "DKUtil/Logger.hpp" + +// F4SEPlugin_Version +DLLEXPORT constinit auto F4SEPlugin_Version = []() noexcept { + F4SE::PluginVersionData data{}; + + data.PluginVersion(Plugin::Version); + data.PluginName(Plugin::NAME); + data.AuthorName(Plugin::AUTHOR); + data.UsesAddressLibrary(true); + data.UsesSigScanning(false); + data.IsLayoutDependent(true); + data.HasNoStructUse(false); + data.CompatibleVersions({ F4SE::RUNTIME_LATEST }); + + return data; +}(); diff --git a/Plugin/src/main.cpp b/Plugin/src/main.cpp new file mode 100644 index 0000000..4dc43a2 --- /dev/null +++ b/Plugin/src/main.cpp @@ -0,0 +1,257 @@ +class Config +{ +public: + class Fixes + { + public: + inline static DKUtil::Alias::Boolean bFixToggleScriptsCommand{ "bFixToggleScriptsCommand", "Fixes" }; + inline static DKUtil::Alias::Boolean bFixScriptPageAllocation{ "bFixScriptPageAllocation", "Fixes" }; + }; + + class Tweaks + { + public: + inline static DKUtil::Alias::Integer iMaxPapyrusOpsPerFrame{ "iMaxPapyrusOpsPerFrame", "Tweaks" }; + }; + + static void Load() + { + static auto Config = COMPILE_PROXY("BakaMaxPapyrusOps.ini"); + Config.Bind(Fixes::bFixToggleScriptsCommand, true); + Config.Bind(Fixes::bFixScriptPageAllocation, true); + Config.Bind(Tweaks::iMaxPapyrusOpsPerFrame, 500); + Config.Load(); + } +}; + +class Fixes +{ +public: + static void Install() + { + if (*Config::Fixes::bFixScriptPageAllocation) { + FixScriptPageAllocation::Install(); + } + + if (*Config::Fixes::bFixToggleScriptsCommand) { + FixToggleScriptsCommand::Install(); + } + } + +private: + class FixScriptPageAllocation + { + public: + static void Install() + { + static REL::Relocation target{ RE::BSScript::SimpleAllocMemoryPagePolicy::VTABLE[0] }; + _GetLargestAvailablePage = target.write_vfunc(0x04, GetLargestAvailablePage); + } + + private: + static RE::BSScript::SimpleAllocMemoryPagePolicy::AllocationStatus GetLargestAvailablePage( + RE::BSScript::SimpleAllocMemoryPagePolicy* a_this, + RE::BSTSmartPointer& a_newPage) + { + const RE::BSAutoLock lock{ a_this->dataLock }; + + auto maxPageSize = a_this->maxAllocatedMemory - a_this->currentMemorySize; + auto currentMemorySize = a_this->currentMemorySize; + if (maxPageSize < 0) + { + a_this->currentMemorySize = a_this->maxAllocatedMemory; + } + + auto result = _GetLargestAvailablePage(a_this, a_newPage); + if (maxPageSize < 0) + { + a_this->currentMemorySize = currentMemorySize; + } + + return result; + } + + inline static REL::Relocation _GetLargestAvailablePage; + }; + + class FixToggleScriptsCommand + { + public: + static void Install() + { + hkEndSaveLoad<2228095, 0x030>::Install(); + hkEndSaveLoad<2228097, 0x69E>::Install(); + hkEndSaveLoad<2228945, 0x30B>::Install(); + hkBSSpinLock_Lock::Install(); + + hkFreeze<2251333, 0x119>::Install(); + hkFreeze<2251336, 0x370>::Install(); + hkFreeze<2251364, 0x382>::Install(); + } + + private: + template + class hkEndSaveLoad + { + public: + static void Install() + { + static REL::Relocation target{ REL::ID(ID), OFF }; + auto& trampoline = F4SE::GetTrampoline(); + trampoline.write_call<5>(target.address(), EndSaveLoad); + } + + private: + static void EndSaveLoad(RE::GameVM* a_this) + { + if (a_this->saveLoadInterface) + { + a_this->saveLoadInterface->CleanupLoad(); + a_this->saveLoadInterface->CleanupSave(); + } + + a_this->RegisterForAllGameEvents(); + a_this->saveLoad = false; + + a_this->handlePolicy.DropSaveLoadRemapData(); + a_this->objectBindPolicy.EndSaveLoad(); + a_this->handlePolicy.UpdatePersistence(); + + if (RE::Script::GetProcessScripts()) + { + const RE::BSAutoLock lock{ a_this->freezeLock }; + a_this->frozen = false; + } + } + }; + + class hkBSSpinLock_Lock + { + public: + static void Install() + { + static REL::Relocation target{ REL::ID(2251339), 0x797 }; + auto& trampoline = F4SE::GetTrampoline(); + trampoline.write_call<5>(target.address(), BSSpinLock_Lock); + + static REL::Relocation tgtNOP{ REL::ID(2251339), 0x79C }; + REL::safe_fill(tgtNOP.address(), REL::NOP, 0x08); + } + + private: + static void BSSpinLock_Lock(void*, void*) + { + auto GameVM = RE::GameVM::GetSingleton(); + if (!GameVM) + { + return; + } + + if (RE::Script::GetProcessScripts()) + { + const RE::BSAutoLock lock{ GameVM->freezeLock }; + GameVM->frozen = false; + } + } + }; + + template + class hkFreeze + { + public: + static void Install() + { + static REL::Relocation target{ REL::ID(ID), OFF }; + auto& trampoline = F4SE::GetTrampoline(); + _Freeze = trampoline.write_call<5>(target.address(), Freeze); + } + + private: + static void Freeze(RE::GameVM* a_this, bool a_freeze) + { + if (RE::Script::GetProcessScripts()) + { + return _Freeze(a_this, a_freeze); + } + } + + inline static REL::Relocation _Freeze; + }; + }; +}; + +class Tweaks +{ +public: + static void Install() + { + if (*Config::Tweaks::iMaxPapyrusOpsPerFrame > 0) { + MaxPapyrusOpsPerFrame::Update(*Config::Tweaks::iMaxPapyrusOpsPerFrame); + MaxPapyrusOpsPerFrame::Install(); + } + } + +private: + class MaxPapyrusOpsPerFrame + { + public: + static void Install() + { + struct PapyrusOpsPerFrame : Xbyak::CodeGenerator + { + PapyrusOpsPerFrame(std::uintptr_t a_begin, std::uintptr_t a_end) + { + inc(r12d); + mov(r8d, 0x1570); + cmp(r12d, MaxOpsPerFrame); + jb("Loop"); + mov(rcx, a_end); + jmp(rcx); + L("Loop"); + mov(rcx, a_begin); + jmp(rcx); + } + }; + + static REL::Relocation target{ REL::ID(2315660), 0xA64 }; + static REL::Relocation tgtBeg{ REL::ID(2315660), 0x0A0 }; + static REL::Relocation tgtEnd{ REL::ID(2315660), 0xA77 }; + + auto code = PapyrusOpsPerFrame(tgtBeg.address(), tgtEnd.address()); + REL::safe_fill(target.address(), REL::NOP, 0x13); + + auto& trampoline = F4SE::GetTrampoline(); + auto result = trampoline.allocate(code); + trampoline.write_branch<5>(target.address(), reinterpret_cast(result)); + } + + template + static void Update(T a_value) + { + MaxOpsPerFrame = static_cast(a_value); + } + + private: + inline static std::int32_t MaxOpsPerFrame{ 100 }; + }; +}; + +DLLEXPORT bool F4SEAPI F4SEPlugin_Load(const F4SE::LoadInterface* a_F4SE) +{ +#ifndef NDEBUG + MessageBoxA(NULL, "Loaded. You can now attach the debugger or continue execution.", Plugin::NAME.data(), NULL); +#endif + + F4SE::Init(a_F4SE); + F4SE::AllocTrampoline(1 << 8); + + DKUtil::Logger::Init(Plugin::NAME, std::to_string(Plugin::Version)); + INFO("{} v{} loaded."sv, Plugin::NAME, Plugin::Version); + + Config::Load(); + + Fixes::Install(); + Tweaks::Install(); + + return true; +} diff --git a/Plugin/vcpkg.json b/Plugin/vcpkg.json new file mode 100644 index 0000000..9cfbcf5 --- /dev/null +++ b/Plugin/vcpkg.json @@ -0,0 +1,21 @@ +{ + "name": "bakamaxpapyrusops", + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "dependencies": [ + "boost-stl-interfaces", + "fmt", + "nlohmann-json", + "rsm-mmio", + "simpleini", + "spdlog", + "tomlplusplus", + "xbyak" + ], + "builtin-baseline": "a42af01b72c28a8e1d7b48107b33e4f286a55ef6", + "overrides": [ + { + "name": "tomlplusplus", + "version": "3.1.0" + } + ] +} diff --git a/build-clang-cl.bat b/build-clang-cl.bat new file mode 100644 index 0000000..03b2c01 --- /dev/null +++ b/build-clang-cl.bat @@ -0,0 +1,4 @@ +echo off +rd /s /q "build" +cmake -B "%~dp0/build" -S "%~dp0/Plugin" --preset=build-release-clang-cl-ninja +cmake --build "%~dp0/build" diff --git a/build-msvc.bat b/build-msvc.bat new file mode 100644 index 0000000..f15a7a6 --- /dev/null +++ b/build-msvc.bat @@ -0,0 +1,4 @@ +echo off +rd /s /q "build" +cmake -B "%~dp0/build" -S "%~dp0/Plugin" --preset=build-release-msvc-msvc +cmake --build "%~dp0/build" diff --git a/cmake/Version.h.in b/cmake/Version.h.in deleted file mode 100644 index 0033cc5..0000000 --- a/cmake/Version.h.in +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -namespace Version -{ - inline constexpr std::size_t MAJOR = @PROJECT_VERSION_MAJOR@; - inline constexpr std::size_t MINOR = @PROJECT_VERSION_MINOR@; - inline constexpr std::size_t PATCH = @PROJECT_VERSION_PATCH@; - inline constexpr auto NAME = "@PROJECT_VERSION@"sv; - inline constexpr auto PROJECT = "@PROJECT_NAME@"sv; -} diff --git a/cmake/ports/autotoml/portfile.cmake b/cmake/ports/autotoml/portfile.cmake deleted file mode 100644 index 894eb39..0000000 --- a/cmake/ports/autotoml/portfile.cmake +++ /dev/null @@ -1,18 +0,0 @@ -vcpkg_from_github( - OUT_SOURCE_PATH SOURCE_PATH - REPO shad0wshayd3/AutoTOML - REF fc0ba2364334503684c4d4dbda6bd10c35dde1fb - SHA512 36e8d2d7f042256723b28865067a7317b4783a419c16c62c02a0b5b4ed1e2256d4ed485a0a921bcd5b74ab74007f6d619e1cf06f63eccf386ea56b7d87785a25 - HEAD_REF master -) - -vcpkg_cmake_configure(SOURCE_PATH ${SOURCE_PATH}) -vcpkg_cmake_install() -vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/AutoTOML) - -file(REMOVE_RECURSE - ${CURRENT_PACKAGES_DIR}/debug - ${CURRENT_PACKAGES_DIR}/lib -) - -file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright) \ No newline at end of file diff --git a/cmake/ports/autotoml/vcpkg.json b/cmake/ports/autotoml/vcpkg.json deleted file mode 100644 index b31a0ac..0000000 --- a/cmake/ports/autotoml/vcpkg.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "autotoml", - "version-string": "2021-12-18", - "homepage": "https://github.com/shad0wshayd3/AutoTOML", - "license": "MIT", - "dependencies": [ - "tomlplusplus", - { - "name": "vcpkg-cmake", - "host": true - }, - { - "name": "vcpkg-cmake-config", - "host": true - } - ] -} \ No newline at end of file diff --git a/extern/BethesdaCMakeModules b/extern/BethesdaCMakeModules deleted file mode 160000 index 61a7cb9..0000000 --- a/extern/BethesdaCMakeModules +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 61a7cb934ab04c227e08a0660079f86f6c3f956f diff --git a/extern/CommonLibF4 b/extern/CommonLibF4 index 948e841..bacb321 160000 --- a/extern/CommonLibF4 +++ b/extern/CommonLibF4 @@ -1 +1 @@ -Subproject commit 948e841a7ed5e9674e0ba032c91bae955e1cc154 +Subproject commit bacb32111fc8c826b96147e786e6042d9615e7f8 diff --git a/extern/DKUtil b/extern/DKUtil new file mode 160000 index 0000000..a19e878 --- /dev/null +++ b/extern/DKUtil @@ -0,0 +1 @@ +Subproject commit a19e878e004670064757cdd5f5964251e9795300 diff --git a/make-sln-clang-cl.bat b/make-sln-clang-cl.bat new file mode 100644 index 0000000..fa22ad2 --- /dev/null +++ b/make-sln-clang-cl.bat @@ -0,0 +1,3 @@ +echo off +rd /s /q "build" +cmake -B "%~dp0/build" -S "%~dp0/Plugin" --preset=build-debug-clang-cl-msvc diff --git a/make-sln-msvc.bat b/make-sln-msvc.bat new file mode 100644 index 0000000..1bb9d73 --- /dev/null +++ b/make-sln-msvc.bat @@ -0,0 +1,3 @@ +echo off +rd /s /q "build" +cmake -B "%~dp0/build" -S "%~dp0/Plugin" --preset=build-debug-msvc-msvc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index f3bb5c4..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(c++) -add_subdirectory(papyrus) diff --git a/src/c++/CMakeLists.txt b/src/c++/CMakeLists.txt deleted file mode 100644 index 86ecc3c..0000000 --- a/src/c++/CMakeLists.txt +++ /dev/null @@ -1,184 +0,0 @@ -set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) - -# ---- Project ---- - -configure_file( - ${ROOT_DIR}/cmake/Version.h.in - ${CMAKE_CURRENT_BINARY_DIR}/include/Version.h - @ONLY -) - -configure_file( - ${ROOT_DIR}/cmake/version.rc.in - ${CMAKE_CURRENT_BINARY_DIR}/version.rc - @ONLY -) - -# ---- Globals ---- - -add_compile_definitions( - F4SE_SUPPORT_XBYAK -) - -if (MSVC) - if (NOT ${CMAKE_GENERATOR} STREQUAL "Ninja") - add_compile_options( - /MP # Build with Multiple Processes - ) - endif () -endif () - -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) -set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DEBUG OFF) - -set(Boost_USE_STATIC_LIBS ON) - -# ---- Dependencies ---- - -if (DEFINED CommonLibPath AND NOT ${CommonLibPath} STREQUAL "" AND IS_DIRECTORY ${CommonLibPath}) - add_subdirectory(${CommonLibPath} ${CommonLibName}) -else () - message( - FATAL_ERROR - "Variable ${CommonLibName}Path is not set or in extern/." - ) -endif() - -# ---- Add source files ---- - -file(GLOB_RECURSE SOURCE_FILES - CONFIGURE_DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/*.h -) - -source_group( - TREE - ${CMAKE_CURRENT_SOURCE_DIR} - PREFIX - "src" - FILES - ${SOURCE_FILES} -) - -source_group( - TREE - ${CMAKE_CURRENT_BINARY_DIR} - FILES - ${CMAKE_CURRENT_BINARY_DIR}/include/Version.h -) - -# ---- Create DLL ---- - -add_library( - ${PROJECT_NAME} - SHARED - ${SOURCE_FILES} - ${CMAKE_CURRENT_BINARY_DIR}/include/Version.h - ${CMAKE_CURRENT_BINARY_DIR}/version.rc - ${ROOT_DIR}/res/settings.toml - ${ROOT_DIR}/.clang-format - ${ROOT_DIR}/.editorconfig -) - -target_compile_features( - ${PROJECT_NAME} - PRIVATE - cxx_std_23 -) - -target_compile_definitions( - ${PROJECT_NAME} - PRIVATE - _UNICODE -) - -target_include_directories( - ${PROJECT_NAME} - PRIVATE - ${CMAKE_CURRENT_BINARY_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR} -) - -target_link_libraries( - ${PROJECT_NAME} - PRIVATE - ${CommonLibName}::${CommonLibName} -) - -target_precompile_headers( - ${PROJECT_NAME} - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/PCH.h -) - -if (MSVC) - target_compile_options( - ${PROJECT_NAME} - PRIVATE - /sdl # Enable Additional Security Checks - /utf-8 # Set Source and Executable character sets to UTF-8 - /Zi # Debug Information Format - - /permissive- # Standards conformance - - /Zc:alignedNew # C++17 over-aligned allocation - /Zc:auto # Deduce Variable Type - /Zc:char8_t - /Zc:__cplusplus # Enable updated __cplusplus macro - /Zc:externC - /Zc:externConstexpr # Enable extern constexpr variables - /Zc:forScope # Force Conformance in for Loop Scope - /Zc:hiddenFriend - /Zc:implicitNoexcept # Implicit Exception Specifiers - /Zc:lambda - /Zc:noexceptTypes # C++17 noexcept rules - /Zc:preprocessor # Enable preprocessor conformance mode - /Zc:referenceBinding # Enforce reference binding rules - /Zc:rvalueCast # Enforce type conversion rules - /Zc:sizedDealloc # Enable Global Sized Deallocation Functions - /Zc:strictStrings # Disable string literal type conversion - /Zc:ternary # Enforce conditional operator rules - /Zc:threadSafeInit # Thread-safe Local Static Initialization - /Zc:tlsGuards - /Zc:trigraphs # Trigraphs Substitution - /Zc:wchar_t # wchar_t Is Native Type - - /external:anglebrackets - /external:W0 - - /W4 # Warning level - /WX # Warning level (warnings are errors) - - "$<$:>" - "$<$:/Zc:inline;/JMC-;/Ob3>" - ) - - target_link_options( - ${PROJECT_NAME} - PRIVATE - /WX # Treat Linker Warnings as Errors - - "$<$:/INCREMENTAL;/OPT:NOREF;/OPT:NOICF>" - "$<$:/INCREMENTAL:NO;/OPT:REF;/OPT:ICF;/DEBUG:FULL>" - ) -endif() - -# ---- Post build ---- - -if (COPY_BUILD) - if (DEFINED Fallout4Path) - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ ${Fallout4Path}/Data/F4SE/Plugins/ - COMMAND ${CMAKE_COMMAND} -E copy $ ${Fallout4Path}/Data/F4SE/Plugins/ - COMMAND ${CMAKE_COMMAND} -E copy ${ROOT_DIR}/res/settings.toml ${Fallout4Path}/Data/F4SE/Plugins/${PROJECT_NAME}.toml - ) - else() - message( - WARNING - "Variable ${Fallout4Path} is not defined. Skipping post-build copy command." - ) - endif() -endif() diff --git a/src/c++/PCH.cpp b/src/c++/PCH.cpp deleted file mode 100644 index 8607860..0000000 --- a/src/c++/PCH.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include "PCH.h" - -namespace stl -{ - namespace detail - { - struct asm_patch : - Xbyak::CodeGenerator - { - asm_patch(std::uintptr_t a_dst) - { - Xbyak::Label dst; - - jmp(ptr[rip + dst]); - - L(dst); - dq(a_dst); - } - }; - } - - void asm_jump(std::uintptr_t a_from, [[maybe_unused]] std::size_t a_size, std::uintptr_t a_to) - { - detail::asm_patch p{ a_to }; - p.ready(); - assert(p.getSize() <= a_size); - REL::safe_write( - a_from, - std::span{ p.getCode(), p.getSize() }); - } - - void asm_replace(std::uintptr_t a_from, std::size_t a_size, std::uintptr_t a_to) - { - REL::safe_fill(a_from, REL::INT3, a_size); - asm_jump(a_from, a_size, a_to); - } -} diff --git a/src/c++/PCH.h b/src/c++/PCH.h deleted file mode 100644 index 6852c0e..0000000 --- a/src/c++/PCH.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX - -#include "F4SE/F4SE.h" -#include "RE/Fallout.h" - -#include -#include -#include - -#define DLLEXPORT __declspec(dllexport) - -using namespace std::literals; - -namespace logger = F4SE::log; - -namespace stl -{ - using namespace F4SE::stl; - - void asm_replace(std::uintptr_t a_from, std::size_t a_size, std::uintptr_t a_to); -} - -// clang-format off -#include "Version.h" -#include "Settings.h" -// clang-format on diff --git a/src/c++/Settings.h b/src/c++/Settings.h deleted file mode 100644 index 9b73cc6..0000000 --- a/src/c++/Settings.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -namespace Settings -{ - namespace - { - using ISetting = AutoTOML::ISetting; - using bSetting = AutoTOML::bSetting; - using iSetting = AutoTOML::iSetting; - } - - namespace General - { - inline bSetting EnableDebugLogging{ "General"s, "EnableDebugLogging"s, false }; - } - - namespace Fixes - { - inline bSetting FixToggleScriptsCommand{ "Tweaks"s, "FixToggleScriptsCommand"s, true, true }; - inline bSetting FixScriptPageAllocation{ "Tweaks"s, "FixScriptPageAllocation"s, true, true }; - } - - namespace Tweaks - { - inline iSetting MaxPapyrusOpsPerFrame{ "Tweaks"s, "MaxPapyrusOpsPerFrame"s, 100, true }; - } - - inline void Load() - { - try - { - const auto table = toml::parse_file( - fmt::format(FMT_STRING("Data/F4SE/Plugins/{:s}.toml"sv), Version::PROJECT)); - for (const auto& setting : ISetting::get_settings()) - { - setting->load(table); - } - } - catch (const toml::parse_error& e) - { - std::ostringstream ss; - ss - << "Error parsing file \'" << *e.source().path << "\':\n" - << '\t' << e.description() << '\n' - << "\t\t(" << e.source().begin << ')'; - logger::error(FMT_STRING("{:s}"sv), ss.str()); - stl::report_and_fail("Failed to load settings."sv); - } - catch (const std::exception& e) - { - stl::report_and_fail(e.what()); - } - catch (...) - { - stl::report_and_fail("Unknown failure."sv); - } - } -} diff --git a/src/c++/main.cpp b/src/c++/main.cpp deleted file mode 100644 index 8fb761e..0000000 --- a/src/c++/main.cpp +++ /dev/null @@ -1,231 +0,0 @@ -class Fixes -{ -public: - class FixScriptPageAllocation - { - public: - static void Install() - { - static REL::Relocation target{ RE::BSScript::SimpleAllocMemoryPagePolicy::VTABLE[0] }; - _GetLargestAvailablePage = target.write_vfunc(0x04, GetLargestAvailablePage); - } - - private: - static RE::BSScript::SimpleAllocMemoryPagePolicy::AllocationStatus GetLargestAvailablePage( - RE::BSScript::SimpleAllocMemoryPagePolicy* a_this, - RE::BSTSmartPointer& a_newPage) - { - const RE::BSAutoLock lock{ a_this->dataLock }; - - auto maxPageSize = a_this->maxAllocatedMemory - a_this->currentMemorySize; - auto currentMemorySize = a_this->currentMemorySize; - if (maxPageSize < 0) - { - a_this->currentMemorySize = a_this->maxAllocatedMemory; - } - - auto result = _GetLargestAvailablePage(a_this, a_newPage); - if (maxPageSize < 0) - { - a_this->currentMemorySize = currentMemorySize; - } - - return result; - } - - inline static REL::Relocation _GetLargestAvailablePage; - }; - - class FixToggleScriptsCommand - { - public: - static void Install() - { - { - static REL::Relocation target{ REL::ID(1321787), 0x5A }; - auto& trampoline = F4SE::GetTrampoline(); - trampoline.write_call<5>(target.address(), EndSaveLoad); - } - - { - static REL::Relocation target{ REL::ID(1014572), 0x5CF }; - auto& trampoline = F4SE::GetTrampoline(); - trampoline.write_call<5>(target.address(), EndSaveLoad); - } - - { - static REL::Relocation target{ REL::ID(124452), 0x32F }; - auto& trampoline = F4SE::GetTrampoline(); - trampoline.write_call<5>(target.address(), EndSaveLoad); - } - - { - static REL::Relocation target{ REL::ID(371005), 0x478 }; - auto& trampoline = F4SE::GetTrampoline(); - trampoline.write_call<5>(target.address(), EndSaveLoad); - } - - { - static REL::Relocation target{ REL::ID(1238017), 0x370 }; - auto& trampoline = F4SE::GetTrampoline(); - _Freeze = trampoline.write_call<5>(target.address(), Freeze); - } - } - - private: - static void EndSaveLoad(RE::GameVM* a_this) - { - if (a_this->saveLoadInterface) - { - a_this->saveLoadInterface->CleanupLoad(); - a_this->saveLoadInterface->CleanupSave(); - } - - a_this->RegisterForAllGameEvents(); - a_this->saveLoad = false; - - a_this->handlePolicy.DropSaveLoadRemapData(); - a_this->objectBindPolicy.EndSaveLoad(); - a_this->handlePolicy.UpdatePersistence(); - - if (RE::Script::GetProcessScripts()) - { - const RE::BSAutoLock lock{ a_this->freezeLock }; - a_this->frozen = false; - } - } - - static void Freeze(RE::GameVM* a_this, bool a_freeze) - { - if (RE::Script::GetProcessScripts()) - { - return _Freeze(a_this, a_freeze); - } - } - - inline static REL::Relocation _Freeze; - }; -}; - -class Tweaks -{ -public: - class MaxPapyrusOpsPerFrame - { - public: - static void Install() - { - struct PapyrusOpsPerFrame : Xbyak::CodeGenerator - { - PapyrusOpsPerFrame(std::uintptr_t a_begin, std::uintptr_t a_end) - { - inc(r14d); - cmp(r14d, MaxOpsPerFrame); - jb("Loop"); - mov(rcx, a_end); - jmp(rcx); - L("Loop"); - mov(rcx, a_begin); - jmp(rcx); - } - }; - - REL::Relocation target{ REL::ID(614585), 0x4F0 }; - REL::Relocation loopBeg{ REL::ID(614585), 0x0A0 }; - REL::Relocation loopEnd{ REL::ID(614585), 0x4FD }; - - auto code = PapyrusOpsPerFrame(loopBeg.address(), loopEnd.address()); - REL::safe_fill(target.address(), REL::NOP, 0x0D); - - auto& trampoline = F4SE::GetTrampoline(); - auto result = trampoline.allocate(code); - trampoline.write_branch<5>(target.address(), reinterpret_cast(result)); - } - - template - static void Update(T a_value) - { - MaxOpsPerFrame = static_cast(a_value); - } - - private: - inline static std::int32_t MaxOpsPerFrame{ 100 }; - }; -}; - -namespace -{ - void InitializeLog() - { - auto path = logger::log_directory(); - if (!path) - { - stl::report_and_fail("Failed to find standard logging directory"sv); - } - - *path /= fmt::format(FMT_STRING("{:s}.log"sv), Version::PROJECT); - auto sink = std::make_shared(path->string(), true); - - auto log = std::make_shared("global log"s, std::move(sink)); - auto lvl = *Settings::General::EnableDebugLogging - ? spdlog::level::trace - : spdlog::level::info; - - log->set_level(lvl); - log->flush_on(lvl); - - spdlog::set_default_logger(std::move(log)); - spdlog::set_pattern("[%m/%d/%Y - %T] [%^%l%$] %v"s); - - logger::info(FMT_STRING("{:s} v{:s}"sv), Version::PROJECT, Version::NAME); - } -} - -extern "C" DLLEXPORT bool F4SEAPI F4SEPlugin_Query(const F4SE::QueryInterface* a_F4SE, F4SE::PluginInfo* a_info) -{ - a_info->infoVersion = F4SE::PluginInfo::kVersion; - a_info->name = Version::PROJECT.data(); - a_info->version = Version::MAJOR; - - const auto rtv = a_F4SE->RuntimeVersion(); - if (rtv < F4SE::RUNTIME_LATEST) - { - stl::report_and_fail( - fmt::format( - FMT_STRING("{:s} does not support runtime v{:s}."sv), - Version::PROJECT, - rtv.string())); - } - - return true; -} - -extern "C" DLLEXPORT bool F4SEAPI F4SEPlugin_Load(const F4SE::LoadInterface* a_F4SE) -{ - Settings::Load(); - InitializeLog(); - - logger::info(FMT_STRING("{:s} loaded."sv), Version::PROJECT); - logger::debug("Debug logging enabled."sv); - - F4SE::Init(a_F4SE); - F4SE::AllocTrampoline(1 << 7); - - if (*Settings::Fixes::FixScriptPageAllocation) - { - Fixes::FixScriptPageAllocation::Install(); - } - - if (*Settings::Fixes::FixToggleScriptsCommand) - { - Fixes::FixToggleScriptsCommand::Install(); - } - - if (*Settings::Tweaks::MaxPapyrusOpsPerFrame > 0) - { - Tweaks::MaxPapyrusOpsPerFrame::Update(*Settings::Tweaks::MaxPapyrusOpsPerFrame); - Tweaks::MaxPapyrusOpsPerFrame::Install(); - } - - return true; -} diff --git a/src/papyrus/CMakeLists.txt b/src/papyrus/CMakeLists.txt deleted file mode 100644 index f4bf091..0000000 --- a/src/papyrus/CMakeLists.txt +++ /dev/null @@ -1,60 +0,0 @@ -set(ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..) - -include(${ROOT_DIR}/extern/BethesdaCMakeModules/Modules/Papyrus.cmake) - -file(GLOB Papyrus_INPUT - LIST_DIRECTORIES false - CONFIGURE_DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/*.psc -) - -add_papyrus( - "Papyrus" - GAME - ${Fallout4Path} - MODE - "Fallout4" - IMPORTS - ${Fallout4Path}/Data/Scripts/Source/User - ${Fallout4Path}/Data/Scripts/Source/CreationClub - ${Fallout4Path}/Data/Scripts/Source/DLC06 - ${Fallout4Path}/Data/Scripts/Source/DLC05 - ${Fallout4Path}/Data/Scripts/Source/DLC04 - ${Fallout4Path}/Data/Scripts/Source/DLC03 - ${Fallout4Path}/Data/Scripts/Source/DLC02 - ${Fallout4Path}/Data/Scripts/Source/DLC01 - ${Fallout4Path}/Data/Scripts/Source/Base - SOURCES - ${Papyrus_INPUT} -) - -source_group( - "Scripts" - FILES - ${Papyrus_INPUT} -) - -if (COPY_BUILD) - if (DEFINED Fallout4Path) - foreach(FILE IN LISTS Papyrus_INPUT) - add_custom_command( - TARGET "Papyrus" - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${FILE} ${Fallout4Path}/Data/Scripts/Source/Baka/ - ) - endforeach() - - foreach(FILE IN LISTS Papyrus_OUTPUT) - add_custom_command( - TARGET "Papyrus" - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${FILE} ${Fallout4Path}/Data/Scripts/ - ) - endforeach() - else () - message( - WARNING - "Variable ${Fallout4Path} is not defined. Skipping post-build copy command." - ) - endif() -endif() diff --git a/update-submodule.bat b/update-submodule.bat new file mode 100644 index 0000000..f82cf7a --- /dev/null +++ b/update-submodule.bat @@ -0,0 +1,2 @@ +git submodule update --init --recursive -f +git submodule update --remote -f \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json deleted file mode 100644 index 64b129d..0000000 --- a/vcpkg.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "bakamaxpapyrusops", - "version-string": "1.0.0", - "description": "Port of MaxPapyrusOpsPerFrame Hook from Papyrus Tweaks NG", - "homepage": "https://github.com/shad0wshayd3/BakaMaxPapyrusOps", - "license": "MIT", - "dependencies": [ - "autotoml", - "boost-stl-interfaces", - "fmt", - "rsm-mmio", - "spdlog", - "xbyak" - ] -}