Compare commits

..

No commits in common. "main" and "v0.19.2" have entirely different histories.

1372 changed files with 24177 additions and 25888 deletions

View File

@ -8,18 +8,20 @@ on:
branches: branches:
- "main" - "main"
env:
PREMAKE_VERSION: "5.0.0-beta2"
jobs: jobs:
build-test-linux: build-test-linux:
strategy: env:
matrix: PREMAKE_CONFIG: gmake2
build_arch: [x86, x64]
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ubuntu:24.04 container: ubuntu:24.04
steps: steps:
- name: Install g++ and multilib - name: Install g++ and multilib
run: | run: |
apt-get update apt-get update
apt-get install -y wget tar git make gcc-13 g++-13 gcc-13-multilib g++-13-multilib apt-get install -y git make gcc-13 g++-13 gcc-13-multilib g++-13-multilib
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13 update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13 update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13
update-alternatives --set gcc /usr/bin/gcc-13 update-alternatives --set gcc /usr/bin/gcc-13
@ -30,35 +32,31 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Setup premake
uses: abel0b/setup-premake@v2.4
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Premake generate - name: Premake generate
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
env: run: premake5 ${{ env.PREMAKE_CONFIG }}
PREMAKE_NO_PROMPT: 1
run: ./generate.sh
- name: Build - name: Build
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
run: make -C build -j$(nproc) config=release_${{ matrix.build_arch }} all run: make -C build -j$(nproc) config=release_x86 all
- name: Test - name: Test
working-directory: ${{ github.workspace }}/build/lib/Release_${{ matrix.build_arch }}/tests working-directory: ${{ github.workspace }}/build/lib/Release_x86/tests
run: | run: |
./ObjCommonTests ./ObjCommonTests
./ObjCompilingTests
./ObjLoadingTests ./ObjLoadingTests
./ParserTests ./ParserTests
./ZoneCodeGeneratorLibTests ./ZoneCodeGeneratorLibTests
./ZoneCommonTests ./ZoneCommonTests
build-test-windows: build-test-windows:
strategy: env:
matrix: PREMAKE_CONFIG: vs2022
build_arch: [x86, x64]
include:
- build_arch: x86
msbuild_config: Win32
- build_arch: x64
msbuild_config: x64
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
@ -69,24 +67,25 @@ jobs:
- name: Add MSBuild to PATH - name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2.0.0 uses: microsoft/setup-msbuild@v2.0.0
- name: Setup premake
uses: abel0b/setup-premake@v2.4
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Premake generate - name: Premake generate
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
env: run: premake5 ${{ env.PREMAKE_CONFIG }}
PREMAKE_NO_PROMPT: 1
run: ./generate.bat
- name: Build - name: Build
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
run: msbuild /m /p:Configuration=Release /p:Platform=${{ matrix.msbuild_config }} build run: msbuild /m /p:Configuration=Release /p:Platform=Win32 build
- name: Test - name: Test
working-directory: ${{ github.workspace }}/build/lib/Release_${{ matrix.build_arch }}/tests working-directory: ${{ github.workspace }}/build/lib/Release_x86/tests
run: | run: |
$combinedExitCode = 0 $combinedExitCode = 0
./ObjCommonTests ./ObjCommonTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE) $combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./ObjCompilingTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./ObjLoadingTests ./ObjLoadingTests
$combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE) $combinedExitCode = [System.Math]::max($combinedExitCode, $LASTEXITCODE)
./ParserTests ./ParserTests

View File

@ -5,15 +5,20 @@ on:
tags: tags:
- "v*.*.*" - "v*.*.*"
env:
PREMAKE_VERSION: "5.0.0-beta2"
jobs: jobs:
build-release-linux: build-release-linux:
env:
PREMAKE_CONFIG: gmake2
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ubuntu:24.04 container: ubuntu:24.04
steps: steps:
- name: Install g++ and multilib - name: Install g++ and multilib
run: | run: |
apt-get update apt-get update
apt-get install -y wget tar git make gcc-13 g++-13 gcc-13-multilib g++-13-multilib apt-get install -y git make gcc-13 g++-13 gcc-13-multilib g++-13-multilib
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13 update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13 update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13
update-alternatives --set gcc /usr/bin/gcc-13 update-alternatives --set gcc /usr/bin/gcc-13
@ -24,11 +29,14 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Setup premake
uses: abel0b/setup-premake@v2.4
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Premake generate - name: Premake generate
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
env: run: premake5 ${{ env.PREMAKE_CONFIG }}
PREMAKE_NO_PROMPT: 1
run: ./generate.sh
- name: Build - name: Build
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
@ -42,6 +50,8 @@ jobs:
${{ github.workspace }}/build/bin/Release_x86 ${{ github.workspace }}/build/bin/Release_x86
build-release-windows: build-release-windows:
env:
PREMAKE_CONFIG: vs2022
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
@ -52,25 +62,28 @@ jobs:
- name: Add MSBuild to PATH - name: Add MSBuild to PATH
uses: microsoft/setup-msbuild@v2.0.0 uses: microsoft/setup-msbuild@v2.0.0
- name: Setup premake
uses: abel0b/setup-premake@v2.4
with:
version: ${{ env.PREMAKE_VERSION }}
- name: Premake generate - name: Premake generate
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
env: run: premake5 ${{ env.PREMAKE_CONFIG }}
PREMAKE_NO_PROMPT: 1
run: ./generate.bat
- name: Build - name: Build
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
run: msbuild /m /p:Configuration=Release /p:Platform=Win32 build run: msbuild /m /p:Configuration=Release /p:Platform=Win32 build
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: oat-windows name: oat-windows
path: | path: |
${{ github.workspace }}/build/bin/Release_x86 ${{ github.workspace }}/build/bin/Release_x86
release: release:
needs: needs:
- build-release-linux - build-release-linux
- build-release-windows - build-release-windows
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -93,4 +106,4 @@ jobs:
allowUpdates: true allowUpdates: true
draft: true draft: true
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
omitDraftDuringUpdate: true omitDraftDuringUpdate: true

3
.gitmodules vendored
View File

@ -16,6 +16,3 @@
[submodule "thirdparty/eigen"] [submodule "thirdparty/eigen"]
path = thirdparty/eigen path = thirdparty/eigen
url = https://gitlab.com/libeigen/eigen.git url = https://gitlab.com/libeigen/eigen.git
[submodule "thirdparty/lz4"]
path = thirdparty/lz4
url = https://github.com/lz4/lz4.git

View File

@ -93,7 +93,7 @@ Since you are most likely on a 64-bit machine you will also need multilib for co
Use `generate.sh` to generate make files. Use `generate.sh` to generate make files.
When this is done you will have a `build` folder with a `Makefile`. When this is done you will have a `build` folder with a `Makefile`.
You now run `make` manually or use `./scripts/make-release.sh` or `./scripts/make-debug.sh` to build. You now run `make` manually or use `./scripts/make_release.sh` or `./scripts/make_debug.sh` to build.
The resulting binaries can be found in `build/bin/<Debug_x86|Release_x86>`. The resulting binaries can be found in `build/bin/<Debug_x86|Release_x86>`.

View File

@ -13,7 +13,7 @@ The following section specify which assets are supported to be dumped to disk (u
| -------------------- | --------------- | --------------- | ----------------------------------------------------------------- | | -------------------- | --------------- | --------------- | ----------------------------------------------------------------- |
| PhysPreset | ❌ | ❌ | | | PhysPreset | ❌ | ❌ | |
| XAnimParts | ❌ | ❌ | | | XAnimParts | ❌ | ❌ | |
| XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. | | XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT`, `OBJ`, `GLB/GLTF`. |
| Material | ❌ | ❌ | | | Material | ❌ | ❌ | |
| MaterialTechniqueSet | ❌ | ❌ | | | MaterialTechniqueSet | ❌ | ❌ | |
| GfxImage | ✅ | ✅ | | | GfxImage | ✅ | ✅ | |
@ -44,7 +44,7 @@ The following section specify which assets are supported to be dumped to disk (u
| PhysPreset | ✅ | ✅ | | | PhysPreset | ✅ | ✅ | |
| PhysCollmap | ❌ | ❌ | | | PhysCollmap | ❌ | ❌ | |
| XAnimParts | ❌ | ❌ | | | XAnimParts | ❌ | ❌ | |
| XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. | | XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT`, `OBJ`, `GLB/GLTF`. |
| Material | ❌ | ❌ | | | Material | ❌ | ❌ | |
| MaterialPixelShader | ✅ | ✅ | Shaders are compiled. Only dumps/loads shader bytecode. | | MaterialPixelShader | ✅ | ✅ | Shaders are compiled. Only dumps/loads shader bytecode. |
| MaterialVertexShader | ✅ | ✅ | Shaders are compiled. Only dumps/loads shader bytecode. | | MaterialVertexShader | ✅ | ✅ | Shaders are compiled. Only dumps/loads shader bytecode. |
@ -85,7 +85,7 @@ The following section specify which assets are supported to be dumped to disk (u
| PhysCollmap | ❌ | ❌ | | | PhysCollmap | ❌ | ❌ | |
| XAnimParts | ❌ | ❌ | | | XAnimParts | ❌ | ❌ | |
| XModelSurfs | ❌ | ❌ | | | XModelSurfs | ❌ | ❌ | |
| XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. | | XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT`, `OBJ`, `GLB/GLTF`. |
| Material | ❌ | ❌ | | | Material | ❌ | ❌ | |
| MaterialPixelShader | ❌ | ❌ | | | MaterialPixelShader | ❌ | ❌ | |
| MaterialVertexShader | ❌ | ❌ | | | MaterialVertexShader | ❌ | ❌ | |
@ -130,7 +130,7 @@ The following section specify which assets are supported to be dumped to disk (u
| PhysConstraints | ❌ | ❌ | | | PhysConstraints | ❌ | ❌ | |
| DestructibleDef | ❌ | ❌ | | | DestructibleDef | ❌ | ❌ | |
| XAnimParts | ❌ | ❌ | | | XAnimParts | ❌ | ❌ | |
| XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. | | XModel | ⁉️ | ❌ | Model data can be exported to `XMODEL_EXPORT`, `OBJ`, `GLB/GLTF`. |
| Material | ❌ | ❌ | | | Material | ❌ | ❌ | |
| MaterialTechniqueSet | ❌ | ❌ | | | MaterialTechniqueSet | ❌ | ❌ | |
| GfxImage | ✅ | ❌ | A few special image encodings are not yet supported. | | GfxImage | ✅ | ❌ | A few special image encodings are not yet supported. |
@ -167,7 +167,7 @@ The following section specify which assets are supported to be dumped to disk (u
| PhysConstraints | ✅ | ✅ | | | PhysConstraints | ✅ | ✅ | |
| DestructibleDef | ❌ | ❌ | | | DestructibleDef | ❌ | ❌ | |
| XAnimParts | ❌ | ❌ | | | XAnimParts | ❌ | ❌ | |
| XModel | ✅ | ✅ | Model data can be exported to `XMODEL_EXPORT/XMODEL_BIN`, `OBJ`, `GLB/GLTF`. | | XModel | ✅ | ✅ | Model data can be exported to `XMODEL_EXPORT`, `OBJ`, `GLB/GLTF`. |
| Material | ⁉️ | ⁉️ | Dumping/Loading is currently possible for materials in their compiled form. There is currently no material pipeline. | | Material | ⁉️ | ⁉️ | Dumping/Loading is currently possible for materials in their compiled form. There is currently no material pipeline. |
| MaterialTechniqueSet | ⁉️ | ❌ | Only dumps compiled shaders. | | MaterialTechniqueSet | ⁉️ | ❌ | Only dumps compiled shaders. |
| GfxImage | ✅ | ✅ | A few special image encodings are not yet supported. | | GfxImage | ✅ | ✅ | A few special image encodings are not yet supported. |
@ -177,7 +177,7 @@ The following section specify which assets are supported to be dumped to disk (u
| ComWorld | ❌ | ❌ | | | ComWorld | ❌ | ❌ | |
| GameWorldSp | ❌ | ❌ | | | GameWorldSp | ❌ | ❌ | |
| GameWorldMp | ❌ | ❌ | | | GameWorldMp | ❌ | ❌ | |
| MapEnts | | ❌ | | | MapEnts | | ❌ | |
| GfxWorld | ❌ | ❌ | | | GfxWorld | ❌ | ❌ | |
| GfxLightDef | ❌ | ❌ | | | GfxLightDef | ❌ | ❌ | |
| Font_s | ❌ | ❌ | | | Font_s | ❌ | ❌ | |

View File

@ -1,88 +1,6 @@
@echo off @echo off
set PREMAKE_URL="https://github.com/premake/premake-core/releases/download/v5.0.0-beta6/premake-5.0.0-beta6-windows.zip"
set PREMAKE_HASH="c34a6e0b15f119f6284886298fdd8df543af87ad16f3ce5f4d0a847be2a88343"
@REM The following variables can be set:
@REM PREMAKE_NO_GLOBAL - Ignore premake5 executable from path
@REM PREMAKE_NO_PROMPT - Download premake5 without prompting
goto start
:downloadpremake
if not exist "build" mkdir "build"
where /q "pwsh"
IF NOT ERRORLEVEL 1 (
set POWERSHELL_BIN="pwsh"
) else (
set POWERSHELL_BIN="powershell"
)
echo Downloading...
%POWERSHELL_BIN% -NoProfile -NonInteractive -Command "Invoke-WebRequest %PREMAKE_URL% -OutFile build/premake.zip"
IF ERRORLEVEL 1 (
echo Download failed >&2
exit 2
)
echo Extracting...
%POWERSHELL_BIN% -NoProfile -NonInteractive -Command "Expand-Archive -LiteralPath build/premake.zip -DestinationPath build -Force"
IF ERRORLEVEL 1 (
echo Extraction failed >&2
exit 2
)
rm build/premake.zip
echo Verifying hash...
%POWERSHELL_BIN% -NoProfile -NonInteractive -Command "if ((Get-FileHash -LiteralPath build/premake5.exe -Algorithm SHA256).Hash -eq \"%PREMAKE_HASH%\") { exit 0 } else { exit 1 }"
IF ERRORLEVEL 1 (
echo Hash verification failed >&2
rm build/premake5.exe
exit 2
)
exit /B 0
cd %~dp0 cd %~dp0
:start
IF "%PREMAKE_NO_GLOBAL%" EQU "" (
where /Q "premake5.exe"
IF NOT ERRORLEVEL 1 (
set PREMAKE_BIN="premake5.exe"
goto runpremake
)
)
IF EXIST build/premake5.exe (
build\premake5.exe --version >NUL
IF NOT ERRORLEVEL 1 (
set PREMAKE_BIN="build/premake5.exe"
goto runpremake
)
)
if "%PREMAKE_NO_PROMPT%" NEQ "" (
call:downloadpremake
set PREMAKE_BIN="build/premake5.exe"
goto runpremake
)
echo Could not find premake5. You can either install it yourself or this script download it for you.
set /p choice="Do you wish to download it automatically? [y/N]> "
if /i "%choice%" == "y" (
call:downloadpremake
set PREMAKE_BIN="build/premake5.exe"
goto runpremake
)
echo Please install premake5 and try again
exit 1
:runpremake
git submodule update --init --recursive git submodule update --init --recursive
%PREMAKE_BIN% %* vs2022 tools\premake5.exe %* vs2022

View File

@ -1,80 +1,7 @@
#!/bin/bash #!/bin/bash
PREMAKE_URL='https://github.com/premake/premake-core/releases/download/v5.0.0-beta6/premake-5.0.0-beta6-linux.tar.gz'
PREMAKE_HASH='fade2839ace1a2953556693e6f3d8f9b8b2897894b5a1f2ad477cdf8e9af042a'
# The following variables can be set:
# PREMAKE_NO_GLOBAL - Ignore premake5 executable from path
# PREMAKE_NO_PROMPT - Download premake5 without prompting
function install_premake {
if [[ ! -x "$(command -v wget)" ]]; then
echo "Failed: Installation requires wget" >&2
exit 2
fi
if [[ ! -x "$(command -v tar)" ]]; then
echo "Failed: Installation requires tar" >&2
exit 2
fi
if [[ ! -x "$(command -v sha256sum)" ]]; then
echo "Failed: Installation requires sha256sum" >&2
exit 2
fi
mkdir -p build
wget -nd -O build/premake.tar.gz "$PREMAKE_URL"
if [[ $? -ne 0 ]]; then
echo "Download failed" >&2
exit 2
fi
tar -xf build/premake.tar.gz -C build
if [[ $? -ne 0 ]]; then
echo "Extraction failed" >&2
exit 2
fi
rm build/premake.tar.gz
echo "${PREMAKE_HASH} build/premake5" | sha256sum -c
if [[ $? -ne 0 ]]; then
echo "Hash verification failed" >&2
rm build/premake5
exit 2
fi
chmod +x build/premake5
}
function expect_inside_git_repository {
inside_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)"
if [ ! -d ".git" ] && [ ! "$inside_git_repo" ]; then
echo "You must clone the OpenAssetTools repository using 'git clone'. Please read README.md." >&2
exit 1
fi
}
# Go to repository root # Go to repository root
cd "$(dirname "$0")" || exit 2 cd "$(dirname "$0")" || exit 2
expect_inside_git_repository
PREMAKE_BIN=''
if [[ -z "$PREMAKE_NO_GLOBAL" ]] && [[ -x "$(command -v premake5)" ]]; then
PREMAKE_BIN='premake5'
elif [[ -x "$(command -v build/premake5)" ]] && [[ ! -z "$(build/premake5 --version)" ]]; then
PREMAKE_BIN='build/premake5'
else
echo "Could not find premake5. You can either install it yourself or this script download it for you."
if [[ ! -z "$PREMAKE_NO_PROMPT" ]] || [[ "$(read -e -p 'Do you wish to download it automatically? [y/N]> '; echo $REPLY)" == [Yy]* ]]; then
echo "Installing premake"
install_premake
PREMAKE_BIN='build/premake5'
else
echo "Please install premake5 and try again"
exit 1
fi
fi
git submodule update --init --recursive git submodule update --init --recursive
$PREMAKE_BIN $@ gmake tools/premake5 $@ gmake2

View File

@ -1,5 +1,3 @@
require("premake", ">=5.0.0-beta5")
include "tools/scripts/folders.lua" include "tools/scripts/folders.lua"
include "tools/scripts/including.lua" include "tools/scripts/including.lua"
include "tools/scripts/linking.lua" include "tools/scripts/linking.lua"
@ -16,7 +14,7 @@ workspace "OpenAssetTools"
objdir "%{wks.location}/obj" objdir "%{wks.location}/obj"
symbols "On" symbols "On"
systemversion "latest" systemversion "latest"
cppdialect "C++23" cppdialect "C++20"
largeaddressaware "on" largeaddressaware "on"
flags { flags {
@ -54,15 +52,13 @@ workspace "OpenAssetTools"
symbols "On" symbols "On"
filter {} filter {}
filter {"system:windows", "configurations:Debug" }
buildoptions { "/bigobj" }
filter {}
filter "configurations:Release" filter "configurations:Release"
defines "NDEBUG" defines "NDEBUG"
optimize "Full" optimize "Full"
symbols "Off" symbols "Off"
fatalwarnings { "All" } flags {
"FatalWarnings"
}
filter {} filter {}
defines { defines {
@ -97,7 +93,6 @@ include "thirdparty/minilzo.lua"
include "thirdparty/minizip.lua" include "thirdparty/minizip.lua"
include "thirdparty/salsa20.lua" include "thirdparty/salsa20.lua"
include "thirdparty/zlib.lua" include "thirdparty/zlib.lua"
include "thirdparty/lz4.lua"
-- ThirdParty group: All projects that are external dependencies -- ThirdParty group: All projects that are external dependencies
group "ThirdParty" group "ThirdParty"
@ -110,14 +105,13 @@ group "ThirdParty"
minizip:project() minizip:project()
salsa20:project() salsa20:project()
zlib:project() zlib:project()
lz4:project()
group "" group ""
-- ======================== -- ========================
-- Projects -- Projects
-- ======================== -- ========================
include "src/Common.lua" include "src/Common.lua"
include "src/Cryptography.lua" include "src/Crypto.lua"
include "src/ImageConverter.lua" include "src/ImageConverter.lua"
include "src/Linker.lua" include "src/Linker.lua"
include "src/Parser.lua" include "src/Parser.lua"
@ -132,7 +126,6 @@ include "src/ZoneLoading.lua"
include "src/ZoneWriting.lua" include "src/ZoneWriting.lua"
include "src/ZoneCommon.lua" include "src/ZoneCommon.lua"
include "src/ObjCommon.lua" include "src/ObjCommon.lua"
include "src/ObjCompiling.lua"
include "src/ObjImage.lua" include "src/ObjImage.lua"
include "src/ObjLoading.lua" include "src/ObjLoading.lua"
include "src/ObjWriting.lua" include "src/ObjWriting.lua"
@ -141,7 +134,7 @@ include "tools/scripts/raw.lua"
-- Components group: All projects assist or are part of a tool -- Components group: All projects assist or are part of a tool
group "Components" group "Components"
Common:project() Common:project()
Cryptography:project() Crypto:project()
Parser:project() Parser:project()
Utils:project() Utils:project()
ZoneCode:project() ZoneCode:project()
@ -150,7 +143,6 @@ group "Components"
ZoneLoading:project() ZoneLoading:project()
ZoneWriting:project() ZoneWriting:project()
ObjCommon:project() ObjCommon:project()
ObjCompiling:project()
ObjImage:project() ObjImage:project()
ObjLoading:project() ObjLoading:project()
ObjWriting:project() ObjWriting:project()
@ -176,10 +168,7 @@ group ""
-- ======================== -- ========================
-- Tests -- Tests
-- ======================== -- ========================
include "test/Catch2Common.lua"
include "test/ObjCommonTestUtils.lua"
include "test/ObjCommonTests.lua" include "test/ObjCommonTests.lua"
include "test/ObjCompilingTests.lua"
include "test/ObjLoadingTests.lua" include "test/ObjLoadingTests.lua"
include "test/ParserTestUtils.lua" include "test/ParserTestUtils.lua"
include "test/ParserTests.lua" include "test/ParserTests.lua"
@ -188,10 +177,7 @@ include "test/ZoneCommonTests.lua"
-- Tests group: Unit test and other tests projects -- Tests group: Unit test and other tests projects
group "Tests" group "Tests"
Catch2Common:project()
ObjCommonTestUtils:project()
ObjCommonTests:project() ObjCommonTests:project()
ObjCompilingTests:project()
ObjLoadingTests:project() ObjLoadingTests:project()
ParserTestUtils:project() ParserTestUtils:project()
ParserTests:project() ParserTests:project()

View File

@ -1,23 +0,0 @@
#!/bin/bash
# Go to repository root
cd "$(dirname "$0")/.." || exit 2
TARGET='all'
ARCHITECTURE='x86'
CONFIG='debug'
for var in "$@"
do
if [ "$var" == "debug" ] || [ "$var" == "release" ]; then
CONFIG="$var"
elif [ "$var" == "x86" ] || [ "$var" == "x64" ]; then
ARCHITECTURE="$var"
else
TARGET="$var"
fi
done
echo "Building config=${CONFIG} architecture=${ARCHITECTURE} target=${TARGET}"
make -C build -j$(nproc) config=${CONFIG}_${ARCHITECTURE} "${TARGET}"

View File

@ -1,6 +0,0 @@
#!/bin/bash
# Go to repository root
cd "$(dirname "$0")/.." || exit 2
docker run --rm -v ".:/code" --user "$(id -u):$(id -g)" silkeh/clang:17 /code/scripts/check-format.sh

View File

@ -4,6 +4,4 @@
cd "$(dirname "$0")/.." || exit 2 cd "$(dirname "$0")/.." || exit 2
make -C build -j$(nproc) config=debug_x86 clean make -C build -j$(nproc) config=debug_x86 clean
make -C build -j$(nproc) config=release_x86 clean make -C build -j$(nproc) config=release_x86 clean
make -C build -j$(nproc) config=debug_x64 clean
make -C build -j$(nproc) config=release_x64 clean

View File

@ -3,4 +3,4 @@
# Go to repository root # Go to repository root
cd "$(dirname "$0")/.." || exit 2 cd "$(dirname "$0")/.." || exit 2
make -C build -j$(nproc) config=debug_x86 all make -C build -j$(nproc) config=debug_x86 all

View File

@ -4,4 +4,4 @@
cd "$(dirname "$0")/.." || exit 2 cd "$(dirname "$0")/.." || exit 2
echo "Start building with $(nproc) threads" echo "Start building with $(nproc) threads"
make -C build -j$(nproc) config=release_x86 all make -C build -j$(nproc) config=release_x86 all

View File

@ -1,6 +0,0 @@
#!/bin/bash
# Go to repository root
cd "$(dirname "$0")/.." || exit 2
docker run --rm -v ".:/code" --user "$(id -u):$(id -g)" silkeh/clang:17 /code/scripts/reformat-all.sh

View File

@ -2,9 +2,6 @@
#include "Zone/ZoneTypes.h" #include "Zone/ZoneTypes.h"
#include <stdexcept>
#include <type_traits>
struct IAssetBase struct IAssetBase
{ {
}; };
@ -15,42 +12,3 @@ public:
static constexpr auto EnumEntry = AssetTypeEnum; static constexpr auto EnumEntry = AssetTypeEnum;
using Type = AssetType; using Type = AssetType;
}; };
template<typename AssetType> struct AssetNameAccessor
{
public:
static_assert(std::is_base_of_v<IAssetBase, AssetType>);
// static constexpr bool IS_SINGLETON = false;
// const char*& operator()(AssetType::Type& asset)
// {
// throw std::runtime_error("Not implemented");
// }
};
#define DEFINE_ASSET_NAME_ACCESSOR(assetType, nameProperty) \
template<> struct AssetNameAccessor<assetType> \
{ \
public: \
static_assert(std::is_base_of_v<IAssetBase, assetType>); \
static constexpr bool IS_SINGLETON = false; \
\
const char*& operator()(assetType::Type& asset) \
{ \
return asset.nameProperty; \
} \
}
#define DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(assetType, singletonName) \
template<> struct AssetNameAccessor<assetType> \
{ \
public: \
static_assert(std::is_base_of_v<IAssetBase, assetType>); \
static constexpr bool IS_SINGLETON = true; \
\
const char* const& operator()(assetType::Type& asset) \
{ \
static const char* NAME = singletonName; \
return NAME; \
} \
}

View File

@ -113,32 +113,3 @@ namespace IW3
using AssetRawFile = Asset<ASSET_TYPE_RAWFILE, RawFile>; using AssetRawFile = Asset<ASSET_TYPE_RAWFILE, RawFile>;
using AssetStringTable = Asset<ASSET_TYPE_STRINGTABLE, StringTable>; using AssetStringTable = Asset<ASSET_TYPE_STRINGTABLE, StringTable>;
} // namespace IW3 } // namespace IW3
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXModelPieces, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetPhysPreset, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSound, aliasName);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSoundCurve, filename);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLoadedSound, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetClipMap, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetClipMapPvs, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGameWorldSp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGameWorldMp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetSoundDriverGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetImpactFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(IW3::AssetStringTable, name);

View File

@ -135,7 +135,7 @@ namespace IW3
typedef float vec2_t[2]; typedef float vec2_t[2];
typedef float vec3_t[3]; typedef float vec3_t[3];
typedef float vec4_t[4]; typedef float vec4_t[4];
typedef tdef_align32(128) unsigned int raw_uint128; typedef tdef_align(128) unsigned int raw_uint128;
struct XModelPiece struct XModelPiece
{ {
@ -179,7 +179,7 @@ namespace IW3
}; };
typedef unsigned char ByteVec[3]; typedef unsigned char ByteVec[3];
typedef tdef_align32(4) unsigned short UShortVec[3]; typedef tdef_align(4) unsigned short UShortVec[3];
union XAnimDynamicIndicesTrans union XAnimDynamicIndicesTrans
{ {
@ -214,7 +214,7 @@ namespace IW3
XAnimPartTransData u; XAnimPartTransData u;
}; };
typedef tdef_align32(4) short XQuat[2]; typedef tdef_align(4) short XQuat[2];
union XAnimDynamicIndicesQuat union XAnimDynamicIndicesQuat
{ {
@ -360,7 +360,7 @@ namespace IW3
uint16_t* vertsBlend; uint16_t* vertsBlend;
}; };
typedef tdef_align32(16) uint16_t r_index16_t; typedef tdef_align(16) uint16_t r_index16_t;
struct XSurface struct XSurface
{ {
@ -709,7 +709,7 @@ namespace IW3
MaterialTextureDefInfo u; MaterialTextureDefInfo u;
}; };
struct gcc_align32(8) GfxDrawSurfFields struct gcc_align(8) GfxDrawSurfFields
{ {
uint64_t objectId : 16; uint64_t objectId : 16;
uint64_t reflectionProbeIndex : 8; uint64_t reflectionProbeIndex : 8;
@ -724,8 +724,8 @@ namespace IW3
union GfxDrawSurf union GfxDrawSurf
{ {
gcc_align32(8) GfxDrawSurfFields fields; gcc_align(8) GfxDrawSurfFields fields;
gcc_align32(8) uint64_t packed; gcc_align(8) uint64_t packed;
}; };
enum materialSurfType_t enum materialSurfType_t
@ -1314,9 +1314,9 @@ namespace IW3
{ {
char levelCount; char levelCount;
char flags; char flags;
uint16_t dimensions[3]; int16_t dimensions[3];
int format; int format;
unsigned int resourceSize; int resourceSize;
char data[1]; char data[1];
}; };
@ -1605,7 +1605,7 @@ namespace IW3
cLeaf_t leaf; cLeaf_t leaf;
}; };
struct type_align32(16) cbrush_t struct type_align(16) cbrush_t
{ {
float mins[3]; float mins[3];
int contents; int contents;
@ -1671,7 +1671,7 @@ namespace IW3
typedef unsigned short LeafBrush; typedef unsigned short LeafBrush;
typedef tdef_align32(16) cbrush_t cbrush_array_t; typedef tdef_align(16) cbrush_t cbrush_array_t;
struct clipMap_t struct clipMap_t
{ {
@ -2265,7 +2265,7 @@ namespace IW3
char pad; char pad;
}; };
typedef tdef_align32(4) GfxSceneDynModel GfxSceneDynModel4; typedef tdef_align(4) GfxSceneDynModel GfxSceneDynModel4;
struct GfxWorld struct GfxWorld
{ {

View File

@ -168,41 +168,3 @@ namespace IW4
using AssetVehicle = Asset<ASSET_TYPE_VEHICLE, VehicleDef>; using AssetVehicle = Asset<ASSET_TYPE_VEHICLE, VehicleDef>;
using AssetAddonMapEnts = Asset<ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts>; using AssetAddonMapEnts = Asset<ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts>;
} // namespace IW4 } // namespace IW4
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPhysPreset, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPhysCollMap, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXModelSurfs, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetPixelShader, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVertexShader, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVertexDecl, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetSound, aliasName);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetSoundCurve, filename);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLoadedSound, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetClipMapSp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetClipMapMp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGameWorldSp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGameWorldMp, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetImpactFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetStringTable, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetLeaderboard, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetStructuredDataDef, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetTracer, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetVehicle, name);
DEFINE_ASSET_NAME_ACCESSOR(IW4::AssetAddonMapEnts, name);

View File

@ -155,10 +155,10 @@ namespace IW4
void* data; void* data;
}; };
typedef tdef_align32(16) char raw_byte16; typedef tdef_align(16) char raw_byte16;
typedef tdef_align32(16) float raw_float16; typedef tdef_align(16) float raw_float16;
typedef unsigned int raw_uint; typedef unsigned int raw_uint;
typedef tdef_align32(128) unsigned int raw_uint128; typedef tdef_align(128) unsigned int raw_uint128;
typedef unsigned char cbrushedge_t; typedef unsigned char cbrushedge_t;
typedef unsigned short r_index_t; typedef unsigned short r_index_t;
typedef float vec2_t[2]; typedef float vec2_t[2];
@ -289,7 +289,7 @@ namespace IW4
}; };
typedef unsigned char ByteVec[3]; typedef unsigned char ByteVec[3];
typedef tdef_align32(4) unsigned short UShortVec[3]; typedef tdef_align(4) unsigned short UShortVec[3];
union XAnimDynamicFrames union XAnimDynamicFrames
{ {
@ -303,7 +303,7 @@ namespace IW4
uint16_t _2[1]; uint16_t _2[1];
}; };
struct type_align32(4) XAnimPartTransFrames struct type_align(4) XAnimPartTransFrames
{ {
float mins[3]; float mins[3];
float size[3]; float size[3];
@ -330,9 +330,9 @@ namespace IW4
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) short XQuat2[2]; typedef tdef_align(4) short XQuat2[2];
struct type_align32(4) XAnimDeltaPartQuatDataFrames2 struct type_align(4) XAnimDeltaPartQuatDataFrames2
{ {
XQuat2* frames; XQuat2* frames;
XAnimDynamicIndicesQuat2 indices; XAnimDynamicIndicesQuat2 indices;
@ -356,7 +356,7 @@ namespace IW4
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) short XQuat[4]; typedef tdef_align(4) short XQuat[4];
struct XAnimDeltaPartQuatDataFrames struct XAnimDeltaPartQuatDataFrames
{ {
@ -489,7 +489,7 @@ namespace IW4
XSurfaceCollisionTree* collisionTree; XSurfaceCollisionTree* collisionTree;
}; };
typedef tdef_align32(16) uint16_t r_index16_t; typedef tdef_align(16) uint16_t r_index16_t;
struct XSurface struct XSurface
{ {
@ -843,7 +843,7 @@ namespace IW4
unsigned int toolFlags; unsigned int toolFlags;
}; };
struct gcc_align32(8) GfxDrawSurfFields struct gcc_align(8) GfxDrawSurfFields
{ {
uint64_t objectId : 16; uint64_t objectId : 16;
uint64_t reflectionProbeIndex : 8; uint64_t reflectionProbeIndex : 8;
@ -860,8 +860,8 @@ namespace IW4
union GfxDrawSurf union GfxDrawSurf
{ {
gcc_align32(8) GfxDrawSurfFields fields; gcc_align(8) GfxDrawSurfFields fields;
gcc_align32(8) uint64_t packed; gcc_align(8) uint64_t packed;
}; };
// The sort key is translated to a numeric value inside the material templates // The sort key is translated to a numeric value inside the material templates
@ -993,7 +993,7 @@ namespace IW4
GfxStateBits* stateBitsTable; GfxStateBits* stateBitsTable;
}; };
struct type_align32(4) GfxImageLoadDef struct type_align(4) GfxImageLoadDef
{ {
char levelCount; char levelCount;
char pad[3]; char pad[3];
@ -2918,8 +2918,8 @@ namespace IW4
float linkMaxs[2]; float linkMaxs[2];
}; };
typedef tdef_align32(128) cbrush_t cbrush_array_t; typedef tdef_align(128) cbrush_t cbrush_array_t;
typedef tdef_align32(128) Bounds BoundsArray; typedef tdef_align(128) Bounds BoundsArray;
struct clipMap_t struct clipMap_t
{ {
@ -3539,7 +3539,7 @@ namespace IW4
Bounds bounds; Bounds bounds;
}; };
struct type_align32(4) GfxBrushModel struct type_align(4) GfxBrushModel
{ {
GfxBrushModelWritable writable; GfxBrushModelWritable writable;
Bounds bounds; Bounds bounds;
@ -3744,8 +3744,8 @@ namespace IW4
int exponent; int exponent;
}; };
typedef tdef_align32(128) GfxCellTree GfxCellTree128; typedef tdef_align(128) GfxCellTree GfxCellTree128;
typedef tdef_align32(4) GfxSceneDynModel GfxSceneDynModel4; typedef tdef_align(4) GfxSceneDynModel GfxSceneDynModel4;
struct GfxWorld struct GfxWorld
{ {

View File

@ -179,44 +179,3 @@ namespace IW5
using AssetVehicle = Asset<ASSET_TYPE_VEHICLE, VehicleDef>; using AssetVehicle = Asset<ASSET_TYPE_VEHICLE, VehicleDef>;
using AssetAddonMapEnts = Asset<ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts>; using AssetAddonMapEnts = Asset<ASSET_TYPE_ADDON_MAP_ENTS, AddonMapEnts>;
} // namespace IW5 } // namespace IW5
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPhysPreset, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPhysCollMap, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXModelSurfs, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPixelShader, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVertexShader, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVertexDecl, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSound, aliasName);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSoundCurve, filename);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLoadedSound, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetClipMap, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetGlassWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetPathData, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVehicleTrack, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetAttachment, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetImpactFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetSurfaceFx, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetScript, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetStringTable, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetLeaderboard, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetStructuredDataDef, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetTracer, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetVehicle, name);
DEFINE_ASSET_NAME_ACCESSOR(IW5::AssetAddonMapEnts, name);

View File

@ -221,9 +221,9 @@ namespace IW5
}; };
}; };
typedef tdef_align32(16) char raw_byte16; typedef tdef_align(16) char raw_byte16;
typedef tdef_align32(16) float raw_float16; typedef tdef_align(16) float raw_float16;
typedef tdef_align32(128) unsigned int raw_uint128; typedef tdef_align(128) unsigned int raw_uint128;
typedef unsigned char raw_byte; typedef unsigned char raw_byte;
typedef unsigned int raw_uint; typedef unsigned int raw_uint;
typedef unsigned short r_index_t; typedef unsigned short r_index_t;
@ -338,7 +338,7 @@ namespace IW5
}; };
typedef unsigned char ByteVec[3]; typedef unsigned char ByteVec[3];
typedef tdef_align32(4) unsigned short UShortVec[3]; typedef tdef_align(4) unsigned short UShortVec[3];
union XAnimDynamicFrames union XAnimDynamicFrames
{ {
@ -352,7 +352,7 @@ namespace IW5
uint16_t _2[1]; uint16_t _2[1];
}; };
struct type_align32(4) XAnimPartTransFrames struct type_align(4) XAnimPartTransFrames
{ {
float mins[3]; float mins[3];
float size[3]; float size[3];
@ -379,9 +379,9 @@ namespace IW5
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) short XQuat2[2]; typedef tdef_align(4) short XQuat2[2];
struct type_align32(4) XAnimDeltaPartQuatDataFrames2 struct type_align(4) XAnimDeltaPartQuatDataFrames2
{ {
XQuat2* frames; XQuat2* frames;
XAnimDynamicIndicesQuat2 indices; XAnimDynamicIndicesQuat2 indices;
@ -405,7 +405,7 @@ namespace IW5
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) short XQuat[4]; typedef tdef_align(4) short XQuat[4];
struct XAnimDeltaPartQuatDataFrames struct XAnimDeltaPartQuatDataFrames
{ {
@ -543,7 +543,7 @@ namespace IW5
uint16_t i[3]; uint16_t i[3];
}; };
typedef tdef_align32(16) XSurfaceTri XSurfaceTri16; typedef tdef_align(16) XSurfaceTri XSurfaceTri16;
struct XSurface struct XSurface
{ {
@ -653,7 +653,7 @@ namespace IW5
float quantization; float quantization;
}; };
struct gcc_align32(8) GfxDrawSurfFields struct gcc_align(8) GfxDrawSurfFields
{ {
uint64_t unused : 1; uint64_t unused : 1;
uint64_t primarySortKey : 6; uint64_t primarySortKey : 6;
@ -671,8 +671,8 @@ namespace IW5
union GfxDrawSurf union GfxDrawSurf
{ {
gcc_align32(8) GfxDrawSurfFields fields; gcc_align(8) GfxDrawSurfFields fields;
gcc_align32(8) uint64_t packed; gcc_align(8) uint64_t packed;
}; };
enum MaterialGameFlags enum MaterialGameFlags
@ -1127,7 +1127,7 @@ namespace IW5
MaterialTechnique* techniques[54]; MaterialTechnique* techniques[54];
}; };
struct type_align32(4) GfxImageLoadDef struct type_align(4) GfxImageLoadDef
{ {
char levelCount; char levelCount;
char pad[3]; char pad[3];
@ -1339,8 +1339,8 @@ namespace IW5
unsigned char edgeCount[2][3]; unsigned char edgeCount[2][3];
}; };
typedef tdef_align32(128) cbrush_t cbrush_array_t; typedef tdef_align(128) cbrush_t cbrush_array_t;
typedef tdef_align32(128) Bounds BoundsArray; typedef tdef_align(128) Bounds BoundsArray;
struct ClipInfo struct ClipInfo
{ {
@ -2190,7 +2190,7 @@ namespace IW5
Bounds bounds; Bounds bounds;
}; };
struct type_align32(4) GfxBrushModel struct type_align(4) GfxBrushModel
{ {
GfxBrushModelWritable writable; GfxBrushModelWritable writable;
Bounds bounds; Bounds bounds;
@ -2396,7 +2396,7 @@ namespace IW5
int exponent; int exponent;
}; };
typedef tdef_align32(128) GfxCellTree GfxCellTree128; typedef tdef_align(128) GfxCellTree GfxCellTree128;
struct GfxWorld struct GfxWorld
{ {
@ -3446,7 +3446,7 @@ namespace IW5
SndAliasCustom projIgnitionSound; SndAliasCustom projIgnitionSound;
}; };
typedef tdef_align32(4) AttSight AttSight4; typedef tdef_align(4) AttSight AttSight4;
struct WeaponAttachment struct WeaponAttachment
{ {

View File

@ -148,38 +148,5 @@ namespace T5
using AssetDDL = Asset<ASSET_TYPE_DDL, ddlRoot_t>; using AssetDDL = Asset<ASSET_TYPE_DDL, ddlRoot_t>;
using AssetGlasses = Asset<ASSET_TYPE_GLASSES, Glasses>; using AssetGlasses = Asset<ASSET_TYPE_GLASSES, Glasses>;
using AssetEmblemSet = Asset<ASSET_TYPE_EMBLEMSET, EmblemSet>; using AssetEmblemSet = Asset<ASSET_TYPE_EMBLEMSET, EmblemSet>;
} // namespace T5
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysPreset, name); } // namespace T5
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPhysConstraints, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDestructibleDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundBank, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundPatch, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMap, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetClipMapPvs, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldSp, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGameWorldMp, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetSoundDriverGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetImpactFx, "ImpactFx");
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetStringTable, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetPackIndex, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetXGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetDDL, name);
DEFINE_ASSET_NAME_ACCESSOR(T5::AssetGlasses, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T5::AssetEmblemSet, "EmblemSet");

View File

@ -193,20 +193,20 @@ namespace T5
void* data; void* data;
}; };
typedef tdef_align32(16) char char16; typedef tdef_align(16) char char16;
typedef tdef_align32(32) char byte32; typedef tdef_align(32) char byte32;
typedef tdef_align32(128) char byte128; typedef tdef_align(128) char byte128;
typedef tdef_align32(4) char char_align4; typedef tdef_align(4) char char_align4;
typedef tdef_align32(128) char char_align128; typedef tdef_align(128) char char_align128;
typedef tdef_align32(16) char raw_byte16; typedef tdef_align(16) char raw_byte16;
typedef tdef_align32(128) char raw_byte128; typedef tdef_align(128) char raw_byte128;
typedef tdef_align32(128) float float_align128; typedef tdef_align(128) float float_align128;
typedef char cbrushedge_t; typedef char cbrushedge_t;
typedef tdef_align32(128) unsigned int raw_uint128; typedef tdef_align(128) unsigned int raw_uint128;
typedef uint16_t ScriptString; typedef uint16_t ScriptString;
@ -350,7 +350,7 @@ namespace T5
}; };
typedef unsigned char ByteVec[3]; typedef unsigned char ByteVec[3];
typedef tdef_align32(4) unsigned short UShortVec[3]; typedef tdef_align(4) unsigned short UShortVec[3];
union XAnimDynamicFrames union XAnimDynamicFrames
{ {
@ -385,7 +385,7 @@ namespace T5
XAnimPartTransData u; XAnimPartTransData u;
}; };
typedef tdef_align32(4) short XQuat[2]; typedef tdef_align(4) short XQuat[2];
union XAnimDynamicIndicesQuat union XAnimDynamicIndicesQuat
{ {
@ -542,7 +542,7 @@ namespace T5
uint16_t i[3]; uint16_t i[3];
}; };
typedef tdef_align32(16) XSurfaceTri XSurfaceTri16; typedef tdef_align(16) XSurfaceTri XSurfaceTri16;
struct XSurface struct XSurface
{ {
@ -627,7 +627,7 @@ namespace T5
int sflags; int sflags;
}; };
struct type_align32(16) BrushWrapper struct type_align(16) BrushWrapper
{ {
vec3_t mins; vec3_t mins;
int contents; int contents;
@ -650,7 +650,7 @@ namespace T5
vec3_t halfLengths; vec3_t halfLengths;
}; };
typedef tdef_align32(16) PhysGeomInfo PhysGeomInfo16; typedef tdef_align(16) PhysGeomInfo PhysGeomInfo16;
struct PhysGeomList struct PhysGeomList
{ {
@ -713,7 +713,7 @@ namespace T5
PhysConstraints* physConstraints; PhysConstraints* physConstraints;
}; };
struct gcc_align32(8) GfxDrawSurfFields struct gcc_align(8) GfxDrawSurfFields
{ {
uint64_t objectId : 16; uint64_t objectId : 16;
uint64_t fade : 4; uint64_t fade : 4;
@ -732,8 +732,8 @@ namespace T5
union GfxDrawSurf union GfxDrawSurf
{ {
gcc_align32(8) GfxDrawSurfFields fields; gcc_align(8) GfxDrawSurfFields fields;
gcc_align32(8) uint64_t packed; gcc_align(8) uint64_t packed;
}; };
struct MaterialInfo struct MaterialInfo
@ -1138,7 +1138,7 @@ namespace T5
SND_ASSET_FLAG_PAD_LOOP_BUFFER = 0x2, SND_ASSET_FLAG_PAD_LOOP_BUFFER = 0x2,
}; };
typedef tdef_align32(2048) char snd_align_char; typedef tdef_align(2048) char snd_align_char;
struct snd_asset struct snd_asset
{ {
@ -1164,7 +1164,7 @@ namespace T5
snd_asset sound; snd_asset sound;
}; };
typedef tdef_align32(2048) char char_align_2048; typedef tdef_align(2048) char char_align_2048;
struct PrimedSound struct PrimedSound
{ {
@ -1311,7 +1311,7 @@ namespace T5
struct SndPatch struct SndPatch
{ {
const char* name; char* name;
unsigned int elementCount; unsigned int elementCount;
unsigned int* elements; unsigned int* elements;
unsigned int fileCount; unsigned int fileCount;
@ -1426,7 +1426,7 @@ namespace T5
cLeaf_s leaf; cLeaf_s leaf;
}; };
struct type_align32(16) cbrush_t struct type_align(16) cbrush_t
{ {
float mins[3]; float mins[3];
int contents; int contents;
@ -1935,7 +1935,7 @@ namespace T5
}; };
}; };
struct type_align32(16) GfxLight struct type_align(16) GfxLight
{ {
char type; char type;
char canUseShadowMap; char canUseShadowMap;
@ -2142,7 +2142,7 @@ namespace T5
char rgb[56][3]; char rgb[56][3];
}; };
typedef tdef_align32(4) char aligned_byte_pointer; typedef tdef_align(4) char aligned_byte_pointer;
struct GfxLightGrid struct GfxLightGrid
{ {
@ -2220,7 +2220,7 @@ namespace T5
uint16_t dynEntId; uint16_t dynEntId;
}; };
typedef tdef_align32(4) GfxSceneDynModel GfxSceneDynModel4; typedef tdef_align(4) GfxSceneDynModel GfxSceneDynModel4;
struct BModelDrawInfo struct BModelDrawInfo
{ {
@ -2283,7 +2283,7 @@ namespace T5
int stream2ByteOffset; int stream2ByteOffset;
}; };
struct type_align32(16) GfxSurface struct type_align(16) GfxSurface
{ {
srfTriangles_t tris; srfTriangles_t tris;
Material* material; Material* material;
@ -2935,7 +2935,7 @@ namespace T5
ITEM_TYPE_MENUMODEL = 0x27 ITEM_TYPE_MENUMODEL = 0x27
}; };
struct type_align32(8) itemDef_s struct type_align(8) itemDef_s
{ {
windowDef_t window; windowDef_t window;
int type; int type;
@ -2949,15 +2949,15 @@ namespace T5
menuDef_t* parent; menuDef_t* parent;
rectData_s* rectExpData; rectData_s* rectExpData;
ExpressionStatement visibleExp; ExpressionStatement visibleExp;
gcc_align32(8) uint64_t showBits; gcc_align(8) uint64_t showBits;
gcc_align32(8) uint64_t hideBits; gcc_align(8) uint64_t hideBits;
ExpressionStatement forecolorAExp; ExpressionStatement forecolorAExp;
int ui3dWindowId; int ui3dWindowId;
GenericEventHandler* onEvent; GenericEventHandler* onEvent;
UIAnimInfo* animInfo; UIAnimInfo* animInfo;
}; };
struct type_align32(8) menuDef_t struct type_align(8) menuDef_t
{ {
windowDef_t window; windowDef_t window;
const char* font; const char* font;
@ -2984,8 +2984,8 @@ namespace T5
GenericEventHandler* onEvent; GenericEventHandler* onEvent;
ItemKeyHandler* onKey; ItemKeyHandler* onKey;
ExpressionStatement visibleExp; ExpressionStatement visibleExp;
gcc_align32(8) uint64_t showBits; gcc_align(8) uint64_t showBits;
gcc_align32(8) uint64_t hideBits; gcc_align(8) uint64_t hideBits;
const char* allowedBinding; const char* allowedBinding;
const char* soundName; const char* soundName;
int imageTrack; int imageTrack;

View File

@ -209,53 +209,3 @@ namespace T6
using AssetFootstepFxTable = Asset<ASSET_TYPE_FOOTSTEPFX_TABLE, FootstepFXTableDef>; using AssetFootstepFxTable = Asset<ASSET_TYPE_FOOTSTEPFX_TABLE, FootstepFXTableDef>;
using AssetZBarrier = Asset<ASSET_TYPE_ZBARRIER, ZBarrierDef>; using AssetZBarrier = Asset<ASSET_TYPE_ZBARRIER, ZBarrierDef>;
} // namespace T6 } // namespace T6
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetPhysPreset, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetPhysConstraints, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetDestructibleDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXAnim, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXModel, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMaterial, info.name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetTechniqueSet, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetImage, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundBank, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundPatch, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetClipMap, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetClipMapPvs, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetComWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGameWorldSp, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGameWorldMp, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGfxWorld, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLightDef, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFont, fontName);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFontIcon, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMenuList, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMenu, window.name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLocalize, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetWeapon, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAttachment, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAttachmentUnique, szInternalName);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetWeaponCamo, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSoundDriverGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFx, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T6::AssetImpactFx, "ImpactFx");
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetRawFile, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetStringTable, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetLeaderboard, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetXGlobals, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetDDL, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetGlasses, name);
DEFINE_ASSET_NAME_ACCESSOR_SINGLETON(T6::AssetEmblemSet, "EmblemSet");
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetScript, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetKeyValuePairs, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetVehicle, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetMemoryBlock, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetAddonMapEnts, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetTracer, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSkinnedVerts, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetQdb, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetSlug, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFootstepTable, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetFootstepFxTable, name);
DEFINE_ASSET_NAME_ACCESSOR(T6::AssetZBarrier, name);

View File

@ -10,17 +10,17 @@ namespace T6
{ {
#endif #endif
typedef tdef_align32(16) char char16; typedef tdef_align(16) char char16;
typedef tdef_align32(32) char byte32; typedef tdef_align(32) char byte32;
typedef tdef_align32(128) char byte128; typedef tdef_align(128) char byte128;
typedef tdef_align32(4) char char_align4; typedef tdef_align(4) char char_align4;
typedef tdef_align32(128) char char_align128; typedef tdef_align(128) char char_align128;
typedef tdef_align32(16) char raw_byte16; typedef tdef_align(16) char raw_byte16;
typedef tdef_align32(128) char raw_byte128; typedef tdef_align(128) char raw_byte128;
typedef tdef_align32(128) float float_align128; typedef tdef_align(128) float float_align128;
typedef uint16_t ScriptString; typedef uint16_t ScriptString;
@ -643,7 +643,7 @@ namespace T6
float lightingOriginRange; float lightingOriginRange;
}; };
struct gcc_align32(8) GfxDrawSurfFields struct gcc_align(8) GfxDrawSurfFields
{ {
uint64_t objectId : 16; uint64_t objectId : 16;
uint64_t customIndex : 9; uint64_t customIndex : 9;
@ -658,8 +658,8 @@ namespace T6
union GfxDrawSurf union GfxDrawSurf
{ {
gcc_align32(8) GfxDrawSurfFields fields; gcc_align(8) GfxDrawSurfFields fields;
gcc_align32(8) uint64_t packed; gcc_align(8) uint64_t packed;
}; };
// The sort key is translated to a numeric value inside the material templates // The sort key is translated to a numeric value inside the material templates
@ -702,7 +702,7 @@ namespace T6
MTL_GAMEFLAG_1000 = 0x1000, MTL_GAMEFLAG_1000 = 0x1000,
}; };
struct type_align32(8) MaterialInfo struct type_align(8) MaterialInfo
{ {
const char* name; const char* name;
unsigned int gameFlags; unsigned int gameFlags;
@ -735,7 +735,7 @@ namespace T6
CAMERA_REGION_NONE = CAMERA_REGION_COUNT, CAMERA_REGION_NONE = CAMERA_REGION_COUNT,
}; };
typedef tdef_align32(8) GfxStateBits GfxStateBitsTable; typedef tdef_align(8) GfxStateBits GfxStateBitsTable;
struct Material struct Material
{ {
@ -960,9 +960,9 @@ namespace T6
unsigned int entryCount; unsigned int entryCount;
unsigned int dependencyCount; unsigned int dependencyCount;
unsigned int pad32; unsigned int pad32;
gcc_align32(8) int64_t fileSize; gcc_align(8) int64_t fileSize;
gcc_align32(8) int64_t entryOffset; gcc_align(8) int64_t entryOffset;
gcc_align32(8) int64_t checksumOffset; gcc_align(8) int64_t checksumOffset;
char checksumChecksum[16]; char checksumChecksum[16];
char dependencies[512]; char dependencies[512];
char padding[1464]; char padding[1464];
@ -970,7 +970,7 @@ namespace T6
#pragma pack(push, 1) #pragma pack(push, 1)
struct type_align32(2) SndRuntimeAssetBank struct type_align(2) SndRuntimeAssetBank
{ {
const char* zone; const char* zone;
const char* language; const char* language;
@ -985,7 +985,7 @@ namespace T6
#pragma pack(pop) #pragma pack(pop)
typedef tdef_align32(2048) char SndChar2048; typedef tdef_align(2048) char SndChar2048;
struct SndLoadedAssets struct SndLoadedAssets
{ {
@ -1041,8 +1041,8 @@ namespace T6
}; };
typedef unsigned short LeafBrush; typedef unsigned short LeafBrush;
typedef tdef_align32(128) cbrush_t cbrush_array_t; typedef tdef_align(128) cbrush_t cbrush_array_t;
typedef tdef_align32(128) Bounds BoundsArray; typedef tdef_align(128) Bounds BoundsArray;
struct ClipInfo struct ClipInfo
{ {
@ -1066,7 +1066,7 @@ namespace T6
int* brushContents; int* brushContents;
}; };
struct type_align32(4) cLeaf_s struct type_align(4) cLeaf_s
{ {
uint16_t firstCollAabbIndex; uint16_t firstCollAabbIndex;
uint16_t collAabbCount; uint16_t collAabbCount;
@ -1273,8 +1273,8 @@ namespace T6
void /*ID3D11Buffer*/* indexBuffer; void /*ID3D11Buffer*/* indexBuffer;
}; };
typedef tdef_align32(4) char aligned_byte_pointer; typedef tdef_align(4) char aligned_byte_pointer;
typedef tdef_align32(4) GfxCompressedLightGridCoeffs GfxCompressedLightGridCoeffs_align4; typedef tdef_align(4) GfxCompressedLightGridCoeffs GfxCompressedLightGridCoeffs_align4;
struct GfxLightGrid struct GfxLightGrid
{ {
@ -1323,7 +1323,7 @@ namespace T6
vec3_t sunFxPosition; vec3_t sunFxPosition;
}; };
typedef tdef_align32(4) GfxDrawSurf GfxDrawSurf_align4; typedef tdef_align(4) GfxDrawSurf GfxDrawSurf_align4;
struct GfxWorldDpvsStatic struct GfxWorldDpvsStatic
{ {
@ -1449,7 +1449,7 @@ namespace T6
int lightingQuality; int lightingQuality;
}; };
struct type_align32(4) GfxLightImage struct type_align(4) GfxLightImage
{ {
GfxImage* image; GfxImage* image;
char samplerState; char samplerState;
@ -1478,8 +1478,8 @@ namespace T6
struct FontIcon struct FontIcon
{ {
const char* name; const char* name;
unsigned int numEntries; int numEntries;
unsigned int numAliasEntries; int numAliasEntries;
FontIconEntry* fontIconEntry; FontIconEntry* fontIconEntry;
FontIconAlias* fontIconAlias; FontIconAlias* fontIconAlias;
}; };
@ -1535,7 +1535,7 @@ namespace T6
expressionRpn* rpn; expressionRpn* rpn;
}; };
struct type_align32(8) menuDef_t struct type_align(8) menuDef_t
{ {
windowDef_t window; windowDef_t window;
const char* font; const char* font;
@ -1562,8 +1562,8 @@ namespace T6
GenericEventHandler* onEvent; GenericEventHandler* onEvent;
ItemKeyHandler* onKey; ItemKeyHandler* onKey;
ExpressionStatement visibleExp; ExpressionStatement visibleExp;
gcc_align32(8) uint64_t showBits; gcc_align(8) uint64_t showBits;
gcc_align32(8) uint64_t hideBits; gcc_align(8) uint64_t hideBits;
const char* allowedBinding; const char* allowedBinding;
const char* soundName; const char* soundName;
int imageTrack; int imageTrack;
@ -1942,7 +1942,7 @@ namespace T6
int columnCount; int columnCount;
int rowCount; int rowCount;
StringTableCell* values; StringTableCell* values;
uint16_t* cellIndex; int16_t* cellIndex;
}; };
enum LbUpdateType enum LbUpdateType
@ -2114,7 +2114,7 @@ namespace T6
struct KeyValuePairs struct KeyValuePairs
{ {
const char* name; const char* name;
unsigned int numVariables; int numVariables;
KeyValuePair* keyValuePairs; KeyValuePair* keyValuePairs;
}; };
@ -2753,9 +2753,9 @@ namespace T6
uint16_t i[3]; uint16_t i[3];
}; };
typedef tdef_align32(16) XSurfaceTri XSurfaceTri16; typedef tdef_align(16) XSurfaceTri XSurfaceTri16;
struct type_align32(16) XSurface struct type_align(16) XSurface
{ {
char tileMode; char tileMode;
unsigned char vertListCount; unsigned char vertListCount;
@ -2783,7 +2783,7 @@ namespace T6
int surfFlags; int surfFlags;
}; };
struct type_align32(4) XBoneInfo struct type_align(4) XBoneInfo
{ {
vec3_t bounds[2]; vec3_t bounds[2];
vec3_t offset; vec3_t offset;
@ -3058,7 +3058,7 @@ namespace T6
{ {
};*/ };*/
struct type_align32(4) GfxImageLoadDef struct type_align(4) GfxImageLoadDef
{ {
char levelCount; char levelCount;
char flags; char flags;
@ -3104,7 +3104,7 @@ namespace T6
float returnHighpass; float returnHighpass;
}; };
typedef tdef_align32(16) float SndFloatAlign16; typedef tdef_align(16) float SndFloatAlign16;
struct SndDuck struct SndDuck
{ {
@ -3206,7 +3206,7 @@ namespace T6
cLeafBrushNodeData_t data; cLeafBrushNodeData_t data;
}; };
struct type_align32(16) cbrush_t struct type_align(16) cbrush_t
{ {
vec3_t mins; vec3_t mins;
int contents; int contents;
@ -3352,7 +3352,7 @@ namespace T6
ROPE_CENTITY_CONSTRAINT = 0x3, ROPE_CENTITY_CONSTRAINT = 0x3,
}; };
struct type_align32(4) constraint_t struct type_align(4) constraint_t
{ {
vec3_t p; vec3_t p;
rope_constraint_e type; rope_constraint_e type;
@ -3374,7 +3374,7 @@ namespace T6
unsigned int frame_index; unsigned int frame_index;
}; };
struct type_align32(4) rope_t struct type_align(4) rope_t
{ {
par_t m_particles[25]; par_t m_particles[25];
constraint_t m_constraints[30]; constraint_t m_constraints[30];
@ -3489,7 +3489,7 @@ namespace T6
uint16_t infoIndex; uint16_t infoIndex;
}; };
struct type_align32(4) pathnode_dynamic_t struct type_align(4) pathnode_dynamic_t
{ {
SentientHandle pOwner; SentientHandle pOwner;
int iFreeTime; int iFreeTime;
@ -3595,7 +3595,7 @@ namespace T6
}; };
}; };
struct type_align32(16) GfxLight struct type_align(16) GfxLight
{ {
char type; char type;
char canUseShadowMap; char canUseShadowMap;
@ -3814,8 +3814,7 @@ namespace T6
uint16_t dynEntId; uint16_t dynEntId;
}; };
// Usually __m128, but that is not portable union gcc_align(8) __m128
union gcc_align32(8) custom_m128
{ {
float m128_f32[4]; float m128_f32[4];
uint64_t m128_u64[2]; uint64_t m128_u64[2];
@ -3828,15 +3827,22 @@ namespace T6
unsigned int m128_u32[4]; unsigned int m128_u32[4];
}; };
struct vector4 struct vector3
{ {
custom_m128 x; __m128 x;
custom_m128 y; __m128 y;
custom_m128 z; __m128 z;
custom_m128 w;
}; };
struct type_align32(16) SSkinInstance struct vector4
{
__m128 x;
__m128 y;
__m128 z;
__m128 w;
};
struct type_align(16) SSkinInstance
{ {
union union
{ {
@ -3888,7 +3894,7 @@ namespace T6
int baseIndex; int baseIndex;
}; };
struct type_align32(16) GfxSurface struct type_align(16) GfxSurface
{ {
srfTriangles_t tris; srfTriangles_t tris;
Material* material; Material* material;
@ -3913,7 +3919,7 @@ namespace T6
uint16_t V2[4]; uint16_t V2[4];
}; };
struct type_align32(4) GfxStaticModelLmapVertexInfo struct type_align(4) GfxStaticModelLmapVertexInfo
{ {
unsigned int* lmapVertexColors; unsigned int* lmapVertexColors;
void /*ID3D11Buffer*/* lmapVertexColorsVB; void /*ID3D11Buffer*/* lmapVertexColorsVB;
@ -4113,7 +4119,7 @@ namespace T6
void* data; void* data;
}; };
struct type_align32(8) itemDef_s struct type_align(8) itemDef_s
{ {
windowDef_t window; windowDef_t window;
int type; int type;
@ -5563,8 +5569,8 @@ namespace T6
struct KeyValuePair struct KeyValuePair
{ {
unsigned int keyHash; int keyHash;
unsigned int namespaceHash; int namespaceHash;
const char* value; const char* value;
}; };
@ -5587,7 +5593,7 @@ namespace T6
LOCAL_CLIENT_COUNT = 0x1, LOCAL_CLIENT_COUNT = 0x1,
}; };
struct type_align32(4) DevGraph struct type_align(4) DevGraph
{ {
vec2_t* knots; vec2_t* knots;
int* knotCount; int* knotCount;
@ -5609,7 +5615,7 @@ namespace T6
}; };
typedef char ByteVec[3]; typedef char ByteVec[3];
typedef tdef_align32(4) uint16_t UShortVec[3]; typedef tdef_align(4) uint16_t UShortVec[3];
union XAnimDynamicFrames union XAnimDynamicFrames
{ {
@ -5623,7 +5629,7 @@ namespace T6
uint16_t _2[1]; uint16_t _2[1];
}; };
struct type_align32(4) XAnimPartTransFrames struct type_align(4) XAnimPartTransFrames
{ {
vec3_t mins; vec3_t mins;
vec3_t size; vec3_t size;
@ -5650,9 +5656,9 @@ namespace T6
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) int16_t XQuat2[2]; typedef tdef_align(4) int16_t XQuat2[2];
struct type_align32(4) XAnimDeltaPartQuatDataFrames2 struct type_align(4) XAnimDeltaPartQuatDataFrames2
{ {
XQuat2* frames; XQuat2* frames;
XAnimDynamicIndicesDeltaQuat2 indices; XAnimDynamicIndicesDeltaQuat2 indices;
@ -5676,9 +5682,9 @@ namespace T6
uint16_t _2[1]; uint16_t _2[1];
}; };
typedef tdef_align32(4) int16_t XQuat[4]; typedef tdef_align(4) int16_t XQuat[4];
struct type_align32(4) XAnimDeltaPartQuatDataFrames struct type_align(4) XAnimDeltaPartQuatDataFrames
{ {
XQuat* frames; XQuat* frames;
XAnimDynamicIndicesDeltaQuat indices; XAnimDynamicIndicesDeltaQuat indices;
@ -5738,7 +5744,7 @@ namespace T6
vec4_t tvec; vec4_t tvec;
}; };
typedef tdef_align32(16) PhysGeomInfo PhysGeomInfo16; typedef tdef_align(16) PhysGeomInfo PhysGeomInfo16;
struct PhysGeomList struct PhysGeomList
{ {
@ -6295,7 +6301,7 @@ namespace T6
static_assert(sizeof(SndAliasFlags) == 8); static_assert(sizeof(SndAliasFlags) == 8);
#endif #endif
struct type_align32(4) pathlink_s struct type_align(4) pathlink_s
{ {
float fDist; float fDist;
uint16_t nodeNum; uint16_t nodeNum;
@ -6404,7 +6410,7 @@ namespace T6
unsigned int v; unsigned int v;
}; };
struct type_align32(4) SSkinVert struct type_align(4) SSkinVert
{ {
half4 pos_bone; half4 pos_bone;
PackedUnitVec normal; PackedUnitVec normal;
@ -6495,7 +6501,7 @@ namespace T6
} vector; } vector;
}; };
struct type_align32(8) dvar_t struct type_align(8) dvar_t
{ {
const char* name; const char* name;
const char* description; const char* description;
@ -7006,7 +7012,7 @@ namespace T6
uint16_t triangleBeginIndex; uint16_t triangleBeginIndex;
}; };
struct type_align32(16) BrushWrapper struct type_align(16) BrushWrapper
{ {
vec3_t mins; vec3_t mins;
int contents; int contents;

View File

@ -7,6 +7,9 @@
#ifdef tdef_align #ifdef tdef_align
#undef tdef_align #undef tdef_align
#endif #endif
#ifdef memb_align
#undef memb_align
#endif
#ifdef gcc_align #ifdef gcc_align
#undef gcc_align #undef gcc_align
#endif #endif
@ -14,44 +17,25 @@
#ifdef __zonecodegenerator #ifdef __zonecodegenerator
#define type_align(x) alignas(x) #define type_align(x) alignas(x)
#define tdef_align(x) alignas(x) #define tdef_align(x) alignas(x)
#define memb_align(x) alignas(x)
#define gcc_align(x) #define gcc_align(x)
#else #else
#ifdef __ida #ifdef __ida
#define type_align(x) __declspec(align(x)) #define type_align(x) __declspec(align(x))
#define tdef_align(x) __declspec(align(x)) #define tdef_align(x) __declspec(align(x))
#define memb_align(x) __declspec(align(x))
#define gcc_align(x) #define gcc_align(x)
#else #else
#ifdef _MSVC_LANG #ifdef _MSVC_LANG
#define type_align(x) __declspec(align(x)) #define type_align(x) __declspec(align(x))
#define tdef_align(x) __declspec(align(x)) #define tdef_align(x) __declspec(align(x))
#define memb_align(x) __declspec(align(x))
#define gcc_align(x) #define gcc_align(x)
#else #else
#define type_align(x) __attribute__((__aligned__(x))) #define type_align(x) __attribute__((__aligned__(x)))
#define tdef_align(x) #define tdef_align(x)
#define memb_align(x) __attribute__((__aligned__(x)))
#define gcc_align(x) __attribute__((__aligned__(x))) #define gcc_align(x) __attribute__((__aligned__(x)))
#endif #endif
#endif #endif
#endif #endif
#if defined(__zonecodegenerator) || defined(__ida)
#define type_align32(x) type_align(x)
#define tdef_align32(x) tdef_align(x)
#define gcc_align32(x) gcc_align(x)
#define type_align64(x) type_align(x)
#define tdef_align64(x) tdef_align(x)
#define gcc_align64(x) gcc_align(x)
#elif defined(ARCH_x86)
#define type_align32(x) type_align(x)
#define tdef_align32(x) tdef_align(x)
#define gcc_align32(x) gcc_align(x)
#define type_align64(x)
#define tdef_align64(x)
#define gcc_align64(x)
#elif defined(ARCH_x64)
#define type_align32(x)
#define tdef_align32(x)
#define gcc_align32(x)
#define type_align64(x) type_align(x)
#define tdef_align64(x) tdef_align(x)
#define gcc_align64(x) gcc_align(x)
#endif

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <limits>
struct ZoneHeader struct ZoneHeader
{ {
@ -8,12 +7,22 @@ struct ZoneHeader
uint32_t m_version; uint32_t m_version;
}; };
#ifdef ARCH_x64
typedef uint32_t scr_string_t;
typedef uint64_t xchunk_size_t;
typedef uint64_t xblock_size_t;
typedef uint64_t zone_pointer_t;
constexpr uint16_t SCR_STRING_MAX = UINT32_MAX;
#elif ARCH_x86
typedef uint16_t scr_string_t; typedef uint16_t scr_string_t;
typedef uint32_t xchunk_size_t; typedef uint32_t xchunk_size_t;
typedef uint32_t xblock_size_t; typedef uint32_t xblock_size_t;
typedef uint32_t zone_pointer_t;
constexpr uint16_t SCR_STRING_MAX = std::numeric_limits<scr_string_t>::max(); constexpr uint16_t SCR_STRING_MAX = UINT16_MAX;
#endif
typedef unsigned block_t; typedef int block_t;
typedef unsigned asset_type_t; typedef int asset_type_t;
typedef unsigned int zone_priority_t; typedef unsigned int zone_priority_t;

View File

@ -1,29 +1,29 @@
Cryptography = {} Crypto = {}
function Cryptography:include(includes) function Crypto:include(includes)
if includes:handle(self:name()) then if includes:handle(self:name()) then
includedirs { includedirs {
path.join(ProjectFolder(), "Cryptography") path.join(ProjectFolder(), "Crypto")
} }
end end
end end
function Cryptography:link(links) function Crypto:link(links)
links:add(self:name()) links:add(self:name())
links:linkto(libtomcrypt) links:linkto(libtomcrypt)
links:linkto(libtommath) links:linkto(libtommath)
links:linkto(salsa20) links:linkto(salsa20)
end end
function Cryptography:use() function Crypto:use()
end end
function Cryptography:name() function Crypto:name()
return "Cryptography" return "Crypto"
end end
function Cryptography:project() function Crypto:project()
local folder = ProjectFolder() local folder = ProjectFolder()
local includes = Includes:create() local includes = Includes:create()
@ -34,8 +34,8 @@ function Cryptography:project()
language "C++" language "C++"
files { files {
path.join(folder, "Cryptography/**.h"), path.join(folder, "Crypto/**.h"),
path.join(folder, "Cryptography/**.cpp") path.join(folder, "Crypto/**.cpp")
} }
self:include(includes) self:include(includes)

32
src/Crypto/Crypto.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "Crypto.h"
#include "Impl/AlgorithmMD5.h"
#include "Impl/AlgorithmRSA.h"
#include "Impl/AlgorithmSHA1.h"
#include "Impl/AlgorithmSHA256.h"
#include "Impl/AlgorithmSalsa20.h"
std::unique_ptr<IHashFunction> Crypto::CreateMD5()
{
return std::make_unique<AlgorithmMD5>();
}
std::unique_ptr<IHashFunction> Crypto::CreateSHA1()
{
return std::make_unique<AlgorithmSHA1>();
}
std::unique_ptr<IHashFunction> Crypto::CreateSHA256()
{
return std::make_unique<AlgorithmSHA256>();
}
std::unique_ptr<IStreamCipher> Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize)
{
return std::make_unique<AlgorithmSalsa20>(keyBytes, keySize);
}
std::unique_ptr<IPublicKeyAlgorithm> Crypto::CreateRSA(const IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, const RSAPaddingMode paddingMode)
{
return std::make_unique<AlgorithmRSA>(hashingAlgorithm, paddingMode);
}

27
src/Crypto/Crypto.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
#include "IHashFunction.h"
#include "IPublicKeyAlgorithm.h"
#include "IStreamCipher.h"
#include <cstddef>
#include <memory>
class Crypto
{
public:
enum class RSAPaddingMode
{
RSA_PADDING_PKS1,
RSA_PADDING_PSS,
};
static std::unique_ptr<IHashFunction> CreateMD5();
static std::unique_ptr<IHashFunction> CreateSHA1();
static std::unique_ptr<IHashFunction> CreateSHA256();
static std::unique_ptr<IStreamCipher> CreateSalsa20(const uint8_t* keyBytes, size_t keySize);
static std::unique_ptr<IPublicKeyAlgorithm> CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, RSAPaddingMode paddingMode);
};

View File

@ -0,0 +1,14 @@
#pragma once
#include <cstddef>
class IHashFunction
{
public:
virtual ~IHashFunction() = default;
virtual size_t GetHashSize() = 0;
virtual void Init() = 0;
virtual void Process(const void* input, size_t inputSize) = 0;
virtual void Finish(void* hashBuffer) = 0;
};

View File

@ -0,0 +1,22 @@
#pragma once
#include <cstddef>
#include <cstdint>
class IPublicKeyAlgorithm
{
public:
enum class HashingAlgorithm
{
RSA_HASH_SHA256,
RSA_HASH_SHA512
};
virtual ~IPublicKeyAlgorithm() = default;
virtual bool SetKey(const uint8_t* keyData, size_t keySize) = 0;
// If needed add a signing method
virtual bool Verify(const uint8_t* signedData, size_t signedDataSize, const uint8_t* signature, size_t signatureSize) = 0;
};

View File

@ -0,0 +1,14 @@
#pragma once
#include <cstddef>
#include <cstdint>
class IStreamCipher
{
public:
virtual ~IStreamCipher() = default;
virtual void SetIV(const uint8_t* iv, size_t ivSize) = 0;
virtual void Process(const void* plainText, void* cipherText, size_t amount) = 0;
};

View File

@ -0,0 +1,64 @@
#include "AlgorithmMD5.h"
#include "CryptoLibrary.h"
#include <cstdint>
class AlgorithmMD5::AlgorithmMD5Impl
{
hash_state m_state{};
public:
AlgorithmMD5Impl()
{
CryptoLibrary::Init();
Init();
}
void Init()
{
md5_init(&m_state);
}
void Process(const void* input, const size_t inputSize)
{
md5_process(&m_state, static_cast<const uint8_t*>(input), inputSize);
}
void Finish(void* hashBuffer)
{
md5_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
};
AlgorithmMD5::AlgorithmMD5()
{
m_impl = new AlgorithmMD5Impl();
}
AlgorithmMD5::~AlgorithmMD5()
{
delete m_impl;
m_impl = nullptr;
}
size_t AlgorithmMD5::GetHashSize()
{
return HASH_SIZE;
}
void AlgorithmMD5::Init()
{
m_impl->Init();
}
void AlgorithmMD5::Process(const void* input, const size_t inputSize)
{
m_impl->Process(input, inputSize);
}
void AlgorithmMD5::Finish(void* hashBuffer)
{
m_impl->Finish(hashBuffer);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IHashFunction.h"
class AlgorithmMD5 : public IHashFunction
{
class AlgorithmMD5Impl;
AlgorithmMD5Impl* m_impl;
public:
static const int HASH_SIZE = 16;
AlgorithmMD5();
~AlgorithmMD5() override;
size_t GetHashSize() override;
void Init() override;
void Process(const void* input, size_t inputSize) override;
void Finish(void* hashBuffer) override;
};

View File

@ -0,0 +1,119 @@
#include "AlgorithmRSA.h"
#include "CryptoLibrary.h"
#include <cstring>
class AlgorithmRSA::AlgorithmRSAImpl
{
rsa_key m_key{};
HashingAlgorithm m_hash;
Crypto::RSAPaddingMode m_padding;
const ltc_hash_descriptor* GetHashDescriptor() const
{
switch (m_hash)
{
case HashingAlgorithm::RSA_HASH_SHA256:
return &sha256_desc;
default:
case HashingAlgorithm::RSA_HASH_SHA512:
return &sha512_desc;
}
}
int GetPaddingMode() const
{
switch (m_padding)
{
case Crypto::RSAPaddingMode::RSA_PADDING_PKS1:
return LTC_PKCS_1_V1_5;
default:
case Crypto::RSAPaddingMode::RSA_PADDING_PSS:
return LTC_PKCS_1_PSS;
}
}
public:
AlgorithmRSAImpl(const HashingAlgorithm hash, const Crypto::RSAPaddingMode padding)
{
m_hash = hash;
m_padding = padding;
CryptoLibrary::Init();
}
~AlgorithmRSAImpl() = default;
AlgorithmRSAImpl(AlgorithmRSAImpl& other) = default;
AlgorithmRSAImpl(AlgorithmRSAImpl&& other) = delete;
AlgorithmRSAImpl& operator=(AlgorithmRSAImpl const& other) = default;
AlgorithmRSAImpl& operator=(AlgorithmRSAImpl&& other) = delete;
bool SetKey(const uint8_t* keyData, const size_t keySize)
{
return rsa_import(keyData, keySize, &m_key) == CRYPT_OK;
}
bool Verify(const uint8_t* signedData, const size_t signedDataSize, const uint8_t* signature, const size_t signatureSize)
{
const ltc_hash_descriptor* hashDesc = GetHashDescriptor();
const int hashId = register_hash(hashDesc);
const int padding = GetPaddingMode();
int result;
rsa_verify_hash_ex(signature, signatureSize, signedData, signedDataSize, padding, hashId, 8, &result, &m_key);
return result == 1;
}
};
AlgorithmRSA::AlgorithmRSA(const HashingAlgorithm hash, const Crypto::RSAPaddingMode padding)
{
m_impl = new AlgorithmRSAImpl(hash, padding);
}
AlgorithmRSA::~AlgorithmRSA()
{
delete m_impl;
m_impl = nullptr;
}
AlgorithmRSA::AlgorithmRSA(AlgorithmRSA& other)
{
m_impl = new AlgorithmRSAImpl(*other.m_impl);
}
AlgorithmRSA::AlgorithmRSA(AlgorithmRSA&& other) noexcept
{
m_impl = other.m_impl;
other.m_impl = nullptr;
}
AlgorithmRSA& AlgorithmRSA::operator=(AlgorithmRSA const& other)
{
m_impl = new AlgorithmRSAImpl(*other.m_impl);
return *this;
}
AlgorithmRSA& AlgorithmRSA::operator=(AlgorithmRSA&& other) noexcept
{
m_impl = other.m_impl;
other.m_impl = nullptr;
return *this;
}
bool AlgorithmRSA::SetKey(const uint8_t* keyData, size_t keySize)
{
return m_impl->SetKey(keyData, keySize);
}
bool AlgorithmRSA::Verify(const uint8_t* signedData, const size_t signedDataSize, const uint8_t* signature, const size_t signatureSize)
{
return m_impl->Verify(signedData, signedDataSize, signature, signatureSize);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "Crypto.h"
#include "IPublicKeyAlgorithm.h"
#include <cstdint>
class AlgorithmRSA final : public IPublicKeyAlgorithm
{
class AlgorithmRSAImpl;
AlgorithmRSAImpl* m_impl;
public:
AlgorithmRSA(HashingAlgorithm hash, Crypto::RSAPaddingMode padding);
~AlgorithmRSA() override;
AlgorithmRSA(AlgorithmRSA& other);
AlgorithmRSA(AlgorithmRSA&& other) noexcept;
AlgorithmRSA& operator=(AlgorithmRSA const& other);
AlgorithmRSA& operator=(AlgorithmRSA&& other) noexcept;
bool SetKey(const uint8_t* keyData, size_t keySize) override;
bool Verify(const uint8_t* signedData, size_t signedDataSize, const uint8_t* signature, size_t signatureSize) override;
};

View File

@ -0,0 +1,64 @@
#include "AlgorithmSHA1.h"
#include "CryptoLibrary.h"
#include <cstdint>
class AlgorithmSHA1::AlgorithmSHA1Impl
{
hash_state m_state{};
public:
AlgorithmSHA1Impl()
{
CryptoLibrary::Init();
Init();
}
void Init()
{
sha1_init(&m_state);
}
void Process(const void* input, const size_t inputSize)
{
sha1_process(&m_state, static_cast<const uint8_t*>(input), inputSize);
}
void Finish(void* hashBuffer)
{
sha1_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
};
AlgorithmSHA1::AlgorithmSHA1()
{
m_impl = new AlgorithmSHA1Impl();
}
AlgorithmSHA1::~AlgorithmSHA1()
{
delete m_impl;
m_impl = nullptr;
}
size_t AlgorithmSHA1::GetHashSize()
{
return HASH_SIZE;
}
void AlgorithmSHA1::Init()
{
m_impl->Init();
}
void AlgorithmSHA1::Process(const void* input, const size_t inputSize)
{
m_impl->Process(input, inputSize);
}
void AlgorithmSHA1::Finish(void* hashBuffer)
{
m_impl->Finish(hashBuffer);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IHashFunction.h"
class AlgorithmSHA1 : public IHashFunction
{
class AlgorithmSHA1Impl;
AlgorithmSHA1Impl* m_impl;
public:
static const int HASH_SIZE = 20;
AlgorithmSHA1();
~AlgorithmSHA1() override;
size_t GetHashSize() override;
void Init() override;
void Process(const void* input, size_t inputSize) override;
void Finish(void* hashBuffer) override;
};

View File

@ -0,0 +1,64 @@
#include "AlgorithmSHA256.h"
#include "CryptoLibrary.h"
#include <cstdint>
class AlgorithmSHA256::Impl
{
hash_state m_state{};
public:
Impl()
{
CryptoLibrary::Init();
Init();
}
void Init()
{
sha256_init(&m_state);
}
void Process(const void* input, const size_t inputSize)
{
sha256_process(&m_state, static_cast<const uint8_t*>(input), inputSize);
}
void Finish(void* hashBuffer)
{
sha256_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
};
AlgorithmSHA256::AlgorithmSHA256()
{
m_impl = new Impl();
}
AlgorithmSHA256::~AlgorithmSHA256()
{
delete m_impl;
m_impl = nullptr;
}
size_t AlgorithmSHA256::GetHashSize()
{
return HASH_SIZE;
}
void AlgorithmSHA256::Init()
{
m_impl->Init();
}
void AlgorithmSHA256::Process(const void* input, const size_t inputSize)
{
m_impl->Process(input, inputSize);
}
void AlgorithmSHA256::Finish(void* hashBuffer)
{
m_impl->Finish(hashBuffer);
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "IHashFunction.h"
class AlgorithmSHA256 : public IHashFunction
{
class Impl;
Impl* m_impl;
public:
static const int HASH_SIZE = 32;
AlgorithmSHA256();
~AlgorithmSHA256() override;
size_t GetHashSize() override;
void Init() override;
void Process(const void* input, size_t inputSize) override;
void Finish(void* hashBuffer) override;
};

View File

@ -0,0 +1,89 @@
#include "AlgorithmSalsa20.h"
#include "salsa20.h"
#include <cassert>
#include <stdexcept>
class AlgorithmSalsa20::AlgorithmSalsa20Impl
{
salsa20_ctx m_context{};
public:
AlgorithmSalsa20Impl(const uint8_t* keyBytes, const size_t keySize)
{
Salsa20_KeySetup(&m_context, keyBytes, keySize * 8);
}
~AlgorithmSalsa20Impl() = default;
AlgorithmSalsa20Impl(AlgorithmSalsa20Impl& other) = default;
AlgorithmSalsa20Impl(AlgorithmSalsa20Impl&& other) = delete;
AlgorithmSalsa20Impl& operator=(AlgorithmSalsa20Impl const& other) = default;
AlgorithmSalsa20Impl& operator=(AlgorithmSalsa20Impl&& other) = delete;
void SetIV(const uint8_t* iv, const size_t ivSize)
{
assert(ivSize == 8);
if (ivSize != 8)
{
throw std::invalid_argument("Salsa20 IV size must be 8");
}
Salsa20_IVSetup(&m_context, iv);
}
void Process(const void* plainText, void* cipherText, const size_t amount)
{
Salsa20_Encrypt_Bytes(&m_context, static_cast<const uint8_t*>(plainText), static_cast<uint8_t*>(cipherText), amount);
}
};
AlgorithmSalsa20::AlgorithmSalsa20(const uint8_t* keyBytes, const size_t keySize)
{
m_impl = new AlgorithmSalsa20Impl(keyBytes, keySize);
}
AlgorithmSalsa20::~AlgorithmSalsa20()
{
delete m_impl;
m_impl = nullptr;
}
AlgorithmSalsa20::AlgorithmSalsa20(AlgorithmSalsa20& other)
{
m_impl = new AlgorithmSalsa20Impl(*other.m_impl);
}
AlgorithmSalsa20::AlgorithmSalsa20(AlgorithmSalsa20&& other) noexcept
{
m_impl = other.m_impl;
other.m_impl = nullptr;
}
AlgorithmSalsa20& AlgorithmSalsa20::operator=(AlgorithmSalsa20 const& other)
{
m_impl = new AlgorithmSalsa20Impl(*other.m_impl);
return *this;
}
AlgorithmSalsa20& AlgorithmSalsa20::operator=(AlgorithmSalsa20&& other) noexcept
{
m_impl = other.m_impl;
other.m_impl = nullptr;
return *this;
}
void AlgorithmSalsa20::SetIV(const uint8_t* iv, const size_t ivSize)
{
m_impl->SetIV(iv, ivSize);
}
void AlgorithmSalsa20::Process(const void* plainText, void* cipherText, const size_t amount)
{
m_impl->Process(plainText, cipherText, amount);
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "IStreamCipher.h"
class AlgorithmSalsa20 final : public IStreamCipher
{
class AlgorithmSalsa20Impl;
AlgorithmSalsa20Impl* m_impl;
public:
AlgorithmSalsa20(const uint8_t* keyBytes, size_t keySize);
~AlgorithmSalsa20() override;
AlgorithmSalsa20(AlgorithmSalsa20& other);
AlgorithmSalsa20(AlgorithmSalsa20&& other) noexcept;
AlgorithmSalsa20& operator=(AlgorithmSalsa20 const& other);
AlgorithmSalsa20& operator=(AlgorithmSalsa20&& other) noexcept;
void SetIV(const uint8_t* iv, size_t ivSize) override;
void Process(const void* plainText, void* cipherText, size_t amount) override;
};

View File

@ -0,0 +1,49 @@
#include "Base64.h"
#define LTC_NO_PROTOTYPES
#include <tomcrypt.h>
namespace base64
{
std::string EncodeBase64(const void* inputData, const size_t inputLength)
{
const auto base64BufferSize = GetBase64EncodeOutputLength(inputLength);
std::string output(base64BufferSize, '\0');
const auto outLength = base64BufferSize + 1u;
const auto result = EncodeBase64(inputData, inputLength, output.data(), outLength);
assert(result);
return output;
}
bool EncodeBase64(const void* inputData, const size_t inputLength, void* outputBuffer, const size_t outputBufferSize)
{
unsigned long outLength = outputBufferSize;
const auto result = base64_encode(static_cast<const unsigned char*>(inputData), inputLength, static_cast<char*>(outputBuffer), &outLength);
return result == CRYPT_OK;
}
size_t GetBase64EncodeOutputLength(const size_t inputLength)
{
return 4u * ((inputLength + 2u) / 3u);
}
size_t DecodeBase64(const void* base64Data, const size_t inputLength, void* outputBuffer, const size_t outputBufferSize)
{
unsigned long outLength = GetBase64DecodeOutputLength(inputLength);
if (outLength > outputBufferSize)
return 0u;
const auto result = base64_decode(static_cast<const char*>(base64Data), inputLength, static_cast<unsigned char*>(outputBuffer), &outLength);
assert(result == CRYPT_OK);
return static_cast<size_t>(outLength);
}
size_t GetBase64DecodeOutputLength(const size_t inputLength)
{
return inputLength / 4u;
}
} // namespace base64

View File

@ -8,6 +8,5 @@ namespace base64
size_t GetBase64EncodeOutputLength(size_t inputLength); size_t GetBase64EncodeOutputLength(size_t inputLength);
size_t DecodeBase64(const void* base64Data, size_t inputLength, void* outputBuffer, size_t outputBufferSize); size_t DecodeBase64(const void* base64Data, size_t inputLength, void* outputBuffer, size_t outputBufferSize);
size_t GetBase64DecodeOutputLength(const void* base64Data, size_t inputLength);
size_t GetBase64DecodeOutputLength(size_t inputLength); size_t GetBase64DecodeOutputLength(size_t inputLength);
} // namespace base64 } // namespace base64

View File

@ -0,0 +1,15 @@
#include "CryptoLibrary.h"
#include "tommath.h"
void CryptoLibrary::Init()
{
static bool initialized = false;
if (!initialized)
{
initialized = true;
ltc_mp = ltm_desc;
}
}

View File

@ -0,0 +1,10 @@
#pragma once
#define LTC_NO_PROTOTYPES
#include "tomcrypt.h"
class CryptoLibrary
{
public:
static void Init();
};

View File

@ -1,54 +0,0 @@
#include "AlgorithmMd5.h"
#include "Internal/CryptoLibrary.h"
#include <cstdint>
using namespace cryptography;
namespace
{
constexpr int HASH_SIZE = 16;
class AlgorithmMd5 final : public IHashFunction
{
public:
AlgorithmMd5()
{
internal::CryptoLibrary::Init();
Init();
}
size_t GetHashSize() override
{
return HASH_SIZE;
}
void Init() override
{
md5_init(&m_state);
}
void Process(const void* input, const size_t inputSize) override
{
md5_process(&m_state, static_cast<const uint8_t*>(input), static_cast<unsigned long>(inputSize));
}
void Finish(void* hashBuffer) override
{
md5_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
private:
hash_state m_state{};
};
} // namespace
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateMd5()
{
return std::make_unique<AlgorithmMd5>();
}
} // namespace cryptography

View File

@ -1,10 +0,0 @@
#pragma once
#include "IHashFunction.h"
#include <memory>
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateMd5();
}

View File

@ -1,84 +0,0 @@
#include "AlgorithmRsa.h"
#include "Internal/CryptoLibrary.h"
using namespace cryptography;
namespace
{
class AlgorithmRsa final : public IPublicKeyAlgorithm
{
public:
AlgorithmRsa(const HashingAlgorithm hash, const RsaPaddingMode padding)
{
m_hash = hash;
m_padding = padding;
internal::CryptoLibrary::Init();
}
bool SetKey(const uint8_t* keyData, const size_t keySize) override
{
return rsa_import(keyData, static_cast<unsigned long>(keySize), &m_key) == CRYPT_OK;
}
bool Verify(const uint8_t* signedData, const size_t signedDataSize, const uint8_t* signature, const size_t signatureSize) override
{
const ltc_hash_descriptor* hashDesc = GetHashDescriptor();
const int hashId = register_hash(hashDesc);
const int padding = GetPaddingMode();
int result;
rsa_verify_hash_ex(signature,
static_cast<unsigned long>(signatureSize),
signedData,
static_cast<unsigned long>(signedDataSize),
padding,
hashId,
8,
&result,
&m_key);
return result == 1;
}
private:
[[nodiscard]] const ltc_hash_descriptor* GetHashDescriptor() const
{
switch (m_hash)
{
case HashingAlgorithm::RSA_HASH_SHA256:
return &sha256_desc;
default:
case HashingAlgorithm::RSA_HASH_SHA512:
return &sha512_desc;
}
}
[[nodiscard]] int GetPaddingMode() const
{
switch (m_padding)
{
case RsaPaddingMode::RSA_PADDING_PKS1:
return LTC_PKCS_1_V1_5;
default:
case RsaPaddingMode::RSA_PADDING_PSS:
return LTC_PKCS_1_PSS;
}
}
rsa_key m_key{};
HashingAlgorithm m_hash;
RsaPaddingMode m_padding;
};
} // namespace
namespace cryptography
{
std::unique_ptr<IPublicKeyAlgorithm> CreateRsa(const HashingAlgorithm hashingAlgorithm, const RsaPaddingMode paddingMode)
{
return std::make_unique<AlgorithmRsa>(hashingAlgorithm, paddingMode);
}
} // namespace cryptography

View File

@ -1,17 +0,0 @@
#pragma once
#include "IPublicKeyAlgorithm.h"
#include <cstdint>
#include <memory>
namespace cryptography
{
enum class RsaPaddingMode : std::uint8_t
{
RSA_PADDING_PKS1,
RSA_PADDING_PSS,
};
std::unique_ptr<IPublicKeyAlgorithm> CreateRsa(HashingAlgorithm hashingAlgorithm, RsaPaddingMode paddingMode);
} // namespace cryptography

View File

@ -1,46 +0,0 @@
#include "AlgorithmSalsa20.h"
#include "salsa20.h"
#include <cassert>
#include <stdexcept>
using namespace cryptography;
namespace
{
class AlgorithmSalsa20 final : public IStreamCipher
{
public:
AlgorithmSalsa20(const uint8_t* keyBytes, const size_t keySize)
{
Salsa20_KeySetup(&m_context, keyBytes, static_cast<uint32_t>(keySize * 8uz));
}
void SetIv(const uint8_t* iv, const size_t ivSize) override
{
assert(ivSize == 8);
if (ivSize != 8)
throw std::invalid_argument("Salsa20 IV size must be 8");
Salsa20_IVSetup(&m_context, iv);
}
void Process(const void* plainText, void* cipherText, const size_t amount) override
{
Salsa20_Encrypt_Bytes(&m_context, static_cast<const uint8_t*>(plainText), static_cast<uint8_t*>(cipherText), static_cast<uint32_t>(amount));
}
private:
salsa20_ctx m_context{};
};
} // namespace
namespace cryptography
{
std::unique_ptr<IStreamCipher> CreateSalsa20(const uint8_t* keyBytes, const size_t keySize)
{
return std::make_unique<AlgorithmSalsa20>(keyBytes, keySize);
}
} // namespace cryptography

View File

@ -1,10 +0,0 @@
#pragma once
#include "IStreamCipher.h"
#include <memory>
namespace cryptography
{
std::unique_ptr<IStreamCipher> CreateSalsa20(const uint8_t* keyBytes, size_t keySize);
}

View File

@ -1,54 +0,0 @@
#include "AlgorithmSha1.h"
#include "Internal/CryptoLibrary.h"
#include <cstdint>
using namespace cryptography;
namespace
{
constexpr int HASH_SIZE = 20;
class AlgorithmSha1 final : public IHashFunction
{
public:
AlgorithmSha1()
{
internal::CryptoLibrary::Init();
Init();
}
size_t GetHashSize() override
{
return HASH_SIZE;
}
void Init() override
{
sha1_init(&m_state);
}
void Process(const void* input, const size_t inputSize) override
{
sha1_process(&m_state, static_cast<const uint8_t*>(input), static_cast<unsigned long>(inputSize));
}
void Finish(void* hashBuffer) override
{
sha1_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
private:
hash_state m_state{};
};
} // namespace
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateSha1()
{
return std::make_unique<AlgorithmSha1>();
}
} // namespace cryptography

View File

@ -1,10 +0,0 @@
#pragma once
#include "IHashFunction.h"
#include <memory>
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateSha1();
}

View File

@ -1,54 +0,0 @@
#include "AlgorithmSha256.h"
#include "Internal/CryptoLibrary.h"
#include <cstdint>
using namespace cryptography;
namespace
{
constexpr int HASH_SIZE = 32;
class AlgorithmSha256 final : public IHashFunction
{
public:
AlgorithmSha256()
{
internal::CryptoLibrary::Init();
Init();
}
size_t GetHashSize() override
{
return HASH_SIZE;
}
void Init() override
{
sha256_init(&m_state);
}
void Process(const void* input, const size_t inputSize) override
{
sha256_process(&m_state, static_cast<const uint8_t*>(input), static_cast<unsigned long>(inputSize));
}
void Finish(void* hashBuffer) override
{
sha256_done(&m_state, static_cast<uint8_t*>(hashBuffer));
}
private:
hash_state m_state{};
};
} // namespace
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateSha256()
{
return std::make_unique<AlgorithmSha256>();
}
} // namespace cryptography

View File

@ -1,10 +0,0 @@
#pragma once
#include "IHashFunction.h"
#include <memory>
namespace cryptography
{
std::unique_ptr<IHashFunction> CreateSha256();
}

View File

@ -1,72 +0,0 @@
#include "Base64.h"
#define LTC_NO_PROTOTYPES
#include <tomcrypt.h>
namespace base64
{
std::string EncodeBase64(const void* inputData, const size_t inputLength)
{
const auto base64BufferSize = GetBase64EncodeOutputLength(inputLength);
std::string output(base64BufferSize, '\0');
const auto outLength = base64BufferSize + 1u;
const auto result = EncodeBase64(inputData, inputLength, output.data(), outLength);
assert(result);
return output;
}
bool EncodeBase64(const void* inputData, const size_t inputLength, void* outputBuffer, const size_t outputBufferSize)
{
unsigned long outLength = static_cast<unsigned long>(outputBufferSize);
const auto result =
base64_encode(static_cast<const unsigned char*>(inputData), static_cast<unsigned long>(inputLength), static_cast<char*>(outputBuffer), &outLength);
return result == CRYPT_OK;
}
size_t GetBase64EncodeOutputLength(const size_t inputLength)
{
return 4u * ((inputLength + 2u) / 3u);
}
size_t DecodeBase64(const void* base64Data, const size_t inputLength, void* outputBuffer, const size_t outputBufferSize)
{
auto outLength = static_cast<unsigned long>(GetBase64DecodeOutputLength(base64Data, inputLength));
assert(outLength <= outputBufferSize);
if (outLength > outputBufferSize)
return 0u;
const auto result =
base64_decode(static_cast<const char*>(base64Data), static_cast<unsigned long>(inputLength), static_cast<unsigned char*>(outputBuffer), &outLength);
assert(result == CRYPT_OK);
return static_cast<size_t>(outLength);
}
size_t GetBase64DecodeOutputLength(const void* base64Data, const size_t inputLength)
{
assert(base64Data);
assert(inputLength);
if (!base64Data || inputLength == 0u)
return 0u;
auto padding = 0u;
if (inputLength >= 1 && static_cast<const char*>(base64Data)[inputLength - 1] == '=')
{
if (inputLength >= 2 && static_cast<const char*>(base64Data)[inputLength - 2] == '=')
padding = 2u;
else
padding = 1u;
}
return ((inputLength / 4u) * 3u) - padding;
}
size_t GetBase64DecodeOutputLength(const size_t inputLength)
{
return (inputLength / 4u) * 3u;
}
} // namespace base64

View File

@ -1,7 +0,0 @@
#pragma once
#include "Algorithms/AlgorithmMd5.h"
#include "Algorithms/AlgorithmRsa.h"
#include "Algorithms/AlgorithmSalsa20.h"
#include "Algorithms/AlgorithmSha1.h"
#include "Algorithms/AlgorithmSha256.h"

View File

@ -1,22 +0,0 @@
#pragma once
#include <cstdlib>
namespace cryptography
{
class IHashFunction
{
public:
IHashFunction() = default;
virtual ~IHashFunction() = default;
IHashFunction(const IHashFunction& other) = default;
IHashFunction(IHashFunction&& other) noexcept = default;
IHashFunction& operator=(const IHashFunction& other) = default;
IHashFunction& operator=(IHashFunction&& other) noexcept = default;
virtual size_t GetHashSize() = 0;
virtual void Init() = 0;
virtual void Process(const void* input, size_t inputSize) = 0;
virtual void Finish(void* hashBuffer) = 0;
};
} // namespace cryptography

View File

@ -1,30 +0,0 @@
#pragma once
#include <cstdint>
#include <cstdlib>
namespace cryptography
{
enum class HashingAlgorithm : std::uint8_t
{
RSA_HASH_SHA256,
RSA_HASH_SHA512
};
class IPublicKeyAlgorithm
{
public:
IPublicKeyAlgorithm() = default;
virtual ~IPublicKeyAlgorithm() = default;
IPublicKeyAlgorithm(const IPublicKeyAlgorithm& other) = default;
IPublicKeyAlgorithm(IPublicKeyAlgorithm&& other) noexcept = default;
IPublicKeyAlgorithm& operator=(const IPublicKeyAlgorithm& other) = default;
IPublicKeyAlgorithm& operator=(IPublicKeyAlgorithm&& other) noexcept = default;
virtual bool SetKey(const uint8_t* keyData, size_t keySize) = 0;
// If needed, add a signing method
virtual bool Verify(const uint8_t* signedData, size_t signedDataSize, const uint8_t* signature, size_t signatureSize) = 0;
};
} // namespace cryptography

View File

@ -1,21 +0,0 @@
#pragma once
#include <cstdint>
#include <cstdlib>
namespace cryptography
{
class IStreamCipher
{
public:
IStreamCipher() = default;
virtual ~IStreamCipher() = default;
IStreamCipher(const IStreamCipher& other) = default;
IStreamCipher(IStreamCipher&& other) noexcept = default;
IStreamCipher& operator=(const IStreamCipher& other) = default;
IStreamCipher& operator=(IStreamCipher&& other) noexcept = default;
virtual void SetIv(const uint8_t* iv, size_t ivSize) = 0;
virtual void Process(const void* plainText, void* cipherText, size_t amount) = 0;
};
} // namespace cryptography

View File

@ -1,18 +0,0 @@
#include "CryptoLibrary.h"
#include "tommath.h"
namespace cryptography::internal
{
void CryptoLibrary::Init()
{
static bool initialized = false;
if (!initialized)
{
initialized = true;
ltc_mp = ltm_desc;
}
}
} // namespace cryptography::internal

View File

@ -1,13 +0,0 @@
#pragma once
#define LTC_NO_PROTOTYPES
#include "tomcrypt.h"
namespace cryptography::internal
{
class CryptoLibrary
{
public:
static void Init();
};
} // namespace cryptography::internal

View File

@ -39,7 +39,6 @@ function Linker:project()
self:include(includes) self:include(includes)
Utils:include(includes) Utils:include(includes)
ZoneLoading:include(includes) ZoneLoading:include(includes)
ObjCompiling:include(includes)
ObjLoading:include(includes) ObjLoading:include(includes)
ObjWriting:include(includes) ObjWriting:include(includes)
ZoneWriting:include(includes) ZoneWriting:include(includes)
@ -47,7 +46,6 @@ function Linker:project()
Raw:use() Raw:use()
links:linkto(Utils) links:linkto(Utils)
links:linkto(ObjCompiling)
links:linkto(ZoneLoading) links:linkto(ZoneLoading)
links:linkto(ZoneWriting) links:linkto(ZoneWriting)
links:linkto(ObjLoading) links:linkto(ObjLoading)

View File

@ -0,0 +1,72 @@
#include "ZoneCreatorIW3.h"
#include "AssetLoading/AssetLoadingContext.h"
#include "Game/IW3/GameAssetPoolIW3.h"
#include "Game/IW3/GameIW3.h"
#include "IObjLoader.h"
#include "ObjLoading.h"
#include "Utils/StringUtils.h"
using namespace IW3;
std::vector<Gdt*> ZoneCreator::CreateGdtList(const ZoneCreationContext& context)
{
std::vector<Gdt*> gdtList;
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList;
}
void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext)
{
for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries)
loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type;
}
void ZoneCreator::CreateZoneAssetPools(Zone* zone) const
{
zone->m_pools = std::make_unique<GameAssetPoolIW3>(zone, zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
}
GameId ZoneCreator::GetGameId() const
{
return GameId::IW3;
}
std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW3));
CreateZoneAssetPools(zone.get());
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
ApplyIgnoredAssets(context, *assetLoadingContext);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW3);
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name))
return nullptr;
}
objLoader->FinalizeAssetsForZone(*assetLoadingContext);
return zone;
}
asset_type_t ZoneCreator::GetImageAssetType() const
{
return ASSET_TYPE_IMAGE;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "AssetLoading/AssetLoadingContext.h"
#include "Zone/ZoneTypes.h"
#include "ZoneCreation/ZoneCreator.h"
namespace IW3
{
class ZoneCreator final : public IZoneCreator
{
static std::vector<Gdt*> CreateGdtList(const ZoneCreationContext& context);
static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext);
void CreateZoneAssetPools(Zone* zone) const;
public:
[[nodiscard]] GameId GetGameId() const override;
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const override;
[[nodiscard]] asset_type_t GetImageAssetType() const override;
};
} // namespace IW3

View File

@ -0,0 +1,71 @@
#include "ZoneCreatorIW4.h"
#include "Game/IW4/GameAssetPoolIW4.h"
#include "Game/IW4/GameIW4.h"
#include "IObjLoader.h"
#include "ObjLoading.h"
#include "Utils/StringUtils.h"
using namespace IW4;
std::vector<Gdt*> ZoneCreator::CreateGdtList(const ZoneCreationContext& context)
{
std::vector<Gdt*> gdtList;
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList;
}
void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext)
{
for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries)
loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type;
}
void ZoneCreator::CreateZoneAssetPools(Zone* zone) const
{
zone->m_pools = std::make_unique<GameAssetPoolIW4>(zone, zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
}
GameId ZoneCreator::GetGameId() const
{
return GameId::IW4;
}
std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW4));
CreateZoneAssetPools(zone.get());
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
ApplyIgnoredAssets(context, *assetLoadingContext);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW4);
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name))
return nullptr;
}
objLoader->FinalizeAssetsForZone(*assetLoadingContext);
return zone;
}
asset_type_t ZoneCreator::GetImageAssetType() const
{
return ASSET_TYPE_IMAGE;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "AssetLoading/AssetLoadingContext.h"
#include "Zone/ZoneTypes.h"
#include "ZoneCreation/ZoneCreator.h"
namespace IW4
{
class ZoneCreator final : public IZoneCreator
{
static std::vector<Gdt*> CreateGdtList(const ZoneCreationContext& context);
static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext);
void CreateZoneAssetPools(Zone* zone) const;
public:
[[nodiscard]] GameId GetGameId() const override;
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const override;
[[nodiscard]] asset_type_t GetImageAssetType() const override;
};
} // namespace IW4

View File

@ -0,0 +1,71 @@
#include "ZoneCreatorIW5.h"
#include "Game/IW5/GameAssetPoolIW5.h"
#include "Game/IW5/GameIW5.h"
#include "IObjLoader.h"
#include "ObjLoading.h"
#include "Utils/StringUtils.h"
using namespace IW5;
std::vector<Gdt*> ZoneCreator::CreateGdtList(const ZoneCreationContext& context)
{
std::vector<Gdt*> gdtList;
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList;
}
void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext)
{
for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries)
loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type;
}
void ZoneCreator::CreateZoneAssetPools(Zone* zone) const
{
zone->m_pools = std::make_unique<GameAssetPoolIW5>(zone, zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
}
GameId ZoneCreator::GetGameId() const
{
return GameId::IW5;
}
std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(GameId::IW5));
CreateZoneAssetPools(zone.get());
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
ApplyIgnoredAssets(context, *assetLoadingContext);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::IW5);
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name))
return nullptr;
}
objLoader->FinalizeAssetsForZone(*assetLoadingContext);
return zone;
}
asset_type_t ZoneCreator::GetImageAssetType() const
{
return ASSET_TYPE_IMAGE;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "AssetLoading/AssetLoadingContext.h"
#include "Zone/ZoneTypes.h"
#include "ZoneCreation/ZoneCreator.h"
namespace IW5
{
class ZoneCreator final : public IZoneCreator
{
static std::vector<Gdt*> CreateGdtList(const ZoneCreationContext& context);
static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext);
void CreateZoneAssetPools(Zone* zone) const;
public:
[[nodiscard]] GameId GetGameId() const override;
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const override;
[[nodiscard]] asset_type_t GetImageAssetType() const override;
};
} // namespace IW5

View File

@ -0,0 +1,72 @@
#include "ZoneCreatorT5.h"
#include "AssetLoading/AssetLoadingContext.h"
#include "Game/T5/GameAssetPoolT5.h"
#include "Game/T5/GameT5.h"
#include "IObjLoader.h"
#include "ObjLoading.h"
#include "Utils/StringUtils.h"
using namespace T5;
std::vector<Gdt*> ZoneCreator::CreateGdtList(ZoneCreationContext& context)
{
std::vector<Gdt*> gdtList;
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList;
}
void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext)
{
for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries)
loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type;
}
void ZoneCreator::CreateZoneAssetPools(Zone* zone) const
{
zone->m_pools = std::make_unique<GameAssetPoolT5>(zone, zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
}
GameId ZoneCreator::GetGameId() const
{
return GameId::T5;
}
std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(GameId::T5));
CreateZoneAssetPools(zone.get());
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
ApplyIgnoredAssets(context, *assetLoadingContext);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::T5);
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name))
return nullptr;
}
objLoader->FinalizeAssetsForZone(*assetLoadingContext);
return zone;
}
asset_type_t ZoneCreator::GetImageAssetType() const
{
return ASSET_TYPE_IMAGE;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include "AssetLoading/AssetLoadingContext.h"
#include "Zone/ZoneTypes.h"
#include "ZoneCreation/ZoneCreator.h"
namespace T5
{
class ZoneCreator final : public IZoneCreator
{
static std::vector<Gdt*> CreateGdtList(ZoneCreationContext& context);
static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext);
void CreateZoneAssetPools(Zone* zone) const;
public:
[[nodiscard]] GameId GetGameId() const override;
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const override;
[[nodiscard]] asset_type_t GetImageAssetType() const override;
};
} // namespace T5

View File

@ -0,0 +1,125 @@
#include "ZoneCreatorT6.h"
#include "Game/T6/CommonT6.h"
#include "Game/T6/GameAssetPoolT6.h"
#include "Game/T6/GameT6.h"
#include "Game/T6/T6.h"
#include "IObjLoader.h"
#include "ObjLoading.h"
#include "Utils/StringUtils.h"
#include <iostream>
using namespace T6;
std::vector<Gdt*> ZoneCreator::CreateGdtList(const ZoneCreationContext& context)
{
std::vector<Gdt*> gdtList;
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList;
}
void ZoneCreator::ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext)
{
for (const auto& ignoreEntry : creationContext.m_ignored_assets.m_entries)
loadingContext.m_ignored_asset_map[ignoreEntry.m_name] = ignoreEntry.m_type;
}
void ZoneCreator::CreateZoneAssetPools(Zone* zone) const
{
zone->m_pools = std::make_unique<GameAssetPoolT6>(zone, zone->m_priority);
for (auto assetType = 0; assetType < ASSET_TYPE_COUNT; assetType++)
zone->m_pools->InitPoolDynamic(assetType);
}
void ZoneCreator::HandleMetadata(Zone* zone, const ZoneCreationContext& context) const
{
std::vector<KeyValuePair> kvpList;
for (const auto& metaData : context.m_definition->m_properties.m_properties)
{
if (metaData.first.rfind("level.", 0) == 0)
{
const std::string strValue = metaData.first.substr(std::char_traits<char>::length("level."));
if (strValue.empty())
continue;
int keyHash;
if (strValue[0] == '@')
{
char* endPtr;
keyHash = strtol(&strValue[1], &endPtr, 16);
if (endPtr != &strValue[strValue.size()])
{
std::cout << "Could not parse metadata key \"" << metaData.first << "\" as hash\n";
continue;
}
}
else
{
keyHash = Common::Com_HashKey(strValue.c_str(), 64);
}
KeyValuePair kvp{keyHash, Common::Com_HashKey(zone->m_name.c_str(), 64), zone->GetMemory()->Dup(metaData.second.c_str())};
kvpList.push_back(kvp);
}
}
if (!kvpList.empty())
{
auto* kvps = zone->GetMemory()->Create<KeyValuePairs>();
kvps->name = zone->GetMemory()->Dup(zone->m_name.c_str());
kvps->numVariables = kvpList.size();
kvps->keyValuePairs = zone->GetMemory()->Alloc<KeyValuePair>(kvpList.size());
for (auto i = 0u; i < kvpList.size(); i++)
kvps->keyValuePairs[i] = kvpList[i];
zone->m_pools->AddAsset(std::make_unique<XAssetInfo<KeyValuePairs>>(ASSET_TYPE_KEYVALUEPAIRS, zone->m_name, kvps));
}
}
GameId ZoneCreator::GetGameId() const
{
return GameId::T6;
}
std::unique_ptr<Zone> ZoneCreator::CreateZoneForDefinition(ZoneCreationContext& context) const
{
auto zone = std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(GameId::T6));
CreateZoneAssetPools(zone.get());
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
const auto assetLoadingContext = std::make_unique<AssetLoadingContext>(*zone, *context.m_asset_search_path, CreateGdtList(context));
ApplyIgnoredAssets(context, *assetLoadingContext);
HandleMetadata(zone.get(), context);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(GameId::T6);
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!objLoader->LoadAssetForZone(*assetLoadingContext, assetEntry.m_asset_type, assetEntry.m_asset_name))
return nullptr;
}
objLoader->FinalizeAssetsForZone(*assetLoadingContext);
return zone;
}
asset_type_t ZoneCreator::GetImageAssetType() const
{
return ASSET_TYPE_IMAGE;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "AssetLoading/AssetLoadingContext.h"
#include "Zone/ZoneTypes.h"
#include "ZoneCreation/ZoneCreator.h"
namespace T6
{
class ZoneCreator final : public IZoneCreator
{
static std::vector<Gdt*> CreateGdtList(const ZoneCreationContext& context);
static void ApplyIgnoredAssets(const ZoneCreationContext& creationContext, AssetLoadingContext& loadingContext);
void CreateZoneAssetPools(Zone* zone) const;
void HandleMetadata(Zone* zone, const ZoneCreationContext& context) const;
public:
[[nodiscard]] GameId GetGameId() const override;
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const override;
[[nodiscard]] asset_type_t GetImageAssetType() const override;
};
} // namespace T6

View File

@ -1,14 +1,16 @@
#include "Linker.h" #include "Linker.h"
#include "LinkerArgs.h" #include "LinkerArgs.h"
#include "LinkerPaths.h" #include "LinkerSearchPaths.h"
#include "ObjContainer/IPak/IPakWriter.h"
#include "ObjContainer/IWD/IWD.h"
#include "ObjContainer/SoundBank/SoundBankWriter.h" #include "ObjContainer/SoundBank/SoundBankWriter.h"
#include "ObjLoading.h"
#include "ObjWriting.h" #include "ObjWriting.h"
#include "SearchPath/OutputPathFilesystem.h"
#include "SearchPath/SearchPaths.h" #include "SearchPath/SearchPaths.h"
#include "Utils/ObjFileStream.h" #include "Utils/ObjFileStream.h"
#include "Zone/AssetList/AssetList.h" #include "Zone/AssetList/AssetList.h"
#include "Zone/AssetList/AssetListReader.h" #include "Zone/AssetList/AssetListStream.h"
#include "Zone/Definition/ZoneDefinitionStream.h" #include "Zone/Definition/ZoneDefinitionStream.h"
#include "ZoneCreation/ZoneCreationContext.h" #include "ZoneCreation/ZoneCreationContext.h"
#include "ZoneCreation/ZoneCreator.h" #include "ZoneCreation/ZoneCreator.h"
@ -19,157 +21,133 @@
#include <filesystem> #include <filesystem>
#include <format> #include <format>
#include <fstream> #include <fstream>
#include <unordered_set> #include <set>
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace
{
class LinkerSearchPathContext
{
public:
explicit LinkerSearchPathContext(const ILinkerSearchPathBuilder& searchPathBuilder)
: m_search_path_builder(searchPathBuilder)
{
m_independent_search_paths = m_search_path_builder.BuildIndependentSearchPaths();
if (m_independent_search_paths)
m_search_paths.IncludeSearchPath(m_independent_search_paths.get());
}
[[nodiscard]] ISearchPath& GetSearchPaths()
{
return m_search_paths;
}
void LoadProjectSpecific(const std::string& projectName)
{
m_project_specific_search_paths = m_search_path_builder.BuildSearchPathsSpecificToProject(projectName);
if (m_project_specific_search_paths)
m_search_paths.IncludeSearchPath(m_project_specific_search_paths.get());
}
void UnloadProjectSpecific()
{
if (!m_project_specific_search_paths)
return;
m_search_paths.RemoveSearchPath(m_project_specific_search_paths.get());
m_project_specific_search_paths.reset();
}
void LoadGameSpecific(const std::string& projectName, const GameId game)
{
m_game_specific_search_paths = m_search_path_builder.BuildSearchPathsSpecificToProjectAndGame(projectName, game);
if (m_game_specific_search_paths)
m_search_paths.IncludeSearchPath(m_game_specific_search_paths.get());
}
void UnloadGameSpecific()
{
if (!m_game_specific_search_paths)
return;
m_search_paths.RemoveSearchPath(m_game_specific_search_paths.get());
m_game_specific_search_paths.reset();
}
private:
const ILinkerSearchPathBuilder& m_search_path_builder;
std::unique_ptr<ISearchPath> m_independent_search_paths;
std::unique_ptr<ISearchPath> m_project_specific_search_paths;
std::unique_ptr<ISearchPath> m_game_specific_search_paths;
SearchPaths m_search_paths;
};
class LinkerPathManager
{
public:
explicit LinkerPathManager(const LinkerArgs& args)
: m_linker_paths(ILinkerPaths::FromArgs(args)),
m_asset_paths(m_linker_paths->AssetSearchPaths()),
m_gdt_paths(m_linker_paths->GdtSearchPaths()),
m_source_paths(m_linker_paths->SourceSearchPaths())
{
}
std::unique_ptr<ILinkerPaths> m_linker_paths;
LinkerSearchPathContext m_asset_paths;
LinkerSearchPathContext m_gdt_paths;
LinkerSearchPathContext m_source_paths;
};
class PathProjectContext
{
public:
PathProjectContext(LinkerPathManager& paths, const std::string& projectName)
: m_paths(paths)
{
m_paths.m_asset_paths.LoadProjectSpecific(projectName);
m_paths.m_gdt_paths.LoadProjectSpecific(projectName);
m_paths.m_source_paths.LoadProjectSpecific(projectName);
}
~PathProjectContext()
{
m_paths.m_asset_paths.UnloadProjectSpecific();
m_paths.m_gdt_paths.UnloadProjectSpecific();
m_paths.m_source_paths.UnloadProjectSpecific();
}
PathProjectContext(const PathProjectContext& other) = delete;
PathProjectContext(PathProjectContext&& other) noexcept = delete;
PathProjectContext& operator=(const PathProjectContext& other) = delete;
PathProjectContext& operator=(PathProjectContext&& other) noexcept = delete;
private:
LinkerPathManager& m_paths;
};
class PathGameContext
{
public:
PathGameContext(LinkerPathManager& paths, const std::string& projectName, const GameId game)
: m_paths(paths)
{
m_paths.m_asset_paths.LoadGameSpecific(projectName, game);
m_paths.m_gdt_paths.LoadGameSpecific(projectName, game);
m_paths.m_source_paths.LoadGameSpecific(projectName, game);
}
~PathGameContext()
{
m_paths.m_asset_paths.UnloadGameSpecific();
m_paths.m_gdt_paths.UnloadGameSpecific();
m_paths.m_source_paths.UnloadGameSpecific();
}
PathGameContext(const PathGameContext& other) = delete;
PathGameContext(PathGameContext&& other) noexcept = delete;
PathGameContext& operator=(const PathGameContext& other) = delete;
PathGameContext& operator=(PathGameContext&& other) noexcept = delete;
private:
LinkerPathManager& m_paths;
};
} // namespace
class LinkerImpl final : public Linker class LinkerImpl final : public Linker
{ {
std::unique_ptr<ZoneDefinition> ReadZoneDefinition(LinkerPathManager& paths, const std::string& targetName, bool logMissing = true) const LinkerArgs m_args;
LinkerSearchPaths m_search_paths;
std::vector<std::unique_ptr<Zone>> m_loaded_zones;
bool IncludeAdditionalZoneDefinitions(const std::string& initialFileName, ZoneDefinition& zoneDefinition, ISearchPath* sourceSearchPath) const
{
std::set<std::string> sourceNames;
sourceNames.emplace(initialFileName);
std::deque<std::string> toIncludeQueue;
for (const auto& include : zoneDefinition.m_includes)
toIncludeQueue.emplace_back(include);
while (!toIncludeQueue.empty())
{
const auto& source = toIncludeQueue.front();
if (sourceNames.find(source) == sourceNames.end())
{
sourceNames.emplace(source);
std::unique_ptr<ZoneDefinition> includeDefinition;
{
const auto definitionFileName = std::format("{}.zone", source);
const auto definitionStream = sourceSearchPath->Open(definitionFileName);
if (!definitionStream.IsOpen())
{
std::cerr << std::format("Could not find zone definition file for project \"{}\".\n", source);
return false;
}
ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, source, definitionFileName, m_args.m_verbose);
zoneDefinitionInputStream.SetPreviouslySetGame(zoneDefinition.m_game);
includeDefinition = zoneDefinitionInputStream.ReadDefinition();
}
if (!includeDefinition)
{
std::cerr << std::format("Failed to read zone definition file for project \"{}\".\n", source);
return false;
}
for (const auto& include : includeDefinition->m_includes)
toIncludeQueue.emplace_back(include);
zoneDefinition.Include(*includeDefinition);
}
toIncludeQueue.pop_front();
}
return true;
}
bool ReadAssetList(const std::string& zoneName, const GameId game, AssetList& assetList, ISearchPath* sourceSearchPath) const
{
{
const auto assetListFileName = std::format("assetlist/{}.csv", zoneName);
const auto assetListStream = sourceSearchPath->Open(assetListFileName);
if (assetListStream.IsOpen())
{
const AssetListInputStream stream(*assetListStream.m_stream, game);
AssetListEntry entry;
bool failure;
while (stream.NextEntry(entry, &failure))
{
assetList.m_entries.emplace_back(std::move(entry));
}
return !failure;
}
}
{
const auto zoneDefinition = ReadZoneDefinition(zoneName, sourceSearchPath);
if (zoneDefinition)
{
for (const auto& entry : zoneDefinition->m_assets)
{
assetList.m_entries.emplace_back(entry.m_asset_type, entry.m_asset_name, entry.m_is_reference);
}
return true;
}
}
return false;
}
bool IncludeAssetLists(ZoneDefinition& zoneDefinition, ISearchPath* sourceSearchPath) const
{
for (const auto& assetListName : zoneDefinition.m_asset_lists)
{
AssetList assetList;
if (!ReadAssetList(assetListName, zoneDefinition.m_game, assetList, sourceSearchPath))
{
std::cerr << std::format("Failed to read asset list \"{}\"\n", assetListName);
return false;
}
zoneDefinition.Include(assetList);
}
return true;
}
std::unique_ptr<ZoneDefinition> ReadZoneDefinition(const std::string& targetName, ISearchPath* sourceSearchPath) const
{ {
auto& sourceSearchPath = paths.m_source_paths.GetSearchPaths();
std::unique_ptr<ZoneDefinition> zoneDefinition; std::unique_ptr<ZoneDefinition> zoneDefinition;
{ {
const auto definitionFileName = std::format("{}.zone", targetName); const auto definitionFileName = std::format("{}.zone", targetName);
const auto definitionStream = sourceSearchPath.Open(definitionFileName); const auto definitionStream = sourceSearchPath->Open(definitionFileName);
if (!definitionStream.IsOpen()) if (!definitionStream.IsOpen())
{ {
if (logMissing) std::cerr << std::format("Could not find zone definition file for target \"{}\".\n", targetName);
std::cerr << std::format("Could not find zone definition file for target \"{}\".\n", targetName);
return nullptr; return nullptr;
} }
ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, targetName, definitionFileName, sourceSearchPath); ZoneDefinitionInputStream zoneDefinitionInputStream(*definitionStream.m_stream, targetName, definitionFileName, m_args.m_verbose);
zoneDefinition = zoneDefinitionInputStream.ReadDefinition(); zoneDefinition = zoneDefinitionInputStream.ReadDefinition();
} }
@ -179,41 +157,20 @@ class LinkerImpl final : public Linker
return nullptr; return nullptr;
} }
// If no type was defined explicitly make it fastfile
if (zoneDefinition->m_type == ProjectType::NONE)
zoneDefinition->m_type = ProjectType::FASTFILE;
if (!IncludeAdditionalZoneDefinitions(targetName, *zoneDefinition, sourceSearchPath))
return nullptr;
if (!IncludeAssetLists(*zoneDefinition, sourceSearchPath))
return nullptr;
return zoneDefinition; return zoneDefinition;
} }
bool ReadIgnoreEntries(LinkerPathManager& paths, const std::string& zoneName, const GameId game, AssetList& assetList) const bool ProcessZoneDefinitionIgnores(const std::string& targetName, ZoneCreationContext& context, ISearchPath* sourceSearchPath) const
{
{
AssetListReader assetListReader(paths.m_source_paths.GetSearchPaths(), game);
const auto maybeReadAssetList = assetListReader.ReadAssetList(zoneName, false);
if (maybeReadAssetList)
{
assetList.m_entries.reserve(assetList.m_entries.size() + maybeReadAssetList->m_entries.size());
for (auto& entry : maybeReadAssetList->m_entries)
assetList.m_entries.emplace_back(std::move(entry));
return true;
}
}
{
const auto zoneDefinition = ReadZoneDefinition(paths, zoneName, false);
if (zoneDefinition)
{
assetList.m_entries.reserve(assetList.m_entries.size() + zoneDefinition->m_assets.size());
for (const auto& entry : zoneDefinition->m_assets)
assetList.m_entries.emplace_back(entry.m_asset_type, entry.m_asset_name, entry.m_is_reference);
return true;
}
}
return false;
}
bool ProcessZoneDefinitionIgnores(LinkerPathManager& paths, const std::string& targetName, ZoneCreationContext& context) const
{ {
if (context.m_definition->m_ignores.empty()) if (context.m_definition->m_ignores.empty())
return true; return true;
@ -223,7 +180,8 @@ class LinkerImpl final : public Linker
if (ignore == targetName) if (ignore == targetName)
continue; continue;
if (!ReadIgnoreEntries(paths, ignore, context.m_definition->m_game, context.m_ignored_assets)) std::vector<AssetListEntry> assetList;
if (!ReadAssetList(ignore, context.m_definition->m_game, context.m_ignored_assets, sourceSearchPath))
{ {
std::cerr << std::format("Failed to read asset listing for ignoring assets of project \"{}\".\n", ignore); std::cerr << std::format("Failed to read asset listing for ignoring assets of project \"{}\".\n", ignore);
return false; return false;
@ -257,95 +215,158 @@ class LinkerImpl final : public Linker
return true; return true;
} }
std::unique_ptr<Zone> CreateZoneForDefinition( std::unique_ptr<Zone> CreateZoneForDefinition(const std::string& targetName,
LinkerPathManager& paths, const fs::path& outDir, const fs::path& cacheDir, const std::string& targetName, ZoneDefinition& zoneDefinition) const ZoneDefinition& zoneDefinition,
ISearchPath* assetSearchPath,
ISearchPath* gdtSearchPath,
ISearchPath* sourceSearchPath) const
{ {
ZoneCreationContext context(&zoneDefinition, &paths.m_asset_paths.GetSearchPaths(), outDir, cacheDir); const auto context = std::make_unique<ZoneCreationContext>(&zoneDefinition, assetSearchPath);
if (!ProcessZoneDefinitionIgnores(paths, targetName, context)) if (!ProcessZoneDefinitionIgnores(targetName, *context, sourceSearchPath))
return nullptr; return nullptr;
if (!LoadGdtFilesFromZoneDefinition(context.m_gdt_files, zoneDefinition, &paths.m_gdt_paths.GetSearchPaths())) if (!LoadGdtFilesFromZoneDefinition(context->m_gdt_files, zoneDefinition, gdtSearchPath))
return nullptr; return nullptr;
return zone_creator::CreateZoneForDefinition(zoneDefinition.m_game, context); const auto* creator = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game);
return creator->CreateZoneForDefinition(*context);
} }
static bool WriteZoneToFile(IOutputPath& outPath, const Zone& zone) bool WriteZoneToFile(const std::string& projectName, Zone* zone) const
{ {
const auto stream = outPath.Open(std::format("{}.ff", zone.m_name)); const fs::path zoneFolderPath(m_args.GetOutputFolderPathForProject(projectName));
if (!stream) auto zoneFilePath(zoneFolderPath);
{ zoneFilePath.append(zone->m_name + ".ff");
std::cerr << std::format("Failed to open file for zone: {}\n", zone.m_name);
fs::create_directories(zoneFolderPath);
std::ofstream stream(zoneFilePath, std::fstream::out | std::fstream::binary);
if (!stream.is_open())
return false; return false;
if (m_args.m_verbose)
{
std::cout << std::format("Building zone \"{}\"\n", zoneFilePath.string());
} }
std::cout << std::format("Building zone \"{}\"\n", zone.m_name); if (!ZoneWriting::WriteZone(stream, zone))
if (!ZoneWriting::WriteZone(*stream, zone))
{ {
std::cerr << "Writing zone failed.\n"; std::cerr << "Writing zone failed.\n";
stream.close();
return false; return false;
} }
std::cout << std::format("Created zone \"{}\"\n", zone.m_name); std::cout << std::format("Created zone \"{}\"\n", zoneFilePath.string());
stream.close();
return true; return true;
} }
bool BuildFastFile(LinkerPathManager& paths, const std::string& projectName, const std::string& targetName, ZoneDefinition& zoneDefinition) const bool BuildFastFile(const std::string& projectName,
const std::string& targetName,
ZoneDefinition& zoneDefinition,
SearchPaths& assetSearchPaths,
SearchPaths& gdtSearchPaths,
SearchPaths& sourceSearchPaths) const
{ {
const fs::path outDir(paths.m_linker_paths->BuildOutputFolderPath(projectName, zoneDefinition.m_game)); SoundBankWriter::OutputPath = fs::path(m_args.GetOutputFolderPathForProject(projectName));
OutputPathFilesystem outputPath(outDir); const auto zone = CreateZoneForDefinition(targetName, zoneDefinition, &assetSearchPaths, &gdtSearchPaths, &sourceSearchPaths);
const fs::path cacheDir(paths.m_linker_paths->BuildCacheFolderPath(projectName, zoneDefinition.m_game));
SoundBankWriter::OutputPath = outDir;
const auto zone = CreateZoneForDefinition(paths, outDir, cacheDir, targetName, zoneDefinition);
auto result = zone != nullptr; auto result = zone != nullptr;
if (zone) if (zone)
result = WriteZoneToFile(outputPath, *zone); result = WriteZoneToFile(projectName, zone.get());
return result; return result;
} }
bool BuildProject(LinkerPathManager& paths, const std::string& projectName, const std::string& targetName) const bool BuildIPak(const std::string& projectName, const ZoneDefinition& zoneDefinition, SearchPaths& assetSearchPaths) const
{ {
std::deque<std::string> targetsToBuild; const fs::path ipakFolderPath(m_args.GetOutputFolderPathForProject(projectName));
std::unordered_set<std::string> alreadyBuiltTargets; auto ipakFilePath(ipakFolderPath);
ipakFilePath.append(std::format("{}.ipak", zoneDefinition.m_name));
targetsToBuild.emplace_back(targetName); fs::create_directories(ipakFolderPath);
while (!targetsToBuild.empty()) std::ofstream stream(ipakFilePath, std::fstream::out | std::fstream::binary);
if (!stream.is_open())
return false;
const auto ipakWriter = IPakWriter::Create(stream, &assetSearchPaths);
const auto imageAssetType = IZoneCreator::GetCreatorForGame(zoneDefinition.m_game)->GetImageAssetType();
for (const auto& assetEntry : zoneDefinition.m_assets)
{ {
const auto currentTarget = std::move(targetsToBuild.front()); if (assetEntry.m_is_reference)
targetsToBuild.pop_front(); continue;
alreadyBuiltTargets.emplace(currentTarget);
PathProjectContext projectContext(paths, projectName); if (assetEntry.m_asset_type == imageAssetType)
ipakWriter->AddImage(assetEntry.m_asset_name);
}
const auto zoneDefinition = ReadZoneDefinition(paths, targetName); if (!ipakWriter->Write())
if (!zoneDefinition) {
return false; std::cerr << "Writing ipak failed.\n";
stream.close();
return false;
}
PathGameContext gameContext(paths, projectName, zoneDefinition->m_game); std::cout << std::format("Created ipak \"{}\"\n", ipakFilePath.string());
if (!zoneDefinition->m_assets.empty()) stream.close();
return true;
}
bool BuildReferencedTargets(const std::string& projectName, const std::string& targetName, const ZoneDefinition& zoneDefinition)
{
return std::ranges::all_of(zoneDefinition.m_targets_to_build,
[this, &projectName, &targetName](const std::string& buildTargetName)
{
if (buildTargetName == targetName)
{
std::cerr << std::format("Cannot build target with same name: \"{}\"\n", targetName);
return false;
}
std::cout << std::format("Building referenced target \"{}\"\n", buildTargetName);
return BuildProject(projectName, buildTargetName);
});
}
bool BuildProject(const std::string& projectName, const std::string& targetName)
{
auto sourceSearchPaths = m_search_paths.GetSourceSearchPathsForProject(projectName);
const auto zoneDefinition = ReadZoneDefinition(targetName, &sourceSearchPaths);
if (!zoneDefinition)
return false;
auto result = true;
if (zoneDefinition->m_type != ProjectType::NONE)
{
const auto& gameName = GameId_Names[static_cast<unsigned>(zoneDefinition->m_game)];
auto assetSearchPaths = m_search_paths.GetAssetSearchPathsForProject(gameName, projectName);
auto gdtSearchPaths = m_search_paths.GetGdtSearchPathsForProject(gameName, projectName);
switch (zoneDefinition->m_type)
{ {
if (!BuildFastFile(paths, projectName, targetName, *zoneDefinition)) case ProjectType::FASTFILE:
return false; result = BuildFastFile(projectName, targetName, *zoneDefinition, assetSearchPaths, gdtSearchPaths, sourceSearchPaths);
break;
for (const auto& referencedTarget : zoneDefinition->m_targets_to_build) case ProjectType::IPAK:
{ result = BuildIPak(projectName, *zoneDefinition, assetSearchPaths);
if (alreadyBuiltTargets.find(referencedTarget) == alreadyBuiltTargets.end()) break;
{
targetsToBuild.emplace_back(referencedTarget); default:
std::cout << std::format("Building referenced target \"{}\"\n", referencedTarget); assert(false);
} result = false;
} break;
} }
} }
return true; m_search_paths.UnloadProjectSpecificSearchPaths();
result = result && BuildReferencedTargets(projectName, targetName, *zoneDefinition);
return result;
} }
bool LoadZones() bool LoadZones()
@ -363,8 +384,8 @@ class LinkerImpl final : public Linker
zoneDirectory = fs::current_path(); zoneDirectory = fs::current_path();
auto absoluteZoneDirectory = absolute(zoneDirectory).string(); auto absoluteZoneDirectory = absolute(zoneDirectory).string();
auto zone = ZoneLoading::LoadZone(zonePath); auto zone = std::unique_ptr<Zone>(ZoneLoading::LoadZone(zonePath));
if (!zone) if (zone == nullptr)
{ {
std::cerr << std::format("Failed to load zone \"{}\".\n", zonePath); std::cerr << std::format("Failed to load zone \"{}\".\n", zonePath);
return false; return false;
@ -431,6 +452,11 @@ class LinkerImpl final : public Linker
} }
public: public:
LinkerImpl()
: m_search_paths(m_args)
{
}
bool Start(const int argc, const char** argv) override bool Start(const int argc, const char** argv) override
{ {
auto shouldContinue = true; auto shouldContinue = true;
@ -440,7 +466,8 @@ public:
if (!shouldContinue) if (!shouldContinue)
return true; return true;
LinkerPathManager paths(m_args); if (!m_search_paths.BuildProjectIndependentSearchPaths())
return false;
if (!LoadZones()) if (!LoadZones())
return false; return false;
@ -456,7 +483,7 @@ public:
break; break;
} }
if (!BuildProject(paths, projectName, targetName)) if (!BuildProject(projectName, targetName))
{ {
result = false; result = false;
break; break;
@ -467,10 +494,6 @@ public:
return result; return result;
} }
private:
LinkerArgs m_args;
std::vector<std::unique_ptr<Zone>> m_loaded_zones;
}; };
std::unique_ptr<Linker> Linker::Create() std::unique_ptr<Linker> Linker::Create()

View File

@ -5,11 +5,11 @@
#include "ObjWriting.h" #include "ObjWriting.h"
#include "Utils/Arguments/UsageInformation.h" #include "Utils/Arguments/UsageInformation.h"
#include "Utils/FileUtils.h" #include "Utils/FileUtils.h"
#include "Utils/PathUtils.h"
#include <filesystem> #include <filesystem>
#include <format> #include <format>
#include <iostream> #include <iostream>
#include <regex>
#include <type_traits> #include <type_traits>
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -46,7 +46,7 @@ const CommandLineOption* const OPTION_BASE_FOLDER =
const CommandLineOption* const OPTION_OUTPUT_FOLDER = const CommandLineOption* const OPTION_OUTPUT_FOLDER =
CommandLineOption::Builder::Create() CommandLineOption::Builder::Create()
.WithLongName("output-folder") .WithLongName("output-folder")
.WithDescription(std::format("Specifies the output folder containing the build artifacts. Defaults to \"{}\".", LinkerArgs::DEFAULT_OUTPUT_FOLDER)) .WithDescription("Specifies the output folder containing the build artifacts. Defaults to \"" + std::string(LinkerArgs::DEFAULT_OUTPUT_FOLDER) + "\".")
.WithParameter("outputFolderPath") .WithParameter("outputFolderPath")
.Build(); .Build();
@ -61,14 +61,14 @@ const CommandLineOption* const OPTION_ADD_ASSET_SEARCH_PATH =
const CommandLineOption* const OPTION_ASSET_SEARCH_PATH = const CommandLineOption* const OPTION_ASSET_SEARCH_PATH =
CommandLineOption::Builder::Create() CommandLineOption::Builder::Create()
.WithLongName("asset-search-path") .WithLongName("asset-search-path")
.WithDescription(std::format("Specifies the search paths used for assets. Defaults to \"{}\".", LinkerArgs::DEFAULT_ASSET_SEARCH_PATH)) .WithDescription("Specifies the search paths used for assets. Defaults to \"" + std::string(LinkerArgs::DEFAULT_ASSET_SEARCH_PATH) + "\".")
.WithParameter("assetSearchPathString") .WithParameter("assetSearchPathString")
.Build(); .Build();
const CommandLineOption* const OPTION_GDT_SEARCH_PATH = const CommandLineOption* const OPTION_GDT_SEARCH_PATH =
CommandLineOption::Builder::Create() CommandLineOption::Builder::Create()
.WithLongName("gdt-search-path") .WithLongName("gdt-search-path")
.WithDescription(std::format("Specifies the search paths used for gdt files. Defaults to \"{}\".", LinkerArgs::DEFAULT_GDT_SEARCH_PATH)) .WithDescription("Specifies the search paths used for gdt files. Defaults to \"" + std::string(LinkerArgs::DEFAULT_GDT_SEARCH_PATH) + "\".")
.WithParameter("gdtSearchPathString") .WithParameter("gdtSearchPathString")
.Build(); .Build();
@ -83,7 +83,7 @@ const CommandLineOption* const OPTION_ADD_SOURCE_SEARCH_PATH =
const CommandLineOption* const OPTION_SOURCE_SEARCH_PATH = const CommandLineOption* const OPTION_SOURCE_SEARCH_PATH =
CommandLineOption::Builder::Create() CommandLineOption::Builder::Create()
.WithLongName("source-search-path") .WithLongName("source-search-path")
.WithDescription(std::format("Specifies the search paths used for source files. Defaults to \"{}\".", LinkerArgs::DEFAULT_SOURCE_SEARCH_PATH)) .WithDescription("Specifies the search paths used for source files. Defaults to \"" + std::string(LinkerArgs::DEFAULT_SOURCE_SEARCH_PATH) + "\".")
.WithParameter("sourceSearchPathString") .WithParameter("sourceSearchPathString")
.Build(); .Build();
@ -129,7 +129,13 @@ const CommandLineOption* const COMMAND_LINE_OPTIONS[]{
LinkerArgs::LinkerArgs() LinkerArgs::LinkerArgs()
: m_verbose(false), : m_verbose(false),
m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>) m_base_folder_depends_on_project(false),
m_out_folder_depends_on_project(false),
m_argument_parser(COMMAND_LINE_OPTIONS, std::extent_v<decltype(COMMAND_LINE_OPTIONS)>),
m_bin_pattern(R"(\?bin\?)"),
m_base_pattern(R"(\?base\?)"),
m_game_pattern(R"(\?game\?)"),
m_project_pattern(R"(\?project\?)")
{ {
} }
@ -153,9 +159,9 @@ void LinkerArgs::PrintVersion()
std::cout << std::format("OpenAssetTools Linker {}\n", GIT_VERSION); std::cout << std::format("OpenAssetTools Linker {}\n", GIT_VERSION);
} }
void LinkerArgs::SetBinFolder() void LinkerArgs::SetBinFolder(const char* argv0)
{ {
const fs::path path(utils::GetExecutablePath()); const fs::path path(argv0);
m_bin_folder = path.parent_path().string(); m_bin_folder = path.parent_path().string();
} }
@ -166,6 +172,76 @@ void LinkerArgs::SetVerbose(const bool isVerbose)
ObjWriting::Configuration.Verbose = isVerbose; ObjWriting::Configuration.Verbose = isVerbose;
} }
std::string LinkerArgs::GetBasePathForProject(const std::string& projectName) const
{
return std::regex_replace(m_base_folder, m_project_pattern, projectName);
}
void LinkerArgs::SetDefaultBasePath()
{
const auto currentDir = fs::absolute(fs::current_path());
if (currentDir.filename() == "bin")
{
m_base_folder = currentDir.parent_path().string();
}
else
{
m_base_folder = currentDir.string();
}
}
std::set<std::string> LinkerArgs::GetProjectIndependentSearchPaths(const std::set<std::string>& set) const
{
std::set<std::string> out;
for (const auto& path : set)
{
if (path.find(PATTERN_GAME) != std::string::npos)
continue;
if (path.find(PATTERN_PROJECT) != std::string::npos)
continue;
if (path.find(PATTERN_BASE) != std::string::npos)
{
if (m_base_folder_depends_on_project)
continue;
out.emplace(std::regex_replace(path, m_base_pattern, m_base_folder));
}
else
{
out.emplace(path);
}
}
return out;
}
std::set<std::string> LinkerArgs::GetSearchPathsForProject(const std::set<std::string>& set, const std::string& gameName, const std::string& projectName) const
{
std::set<std::string> out;
const auto basePath = GetBasePathForProject(projectName);
for (const auto& path : set)
{
if (path.find(PATTERN_GAME) == std::string::npos && path.find(PATTERN_PROJECT) == std::string::npos
&& (!m_base_folder_depends_on_project || path.find(PATTERN_BASE) == std::string::npos))
{
continue;
}
fs::path p(std::regex_replace(std::regex_replace(std::regex_replace(std::regex_replace(path, m_project_pattern, projectName), m_game_pattern, gameName),
m_base_pattern,
basePath),
m_bin_pattern,
m_bin_folder));
out.emplace(p.make_preferred().string());
}
return out;
}
bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContinue) bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContinue)
{ {
shouldContinue = true; shouldContinue = true;
@ -191,7 +267,7 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin
return true; return true;
} }
SetBinFolder(); SetBinFolder(argv[0]);
m_project_specifiers_to_build = m_argument_parser.GetArguments(); m_project_specifiers_to_build = m_argument_parser.GetArguments();
if (m_project_specifiers_to_build.empty()) if (m_project_specifiers_to_build.empty())
@ -208,13 +284,15 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin
if (m_argument_parser.IsOptionSpecified(OPTION_BASE_FOLDER)) if (m_argument_parser.IsOptionSpecified(OPTION_BASE_FOLDER))
m_base_folder = m_argument_parser.GetValueForOption(OPTION_BASE_FOLDER); m_base_folder = m_argument_parser.GetValueForOption(OPTION_BASE_FOLDER);
else else
m_base_folder = DEFAULT_BASE_FOLDER; SetDefaultBasePath();
m_base_folder_depends_on_project = m_base_folder.find(PATTERN_GAME) != std::string::npos || m_base_folder.find(PATTERN_PROJECT) != std::string::npos;
// --output-folder // --output-folder
if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER)) if (m_argument_parser.IsOptionSpecified(OPTION_OUTPUT_FOLDER))
m_out_folder = m_argument_parser.GetValueForOption(OPTION_OUTPUT_FOLDER); m_out_folder = m_argument_parser.GetValueForOption(OPTION_OUTPUT_FOLDER);
else else
m_out_folder = DEFAULT_OUTPUT_FOLDER; m_out_folder = DEFAULT_OUTPUT_FOLDER;
m_out_folder_depends_on_project = m_out_folder.find(PATTERN_PROJECT) != std::string::npos;
// --asset-search-path // --asset-search-path
if (m_argument_parser.IsOptionSpecified(OPTION_ASSET_SEARCH_PATH)) if (m_argument_parser.IsOptionSpecified(OPTION_ASSET_SEARCH_PATH))
@ -280,3 +358,38 @@ bool LinkerArgs::ParseArgs(const int argc, const char** argv, bool& shouldContin
return true; return true;
} }
std::string LinkerArgs::GetOutputFolderPathForProject(const std::string& projectName) const
{
return std::regex_replace(std::regex_replace(m_out_folder, m_project_pattern, projectName), m_base_pattern, GetBasePathForProject(projectName));
}
std::set<std::string> LinkerArgs::GetProjectIndependentAssetSearchPaths() const
{
return GetProjectIndependentSearchPaths(m_asset_search_paths);
}
std::set<std::string> LinkerArgs::GetProjectIndependentGdtSearchPaths() const
{
return GetProjectIndependentSearchPaths(m_gdt_search_paths);
}
std::set<std::string> LinkerArgs::GetProjectIndependentSourceSearchPaths() const
{
return GetProjectIndependentSearchPaths(m_source_search_paths);
}
std::set<std::string> LinkerArgs::GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) const
{
return GetSearchPathsForProject(m_asset_search_paths, gameName, projectName);
}
std::set<std::string> LinkerArgs::GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) const
{
return GetSearchPathsForProject(m_gdt_search_paths, gameName, projectName);
}
std::set<std::string> LinkerArgs::GetSourceSearchPathsForProject(const std::string& projectName) const
{
return GetSearchPathsForProject(m_source_search_paths, "", projectName);
}

View File

@ -1,14 +1,22 @@
#pragma once #pragma once
#include "Utils/Arguments/ArgumentParser.h" #include "Utils/Arguments/ArgumentParser.h"
#include "Utils/ClassUtils.h"
#include "Zone/Zone.h"
#include <regex>
#include <set> #include <set>
#include <vector> #include <vector>
class LinkerArgs class LinkerArgs
{ {
public: public:
static constexpr auto PATTERN_BIN = "?bin?";
static constexpr auto PATTERN_BASE = "?base?";
static constexpr auto PATTERN_GAME = "?game?";
static constexpr auto PATTERN_PROJECT = "?project?";
static constexpr auto DEFAULT_BASE_FOLDER = "."; static constexpr auto DEFAULT_BASE_FOLDER = ".";
static constexpr auto DEFAULT_CACHE_FOLDER = "?base?/.oat/cache/?project?"; static constexpr auto DEFAULT_BASE_FOLDER_MOD_TOOLS = "..";
static constexpr auto DEFAULT_OUTPUT_FOLDER = "?base?/zone_out/?project?"; static constexpr auto DEFAULT_OUTPUT_FOLDER = "?base?/zone_out/?project?";
static constexpr auto DEFAULT_ASSET_SEARCH_PATH = "?bin?/raw/?game?;?base?/raw;?base?/raw/?game?;?base?/zone_raw/?project?"; static constexpr auto DEFAULT_ASSET_SEARCH_PATH = "?bin?/raw/?game?;?base?/raw;?base?/raw/?game?;?base?/zone_raw/?project?";
static constexpr auto DEFAULT_GDT_SEARCH_PATH = "?base?/source_data;?base?/zone_raw/?project?/source_data"; static constexpr auto DEFAULT_GDT_SEARCH_PATH = "?base?/source_data;?base?/zone_raw/?project?/source_data";
@ -17,6 +25,21 @@ public:
LinkerArgs(); LinkerArgs();
bool ParseArgs(int argc, const char** argv, bool& shouldContinue); bool ParseArgs(int argc, const char** argv, bool& shouldContinue);
/**
* \brief Converts the output path specified by command line arguments to a path applies for the specified project.
* \param projectName The name of the project to resolve the path input for.
* \return An output path for the project based on the user input.
*/
_NODISCARD std::string GetOutputFolderPathForProject(const std::string& projectName) const;
_NODISCARD std::set<std::string> GetProjectIndependentAssetSearchPaths() const;
_NODISCARD std::set<std::string> GetProjectIndependentGdtSearchPaths() const;
_NODISCARD std::set<std::string> GetProjectIndependentSourceSearchPaths() const;
_NODISCARD std::set<std::string> GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName) const;
_NODISCARD std::set<std::string> GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName) const;
_NODISCARD std::set<std::string> GetSourceSearchPathsForProject(const std::string& projectName) const;
bool m_verbose; bool m_verbose;
std::vector<std::string> m_zones_to_load; std::vector<std::string> m_zones_to_load;
@ -25,6 +48,8 @@ public:
std::string m_bin_folder; std::string m_bin_folder;
std::string m_base_folder; std::string m_base_folder;
std::string m_out_folder; std::string m_out_folder;
bool m_base_folder_depends_on_project;
bool m_out_folder_depends_on_project;
std::set<std::string> m_asset_search_paths; std::set<std::string> m_asset_search_paths;
std::set<std::string> m_gdt_search_paths; std::set<std::string> m_gdt_search_paths;
@ -37,8 +62,19 @@ private:
void PrintUsage() const; void PrintUsage() const;
static void PrintVersion(); static void PrintVersion();
void SetBinFolder(); void SetBinFolder(const char* argv0);
void SetVerbose(bool isVerbose); void SetVerbose(bool isVerbose);
_NODISCARD std::string GetBasePathForProject(const std::string& projectName) const;
void SetDefaultBasePath();
_NODISCARD std::set<std::string> GetProjectIndependentSearchPaths(const std::set<std::string>& set) const;
_NODISCARD std::set<std::string>
GetSearchPathsForProject(const std::set<std::string>& set, const std::string& gameName, const std::string& projectName) const;
ArgumentParser m_argument_parser; ArgumentParser m_argument_parser;
std::regex m_bin_pattern;
std::regex m_base_pattern;
std::regex m_game_pattern;
std::regex m_project_pattern;
}; };

View File

@ -1,342 +0,0 @@
#include "LinkerPaths.h"
#include "SearchPath/IWD.h"
#include "SearchPath/SearchPathFilesystem.h"
#include "SearchPath/SearchPaths.h"
#include "Utils/StringUtils.h"
#include <cassert>
#include <cstdint>
#include <cstring>
#include <filesystem>
#include <format>
#include <iostream>
#include <sstream>
#include <type_traits>
#include <unordered_set>
namespace fs = std::filesystem;
namespace
{
enum class PathTemplateParameterType : std::uint8_t
{
BIN = 1 << 0,
BASE = 1 << 1,
PROJECT = 1 << 2,
GAME = 1 << 3,
};
class LinkerPathTemplate
{
static constexpr auto PATTERN_BIN = "?bin?";
static constexpr auto PATTERN_BASE = "?base?";
static constexpr auto PATTERN_GAME = "?game?";
static constexpr auto PATTERN_PROJECT = "?project?";
struct Pattern
{
const char* m_str;
PathTemplateParameterType m_type;
};
static constexpr Pattern PATTERNS[]{
{PATTERN_BIN, PathTemplateParameterType::BIN },
{PATTERN_BASE, PathTemplateParameterType::BASE },
{PATTERN_GAME, PathTemplateParameterType::GAME },
{PATTERN_PROJECT, PathTemplateParameterType::PROJECT},
};
public:
LinkerPathTemplate()
: m_parameter_type_flags(0u)
{
}
void CreateFromString(const std::string& templateString)
{
const auto templateStringLength = templateString.size();
auto partStart = 0uz;
for (auto i = 0uz; i < templateStringLength; i++)
{
if (templateString[i] != '?')
continue;
for (const auto& pattern : PATTERNS)
{
const auto patternLength = std::strlen(pattern.m_str);
if (templateString.compare(i, patternLength, pattern.m_str) == 0)
{
m_parts.emplace_back(templateString.substr(partStart, i - partStart));
m_parameters.emplace_back(pattern.m_type);
m_parameter_type_flags |= static_cast<std::underlying_type_t<PathTemplateParameterType>>(pattern.m_type);
i += patternLength;
partStart = i;
break;
}
}
}
if (partStart < templateStringLength)
m_parts.emplace_back(templateString.substr(partStart, templateStringLength - partStart));
}
[[nodiscard]] std::string
Render(const std::string& binDir, const std::string& baseDir, const std::string& projectName, const std::string& gameName) const
{
if (m_parts.empty())
return "";
if (m_parameters.empty())
return m_parts[0];
std::ostringstream ss;
ss << m_parts[0];
const auto partsCount = m_parts.size();
const auto parameterCount = m_parameters.size();
for (auto parameterIndex = 0u; parameterIndex < parameterCount; parameterIndex++)
{
switch (m_parameters[parameterIndex])
{
case PathTemplateParameterType::BIN:
ss << binDir;
break;
case PathTemplateParameterType::BASE:
ss << baseDir;
break;
case PathTemplateParameterType::PROJECT:
ss << projectName;
break;
case PathTemplateParameterType::GAME:
ss << gameName;
break;
default:
assert(false);
break;
}
if (parameterIndex + 1 < partsCount)
ss << m_parts[parameterIndex + 1];
}
return fs::path(ss.str()).make_preferred().string();
}
[[nodiscard]] bool CanRender(const std::underlying_type_t<PathTemplateParameterType> availableParameters) const
{
return (m_parameter_type_flags & ~availableParameters) == 0;
}
private:
std::vector<std::string> m_parts;
std::vector<PathTemplateParameterType> m_parameters;
std::underlying_type_t<PathTemplateParameterType> m_parameter_type_flags;
};
class LinkerSearchPathBuilder final : public ILinkerSearchPathBuilder
{
static constexpr auto INDEPENDENT_MASK = static_cast<unsigned>(PathTemplateParameterType::BIN) | static_cast<unsigned>(PathTemplateParameterType::BASE);
static constexpr auto PROJECT_MASK = static_cast<unsigned>(PathTemplateParameterType::BIN) | static_cast<unsigned>(PathTemplateParameterType::BASE)
| static_cast<unsigned>(PathTemplateParameterType::PROJECT);
static constexpr auto GAME_MASK = static_cast<unsigned>(PathTemplateParameterType::BIN) | static_cast<unsigned>(PathTemplateParameterType::BASE)
| static_cast<unsigned>(PathTemplateParameterType::PROJECT) | static_cast<unsigned>(PathTemplateParameterType::GAME);
public:
LinkerSearchPathBuilder(const char* typeName, std::string binDir, std::string baseDir)
: m_type_name(typeName),
m_bin_dir(std::move(binDir)),
m_base_dir(std::move(baseDir))
{
}
void BuildFromArgs(const std::set<std::string>& templates)
{
m_templates.reserve(templates.size());
for (const auto& templateString : templates)
{
LinkerPathTemplate templateStruct;
templateStruct.CreateFromString(templateString);
m_templates.emplace_back(std::move(templateStruct));
}
}
[[nodiscard]] std::unique_ptr<ISearchPath> BuildIndependentSearchPaths() const override
{
SearchPaths searchPaths;
std::unordered_set<std::string> addedSearchPaths;
auto hasSearchPath = false;
for (const auto& curTemplate : m_templates)
{
if (curTemplate.CanRender(INDEPENDENT_MASK))
{
auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, std::string(), std::string());
if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate))
hasSearchPath = true;
}
}
if (hasSearchPath)
return std::make_unique<SearchPaths>(std::move(searchPaths));
return {};
}
[[nodiscard]] std::unique_ptr<ISearchPath> BuildSearchPathsSpecificToProject(const std::string& projectName) const override
{
SearchPaths searchPaths;
std::unordered_set<std::string> addedSearchPaths;
auto hasSearchPath = false;
for (const auto& curTemplate : m_templates)
{
if (!curTemplate.CanRender(INDEPENDENT_MASK) && curTemplate.CanRender(PROJECT_MASK))
{
auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, projectName, std::string());
if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate))
hasSearchPath = true;
}
}
if (hasSearchPath)
return std::make_unique<SearchPaths>(std::move(searchPaths));
return {};
}
[[nodiscard]] std::unique_ptr<ISearchPath> BuildSearchPathsSpecificToProjectAndGame(const std::string& projectName, GameId game) const override
{
SearchPaths searchPaths;
std::unordered_set<std::string> addedSearchPaths;
auto hasSearchPath = false;
for (const auto& curTemplate : m_templates)
{
if (!curTemplate.CanRender(PROJECT_MASK) && curTemplate.CanRender(GAME_MASK))
{
std::string gameName(GameId_Names[static_cast<unsigned>(game)]);
utils::MakeStringLowerCase(gameName);
auto renderedTemplate = curTemplate.Render(m_bin_dir, m_base_dir, projectName, gameName);
if (AddSearchPath(addedSearchPaths, searchPaths, renderedTemplate))
hasSearchPath = true;
}
}
if (hasSearchPath)
return std::make_unique<SearchPaths>(std::move(searchPaths));
return {};
}
private:
bool AddSearchPath(std::unordered_set<std::string>& existingSearchPaths, SearchPaths& searchPaths, const std::string& path) const
{
const auto existingSearchPath = existingSearchPaths.find(path);
if (existingSearchPath != existingSearchPaths.end())
return false;
existingSearchPaths.emplace(path);
if (!fs::is_directory(path))
{
std::cout << std::format("Adding {} search path (Not found): {}\n", m_type_name, path);
return false;
}
std::cout << std::format("Adding {} search path: {}\n", m_type_name, path);
searchPaths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(path));
return true;
}
const char* m_type_name;
std::vector<LinkerPathTemplate> m_templates;
std::string m_bin_dir;
std::string m_base_dir;
};
class LinkerPaths final : public ILinkerPaths
{
public:
LinkerPaths(std::string binDir,
std::string baseDir,
LinkerSearchPathBuilder assetSearchPaths,
LinkerSearchPathBuilder gdtSearchPaths,
LinkerSearchPathBuilder sourceSearchPaths,
LinkerPathTemplate cacheTemplate,
LinkerPathTemplate outTemplate)
: m_bin_dir(std::move(binDir)),
m_base_dir(std::move(baseDir)),
m_asset_search_paths(std::move(assetSearchPaths)),
m_gdt_search_paths(std::move(gdtSearchPaths)),
m_source_search_paths(std::move(sourceSearchPaths)),
m_cache_template(std::move(cacheTemplate)),
m_out_template(std::move(outTemplate))
{
}
[[nodiscard]] const ILinkerSearchPathBuilder& AssetSearchPaths() const override
{
return m_asset_search_paths;
}
[[nodiscard]] const ILinkerSearchPathBuilder& GdtSearchPaths() const override
{
return m_gdt_search_paths;
}
[[nodiscard]] const ILinkerSearchPathBuilder& SourceSearchPaths() const override
{
return m_source_search_paths;
}
[[nodiscard]] std::string BuildCacheFolderPath(const std::string& projectName, GameId game) const override
{
return m_cache_template.Render(m_bin_dir, m_base_dir, projectName, GameId_Names[static_cast<unsigned>(game)]);
}
[[nodiscard]] std::string BuildOutputFolderPath(const std::string& projectName, GameId game) const override
{
return m_out_template.Render(m_bin_dir, m_base_dir, projectName, GameId_Names[static_cast<unsigned>(game)]);
}
private:
std::string m_bin_dir;
std::string m_base_dir;
LinkerSearchPathBuilder m_asset_search_paths;
LinkerSearchPathBuilder m_gdt_search_paths;
LinkerSearchPathBuilder m_source_search_paths;
LinkerPathTemplate m_cache_template;
LinkerPathTemplate m_out_template;
};
} // namespace
std::unique_ptr<ILinkerPaths> ILinkerPaths::FromArgs(const LinkerArgs& args)
{
std::string normalizedBinPath = fs::weakly_canonical(args.m_bin_folder).make_preferred().string();
std::string normalizedBasePath = fs::weakly_canonical(args.m_base_folder).make_preferred().string();
LinkerSearchPathBuilder assetSearchPaths("asset", normalizedBinPath, normalizedBasePath);
assetSearchPaths.BuildFromArgs(args.m_asset_search_paths);
LinkerSearchPathBuilder gdtSearchPaths("gdt", normalizedBinPath, normalizedBasePath);
gdtSearchPaths.BuildFromArgs(args.m_gdt_search_paths);
LinkerSearchPathBuilder sourceSearchPaths("source", normalizedBinPath, normalizedBasePath);
sourceSearchPaths.BuildFromArgs(args.m_source_search_paths);
LinkerPathTemplate cacheTemplate;
cacheTemplate.CreateFromString(LinkerArgs::DEFAULT_CACHE_FOLDER);
LinkerPathTemplate outTemplate;
outTemplate.CreateFromString(args.m_out_folder);
return std::make_unique<LinkerPaths>(std::move(normalizedBinPath),
std::move(normalizedBasePath),
std::move(assetSearchPaths),
std::move(gdtSearchPaths),
std::move(sourceSearchPaths),
std::move(cacheTemplate),
std::move(outTemplate));
}

View File

@ -1,74 +0,0 @@
#pragma once
#include "Game/IGame.h"
#include "LinkerArgs.h"
#include "SearchPath/ISearchPath.h"
#include <memory>
class ILinkerSearchPathBuilder
{
public:
ILinkerSearchPathBuilder() = default;
virtual ~ILinkerSearchPathBuilder() = default;
ILinkerSearchPathBuilder(const ILinkerSearchPathBuilder& other) = default;
ILinkerSearchPathBuilder(ILinkerSearchPathBuilder&& other) noexcept = default;
ILinkerSearchPathBuilder& operator=(const ILinkerSearchPathBuilder& other) = default;
ILinkerSearchPathBuilder& operator=(ILinkerSearchPathBuilder&& other) noexcept = default;
[[nodiscard]] virtual std::unique_ptr<ISearchPath> BuildIndependentSearchPaths() const = 0;
[[nodiscard]] virtual std::unique_ptr<ISearchPath> BuildSearchPathsSpecificToProject(const std::string& projectName) const = 0;
[[nodiscard]] virtual std::unique_ptr<ISearchPath> BuildSearchPathsSpecificToProjectAndGame(const std::string& projectName, GameId game) const = 0;
};
class ILinkerPaths
{
public:
ILinkerPaths() = default;
virtual ~ILinkerPaths() = default;
ILinkerPaths(const ILinkerPaths& other) = default;
ILinkerPaths(ILinkerPaths&& other) noexcept = default;
ILinkerPaths& operator=(const ILinkerPaths& other) = default;
ILinkerPaths& operator=(ILinkerPaths&& other) noexcept = default;
/**
* \brief Creates linker search paths based on templates from user specified args.
* \param args The user specified args.
* \return Linker search paths based on user specified templates.
*/
static std::unique_ptr<ILinkerPaths> FromArgs(const LinkerArgs& args);
/**
* \brief Grants access to the builder for asset search paths.
* \return A builder instance for building asset search paths.
*/
[[nodiscard]] virtual const ILinkerSearchPathBuilder& AssetSearchPaths() const = 0;
/**
* \brief Grants access to the builder for gdt search paths.
* \return A builder instance for building gdt search paths.
*/
[[nodiscard]] virtual const ILinkerSearchPathBuilder& GdtSearchPaths() const = 0;
/**
* \brief Grants access to the builder for source search paths.
* \return A builder instance for building source search paths.
*/
[[nodiscard]] virtual const ILinkerSearchPathBuilder& SourceSearchPaths() const = 0;
/**
* \brief Builds the cache path based on the specified information.
* \param projectName The name of the project to resolve the path input for.
* \param game The game to resolve the path input for.
* \return A cache path based on the input and preconfigured template.
*/
[[nodiscard]] virtual std::string BuildCacheFolderPath(const std::string& projectName, GameId game) const = 0;
/**
* \brief Builds the output path based on the specified information.
* \param projectName The name of the project to resolve the path input for.
* \param game The game to resolve the path input for.
* \return An output path based on the input and preconfigured template.
*/
[[nodiscard]] virtual std::string BuildOutputFolderPath(const std::string& projectName, GameId game) const = 0;
};

View File

@ -0,0 +1,190 @@
#include "LinkerSearchPaths.h"
#include "ObjContainer/IWD/IWD.h"
#include "ObjLoading.h"
#include "SearchPath/SearchPathFilesystem.h"
#include <filesystem>
#include <format>
#include <iostream>
namespace fs = std::filesystem;
LinkerSearchPaths::LinkerSearchPaths(const LinkerArgs& args)
: m_args(args)
{
}
void LinkerSearchPaths::LoadSearchPath(ISearchPath& searchPath) const
{
if (m_args.m_verbose)
{
std::cout << std::format("Loading search path: \"{}\"\n", searchPath.GetPath());
}
ObjLoading::LoadIWDsInSearchPath(searchPath);
}
void LinkerSearchPaths::UnloadSearchPath(ISearchPath& searchPath) const
{
if (m_args.m_verbose)
{
std::cout << std::format("Unloading search path: \"{}\"\n", searchPath.GetPath());
}
ObjLoading::UnloadIWDsInSearchPath(searchPath);
}
SearchPaths LinkerSearchPaths::GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName)
{
SearchPaths searchPathsForProject;
for (const auto& searchPathStr : m_args.GetAssetSearchPathsForProject(gameName, projectName))
{
auto absolutePath = fs::absolute(searchPathStr);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding asset search path: {}\n", absolutePath.string());
auto searchPath = std::make_unique<SearchPathFilesystem>(searchPathStr);
LoadSearchPath(*searchPath);
searchPathsForProject.IncludeSearchPath(searchPath.get());
m_loaded_project_search_paths.emplace_back(std::move(searchPath));
}
searchPathsForProject.IncludeSearchPath(&m_asset_search_paths);
for (auto* iwd : IWD::Repository)
{
searchPathsForProject.IncludeSearchPath(iwd);
}
return searchPathsForProject;
}
SearchPaths LinkerSearchPaths::GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName)
{
SearchPaths searchPathsForProject;
for (const auto& searchPathStr : m_args.GetGdtSearchPathsForProject(gameName, projectName))
{
auto absolutePath = fs::absolute(searchPathStr);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Adding gdt search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string());
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
}
searchPathsForProject.IncludeSearchPath(&m_gdt_search_paths);
return searchPathsForProject;
}
SearchPaths LinkerSearchPaths::GetSourceSearchPathsForProject(const std::string& projectName)
{
SearchPaths searchPathsForProject;
for (const auto& searchPathStr : m_args.GetSourceSearchPathsForProject(projectName))
{
auto absolutePath = fs::absolute(searchPathStr);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Adding source search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding source search path: {}\n", absolutePath.string());
searchPathsForProject.CommitSearchPath(std::make_unique<SearchPathFilesystem>(searchPathStr));
}
searchPathsForProject.IncludeSearchPath(&m_source_search_paths);
return searchPathsForProject;
}
bool LinkerSearchPaths::BuildProjectIndependentSearchPaths()
{
for (const auto& path : m_args.GetProjectIndependentAssetSearchPaths())
{
auto absolutePath = fs::absolute(path);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Adding asset search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding asset search path: {}\n", absolutePath.string());
auto searchPath = std::make_unique<SearchPathFilesystem>(absolutePath.string());
LoadSearchPath(*searchPath);
m_asset_search_paths.CommitSearchPath(std::move(searchPath));
}
for (const auto& path : m_args.GetProjectIndependentGdtSearchPaths())
{
auto absolutePath = fs::absolute(path);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Loading gdt search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding gdt search path: {}\n", absolutePath.string());
m_gdt_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
}
for (const auto& path : m_args.GetProjectIndependentSourceSearchPaths())
{
auto absolutePath = fs::absolute(path);
if (!fs::is_directory(absolutePath))
{
if (m_args.m_verbose)
std::cout << std::format("Loading source search path (Not found): {}\n", absolutePath.string());
continue;
}
if (m_args.m_verbose)
std::cout << std::format("Adding source search path: {}\n", absolutePath.string());
m_source_search_paths.CommitSearchPath(std::make_unique<SearchPathFilesystem>(absolutePath.string()));
}
return true;
}
void LinkerSearchPaths::UnloadProjectSpecificSearchPaths()
{
for (const auto& loadedSearchPath : m_loaded_project_search_paths)
{
UnloadSearchPath(*loadedSearchPath);
}
m_loaded_project_search_paths.clear();
}

View File

@ -0,0 +1,45 @@
#pragma once
#include "LinkerArgs.h"
#include "SearchPath/SearchPaths.h"
#include <memory>
#include <vector>
class LinkerSearchPaths
{
public:
explicit LinkerSearchPaths(const LinkerArgs& args);
/**
* \brief Loads a search path.
* \param searchPath The search path to load.
*/
void LoadSearchPath(ISearchPath& searchPath) const;
/**
* \brief Unloads a search path.
* \param searchPath The search path to unload.
*/
void UnloadSearchPath(ISearchPath& searchPath) const;
SearchPaths GetAssetSearchPathsForProject(const std::string& gameName, const std::string& projectName);
SearchPaths GetGdtSearchPathsForProject(const std::string& gameName, const std::string& projectName);
SearchPaths GetSourceSearchPathsForProject(const std::string& projectName);
/**
* \brief Initializes the Linker object's search paths based on the user's input.
* \return \c true if building the search paths was successful, otherwise \c false.
*/
bool BuildProjectIndependentSearchPaths();
void UnloadProjectSpecificSearchPaths();
private:
const LinkerArgs& m_args;
std::vector<std::unique_ptr<ISearchPath>> m_loaded_project_search_paths;
SearchPaths m_asset_search_paths;
SearchPaths m_gdt_search_paths;
SearchPaths m_source_search_paths;
};

View File

@ -1,17 +1,13 @@
#include "ZoneCreationContext.h" #include "ZoneCreationContext.h"
namespace fs = std::filesystem;
ZoneCreationContext::ZoneCreationContext() ZoneCreationContext::ZoneCreationContext()
: m_definition(nullptr), : m_definition(nullptr),
m_asset_search_path(nullptr) m_asset_search_path(nullptr)
{ {
} }
ZoneCreationContext::ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath, fs::path outDir, fs::path cacheDir) ZoneCreationContext::ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath)
: m_definition(definition), : m_definition(definition),
m_asset_search_path(assetSearchPath), m_asset_search_path(assetSearchPath)
m_out_dir(std::move(outDir)),
m_cache_dir(std::move(cacheDir))
{ {
} }

View File

@ -4,7 +4,6 @@
#include "Zone/AssetList/AssetList.h" #include "Zone/AssetList/AssetList.h"
#include "Zone/Definition/ZoneDefinition.h" #include "Zone/Definition/ZoneDefinition.h"
#include <filesystem>
#include <memory> #include <memory>
#include <vector> #include <vector>
@ -13,11 +12,9 @@ class ZoneCreationContext
public: public:
ZoneDefinition* m_definition; ZoneDefinition* m_definition;
ISearchPath* m_asset_search_path; ISearchPath* m_asset_search_path;
std::filesystem::path m_out_dir;
std::filesystem::path m_cache_dir;
std::vector<std::unique_ptr<Gdt>> m_gdt_files; std::vector<std::unique_ptr<Gdt>> m_gdt_files;
AssetList m_ignored_assets; AssetList m_ignored_assets;
ZoneCreationContext(); ZoneCreationContext();
ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath, std::filesystem::path outDir, std::filesystem::path cacheDir); ZoneCreationContext(ZoneDefinition* definition, ISearchPath* assetSearchPath);
}; };

View File

@ -1,91 +1,27 @@
#include "ZoneCreator.h" #include "ZoneCreator.h"
#include "Gdt/GdtLookup.h" #include "AssetLoading/AssetLoadingContext.h"
#include "IObjCompiler.h" #include "Game/IW3/ZoneCreatorIW3.h"
#include "IObjLoader.h" #include "Game/IW4/ZoneCreatorIW4.h"
#include "SearchPath/OutputPathFilesystem.h" #include "Game/IW5/ZoneCreatorIW5.h"
#include "Game/T5/ZoneCreatorT5.h"
#include "Game/T6/ZoneCreatorT6.h"
#include <cassert> #include <cassert>
namespace const IZoneCreator* IZoneCreator::GetCreatorForGame(GameId game)
{ {
std::unique_ptr<Zone> CreateZone(const ZoneCreationContext& context, const GameId gameId) static const IZoneCreator* zoneCreators[static_cast<unsigned>(GameId::COUNT)]{
{ new IW3::ZoneCreator(),
return std::make_unique<Zone>(context.m_definition->m_name, 0, IGame::GetGameById(gameId)); new IW4::ZoneCreator(),
} new IW5::ZoneCreator(),
new T5::ZoneCreator(),
new T6::ZoneCreator(),
};
std::vector<Gdt*> CreateGdtList(const ZoneCreationContext& context) assert(static_cast<unsigned>(game) < static_cast<unsigned>(GameId::COUNT));
{ const auto* result = zoneCreators[static_cast<unsigned>(game)];
std::vector<Gdt*> gdtList; assert(result);
gdtList.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
gdtList.push_back(gdt.get());
return gdtList; return result;
} }
void IgnoreReferencesFromAssets(ZoneCreationContext& context)
{
for (const auto& assetEntry : context.m_definition->m_assets)
{
if (!assetEntry.m_is_reference)
continue;
context.m_ignored_assets.m_entries.emplace_back(assetEntry.m_asset_type, assetEntry.m_asset_name, assetEntry.m_is_reference);
}
}
} // namespace
namespace zone_creator
{
void InitLookup(const ZoneCreationContext& context, GdtLookup& lookup)
{
std::vector<const Gdt*> gdtFiles;
gdtFiles.reserve(context.m_gdt_files.size());
for (const auto& gdt : context.m_gdt_files)
{
gdtFiles.emplace_back(gdt.get());
}
lookup.Initialize(gdtFiles);
}
std::unique_ptr<Zone> CreateZoneForDefinition(GameId gameId, ZoneCreationContext& context)
{
auto zone = CreateZone(context, gameId);
IgnoreReferencesFromAssets(context);
IgnoredAssetLookup ignoredAssetLookup(context.m_ignored_assets);
GdtLookup lookup;
InitLookup(context, lookup);
const auto* objCompiler = IObjCompiler::GetObjCompilerForGame(gameId);
const auto* objLoader = IObjLoader::GetObjLoaderForGame(gameId);
AssetCreatorCollection creatorCollection(*zone);
ZoneDefinitionContext zoneDefinitionContext(*context.m_definition);
AssetCreationContext creationContext(*zone, &creatorCollection, &ignoredAssetLookup);
OutputPathFilesystem outDir(context.m_out_dir);
OutputPathFilesystem cacheDir(context.m_cache_dir);
objCompiler->ConfigureCreatorCollection(
creatorCollection, *zone, zoneDefinitionContext, *context.m_asset_search_path, lookup, creationContext, outDir, cacheDir);
objLoader->ConfigureCreatorCollection(creatorCollection, *zone, *context.m_asset_search_path, lookup);
for (const auto& assetEntry : context.m_definition->m_assets)
{
const auto* createdAsset = creationContext.LoadDependencyGeneric(assetEntry.m_asset_type, assetEntry.m_asset_name);
if (!createdAsset)
return nullptr;
++zoneDefinitionContext.m_asset_index_in_definition;
}
creatorCollection.FinalizeZone(creationContext);
return zone;
}
} // namespace zone_creator

View File

@ -3,7 +3,19 @@
#include "Zone/Zone.h" #include "Zone/Zone.h"
#include "ZoneCreationContext.h" #include "ZoneCreationContext.h"
namespace zone_creator class IZoneCreator
{ {
[[nodiscard]] std::unique_ptr<Zone> CreateZoneForDefinition(GameId game, ZoneCreationContext& context); public:
} IZoneCreator() = default;
virtual ~IZoneCreator() = default;
IZoneCreator(const IZoneCreator& other) = default;
IZoneCreator(IZoneCreator&& other) noexcept = default;
IZoneCreator& operator=(const IZoneCreator& other) = default;
IZoneCreator& operator=(IZoneCreator&& other) noexcept = default;
[[nodiscard]] virtual GameId GetGameId() const = 0;
[[nodiscard]] virtual std::unique_ptr<Zone> CreateZoneForDefinition(ZoneCreationContext& context) const = 0;
[[nodiscard]] virtual asset_type_t GetImageAssetType() const = 0;
static const IZoneCreator* GetCreatorForGame(GameId game);
};

View File

@ -5,7 +5,6 @@ function ObjCommon:include(includes)
Common:include(includes) Common:include(includes)
json:include(includes) json:include(includes)
minizip:include(includes) minizip:include(includes)
Parser:include(includes)
includedirs { includedirs {
path.join(ProjectFolder(), "ObjCommon") path.join(ProjectFolder(), "ObjCommon")
} }
@ -17,7 +16,6 @@ function ObjCommon:link(links)
links:linkto(Utils) links:linkto(Utils)
links:linkto(Common) links:linkto(Common)
links:linkto(minizip) links:linkto(minizip)
links:linkto(Parser)
end end
function ObjCommon:use() function ObjCommon:use()

View File

@ -21,7 +21,7 @@ bool CsvHeaderRow::RequireIndexForHeader(const std::string& headerName, unsigned
if (existingHeader == m_header_row.end()) if (existingHeader == m_header_row.end())
return false; return false;
out = static_cast<unsigned>(std::distance(m_header_row.begin(), existingHeader)); out = std::distance(m_header_row.begin(), existingHeader);
return true; return true;
} }

View File

@ -13,7 +13,7 @@ public:
bool Read(const CsvInputStream& inputStream); bool Read(const CsvInputStream& inputStream);
[[nodiscard]] const std::string& HeaderNameForColumn(unsigned columnIndex) const; const std::string& HeaderNameForColumn(unsigned columnIndex) const;
bool RequireIndexForHeader(const std::string& headerName, unsigned& out) const; bool RequireIndexForHeader(const std::string& headerName, unsigned& out) const;
[[nodiscard]] std::optional<unsigned> GetIndexForHeader(const std::string& headerName) const; [[nodiscard]] std::optional<unsigned> GetIndexForHeader(const std::string& headerName) const;

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#include "Game/IW4/IW4.h" #include "Game/IW4/IW4.h"
namespace IW4 namespace IW4

View File

@ -36,11 +36,31 @@ namespace T6
"crosshair", "crosshair",
}; };
inline const char* penetrateTypeNames[]{ inline const char* szWeapInventoryTypeNames[]{
"none", "primary",
"small", "offhand",
"medium", "item",
"large", "altmode",
"melee",
"dwlefthand",
};
inline const char* szWeapClipTypeNames[]{
"bottom",
"top",
"left",
"dp28",
"ptrs",
"lmg",
};
inline const char* barrelTypeNames[]{
"Single",
"Dual Barrel",
"Dual Barrel Alternate",
"Quad Barrel",
"Quad Barrel Alternate",
"Quad Barrel Double Alternate",
}; };
inline const char* impactTypeNames[]{ inline const char* impactTypeNames[]{
@ -145,37 +165,6 @@ namespace T6
"Turret Scope", "Turret Scope",
}; };
inline const char* szWeapInventoryTypeNames[]{
"primary",
"offhand",
"item",
"altmode",
"melee",
"dwlefthand",
};
inline const char* szWeapFireTypeNames[]{
"Full Auto",
"Single Shot",
"2-Round Burst",
"3-Round Burst",
"4-Round Burst",
"5-Round Burst",
"Stacked Fire",
"Minigun",
"Charge Shot",
"Jetgun",
};
inline const char* szWeapClipTypeNames[]{
"bottom",
"top",
"left",
"dp28",
"ptrs",
"lmg",
};
inline const char* ammoCounterClipNames[]{ inline const char* ammoCounterClipNames[]{
"None", "None",
"Magazine", "Magazine",
@ -192,13 +181,75 @@ namespace T6
"4:1", "4:1",
}; };
inline const char* barrelTypeNames[]{ inline const char* szAttachmentTypeNames[]{
"Single", "none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
"Dual Barrel", "fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
"Dual Barrel Alternate", "reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
"Quad Barrel", };
"Quad Barrel Alternate",
"Quad Barrel Double Alternate", inline const char* szWeapFireTypeNames[]{
"Full Auto",
"Single Shot",
"2-Round Burst",
"3-Round Burst",
"4-Round Burst",
"5-Round Burst",
"Stacked Fire",
"Minigun",
"Charge Shot",
"Jetgun",
};
inline const char* penetrateTypeNames[]{
"none",
"small",
"medium",
"large",
};
inline const char* s_constraintTypeNames[]{
"none",
"point",
"distance",
"hinge",
"joint",
"actuator",
"fake_shake",
"launch",
"rope",
"light",
};
inline const char* s_vehicleClassNames[]{
"4 wheel",
"motorcycle",
"tank",
"plane",
"boat",
"artillery",
"helicopter",
};
inline const char* s_vehicleCameraModes[]{
"first",
"chase",
"view",
"strafe",
"horse",
"oldtank",
"hover",
"vtol",
};
inline const char* s_tractionTypeNames[]{
"TRACTION_TYPE_FRONT",
"TRACTION_TYPE_BACK",
"TRACTION_TYPE_ALL_WD",
};
inline const char* tracerTypeNames[]{
"Laser",
"Smoke",
}; };
inline const char* bounceSoundSuffixes[]{ inline const char* bounceSoundSuffixes[]{
@ -206,10 +257,4 @@ namespace T6
"_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood", "_gravel", "_ice", "_metal", "_mud", "_paper", "_plaster", "_rock", "_sand", "_snow", "_water", "_wood",
"_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield", "_asphalt", "_ceramic", "_plastic", "_rubber", "_cushion", "_fruit", "_paintedmetal", "_player", "_tallgrass", "_riotshield",
}; };
inline const char* szAttachmentTypeNames[]{
"none", "acog", "dualclip", "dualoptic", "dw", "extbarrel", "extclip", "extramags", "fastads", "fastreload",
"fmj", "gl", "grip", "holo", "ir", "is", "longbreath", "mk", "mms", "rangefinder",
"reflex", "rf", "sf", "silencer", "stackfire", "stalker", "steadyaim", "swayreduc", "tacknife", "vzoom",
};
} // namespace T6 } // namespace T6

View File

@ -81,17 +81,4 @@ namespace T6
{"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT }, {"c4_yaw", offsetof(PhysConstraints, data[3].scale.y), CSPFT_FLOAT },
{"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT }, {"c4_pitch", offsetof(PhysConstraints, data[3].scale.x), CSPFT_FLOAT },
}; };
}
inline const char* s_constraintTypeNames[]{
"none",
"point",
"distance",
"hinge",
"joint",
"actuator",
"fake_shake",
"launch",
"rope",
"light",
};
} // namespace T6

View File

@ -36,9 +36,4 @@ namespace T6
{"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT }, {"colorB4", offsetof(TracerDef, colors[4].b), CSPFT_FLOAT },
{"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT }, {"colorA4", offsetof(TracerDef, colors[4].a), CSPFT_FLOAT },
}; };
}
inline const char* tracerTypeNames[]{
"Laser",
"Smoke",
};
} // namespace T6

View File

@ -561,31 +561,4 @@ namespace T6
{"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL }, {"customBool1", offsetof(VehicleDef, customBool1), CSPFT_BOOL },
{"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL }, {"customBool2", offsetof(VehicleDef, customBool2), CSPFT_BOOL },
}; };
}
inline const char* s_vehicleClassNames[]{
"4 wheel",
"motorcycle",
"tank",
"plane",
"boat",
"artillery",
"helicopter",
};
inline const char* s_vehicleCameraModes[]{
"first",
"chase",
"view",
"strafe",
"horse",
"oldtank",
"hover",
"vtol",
};
inline const char* s_tractionTypeNames[]{
"TRACTION_TYPE_FRONT",
"TRACTION_TYPE_BACK",
"TRACTION_TYPE_ALL_WD",
};
} // namespace T6

View File

@ -81,4 +81,4 @@ namespace T6
{"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL }, {"customBool1", offsetof(WeaponAttachment, customBool1), CSPFT_BOOL },
{"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL }, {"customBool2", offsetof(WeaponAttachment, customBool2), CSPFT_BOOL },
}; };
} // namespace T6 }

Some files were not shown because too many files have changed in this diff Show More