diff --git a/.gitignore b/.gitignore
index d888e49e..7e076e59 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,8 +11,13 @@
*.obj
*.log
*.bak
+
ipch/*
+
.vs/
-local/
bin/
-obj/
\ No newline at end of file
+lib/
+local/
+obj/
+packages/
+TestResults/
\ No newline at end of file
diff --git a/OpenAssetTools.sln b/OpenAssetTools.sln
index 894a926a..8e621d8f 100644
--- a/OpenAssetTools.sln
+++ b/OpenAssetTools.sln
@@ -4,6 +4,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00
VisualStudioVersion = 15.0.28307.852
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Linker", "src\Linker\Linker.vcxproj", "{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}"
+ ProjectSection(ProjectDependencies) = postProject
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D} = {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
+ EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{EB945BC9-2451-4AB5-B434-BD07FAA2D06A}"
EndProject
@@ -14,31 +18,177 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneCommon", "src\ZoneCommon\ZoneCommon.vcxproj", "{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneLoader", "src\ZoneLoader\ZoneLoader.vcxproj", "{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C} = {FC57DC08-3496-4DCF-B52F-6EDC568B333C}
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D} = {757FB12A-B410-4B76-B525-2D11A14DAD9D}
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681} = {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoneWriter", "src\ZoneWriter\ZoneWriter.vcxproj", "{B92A6638-68F9-45D2-AB03-6ED69E349381}"
+ ProjectSection(ProjectDependencies) = postProject
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZoneCodeGenerator", "src\ZoneCodeGenerator\ZoneCodeGenerator.csproj", "{D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{4D65E9A0-1798-4E93-A12F-128FFDC6A690}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZoneCodeGeneratorTests", "test\ZoneCodeGeneratorTests\ZoneCodeGeneratorTests.csproj", "{C29242DB-84D0-4A37-AD3F-19B72B23C7E0}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Crypto", "src\Crypto\Crypto.vcxproj", "{8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}"
+ ProjectSection(ProjectDependencies) = postProject
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01} = {6A26AA97-96CF-4E2E-8883-47F0960F0E01}
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77} = {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7} = {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "src\Utils\Utils.vcxproj", "{757FB12A-B410-4B76-B525-2D11A14DAD9D}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libsquish", "thirdparty\libsquish\libsquish.vcxproj", "{E4E28AD7-6C59-419B-9463-817AF6384AC5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtomcrypt", "thirdparty\libtomcrypt\libtomcrypt.vcxproj", "{CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libtommath", "thirdparty\libtommath\libtommath.vcxproj", "{6A26AA97-96CF-4E2E-8883-47F0960F0E01}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minilzo", "thirdparty\minilzo\minilzo.vcxproj", "{4A4B90B9-1D76-4006-A1D7-D502DDD2C052}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "thirdparty\minizip\minizip.vcxproj", "{46297F21-4D05-4582-85EB-FD07B3243194}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "salsa20", "thirdparty\salsa20\salsa20.vcxproj", "{599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "thirdparty\zlib\zlib.vcxproj", "{FC57DC08-3496-4DCF-B52F-6EDC568B333C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x64.ActiveCfg = Debug|x64
+ {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x64.Build.0 = Debug|x64
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x86.ActiveCfg = Debug|Win32
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Debug|x86.Build.0 = Debug|Win32
- {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.ActiveCfg = Release|Win32
+ {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x64.ActiveCfg = Release|x64
+ {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x64.Build.0 = Release|x64
+ {A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.ActiveCfg = Debug|Win32
{A70826FD-9A3E-498C-B5D6-585C4DA14FEB}.Release|x86.Build.0 = Release|Win32
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x64.ActiveCfg = Debug|x64
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x64.Build.0 = Debug|x64
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x86.ActiveCfg = Debug|Win32
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Debug|x86.Build.0 = Debug|Win32
- {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.ActiveCfg = Release|Win32
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x64.ActiveCfg = Release|x64
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x64.Build.0 = Release|x64
+ {2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.ActiveCfg = Debug|Win32
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7}.Release|x86.Build.0 = Release|Win32
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x64.ActiveCfg = Debug|x64
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x64.Build.0 = Debug|x64
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x86.ActiveCfg = Debug|Win32
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Debug|x86.Build.0 = Debug|Win32
- {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.ActiveCfg = Release|Win32
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x64.ActiveCfg = Release|x64
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x64.Build.0 = Release|x64
+ {C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.ActiveCfg = Debug|Win32
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D}.Release|x86.Build.0 = Release|Win32
+ {B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x64.ActiveCfg = Debug|x64
+ {B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x64.Build.0 = Debug|x64
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x86.ActiveCfg = Debug|Win32
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Debug|x86.Build.0 = Debug|Win32
- {B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.ActiveCfg = Release|Win32
+ {B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x64.ActiveCfg = Release|x64
+ {B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x64.Build.0 = Release|x64
+ {B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.ActiveCfg = Debug|Win32
{B92A6638-68F9-45D2-AB03-6ED69E349381}.Release|x86.Build.0 = Release|Win32
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x64.Build.0 = Debug|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Debug|x86.Build.0 = Debug|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x64.ActiveCfg = Release|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x64.Build.0 = Release|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x86.ActiveCfg = Debug|Any CPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}.Release|x86.Build.0 = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x64.Build.0 = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Debug|x86.Build.0 = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x64.ActiveCfg = Release|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x64.Build.0 = Release|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x86.ActiveCfg = Debug|Any CPU
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0}.Release|x86.Build.0 = Debug|Any CPU
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x64.ActiveCfg = Debug|x64
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x64.Build.0 = Debug|x64
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x86.ActiveCfg = Debug|Win32
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Debug|x86.Build.0 = Debug|Win32
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x64.ActiveCfg = Release|x64
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x64.Build.0 = Release|x64
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x86.ActiveCfg = Release|Win32
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}.Release|x86.Build.0 = Release|Win32
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x64.ActiveCfg = Debug|x64
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x64.Build.0 = Debug|x64
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x86.ActiveCfg = Debug|Win32
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Debug|x86.Build.0 = Debug|Win32
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x64.ActiveCfg = Release|x64
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x64.Build.0 = Release|x64
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x86.ActiveCfg = Release|Win32
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}.Release|x86.Build.0 = Release|Win32
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x64.ActiveCfg = Debug|x64
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x64.Build.0 = Debug|x64
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x86.ActiveCfg = Debug|Win32
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Debug|x86.Build.0 = Debug|Win32
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x64.ActiveCfg = Release|x64
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x64.Build.0 = Release|x64
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x86.ActiveCfg = Release|Win32
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5}.Release|x86.Build.0 = Release|Win32
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x64.ActiveCfg = Debug|x64
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x64.Build.0 = Debug|x64
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x86.ActiveCfg = Debug|Win32
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Debug|x86.Build.0 = Debug|Win32
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x64.ActiveCfg = Release|x64
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x64.Build.0 = Release|x64
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x86.ActiveCfg = Release|Win32
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7}.Release|x86.Build.0 = Release|Win32
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x64.ActiveCfg = Debug|x64
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x64.Build.0 = Debug|x64
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x86.ActiveCfg = Debug|Win32
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Debug|x86.Build.0 = Debug|Win32
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x64.ActiveCfg = Release|x64
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x64.Build.0 = Release|x64
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x86.ActiveCfg = Release|Win32
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01}.Release|x86.Build.0 = Release|Win32
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x64.ActiveCfg = Debug|x64
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x64.Build.0 = Debug|x64
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x86.ActiveCfg = Debug|Win32
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Debug|x86.Build.0 = Debug|Win32
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x64.ActiveCfg = Release|x64
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x64.Build.0 = Release|x64
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x86.ActiveCfg = Release|Win32
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052}.Release|x86.Build.0 = Release|Win32
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x64.ActiveCfg = Debug|x64
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x64.Build.0 = Debug|x64
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x86.ActiveCfg = Debug|Win32
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Debug|x86.Build.0 = Debug|Win32
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Release|x64.ActiveCfg = Release|x64
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Release|x64.Build.0 = Release|x64
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Release|x86.ActiveCfg = Release|Win32
+ {46297F21-4D05-4582-85EB-FD07B3243194}.Release|x86.Build.0 = Release|Win32
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x64.ActiveCfg = Debug|x64
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x64.Build.0 = Debug|x64
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x86.ActiveCfg = Debug|Win32
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Debug|x86.Build.0 = Debug|Win32
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x64.ActiveCfg = Release|x64
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x64.Build.0 = Release|x64
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x86.ActiveCfg = Release|Win32
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77}.Release|x86.Build.0 = Release|Win32
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x64.ActiveCfg = Debug|x64
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x64.Build.0 = Debug|x64
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Debug|x86.Build.0 = Debug|Win32
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x64.ActiveCfg = Release|x64
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x64.Build.0 = Release|x64
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x86.ActiveCfg = Release|Win32
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -48,6 +198,17 @@ Global
{2A92076F-6DFD-4FB1-9E6A-4542B4B049C7} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
{C3308B0A-D7C7-4560-B5F7-3654DD4B668D} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
{B92A6638-68F9-45D2-AB03-6ED69E349381} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
+ {C29242DB-84D0-4A37-AD3F-19B72B23C7E0} = {4D65E9A0-1798-4E93-A12F-128FFDC6A690}
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D} = {6C048B51-3E90-45B8-8376-F3FFB5E216FC}
+ {E4E28AD7-6C59-419B-9463-817AF6384AC5} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {CCE930DE-1B5E-4925-8DD8-F1E4CC9F46C7} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {6A26AA97-96CF-4E2E-8883-47F0960F0E01} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {4A4B90B9-1D76-4006-A1D7-D502DDD2C052} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {46297F21-4D05-4582-85EB-FD07B3243194} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {599A7D9D-0CB8-4B99-AA2E-EA5EC081CF77} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
+ {FC57DC08-3496-4DCF-B52F-6EDC568B333C} = {562895A0-B72F-4A89-9A10-DF97A5D35269}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FBB5097F-0C5C-439C-8E82-19EF614DE3BE}
diff --git a/src/Crypto/Crypto.cpp b/src/Crypto/Crypto.cpp
new file mode 100644
index 00000000..759bcd83
--- /dev/null
+++ b/src/Crypto/Crypto.cpp
@@ -0,0 +1,19 @@
+#include "Crypto.h"
+#include "Impl/AlgorithmRSA.h"
+#include "Impl/AlgorithmSHA1.h"
+#include "Impl/AlgorithmSalsa20.h"
+
+IHashFunction* Crypto::CreateSHA1()
+{
+ return new AlgorithmSHA1();
+}
+
+IStreamCipher* Crypto::CreateSalsa20(const uint8_t* keyBytes, const size_t keySize)
+{
+ return new AlgorithmSalsa20(keyBytes, keySize);
+}
+
+IPublicKeyAlgorithm* Crypto::CreateRSA(const IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, const RSAPaddingMode paddingMode)
+{
+ return new AlgorithmRSA(hashingAlgorithm, paddingMode);
+}
\ No newline at end of file
diff --git a/src/Crypto/Crypto.h b/src/Crypto/Crypto.h
new file mode 100644
index 00000000..9a1e4ce1
--- /dev/null
+++ b/src/Crypto/Crypto.h
@@ -0,0 +1,20 @@
+#pragma once
+#include "IHashFunction.h"
+#include "IStreamCipher.h"
+#include "IPublicKeyAlgorithm.h"
+
+class Crypto
+{
+public:
+ enum RSAPaddingMode
+ {
+ RSA_PADDING_PKS1,
+ RSA_PADDING_PSS,
+ };
+
+ static IHashFunction* CreateSHA1();
+
+ static IStreamCipher* CreateSalsa20(const uint8_t* keyBytes, size_t keySize);
+
+ static IPublicKeyAlgorithm* CreateRSA(IPublicKeyAlgorithm::HashingAlgorithm hashingAlgorithm, RSAPaddingMode paddingMode);
+};
diff --git a/src/Crypto/Crypto.vcxproj b/src/Crypto/Crypto.vcxproj
new file mode 100644
index 00000000..a2e7f888
--- /dev/null
+++ b/src/Crypto/Crypto.vcxproj
@@ -0,0 +1,204 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {8D511FF0-0294-47EE-9AC4-BD9FE5DCC681}
+ Win32Proj
+ Crypto
+ 10.0.17763.0
+
+
+
+ StaticLibrary
+ true
+ v141
+ Unicode
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v141
+ Unicode
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+
+
+ true
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+
+
+ false
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+
+
+ false
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+
+
+
+ Level3
+ Disabled
+ true
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)
+ 4715;%(TreatSpecificWarningsAsErrors)
+ 4221;%(DisableSpecificWarnings)
+
+
+ Windows
+ true
+
+
+ libtomcrypt.lib;libtommath.lib;salsa20.lib
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)
+ /ignore:4221
+
+
+
+
+ Level3
+ Disabled
+ true
+ _DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)
+ 4715;%(TreatSpecificWarningsAsErrors)
+ 4221;%(DisableSpecificWarnings)
+
+
+ Windows
+ true
+
+
+ libtomcrypt.lib;libtommath.lib;salsa20.lib
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)
+ /ignore:4221
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)
+ 4715;%(TreatSpecificWarningsAsErrors)
+ 4221;%(DisableSpecificWarnings)
+
+
+ Windows
+ true
+ true
+ true
+
+
+ libtomcrypt.lib;libtommath.lib;salsa20.lib
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)
+ /ignore:4221
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ $(ProjectDir);$(SolutionDir)thirdparty\libtomcrypt\headers;$(SolutionDir)thirdparty\salsa20;%(AdditionalIncludeDirectories)
+ 4715;%(TreatSpecificWarningsAsErrors)
+ 4221;%(DisableSpecificWarnings)
+
+
+ Windows
+ true
+ true
+ true
+
+
+ libtomcrypt.lib;libtommath.lib;salsa20.lib
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\;%(AdditionalLibraryDirectories)
+ /ignore:4221
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Crypto/IHashFunction.h b/src/Crypto/IHashFunction.h
new file mode 100644
index 00000000..c6780cfa
--- /dev/null
+++ b/src/Crypto/IHashFunction.h
@@ -0,0 +1,12 @@
+#pragma once
+
+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;
+};
\ No newline at end of file
diff --git a/src/Crypto/IPublicKeyAlgorithm.h b/src/Crypto/IPublicKeyAlgorithm.h
new file mode 100644
index 00000000..323ceebf
--- /dev/null
+++ b/src/Crypto/IPublicKeyAlgorithm.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include
+
+class IPublicKeyAlgorithm
+{
+public:
+ enum 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;
+};
\ No newline at end of file
diff --git a/src/Crypto/IStreamCipher.h b/src/Crypto/IStreamCipher.h
new file mode 100644
index 00000000..36cda6cf
--- /dev/null
+++ b/src/Crypto/IStreamCipher.h
@@ -0,0 +1,12 @@
+#pragma once
+#include
+
+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;
+};
diff --git a/src/Crypto/Impl/AlgorithmRSA.cpp b/src/Crypto/Impl/AlgorithmRSA.cpp
new file mode 100644
index 00000000..209ece1f
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmRSA.cpp
@@ -0,0 +1,118 @@
+#include "AlgorithmRSA.h"
+#include
+
+#include "CryptoLibrary.h"
+
+class AlgorithmRSA::AlgorithmRSAImpl
+{
+ rsa_key m_key{};
+ HashingAlgorithm m_hash;
+ Crypto::RSAPaddingMode m_padding;
+
+ const ltc_hash_descriptor* GetHashDescriptor() const
+ {
+ switch(m_hash)
+ {
+ case RSA_HASH_SHA256:
+ return &sha256_desc;
+
+ default:
+ case RSA_HASH_SHA512:
+ return &sha512_desc;
+ }
+ }
+
+ int GetPaddingMode() const
+ {
+ switch(m_padding)
+ {
+ case Crypto::RSA_PADDING_PKS1:
+ return LTC_PKCS_1_V1_5;
+
+ default:
+ case Crypto::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);
+}
\ No newline at end of file
diff --git a/src/Crypto/Impl/AlgorithmRSA.h b/src/Crypto/Impl/AlgorithmRSA.h
new file mode 100644
index 00000000..eb3c7d86
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmRSA.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "IPublicKeyAlgorithm.h"
+#include "Crypto.h"
+#include
+
+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;
+};
diff --git a/src/Crypto/Impl/AlgorithmSHA1.cpp b/src/Crypto/Impl/AlgorithmSHA1.cpp
new file mode 100644
index 00000000..881345fd
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmSHA1.cpp
@@ -0,0 +1,63 @@
+#include "AlgorithmSHA1.h"
+
+#include "CryptoLibrary.h"
+#include
+
+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(input), inputSize);
+ }
+
+ void Finish(void* hashBuffer)
+ {
+ sha1_done(&m_state, static_cast(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);
+}
\ No newline at end of file
diff --git a/src/Crypto/Impl/AlgorithmSHA1.h b/src/Crypto/Impl/AlgorithmSHA1.h
new file mode 100644
index 00000000..f9ae0514
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmSHA1.h
@@ -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;
+};
diff --git a/src/Crypto/Impl/AlgorithmSalsa20.cpp b/src/Crypto/Impl/AlgorithmSalsa20.cpp
new file mode 100644
index 00000000..46bc8d8d
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmSalsa20.cpp
@@ -0,0 +1,87 @@
+#include "AlgorithmSalsa20.h"
+#include "salsa20.h"
+#include
+#include
+
+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::exception("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(plainText), static_cast(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);
+}
\ No newline at end of file
diff --git a/src/Crypto/Impl/AlgorithmSalsa20.h b/src/Crypto/Impl/AlgorithmSalsa20.h
new file mode 100644
index 00000000..88c0d6ca
--- /dev/null
+++ b/src/Crypto/Impl/AlgorithmSalsa20.h
@@ -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;
+};
diff --git a/src/Crypto/Impl/CryptoLibrary.h b/src/Crypto/Impl/CryptoLibrary.h
new file mode 100644
index 00000000..f04d5761
--- /dev/null
+++ b/src/Crypto/Impl/CryptoLibrary.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#define LTC_NO_PROTOTYPES
+#include "tomcrypt.h"
+
+class CryptoLibrary
+{
+public:
+ static void Init()
+ {
+ static bool initialized = false;
+
+ if(!initialized)
+ {
+ initialized = true;
+
+ ltc_mp = ltm_desc;
+ }
+ }
+};
\ No newline at end of file
diff --git a/src/Linker/Linker.vcxproj b/src/Linker/Linker.vcxproj
index 8bac1a85..60bb5940 100644
--- a/src/Linker/Linker.vcxproj
+++ b/src/Linker/Linker.vcxproj
@@ -91,11 +91,13 @@
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
pch.h
+ 4715;%(TreatSpecificWarningsAsErrors)
Console
true
$(TargetDir)
+ /ignore:4221
@@ -109,6 +111,7 @@
WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
true
pch.h
+ 4715;%(TreatSpecificWarningsAsErrors)
Console
@@ -116,17 +119,26 @@
true
true
$(TargetDir)
+ /ignore:4221
$(TargetDir)
+ /ignore:4221
+
+ 4715;%(TreatSpecificWarningsAsErrors)
+
$(TargetDir)
+ /ignore:4221
+
+ 4715;%(TreatSpecificWarningsAsErrors)
+
diff --git a/src/Utils/Utils.vcxproj b/src/Utils/Utils.vcxproj
new file mode 100644
index 00000000..b6ea4fc5
--- /dev/null
+++ b/src/Utils/Utils.vcxproj
@@ -0,0 +1,179 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+ 15.0
+ {757FB12A-B410-4B76-B525-2D11A14DAD9D}
+ Win32Proj
+ Utils
+ 10.0.17763.0
+
+
+
+ StaticLibrary
+ true
+ v141
+ Unicode
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v141
+ Unicode
+
+
+ StaticLibrary
+ false
+ v141
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+
+
+ true
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+
+
+ false
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+
+
+ false
+ $(SolutionDir)lib\$(Configuration)_$(Platform)\
+ $(SolutionDir)obj\$(ProjectName)\$(Configuration)_$(Platform)\
+
+
+
+ Level3
+ Disabled
+ true
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ 4715;%(TreatSpecificWarningsAsErrors)
+
+
+ Windows
+ true
+
+
+ /ignore:4221
+
+
+
+
+ Level3
+ Disabled
+ true
+ _DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ 4715;%(TreatSpecificWarningsAsErrors)
+
+
+ Windows
+ true
+
+
+ /ignore:4221
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ 4715;%(TreatSpecificWarningsAsErrors)
+
+
+ Windows
+ true
+ true
+ true
+
+
+ /ignore:4221
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+ NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ 4715;%(TreatSpecificWarningsAsErrors)
+
+
+ Windows
+ true
+ true
+ true
+
+
+ /ignore:4221
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Utils/Utils/ClassUtils.h b/src/Utils/Utils/ClassUtils.h
new file mode 100644
index 00000000..b8276d86
--- /dev/null
+++ b/src/Utils/Utils/ClassUtils.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define STR(x) #x
\ No newline at end of file
diff --git a/src/Utils/Utils/FileAPI.cpp b/src/Utils/Utils/FileAPI.cpp
new file mode 100644
index 00000000..9398ab0c
--- /dev/null
+++ b/src/Utils/Utils/FileAPI.cpp
@@ -0,0 +1,145 @@
+#include "FileAPI.h"
+
+#include
+#include
+
+bool FileAPI::FileExists(const std::string& fileName)
+{
+ struct stat st{};
+
+ return stat(fileName.c_str(), &st) >= 0 && !(st.st_mode & S_IFDIR);
+}
+
+uint64_t FileAPI::FileSize(const std::string& fileName)
+{
+ struct stat st{};
+
+ if (stat(fileName.c_str(), &st) >= 0 && !(st.st_mode & S_IFDIR))
+ {
+ return st.st_size;
+ }
+
+ return 0;
+}
+
+bool FileAPI::DirectoryExists(const std::string& directoryName)
+{
+ struct stat st{};
+
+ return stat(directoryName.c_str(), &st) >= 0 && st.st_mode & S_IFDIR;
+}
+
+FileAPI::File FileAPI::Open(const std::string& filename, const Mode mode)
+{
+ const char* modeStr;
+ switch(mode)
+ {
+ default:
+ case MODE_READ:
+ modeStr = "rb";
+ break;
+
+ case MODE_WRITE:
+ modeStr = "wb";
+ break;
+ }
+
+ FILE* handle;
+ if (fopen_s(&handle, filename.c_str(), modeStr) != 0)
+ {
+ return File(nullptr);
+ }
+
+ return File(handle);
+}
+
+FileAPI::File::File()
+{
+ this->m_handle = nullptr;
+}
+
+FileAPI::File::File(void* handle)
+{
+ this->m_handle = handle;
+}
+
+FileAPI::File::File(File&& f) noexcept
+{
+ m_handle = f.m_handle;
+ f.m_handle = nullptr;
+}
+
+FileAPI::File::~File()
+{
+ this->Close();
+}
+
+FileAPI::File& FileAPI::File::operator=(File&& f) noexcept
+{
+ m_handle = f.m_handle;
+ f.m_handle = nullptr;
+
+ return *this;
+}
+
+bool FileAPI::File::IsOpen() const
+{
+ return this->m_handle != nullptr;
+}
+
+size_t FileAPI::File::Read(void* buffer, const size_t elementSize, const size_t elementCount) const
+{
+ if (!this->IsOpen())
+ return 0;
+
+ return fread(buffer, elementSize, elementCount, static_cast(m_handle));
+}
+
+size_t FileAPI::File::Write(void* data, const size_t elementSize, const size_t elementCount) const
+{
+ if (!this->IsOpen())
+ return 0;
+
+ return fwrite(data, elementSize, elementCount, static_cast(m_handle));
+}
+
+void FileAPI::File::Skip(const size_t amount) const
+{
+ if(!this->IsOpen())
+ return;
+
+ fseek(static_cast(m_handle), amount, SEEK_CUR);
+}
+
+size_t FileAPI::File::Printf(char* fmt, ...) const
+{
+ va_list ap;
+
+ if (!this->IsOpen())
+ return 0;
+
+ va_start(ap, fmt);
+ const int result = fprintf(static_cast(m_handle), fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
+int64_t FileAPI::File::Pos() const
+{
+ return _ftelli64(static_cast(m_handle));
+}
+
+void FileAPI::File::Goto(const int64_t pos) const
+{
+ _fseeki64(static_cast(m_handle), pos, SEEK_SET);
+}
+
+void FileAPI::File::Close()
+{
+ if (this->m_handle != nullptr)
+ {
+ fclose(static_cast(m_handle));
+ this->m_handle = nullptr;
+ }
+}
\ No newline at end of file
diff --git a/src/Utils/Utils/FileAPI.h b/src/Utils/Utils/FileAPI.h
new file mode 100644
index 00000000..f8cc0c25
--- /dev/null
+++ b/src/Utils/Utils/FileAPI.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include
+#include
+
+class FileAPI
+{
+public:
+ enum Mode
+ {
+ MODE_READ = 0,
+ MODE_WRITE = 1
+ };
+
+ class File
+ {
+ void* m_handle;
+
+ public:
+ File();
+ explicit File(void* handle);
+ File(File&) = delete;
+ File(File&& f) noexcept;
+ ~File();
+
+ File& operator=(File&) = delete;
+ File& operator=(File&& f) noexcept;
+
+ bool IsOpen() const;
+ size_t Read(void* buffer, size_t elementSize, size_t elementCount) const;
+ size_t Write(void* data, size_t elementSize, size_t elementCount) const;
+ void Skip(size_t amount) const;
+ size_t Printf(char* fmt, ...) const;
+ int64_t Pos() const;
+ void Goto(int64_t pos) const;
+ void Close();
+ };
+
+ static bool FileExists(const std::string& fileName);
+ static uint64_t FileSize(const std::string& fileName);
+ static bool DirectoryExists(const std::string& directoryName);
+ static File Open(const std::string& filename, Mode mode);
+};
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/App.config b/src/ZoneCodeGenerator/App.config
new file mode 100644
index 00000000..731f6de6
--- /dev/null
+++ b/src/ZoneCodeGenerator/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Domain/DataException.cs b/src/ZoneCodeGenerator/Domain/DataException.cs
new file mode 100644
index 00000000..3ca526d8
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataException.cs
@@ -0,0 +1,9 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class DataException : LoadingException
+ {
+ public DataException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataType.cs b/src/ZoneCodeGenerator/Domain/DataType.cs
new file mode 100644
index 00000000..4a93b670
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataType.cs
@@ -0,0 +1,20 @@
+namespace ZoneCodeGenerator.Domain
+{
+ abstract class DataType
+ {
+ public string Namespace { get; }
+ public string Name { get; }
+ public DataTypeType Type { get; }
+ public string FullName => string.IsNullOrEmpty(Namespace) ? Name : $"{Namespace}::{Name}";
+
+ public abstract int Alignment { get; }
+ public abstract int Size { get; }
+
+ protected DataType(string _namespace, string name, DataTypeType type)
+ {
+ Namespace = _namespace;
+ Name = name;
+ Type = type;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs b/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs
new file mode 100644
index 00000000..c20efdab
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeBaseType.cs
@@ -0,0 +1,47 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class DataTypeBaseType : DataType
+ {
+ public static readonly DataTypeBaseType FLOAT = new DataTypeBaseType("float", 4);
+ public static readonly DataTypeBaseType DOUBLE = new DataTypeBaseType("double", 8);
+ public static readonly DataTypeBaseType BOOL = new DataTypeBaseType("bool", 1);
+ public static readonly DataTypeBaseType CHAR = new DataTypeBaseType("char", 1);
+ public static readonly DataTypeBaseType CONST_CHAR = new DataTypeBaseType("const char", 1);
+ public static readonly DataTypeBaseType UNSIGNED_CHAR = new DataTypeBaseType("unsigned char", 1);
+ public static readonly DataTypeBaseType SHORT = new DataTypeBaseType("short", 2);
+ public static readonly DataTypeBaseType UNSIGNED_SHORT = new DataTypeBaseType("unsigned short", 2);
+ public static readonly DataTypeBaseType INT = new DataTypeBaseType("int", 4);
+ public static readonly DataTypeBaseType UNSIGNED_INT = new DataTypeBaseType("unsigned int", 4);
+ public static readonly DataTypeBaseType LONG = new DataTypeBaseType("long", 4);
+ public static readonly DataTypeBaseType UNSIGNED_LONG = new DataTypeBaseType("unsigned long", 4);
+ public static readonly DataTypeBaseType LONG_LONG = new DataTypeBaseType("long long", 8);
+ public static readonly DataTypeBaseType UNSIGNED_LONG_LONG = new DataTypeBaseType("unsigned long long", 8);
+ public static readonly DataTypeBaseType VOID = new DataTypeBaseType("void", 0);
+
+ public static readonly DataTypeBaseType[] BASE_TYPES = {
+ FLOAT,
+ DOUBLE,
+ BOOL,
+ CHAR,
+ CONST_CHAR,
+ UNSIGNED_CHAR,
+ SHORT,
+ UNSIGNED_SHORT,
+ INT,
+ UNSIGNED_INT,
+ LONG,
+ UNSIGNED_LONG,
+ LONG_LONG,
+ UNSIGNED_LONG_LONG,
+ VOID
+ };
+
+ public override int Size { get; }
+ public override int Alignment => Size;
+
+ private DataTypeBaseType(string name, int size) : base("", name, DataTypeType.BaseType)
+ {
+ Size = size;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeEnum.cs b/src/ZoneCodeGenerator/Domain/DataTypeEnum.cs
new file mode 100644
index 00000000..63be8f77
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeEnum.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class DataTypeEnum : DataType
+ {
+ public DataTypeBaseType ParentType { get; }
+ public List Members { get; }
+
+ public override int Size => ParentType.Size;
+ public override int Alignment => ParentType.Alignment;
+
+ public DataTypeEnum(string _namespace, string name, DataTypeBaseType parentType) : base(_namespace, name, DataTypeType.Enum)
+ {
+ Members = new List();
+ ParentType = parentType;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeStruct.cs b/src/ZoneCodeGenerator/Domain/DataTypeStruct.cs
new file mode 100644
index 00000000..7727864b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeStruct.cs
@@ -0,0 +1,46 @@
+using System;
+using ZoneCodeGenerator.Utils;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class DataTypeStruct : DataTypeWithMembers
+ {
+ public DataTypeStruct(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Struct)
+ {
+ }
+
+ protected override int CalculateSize()
+ {
+ var currentSize = 0;
+ var currentBitOffset = 0;
+
+ foreach (var member in Members)
+ {
+ if (member.VariableType.HasCustomBitSize)
+ {
+ currentBitOffset += member.VariableType.CustomBitSize.GetValueOrDefault(0);
+ }
+ else
+ {
+ if (currentBitOffset > 0)
+ {
+ currentBitOffset = currentBitOffset.Align(8);
+ currentSize += currentBitOffset / 8;
+ currentBitOffset = 0;
+ }
+
+ currentSize = currentSize.Align(Math.Min(member.Alignment, Pack));
+ currentSize += member.VariableType.Size;
+ }
+ }
+
+ if (currentBitOffset > 0)
+ {
+ currentBitOffset = currentBitOffset.Align(8);
+ currentSize += currentBitOffset / 8;
+ }
+
+ return currentSize.Align(Alignment);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeType.cs b/src/ZoneCodeGenerator/Domain/DataTypeType.cs
new file mode 100644
index 00000000..fd4632e2
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeType.cs
@@ -0,0 +1,11 @@
+namespace ZoneCodeGenerator.Domain
+{
+ enum DataTypeType
+ {
+ Struct,
+ Union,
+ Enum,
+ Typedef,
+ BaseType
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs b/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs
new file mode 100644
index 00000000..1c4c4454
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeTypedef.cs
@@ -0,0 +1,15 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class DataTypeTypedef : DataType
+ {
+ public TypeDeclaration TypeDefinition { get; }
+
+ public DataTypeTypedef(string _namespace, string name, TypeDeclaration typeDefinitionDeclaration) : base(_namespace, name, DataTypeType.Typedef)
+ {
+ TypeDefinition = typeDefinitionDeclaration;
+ }
+
+ public override int Alignment => TypeDefinition.Alignment;
+ public override int Size => TypeDefinition.Size;
+ }
+}
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeUnion.cs b/src/ZoneCodeGenerator/Domain/DataTypeUnion.cs
new file mode 100644
index 00000000..33ee8175
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeUnion.cs
@@ -0,0 +1,20 @@
+using System.Linq;
+using ZoneCodeGenerator.Utils;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class DataTypeUnion : DataTypeWithMembers
+ {
+ public DataTypeUnion(string _namespace, string name, int pack) : base(_namespace, name, pack, DataTypeType.Union)
+ {
+ }
+
+ protected override int CalculateSize()
+ {
+ return Members
+ .Select(variable => variable.VariableType.Size)
+ .Max()
+ .Align(Alignment);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/DataTypeWithMembers.cs b/src/ZoneCodeGenerator/Domain/DataTypeWithMembers.cs
new file mode 100644
index 00000000..bd3df7fc
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/DataTypeWithMembers.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ZoneCodeGenerator.Domain
+{
+ abstract class DataTypeWithMembers : DataType
+ {
+ public int? AlignmentOverride { get; set; }
+ private int alignment;
+ public override int Alignment => AlignmentOverride ?? alignment;
+
+ private int size;
+ public override int Size => size;
+
+ public int Pack { get; }
+
+ public List Members { get; }
+
+ private bool finalized;
+ public void FinalizeDataType()
+ {
+ if (finalized) return;
+
+ finalized = true;
+ CalculateProperties();
+ }
+
+ protected DataTypeWithMembers(string _namespace, string name, int pack, DataTypeType type) : base(_namespace, name, type)
+ {
+ Members = new List();
+ Pack = pack;
+ finalized = false;
+ }
+
+ private void CalculateProperties()
+ {
+ foreach (var member in Members
+ .Select(variable => variable.VariableType.Type)
+ .OfType())
+ {
+ member.FinalizeDataType();
+ }
+
+ alignment = Members.Select(variable => variable.Alignment).Max();
+ size = CalculateSize();
+ }
+
+ protected abstract int CalculateSize();
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/EnumMember.cs b/src/ZoneCodeGenerator/Domain/EnumMember.cs
new file mode 100644
index 00000000..ff2bb3ae
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/EnumMember.cs
@@ -0,0 +1,14 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class EnumMember
+ {
+ public string Name { get; }
+ public long Value { get; }
+
+ public EnumMember(string name, long value)
+ {
+ Name = name;
+ Value = value;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/FastFileStructure/FastFileBlock.cs b/src/ZoneCodeGenerator/Domain/FastFileStructure/FastFileBlock.cs
new file mode 100644
index 00000000..afacb5c2
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/FastFileStructure/FastFileBlock.cs
@@ -0,0 +1,30 @@
+namespace ZoneCodeGenerator.Domain.FastFileStructure
+{
+ class FastFileBlock
+ {
+ public enum Type
+ {
+ Temp,
+ Runtime,
+ Delay,
+ Normal
+ }
+
+ public string Name { get; }
+ public int Index { get; }
+ public Type BlockType { get; }
+ public bool IsDefault { get; }
+ public bool IsTemp => BlockType == Type.Temp;
+ public bool IsRuntime => BlockType == Type.Runtime;
+ public bool IsDelay => BlockType == Type.Delay;
+ public bool IsNormal => BlockType == Type.Normal;
+
+ public FastFileBlock(string name, int index, Type blockType, bool isDefault)
+ {
+ Name = name;
+ Index = index;
+ BlockType = blockType;
+ IsDefault = isDefault;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/ForwardDeclaration.cs b/src/ZoneCodeGenerator/Domain/ForwardDeclaration.cs
new file mode 100644
index 00000000..f038c9ec
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/ForwardDeclaration.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class ForwardDeclaration : DataType
+ {
+ private DataType forwardedType;
+
+ public DataType ForwardedType
+ {
+ get => forwardedType;
+
+ set
+ {
+ if (forwardedType == null)
+ {
+ if(value.Type != Type)
+ throw new DataException($"Type of forwarded type '{Name}' does not match previous declaration");
+
+ forwardedType = value;
+ }
+ else if(forwardedType != value)
+ {
+ throw new DataException($"Tried to set forwarded type '{Name}' multiple times with different types");
+ }
+ }
+ }
+
+ public ForwardDeclaration(string _namespace, string name, DataTypeType dataTypeType) : base(_namespace, name, dataTypeType)
+ {
+ switch (dataTypeType)
+ {
+ case DataTypeType.Enum:
+ case DataTypeType.Struct:
+ case DataTypeType.Union:
+ break;
+
+ default:
+ throw new ArgumentException($"Cannot create forward declaration for type '{dataTypeType}'");
+ }
+ forwardedType = null;
+ }
+
+ public override int Alignment => 0;
+ public override int Size => 0;
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/Namespace.cs b/src/ZoneCodeGenerator/Domain/Namespace.cs
new file mode 100644
index 00000000..a9aecd84
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/Namespace.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class Namespace
+ {
+ private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
+ private readonly Stack namespaceStack;
+
+ public Namespace()
+ {
+ namespaceStack = new Stack();
+ }
+
+ public void Push(string _namespace)
+ {
+ if(!nameRegex.IsMatch(_namespace))
+ throw new ArgumentException("Namespace name invalid");
+
+ namespaceStack.Push(_namespace);
+ }
+
+ public string Pop()
+ {
+ return namespaceStack.Pop();
+ }
+
+ public string GetName()
+ {
+ if (namespaceStack.Count == 0)
+ return "";
+
+ var result = "";
+ var stackSnapshot = namespaceStack.ToArray();
+
+ // The stack is read from top to bottom. Therefore we need to access it in reverse order here.
+ for(var i = stackSnapshot.Length - 1; i >= 0; i--)
+ {
+ if (!string.IsNullOrEmpty(result))
+ result += "::";
+ result += stackSnapshot[i];
+ }
+
+ return result;
+ }
+
+ public override string ToString()
+ {
+ return GetName();
+ }
+
+ public static string Combine(Namespace _namespace, string typename)
+ {
+ return $"{_namespace}::{typename}";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/ReferenceType.cs b/src/ZoneCodeGenerator/Domain/ReferenceType.cs
new file mode 100644
index 00000000..22369ce9
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/ReferenceType.cs
@@ -0,0 +1,7 @@
+namespace ZoneCodeGenerator.Domain
+{
+ abstract class ReferenceType
+ {
+
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs b/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs
new file mode 100644
index 00000000..ef7983c1
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs
@@ -0,0 +1,12 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class ReferenceTypeArray : ReferenceType
+ {
+ public int ArraySize { get; }
+
+ public ReferenceTypeArray(int arraySize)
+ {
+ ArraySize = arraySize;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/ReferenceTypePointer.cs b/src/ZoneCodeGenerator/Domain/ReferenceTypePointer.cs
new file mode 100644
index 00000000..fab73a2a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/ReferenceTypePointer.cs
@@ -0,0 +1,6 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class ReferenceTypePointer : ReferenceType
+ {
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/StructureInformation/MemberInformation.cs b/src/ZoneCodeGenerator/Domain/StructureInformation/MemberInformation.cs
new file mode 100644
index 00000000..e377b872
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/StructureInformation/MemberInformation.cs
@@ -0,0 +1,16 @@
+namespace ZoneCodeGenerator.Domain.StructureInformation
+{
+ class MemberInformation
+ {
+ public StructureInformation StructureType { get; }
+ public Variable Member { get; set; }
+ public bool IsScriptString { get; set; }
+
+ public MemberInformation(Variable member, StructureInformation structureType)
+ {
+ Member = member;
+ StructureType = structureType;
+ IsScriptString = false;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/StructureInformation/StructureInformation.cs b/src/ZoneCodeGenerator/Domain/StructureInformation/StructureInformation.cs
new file mode 100644
index 00000000..c4be7381
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/StructureInformation/StructureInformation.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Domain.StructureInformation
+{
+ class StructureInformation
+ {
+ public DataTypeWithMembers Type { get; }
+ public bool IsUnion => Type is DataTypeUnion;
+ public FastFileBlock Block { get; set; }
+
+ public EnumMember AssetEnumEntry { get; set; }
+ public bool IsAsset => AssetEnumEntry != null;
+
+ private int? fastFileAlign;
+ public bool HasNonDefaultAlign => fastFileAlign != null;
+ public int FastFileAlign
+ {
+ get => fastFileAlign ?? Type.Alignment;
+ set => fastFileAlign = value;
+ }
+
+ public List Usages { get; }
+ public List OrderedMembers { get; }
+ public bool NonEmbeddedReferenceExists { get; set; }
+ public bool PointerReferenceExists { get; set; }
+ public bool ArrayReferenceExists { get; set; }
+
+ public bool HasNameMember => Type.Members.Any(variable => variable.Name.Equals("name", StringComparison.CurrentCultureIgnoreCase));
+
+ public StructureInformation(DataTypeWithMembers type)
+ {
+ AssetEnumEntry = null;
+ fastFileAlign = null;
+ Type = type;
+ NonEmbeddedReferenceExists = false;
+ PointerReferenceExists = false;
+ ArrayReferenceExists = false;
+ Usages = new List();
+ OrderedMembers = new List();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs b/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs
new file mode 100644
index 00000000..0241a25f
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/TypeDeclaration.cs
@@ -0,0 +1,70 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ZoneCodeGenerator.Domain
+{
+ class TypeDeclaration
+ {
+ private const int PointerSize = 4;
+
+ private DataType type;
+ public DataType Type
+ {
+ get
+ {
+ if (type is DataTypeTypedef typedef)
+ {
+ return typedef.TypeDefinition.Type;
+ }
+
+ return type;
+ }
+
+ set => type = value;
+ }
+
+ public int? CustomBitSize { get; }
+
+ public bool HasCustomBitSize => CustomBitSize != null;
+
+ private readonly List references;
+ public IReadOnlyList References => references.AsReadOnly();
+
+ public int Alignment => references.OfType().Any() ? PointerSize : type.Alignment;
+
+ public int Size
+ {
+ get
+ {
+ var currentSize = Type.Size;
+
+ foreach (var reference in References.Reverse())
+ {
+ switch (reference)
+ {
+ case ReferenceTypePointer _:
+ currentSize = PointerSize;
+ break;
+ case ReferenceTypeArray array:
+ currentSize *= array.ArraySize;
+ break;
+ }
+ }
+
+ return currentSize;
+ }
+ }
+
+ public TypeDeclaration(DataType type, List references)
+ {
+ this.type = type;
+ this.references = references ?? new List();
+ CustomBitSize = null;
+ }
+
+ public TypeDeclaration(DataType type, int customBitSize, List references) : this(type, references)
+ {
+ CustomBitSize = customBitSize;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Domain/Variable.cs b/src/ZoneCodeGenerator/Domain/Variable.cs
new file mode 100644
index 00000000..5c212c63
--- /dev/null
+++ b/src/ZoneCodeGenerator/Domain/Variable.cs
@@ -0,0 +1,19 @@
+namespace ZoneCodeGenerator.Domain
+{
+ class Variable
+ {
+ public string Name { get; }
+
+ public int? AlignmentOverride { get; set; }
+
+ public int Alignment => AlignmentOverride ?? VariableType.Alignment;
+
+ public TypeDeclaration VariableType { get; }
+
+ public Variable(string name, TypeDeclaration type)
+ {
+ Name = name;
+ VariableType = type;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Generating/CodeGenerator.cs b/src/ZoneCodeGenerator/Generating/CodeGenerator.cs
new file mode 100644
index 00000000..c2494d4a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/CodeGenerator.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using ZoneCodeGenerator.Domain.StructureInformation;
+using ZoneCodeGenerator.Interface;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Generating
+{
+ static class CodeGenerator
+ {
+ private class GeneratorPreset
+ {
+ public string FileName { get; }
+ public string TemplateName { get; }
+
+ public GeneratorPreset(string fileName, string templateName)
+ {
+ FileName = fileName;
+ TemplateName = templateName;
+ }
+ }
+
+ private static readonly Dictionary presets =
+ new Dictionary(StringComparer.CurrentCultureIgnoreCase)
+ {
+ {
+ "ZoneLoad", new GeneratorPreset("$asset/$asset_load_db", "ZoneLoad.stg")
+ },
+ {
+ "ZoneWrite", new GeneratorPreset("$asset/$asset_write_db", "ZoneWrite.stg")
+ }
+ };
+
+ public static IEnumerable Presets => presets.Keys;
+
+ public static bool GenerateCodeForPreset(string presetName, StructureInformation asset, CUISession session)
+ {
+ if (!presets.ContainsKey(presetName))
+ return false;
+
+ var preset = presets[presetName];
+
+ try
+ {
+ if (!Directory.Exists(session.GeneratorOutputPath))
+ Directory.CreateDirectory(session.GeneratorOutputPath);
+
+ var codeTemplate = CodeTemplate.FromResources(preset.TemplateName);
+
+ if (codeTemplate == null)
+ {
+ Console.WriteLine($"Could not find template '{preset.TemplateName}'");
+ return false;
+ }
+
+ var resolvedFileName = preset.FileName.Replace("$asset", asset.Type.Name.ToLower());
+ var fullPath = Path.Combine(session.GeneratorOutputPath, resolvedFileName);
+ var folderOfFile = Path.GetDirectoryName(fullPath);
+
+ if (!Directory.Exists(folderOfFile))
+ Directory.CreateDirectory(folderOfFile);
+
+ var renderingContext = RenderingContext.BuildContext(session, asset);
+
+ if (renderingContext == null)
+ return false;
+
+ var generatedCode = false;
+ if (codeTemplate.HasHeaderTemplate)
+ {
+ generatedCode = true;
+ using (var fileStream = new FileStream(fullPath + ".h", FileMode.Create))
+ {
+ codeTemplate.RenderHeaderFile(fileStream, renderingContext);
+ fileStream.Close();
+ }
+ }
+
+ if (codeTemplate.HasSourceTemplate)
+ {
+ generatedCode = true;
+ using (var fileStream = new FileStream(fullPath + ".cpp", FileMode.Create))
+ {
+ codeTemplate.RenderSourceFile(fileStream, renderingContext);
+ fileStream.Close();
+ }
+ }
+
+ return generatedCode;
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Generating/CodeTemplate.cs b/src/ZoneCodeGenerator/Generating/CodeTemplate.cs
new file mode 100644
index 00000000..2e5fd97f
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/CodeTemplate.cs
@@ -0,0 +1,54 @@
+using System.IO;
+using Antlr4.StringTemplate;
+
+namespace ZoneCodeGenerator.Generating
+{
+ class CodeTemplate
+ {
+ private const string SourceTemplateName = "source";
+ private const string HeaderTemplateName = "header";
+
+ private readonly TemplateGroup templateGroup;
+
+ public bool HasSourceTemplate => templateGroup.IsDefined(SourceTemplateName);
+ public bool HasHeaderTemplate => templateGroup.IsDefined(HeaderTemplateName);
+
+ private CodeTemplate(TemplateGroup templateGroup)
+ {
+ this.templateGroup = templateGroup;
+ templateGroup.RegisterRenderer(typeof(string), new StringRenderer());
+ }
+
+ public static CodeTemplate FromResources(string fileName)
+ {
+ var templateGroup = new TemplateGroupResources(fileName);
+
+ templateGroup.Load();
+
+ return new CodeTemplate(templateGroup);
+ }
+
+ public void RenderSourceFile(Stream stream, RenderingContext context)
+ {
+ RenderTemplate(stream, templateGroup.GetInstanceOf(SourceTemplateName), context);
+ }
+
+ public void RenderHeaderFile(Stream stream, RenderingContext context)
+ {
+ RenderTemplate(stream, templateGroup.GetInstanceOf(HeaderTemplateName), context);
+ }
+
+ private static void RenderTemplate(Stream stream, Template template, RenderingContext context)
+ {
+ if (template == null)
+ return;
+
+ template.Add("context", context);
+
+ using (var writer = new StreamWriter(stream))
+ {
+ template.Write(new AutoIndentWriter(writer));
+ }
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Generating/RenderingContext.cs b/src/ZoneCodeGenerator/Generating/RenderingContext.cs
new file mode 100644
index 00000000..04b20426
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/RenderingContext.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Domain.StructureInformation;
+using ZoneCodeGenerator.Interface;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Generating
+{
+ class RenderingContext
+ {
+ public string Game { get; set; }
+ public StructureInformation Asset { get; set; }
+ public HashSet Structures { get; }
+ public IEnumerable ReferencedAssets => Structures.Where(inf => inf.IsAsset && inf != Asset);
+
+ public List Blocks { get; private set; }
+
+ public FastFileBlock DefaultNormalBlock => Blocks.FirstOrDefault(block => block.IsDefault && block.IsNormal) ??
+ Blocks.FirstOrDefault(block => block.IsNormal);
+
+ private RenderingContext()
+ {
+ Structures = new HashSet();
+ }
+
+ private void AddToContext(StructureInformation structureInformation)
+ {
+ if (!Structures.Add(structureInformation))
+ return;
+
+ if (structureInformation.IsAsset && structureInformation != Asset)
+ return;
+
+ foreach (var member in structureInformation.OrderedMembers)
+ {
+ if(member.StructureType != null)
+ AddToContext(member.StructureType);
+ }
+ }
+
+ public static RenderingContext BuildContext(CUISession session, StructureInformation asset)
+ {
+ var context = new RenderingContext
+ {
+ Asset = asset,
+ Game = session.Game,
+ Blocks = session.Repository.GetAllFastFileBlocks().ToList()
+ };
+
+ context.AddToContext(asset);
+
+ return context;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Generating/TemplateGroupResources.cs b/src/ZoneCodeGenerator/Generating/TemplateGroupResources.cs
new file mode 100644
index 00000000..7cf048a8
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/TemplateGroupResources.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+using System.Reflection;
+using Antlr.Runtime;
+using Antlr4.StringTemplate;
+using Antlr4.StringTemplate.Compiler;
+using Antlr4.StringTemplate.Misc;
+
+namespace ZoneCodeGenerator.Generating
+{
+ public class TemplateGroupResources : TemplateGroup
+ {
+ private const string ResourceBasePath = "ZoneCodeGenerator.Generating.Templates";
+ private const char DefaultDelimiterStart = '<';
+ private const char DefaultDelimiterStop = '>';
+
+ private bool alreadyLoaded;
+ private readonly string fileName;
+
+ public TemplateGroupResources(string fileName, char delimiterStartChar, char delimiterStopChar) : base(delimiterStartChar, delimiterStopChar)
+ {
+ this.fileName = fileName;
+ alreadyLoaded = false;
+ }
+
+ public TemplateGroupResources(string fileName) : this(fileName, DefaultDelimiterStart, DefaultDelimiterStop)
+ {
+
+ }
+
+ public override void ImportTemplates(IToken fileNameToken)
+ {
+ var text = Utility.Strip(fileNameToken.Text, 1);
+
+ TemplateGroup importingGroup = null;
+ if (text.EndsWith(GroupFileExtension))
+ {
+ importingGroup = new TemplateGroupResources(text, DelimiterStartChar, DelimiterStopChar);
+ }
+ else if (text.EndsWith(TemplateFileExtension))
+ {
+ importingGroup = new TemplateGroup(DelimiterStartChar, DelimiterStopChar);
+
+ using (var resourceStream = StreamFromResources(text))
+ {
+ if (resourceStream != null)
+ {
+ using (var textStream = new StreamReader(resourceStream))
+ {
+ var inputStream = new ANTLRReaderStream(textStream)
+ {
+ name = fileName
+ };
+
+ importingGroup.LoadTemplateFile("/", fileName, inputStream);
+ }
+ }
+ }
+ }
+
+ if (importingGroup != null)
+ {
+ importingGroup.Load();
+ ImportTemplates(importingGroup);
+ }
+ else
+ {
+ ErrorManager.CompiletimeError(ErrorType.CANT_IMPORT, null, fileNameToken, text);
+ }
+ }
+
+ public override void Load()
+ {
+ if (alreadyLoaded)
+ return;
+ alreadyLoaded = true;
+
+ if (Verbose)
+ Console.WriteLine($"loading group file '{fileName}'");
+
+ using (var resourceStream = StreamFromResources(fileName))
+ {
+ if (resourceStream == null)
+ {
+ if (Verbose)
+ Console.WriteLine($"Resource '{fileName}' doesn't exist");
+
+ return;
+ }
+
+ using (var textStream = new StreamReader(resourceStream))
+ {
+ var inputStream = new ANTLRReaderStream(textStream)
+ {
+ name = fileName
+ };
+
+ try
+ {
+ var lexer = new GroupLexer(inputStream);
+ var tokenStream = new CommonTokenStream(lexer);
+ var parser = new GroupParser(tokenStream);
+
+ parser.group(this, "/");
+ }
+ catch (Exception ex)
+ {
+ ErrorManager.IOError(null, ErrorType.CANT_LOAD_GROUP_FILE, ex, FileName);
+ }
+ }
+ }
+ }
+
+ private static Stream StreamFromResources(string fileName)
+ {
+ var resourceName = $"{ResourceBasePath}.{fileName}";
+ var assembly = Assembly.GetExecutingAssembly();
+
+ return assembly.GetManifestResourceStream(resourceName);
+ }
+
+ public override string Name => "TemplateGroupResources";
+
+ public override string FileName => Name;
+ }
+}
diff --git a/src/ZoneCodeGenerator/Generating/Templates/Common.stg b/src/ZoneCodeGenerator/Generating/Templates/Common.stg
new file mode 100644
index 00000000..ce0ef5ac
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/Templates/Common.stg
@@ -0,0 +1,2 @@
+test() ::= <<
+>>
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg b/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg
new file mode 100644
index 00000000..8f96e655
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/Templates/ZoneLoad.stg
@@ -0,0 +1,225 @@
+delimiters "$", "$"
+
+import "Common.stg"
+
+Capital(name) ::= "$name; format=\"cap\"$"
+
+LoaderClassName(asset) ::= "Loader_$asset.Type.Name$"
+
+HeaderConstructor(context) ::= "$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream);"
+
+HeaderPtrLoadMethodDeclaration(structure) ::= "void LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr);"
+HeaderArrayLoadMethodDeclaration(structure) ::= "void LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, size_t count, bool atStreamStart);"
+HeaderLoadMethodDeclaration(structure) ::= "void Load_$structure.Type.Name$($structure.Type.FullName$** p$structure.Type.Name$, bool atStreamStart);"
+
+HeaderGetNameMethodDeclaration(asset) ::= "static std::string GetAssetName($asset.Type.FullName$* p$asset.Type.Name$);"
+HeaderAssetLoadMethodDeclaration(asset) ::= "void LoadAsset_$asset.Type.Name$($asset.Type.FullName$** pPtr);"
+
+HeaderDeclaration(structure) ::= <%
+$if(structure.PointerReferenceExists)$
+$HeaderPtrLoadMethodDeclaration(structure)$
+$\n$
+$endif$
+
+$if(structure.ArrayReferenceExists)$
+$HeaderArrayLoadMethodDeclaration(structure)$
+$\n$
+$endif$
+
+$if(structure.NonEmbeddedReferenceExists)$
+$HeaderLoadMethodDeclaration(structure)$
+$\n$
+$endif$
+%>
+
+// =======================
+// Header file entry point
+// =======================
+header(context) ::= <<
+// ====================================================================
+// This file has been generated by ZoneCodeGenerator.
+// Do not modify.
+// Any changes will be discarded when regenerating.
+// ====================================================================
+
+#pragma once
+
+#include "Loading/AssetLoader.h"
+#include "Game/$context.Game$/$context.Game$.h"
+#include
+
+namespace $context.Game$
+{
+ class $LoaderClassName(context.Asset)$
+ {
+ $context.Structures:{structure | $if(!structure.IsAsset)$$HeaderDeclaration(structure)$$endif$}$
+ $HeaderLoadMethodDeclaration(context.Asset)$
+ $HeaderAssetLoadMethodDeclaration(context.Asset)$
+
+ public:
+ $HeaderConstructor(context)$
+
+ $HeaderPtrLoadMethodDeclaration(context.Asset)$
+ $HeaderGetNameMethodDeclaration(context.Asset)$
+ };
+}
+>>
+
+IncludeHeaderOfOtherAsset(asset) ::= <<
+#include "../$asset.Type.Name$/$asset.Type.Name; format="lower"$_load_db.h"
+
+>>
+
+LoadMethod(structure, context) ::= <<
+void $LoaderClassName(context.Asset)$::Load_$structure.Type.Name$($structure.Type.FullName$* p$structure.Type.Name$, const bool atStreamStart)
+{
+ assert(p$structure.Type.Name$ != nullptr);
+
+ if(atStreamStart)
+ m_stream->Load<$structure.Type.FullName$>();
+ $if(structure.Block.IsTemp)$
+
+ m_stream->PushBlock($context.DefaultNormalBlock.Name$);
+ $endif$
+
+ // Load content here
+ $if(structure.Block.IsTemp)$
+
+ m_stream->PopBlock();
+ $endif$
+}
+>>
+
+LoadPtrMethod(structure, context) ::= <<
+void $LoaderClassName(context.Asset)$::LoadPtr_$structure.Type.Name$($structure.Type.FullName$** pPtr)
+{
+ assert(pPtr != nullptr);
+
+ m_stream->PushBlock($structure.Block.Name$);
+
+ if(*pPtr != nullptr)
+ {
+ $if(structure.Block.IsTemp)$
+ if(*pPtr == PTR_FOLLOWING || *pPtr == PTR_INSERT)
+ $else$
+ if(*pPtr == PTR_FOLLOWING)
+ $endif$
+ {
+ $if(structure.Block.IsTemp)$
+ $structure.Type.FullName$** toInsert = nullptr;
+ if(*pPtr == PTR_INSERT)
+ toInsert = m_stream->InsertPointer<$structure.Type.FullName$>();
+
+ $endif$
+ $if(structure.HasNonDefaultAlign)$
+ *pPtr = m_stream->Alloc<$structure.Type.FullName$>($structure.FastFileAlign$);
+ $else$
+ *pPtr = m_stream->Alloc<$structure.Type.FullName$>();
+ $endif$
+ Load_$structure.Type.Name$(*pPtr, true);
+ $if(structure.IsAsset)$
+ LoadAsset_$structure.Type.Name$(pPtr);
+ $endif$
+ $if(structure.Block.IsTemp)$
+
+ if(toInsert != nullptr)
+ *toInsert = *pPtr;
+ $endif$
+ }
+ else
+ {
+ $if(structure.Block.IsTemp)$
+ *pPtr = m_stream->ConvertOffsetToAlias(*ptr);
+ $else$
+ *pPtr = m_stream->ConvertOffsetToPointer(*ptr);
+ $endif$
+ }
+ }
+
+ m_stream->PopBlock();
+}
+>>
+
+LoadArrayMethod(structure, context) ::= <<
+void $LoaderClassName(context.Asset)$::LoadArray_$structure.Type.Name$($structure.Type.FullName$** pArray, const size_t count, const bool atStreamStart)
+{
+ assert(pArray != nullptr);
+
+ if(atStreamStart)
+ m_stream->Load<$structure.Type.FullName$>(count);
+
+ for(size_t index = 0; index < count; index++)
+ {
+ Load_$structure.Type.Name$(&pArray[index], false);
+ }
+}
+>>
+
+SourceDefinition(structure, context) ::= <<
+$if(structure.NonEmbeddedReferenceExists)$
+$LoadMethod(structure, context)$
+
+$endif$
+$if(structure.PointerReferenceExists)$
+$LoadPtrMethod(structure, context)$
+
+$endif$
+$if(structure.ArrayReferenceExists)$
+$LoadArrayMethod(structure, context)$
+
+$endif$
+>>
+
+ConstructorMethod(context) ::= <<
+$LoaderClassName(context.Asset)$::$LoaderClassName(context.Asset)$(IZoneScriptStringProvider* scriptStringProvider, Zone* zone, IZoneInputStream* stream)
+ : AssetLoader($context.Asset.AssetEnumEntry.Name$, scriptStringProvider, zone, stream){}
+>>
+
+LoadAssetMethod(structure, context) ::= <<
+void $LoaderClassName(context.Asset)$::LoadAsset_$structure.Type.Name$($structure.Type.FullName$** pPtr)
+{
+ assert(pPtr != nullptr);
+ *pPtr = static_cast<$structure.Type.FullName$*>(LinkAsset(GetAssetName(*pPtr), *pPtr));
+}
+>>
+
+GetNameMethod(context) ::= <<
+std::string $LoaderClassName(context.Asset)$::GetAssetName($context.Asset.Type.FullName$* p$context.Asset.Type.Name$)
+{
+$if(context.Asset.HasNameMember)$
+ return p$context.Asset.Type.Name$->name;
+$else$
+ return "$context.Asset.Type.Name$";
+$endif$
+}
+>>
+
+// =======================
+// Source file entry point
+// =======================
+source(context) ::= <<
+// ====================================================================
+// This file has been generated by ZoneCodeGenerator.
+// Do not modify.
+// Any changes will be discarded when regenerating.
+// ====================================================================
+
+#include "$context.Asset.Type.Name; format="lower"$_load_db.h"
+#include
+
+// Referenced Assets:
+$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
+
+using namespace $context.Game$;
+
+$ConstructorMethod(context)$
+
+$context.Structures:{structure | $if(!structure.IsAsset)$$SourceDefinition(structure, context)$$endif$}$
+$LoadMethod(context.Asset, context)$
+
+$LoadAssetMethod(context.Asset, context)$
+
+$LoadPtrMethod(context.Asset, context)$
+
+$GetNameMethod(context)$
+>>
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Generating/Templates/ZoneWrite.stg b/src/ZoneCodeGenerator/Generating/Templates/ZoneWrite.stg
new file mode 100644
index 00000000..f6dd71b2
--- /dev/null
+++ b/src/ZoneCodeGenerator/Generating/Templates/ZoneWrite.stg
@@ -0,0 +1,38 @@
+delimiters "$", "$"
+
+import "Common.stg"
+
+WriterClassName(asset) ::= "$asset.Type.Name; format=\"cap\"$ZoneWriter"
+
+// =======================
+// Header file entry point
+// =======================
+header(context) ::= <<
+#pragma once
+
+namespace ZoneLoader
+{
+ class $WriterClassName(context.Asset)$
+ {
+ public:
+ // TODO
+ }
+}
+>>
+
+IncludeHeaderOfOtherAsset(asset) ::= <<
+#include "../$asset.Type.Name$/$asset.Type.Name; format="lower"$_write_db.h"
+
+>>
+
+// =======================
+// Source file entry point
+// =======================
+source(context) ::= <<
+#include "$context.Asset.Type.Name; format="lower"$_write_db.h"
+
+// Referenced Assets:
+$context.ReferencedAssets:IncludeHeaderOfOtherAsset()$
+
+// TODO
+>>
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Interface/Arguments/ArgumentParser.cs b/src/ZoneCodeGenerator/Interface/Arguments/ArgumentParser.cs
new file mode 100644
index 00000000..bfa621d0
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/Arguments/ArgumentParser.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ZoneCodeGenerator.Interface.Arguments
+{
+ class ArgumentParser
+ {
+ private readonly CommandLineOption[] options;
+
+ private readonly List noOptionArgs;
+ private readonly Dictionary> optionArgs;
+
+ public IReadOnlyList Arguments => noOptionArgs.AsReadOnly();
+
+ public ArgumentParser(CommandLineOption[] options)
+ {
+ this.options = options;
+ noOptionArgs = new List();
+ optionArgs = new Dictionary>();
+ }
+
+ public bool ParseArguments(string[] args)
+ {
+ noOptionArgs.Clear();
+ optionArgs.Clear();
+
+ for (var i = 0; i < args.Length; i++)
+ {
+ var arg = args[i];
+
+ if (arg.StartsWith("-"))
+ {
+ CommandLineOption matchedOption;
+
+ if (arg.StartsWith("--"))
+ {
+ var longNameToFind = arg.Substring(2);
+ matchedOption = options.FirstOrDefault(option => longNameToFind.Equals(option.LongName));
+ }
+ else
+ {
+ var shortNameToFind = arg.Substring(1);
+ matchedOption = options.FirstOrDefault(option => shortNameToFind.Equals(option.ShortName));
+ }
+
+ if (matchedOption == null)
+ {
+ Console.WriteLine($"Unknown option '{arg}'.");
+ return false;
+ }
+
+ List parameters;
+ if (optionArgs.ContainsKey(matchedOption))
+ {
+ if (!matchedOption.MultiUse)
+ {
+ Console.WriteLine($"Option '{arg}' already specified.");
+ return false;
+ }
+
+ parameters = optionArgs[matchedOption];
+ }
+ else
+ {
+ parameters = new List();
+ optionArgs.Add(matchedOption, parameters);
+ }
+
+ if (i + matchedOption.ParameterCount >= args.Length)
+ {
+ Console.WriteLine($"Not enough parameters for option '{arg}'.");
+ return false;
+ }
+
+ for (var parameter = 0; parameter < matchedOption.ParameterCount; parameter++)
+ {
+ if (args[i + parameter + 1].StartsWith("-"))
+ {
+ Console.WriteLine($"Not enough parameters for option '{arg}'.");
+ return false;
+ }
+
+ parameters.Add(args[i + parameter + 1]);
+ }
+
+ i += matchedOption.ParameterCount;
+ }
+ else
+ {
+ noOptionArgs.Add(arg);
+ }
+ }
+
+ return true;
+ }
+
+ public bool IsOptionSpecified(CommandLineOption option)
+ {
+ return optionArgs.ContainsKey(option);
+ }
+
+ public string GetValueForOption(CommandLineOption option)
+ {
+ return IsOptionSpecified(option) ? string.Join(" ", optionArgs[option]) : null;
+ }
+
+ public IReadOnlyList GetParametersForOption(CommandLineOption option)
+ {
+ return IsOptionSpecified(option) ? optionArgs[option].AsReadOnly() : null;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/Arguments/CommandLineOption.cs b/src/ZoneCodeGenerator/Interface/Arguments/CommandLineOption.cs
new file mode 100644
index 00000000..53a04be4
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/Arguments/CommandLineOption.cs
@@ -0,0 +1,83 @@
+using System.Collections.Generic;
+
+namespace ZoneCodeGenerator.Interface.Arguments
+{
+ class CommandLineOption
+ {
+ public string ShortName { get; private set; }
+ public string LongName { get; private set; }
+ public string Description { get; private set; }
+ public string Category { get; private set; }
+ public bool MultiUse { get; private set; }
+
+ private readonly List parameters;
+ public IReadOnlyList Parameters => parameters.AsReadOnly();
+ public int ParameterCount => parameters.Count;
+
+ private CommandLineOption()
+ {
+ ShortName = null;
+ LongName = null;
+ Description = "";
+ Category = "";
+ MultiUse = false;
+ parameters = new List();
+ }
+
+ public class CommandLineOptionBuilder
+ {
+ private readonly CommandLineOption option;
+
+ private CommandLineOptionBuilder()
+ {
+ option = new CommandLineOption();
+ }
+
+ public static CommandLineOptionBuilder Create()
+ {
+ return new CommandLineOptionBuilder();
+ }
+
+ public CommandLineOptionBuilder WithShortName(string shortName)
+ {
+ option.ShortName = shortName;
+ return this;
+ }
+
+ public CommandLineOptionBuilder WithLongName(string longName)
+ {
+ option.LongName = longName;
+ return this;
+ }
+
+ public CommandLineOptionBuilder WithDescription(string description)
+ {
+ option.Description = description;
+ return this;
+ }
+
+ public CommandLineOptionBuilder WithCategory(string category)
+ {
+ option.Category = category;
+ return this;
+ }
+
+ public CommandLineOptionBuilder WithParameter(string argumentName)
+ {
+ option.parameters.Add(argumentName);
+ return this;
+ }
+
+ public CommandLineOptionBuilder Reusable()
+ {
+ option.MultiUse = true;
+ return this;
+ }
+
+ public CommandLineOption Build()
+ {
+ return option;
+ }
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/Arguments/UsageInformation.cs b/src/ZoneCodeGenerator/Interface/Arguments/UsageInformation.cs
new file mode 100644
index 00000000..8cacb0e8
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/Arguments/UsageInformation.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Linq;
+using System.Text;
+
+namespace ZoneCodeGenerator.Interface.Arguments
+{
+ static class UsageInformation
+ {
+ public static string FromCommandlineOptions(CommandLineOption[] options)
+ {
+ var usageInformation = new StringBuilder();
+ usageInformation.AppendLine("Usage:");
+ usageInformation.AppendLine();
+
+ var longestShortName = 0;
+ var longestLongName = 0;
+ var longestArgumentLength = 0;
+
+ foreach (var option in CommandLineOptions.ALL_OPTIONS)
+ {
+ if (option.ShortName != null && longestShortName < option.ShortName.Length)
+ longestShortName = option.ShortName.Length;
+
+ if (option.LongName != null && longestLongName < option.LongName.Length)
+ longestLongName = option.LongName.Length;
+
+ var argumentLength = GetOptionArgumentLength(option);
+ if (longestArgumentLength < argumentLength)
+ longestArgumentLength = argumentLength;
+ }
+
+ var categories = CommandLineOptions.ALL_OPTIONS
+ .Select(option => option.Category)
+ .Distinct();
+
+ var firstCategory = true;
+ foreach (var category in categories)
+ {
+ var optionsOfCategory = CommandLineOptions.ALL_OPTIONS
+ .Where(option => category.Equals(option.Category));
+
+ if(!firstCategory)
+ usageInformation.AppendLine();
+
+ if (!string.IsNullOrEmpty(category))
+ {
+ usageInformation.AppendLine($"== {category} ==");
+ }
+
+ foreach (var option in optionsOfCategory)
+ {
+ if (option.ShortName != null)
+ {
+ usageInformation.Append($"-{option.ShortName}");
+ usageInformation.Append(' ', longestShortName - option.ShortName.Length);
+
+ if (option.LongName != null)
+ usageInformation.Append(", ");
+ else
+ usageInformation.Append(' ', 2);
+ }
+ else
+ {
+ usageInformation.Append(' ', longestShortName + 1 + 2);
+ }
+
+ if (option.LongName != null)
+ {
+ usageInformation.Append($"--{option.LongName}");
+ usageInformation.Append(' ', longestLongName - option.LongName.Length);
+ }
+ else
+ {
+ usageInformation.Append(' ', longestLongName + 2);
+ }
+
+ usageInformation.Append(' ');
+
+ var argumentLength = GetOptionArgumentLength(option);
+ for(var i = 0; i < option.ParameterCount; i++)
+ {
+ if (i != 0)
+ usageInformation.Append(' ');
+
+ usageInformation.Append($"<{option.Parameters[i]}>");
+ }
+
+ usageInformation.Append(' ', longestArgumentLength - argumentLength + 1);
+
+ usageInformation.Append(option.Description);
+
+ usageInformation.AppendLine();
+ }
+
+ firstCategory = false;
+ }
+
+ return usageInformation.ToString();
+ }
+
+ private static int GetOptionArgumentLength(CommandLineOption option)
+ {
+ return option.ParameterCount * 2 // < and >
+ + option.Parameters.Select(s => s.Length).Sum() // Length of the argument name
+ + Math.Max(0, option.ParameterCount - 1); // One space between each argument
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/CUI.cs b/src/ZoneCodeGenerator/Interface/CUI.cs
new file mode 100644
index 00000000..515a7331
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/CUI.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Linq;
+using ZoneCodeGenerator.Generating;
+using ZoneCodeGenerator.Interface.Arguments;
+using ZoneCodeGenerator.Parsing.C_Header;
+using ZoneCodeGenerator.Parsing.CommandFile;
+
+namespace ZoneCodeGenerator.Interface
+{
+ class CUI
+ {
+ public bool Start(string[] args)
+ {
+ var argumentParser = new ArgumentParser(CommandLineOptions.ALL_OPTIONS);
+
+ if (args.Length == 0 || !argumentParser.ParseArguments(args))
+ {
+ PrintUsage();
+ return false;
+ }
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_HELP))
+ {
+ PrintUsage();
+ return true;
+ }
+
+ var session = new CUISession();
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_OUTPUT_FOLDER))
+ {
+ session.GeneratorOutputPath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_OUTPUT_FOLDER);
+ }
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_CREATE))
+ {
+ session.SourceFilePath = argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE);
+ session.Repository = HeaderReader.ReadFile(session.SourceFilePath);
+
+ if (session.Repository == null)
+ {
+ Console.WriteLine($"Creating a database from header file '{argumentParser.GetValueForOption(CommandLineOptions.OPTION_CREATE)}' failed.");
+ return false;
+ }
+ }
+ else
+ {
+ Console.WriteLine("Parsing a c header is needed to perform any other action.");
+ return false;
+ }
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_EDITING_COMMANDS))
+ {
+ if (!CommandFileReader.ReadFile(argumentParser.GetValueForOption(CommandLineOptions.OPTION_EDITING_COMMANDS), session))
+ {
+ return false;
+ }
+ }
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_PRINT))
+ {
+ var printer = new PrettyPrinter(session.Repository);
+ printer.PrintAll();
+ }
+
+ if (argumentParser.IsOptionSpecified(CommandLineOptions.OPTION_GENERATE))
+ {
+ var generationArgs = argumentParser.GetParametersForOption(CommandLineOptions.OPTION_GENERATE);
+ for (var i = 0; i < generationArgs.Count; i += CommandLineOptions.OPTION_GENERATE.ParameterCount)
+ {
+ var assetName = generationArgs[i];
+ var preset = generationArgs[i + 1];
+
+ var assets = session.Repository.GetAllStructureInformation()
+ .Where(inf => inf.IsAsset);
+
+ if (!assetName.Equals("*"))
+ assets = assets.Where(inf =>
+ inf.Type.FullName.Equals(assetName, StringComparison.CurrentCultureIgnoreCase));
+
+ if (!assets.Any())
+ {
+ Console.WriteLine($"Could not find asset '{assetName}'.");
+ continue;
+ }
+
+ foreach (var asset in assets)
+ {
+ if (CodeGenerator.GenerateCodeForPreset(preset, asset, session))
+ {
+ Console.WriteLine($"Successfully generated code for asset '{asset.Type.FullName}' with preset '{preset}'");
+ }
+ else
+ {
+ Console.WriteLine($"Could not generate code for asset '{asset.Type.FullName}' with preset '{preset}'");
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static void PrintUsage()
+ {
+ Console.WriteLine(UsageInformation.FromCommandlineOptions(CommandLineOptions.ALL_OPTIONS));
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/CUISession.cs b/src/ZoneCodeGenerator/Interface/CUISession.cs
new file mode 100644
index 00000000..0a4262f6
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/CUISession.cs
@@ -0,0 +1,18 @@
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Interface
+{
+ class CUISession
+ {
+ public string Game { get; set; }
+ public IDataRepository Repository { get; set; }
+ public string GeneratorOutputPath { get; set; }
+ public string SourceFilePath { get; set; }
+
+ public CUISession()
+ {
+ Repository = null;
+ GeneratorOutputPath = ".";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/CommandLineOptions.cs b/src/ZoneCodeGenerator/Interface/CommandLineOptions.cs
new file mode 100644
index 00000000..85078405
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/CommandLineOptions.cs
@@ -0,0 +1,91 @@
+using ZoneCodeGenerator.Generating;
+using ZoneCodeGenerator.Interface.Arguments;
+
+namespace ZoneCodeGenerator.Interface
+{
+ static class CommandLineOptions
+ {
+ // ------
+ // GENERAL
+ // ------
+
+ public static readonly CommandLineOption OPTION_HELP = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("?")
+ .WithLongName("help")
+ .WithDescription("Show usage.")
+ .Build();
+
+ // ------
+ // INPUT
+ // ------
+ private const string CategoryInput = "Input";
+
+ public static readonly CommandLineOption OPTION_CREATE = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("h")
+ .WithLongName("header")
+ .WithDescription("Create a new database from the specified header file.")
+ .WithCategory(CategoryInput)
+ .WithParameter("headerFile")
+ .Build();
+
+ // ------
+ // EDITING
+ // ------
+ private const string CategoryEditing = "Editing";
+
+ public static readonly CommandLineOption OPTION_EDITING_COMMANDS = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("e")
+ .WithLongName("editing-commands")
+ .WithDescription("Specifies the editing command file. Defaults to stdin.")
+ .WithCategory(CategoryEditing)
+ .WithParameter("commandFile")
+ .Build();
+
+ // ------
+ // OUTPUT
+ // ------
+ private const string CategoryOutput = "Output";
+
+ public static readonly CommandLineOption OPTION_OUTPUT_FOLDER = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("o")
+ .WithLongName("output")
+ .WithDescription("Specify the folder to save the generate code files to. Defaults to the current directory.")
+ .WithCategory(CategoryOutput)
+ .WithParameter("outputPath")
+ .Build();
+
+ public static readonly CommandLineOption OPTION_PRINT = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("p")
+ .WithLongName("print")
+ .WithDescription("Print the loaded data.")
+ .WithCategory(CategoryOutput)
+ .Build();
+
+ public static readonly CommandLineOption OPTION_GENERATE = CommandLineOption.CommandLineOptionBuilder.Create()
+ .WithShortName("g")
+ .WithLongName("generate")
+ .WithDescription($"Generates a specified asset/preset combination. Can be used multiple times. Available presets: {string.Join(", ", CodeGenerator.Presets)}")
+ .WithCategory(CategoryOutput)
+ .WithParameter("assetName")
+ .WithParameter("preset")
+ .Reusable()
+ .Build();
+
+ public static readonly CommandLineOption[] ALL_OPTIONS =
+ {
+ // GENERAL
+ OPTION_HELP,
+
+ // INPUT
+ OPTION_CREATE,
+
+ // EDITING
+ OPTION_EDITING_COMMANDS,
+
+ // OUTPUT
+ OPTION_OUTPUT_FOLDER,
+ OPTION_PRINT,
+ OPTION_GENERATE,
+ };
+ }
+}
diff --git a/src/ZoneCodeGenerator/Interface/PrettyPrinter.cs b/src/ZoneCodeGenerator/Interface/PrettyPrinter.cs
new file mode 100644
index 00000000..f18a4ba9
--- /dev/null
+++ b/src/ZoneCodeGenerator/Interface/PrettyPrinter.cs
@@ -0,0 +1,315 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Interface
+{
+ class PrettyPrinter
+ {
+ private readonly IDataRepository dataRepository;
+
+ public PrettyPrinter(IDataRepository dataRepository)
+ {
+ this.dataRepository = dataRepository;
+ }
+
+ public void PrintEnums()
+ {
+ var allEnums = dataRepository.GetAllEnums();
+ var dataTypeEnums = allEnums.ToList();
+
+ Console.WriteLine($"{dataTypeEnums.Count} enums:");
+
+ foreach(var _enum in dataTypeEnums)
+ {
+ Console.WriteLine($" Name: {_enum.FullName}");
+ Console.WriteLine($" Alignment: {_enum.Alignment}");
+ Console.WriteLine($" Size: {_enum.Size}");
+
+ foreach(var member in _enum.Members)
+ {
+ Console.WriteLine($" {member.Name} = {member.Value}");
+ }
+
+ Console.WriteLine();
+ }
+ }
+
+ private static void PrintVariablePointerToArray(Variable variable)
+ {
+ var arraySize = new List();
+ var pointerDepth = 0;
+ var referenceOffset = 0;
+
+ for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
+ {
+ if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
+ break;
+
+ pointerDepth++;
+ }
+
+ for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
+ {
+ if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
+ throw new Exception("Expected the rest of the references to be array references");
+
+ arraySize.Add(array.ArraySize);
+ }
+
+ var memberBuilder = new StringBuilder();
+ memberBuilder.Append(" ");
+ memberBuilder.Append(variable.VariableType.Type.FullName);
+ memberBuilder.Append('(');
+ memberBuilder.Append('*', pointerDepth);
+ memberBuilder.Append(variable.Name);
+ memberBuilder.Append(')');
+
+ foreach (var array in arraySize)
+ {
+ memberBuilder.Append('[');
+ memberBuilder.Append(array);
+ memberBuilder.Append(']');
+ }
+
+ Console.WriteLine(memberBuilder.ToString());
+ }
+
+ private static void PrintVariableArrayOfPointers(Variable variable)
+ {
+ var arraySize = new List();
+ var pointerDepth = 0;
+ var referenceOffset = 0;
+
+ for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
+ {
+ if (!(variable.VariableType.References[referenceOffset] is ReferenceTypeArray array))
+ break;
+
+ arraySize.Add(array.ArraySize);
+ }
+
+ for (; referenceOffset < variable.VariableType.References.Count; referenceOffset++)
+ {
+ if (!(variable.VariableType.References[referenceOffset] is ReferenceTypePointer))
+ throw new Exception("Expected the rest of the references to be pointer references");
+
+ pointerDepth++;
+ }
+
+ var memberBuilder = new StringBuilder();
+ memberBuilder.Append(" ");
+ memberBuilder.Append(variable.VariableType.Type.FullName);
+ memberBuilder.Append('*', pointerDepth);
+ memberBuilder.Append(" ");
+ memberBuilder.Append(variable.Name);
+
+ foreach (var array in arraySize)
+ {
+ memberBuilder.Append('[');
+ memberBuilder.Append(array);
+ memberBuilder.Append(']');
+ }
+
+ Console.WriteLine(memberBuilder.ToString());
+ }
+
+ private static void PrintVariable(Variable variable)
+ {
+ if (variable.VariableType.References.Count == 0)
+ {
+ Console.WriteLine($" {variable.VariableType.Type.FullName} {variable.Name}");
+ }
+ else
+ {
+ if (variable.VariableType.References[0] is ReferenceTypePointer &&
+ variable.VariableType.References.OfType().Any())
+ {
+ PrintVariablePointerToArray(variable);
+ }
+ else
+ {
+ PrintVariableArrayOfPointers(variable);
+ }
+ }
+ }
+
+ public void PrintStructs()
+ {
+ var allStructs = dataRepository.GetAllStructs();
+ var dataTypeStructs = allStructs.ToList();
+
+ Console.WriteLine($"{dataTypeStructs.Count} structs:");
+
+ foreach(var _struct in dataTypeStructs)
+ {
+ Console.WriteLine($" Name: {_struct.FullName}");
+ Console.WriteLine($" Alignment: {_struct.Alignment}");
+ Console.WriteLine($" Size: {_struct.Size}");
+
+ foreach(var member in _struct.Members)
+ PrintVariable(member);
+
+ Console.WriteLine();
+ }
+
+ }
+
+ public void PrintUnions()
+ {
+ var allUnions = dataRepository.GetAllUnions();
+ var dataTypeUnions = allUnions.ToList();
+
+ Console.WriteLine($"{dataTypeUnions.Count} unions:");
+
+ foreach(var union in dataTypeUnions)
+ {
+ Console.WriteLine($" Name: {union.FullName}");
+ Console.WriteLine($" Alignment: {union.Alignment}");
+ Console.WriteLine($" Size: {union.Size}");
+
+ foreach(var member in union.Members)
+ PrintVariable(member);
+
+ Console.WriteLine();
+ }
+ }
+
+ private static void PrintTypedefPointerToArray(DataTypeTypedef typedef)
+ {
+ var arraySize = new List();
+ var pointerDepth = 0;
+ var referenceOffset = 0;
+
+ for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
+ {
+ if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
+ break;
+
+ pointerDepth++;
+ }
+
+ for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
+ {
+ if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
+ throw new Exception("Expected the rest of the references to be array references");
+
+ arraySize.Add(array.ArraySize);
+ }
+
+ var memberBuilder = new StringBuilder();
+ memberBuilder.Append(" ");
+ memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
+ memberBuilder.Append('(');
+ memberBuilder.Append('*', pointerDepth);
+ memberBuilder.Append(')');
+
+ foreach (var array in arraySize)
+ {
+ memberBuilder.Append('[');
+ memberBuilder.Append(array);
+ memberBuilder.Append(']');
+ }
+
+ Console.WriteLine(memberBuilder.ToString());
+ }
+
+ private static void PrintTypedefArrayOfPointers(DataTypeTypedef typedef)
+ {
+ var arraySize = new List();
+ var pointerDepth = 0;
+ var referenceOffset = 0;
+
+ for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
+ {
+ if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypeArray array))
+ break;
+
+ arraySize.Add(array.ArraySize);
+ }
+
+ for (; referenceOffset < typedef.TypeDefinition.References.Count; referenceOffset++)
+ {
+ if (!(typedef.TypeDefinition.References[referenceOffset] is ReferenceTypePointer))
+ throw new Exception("Expected the rest of the references to be pointer references");
+
+ pointerDepth++;
+ }
+
+ var memberBuilder = new StringBuilder();
+ memberBuilder.Append(" ");
+ memberBuilder.Append(typedef.TypeDefinition.Type.FullName);
+ memberBuilder.Append('*', pointerDepth);
+
+ foreach (var array in arraySize)
+ {
+ memberBuilder.Append('[');
+ memberBuilder.Append(array);
+ memberBuilder.Append(']');
+ }
+
+ Console.WriteLine(memberBuilder.ToString());
+ }
+
+ public void PrintTypedefs()
+ {
+ var allTypedefs = dataRepository.GetAllTypedefs();
+ var dataTypeTypedefs = allTypedefs.ToList();
+
+ Console.WriteLine($"{dataTypeTypedefs.Count} typedefs:");
+
+ foreach (var typeDef in dataTypeTypedefs)
+ {
+ Console.WriteLine($" Name: {typeDef.FullName}");
+ Console.WriteLine($" Alignment: {typeDef.Alignment}");
+ Console.WriteLine($" Size: {typeDef.Size}");
+
+ if (typeDef.TypeDefinition.References.Count == 0)
+ {
+ Console.WriteLine($" {typeDef.TypeDefinition.Type.FullName}");
+ }
+ else
+ {
+ if (typeDef.TypeDefinition.References[0] is ReferenceTypePointer &&
+ typeDef.TypeDefinition.References.OfType().Any())
+ {
+ PrintTypedefPointerToArray(typeDef);
+ }
+ else
+ {
+ PrintTypedefArrayOfPointers(typeDef);
+ }
+ }
+
+ Console.WriteLine();
+ }
+
+ }
+
+ public void PrintAll()
+ {
+ PrintEnums();
+
+ Console.WriteLine();
+ Console.WriteLine("==========================================================================================================");
+ Console.WriteLine();
+
+ PrintStructs();
+
+ Console.WriteLine();
+ Console.WriteLine("==========================================================================================================");
+ Console.WriteLine();
+
+ PrintUnions();
+
+ Console.WriteLine();
+ Console.WriteLine("==========================================================================================================");
+ Console.WriteLine();
+
+ PrintTypedefs();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/LoadingException.cs b/src/ZoneCodeGenerator/LoadingException.cs
new file mode 100644
index 00000000..67ffa365
--- /dev/null
+++ b/src/ZoneCodeGenerator/LoadingException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace ZoneCodeGenerator
+{
+ class LoadingException : Exception
+ {
+ public LoadingException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/BlockType.cs b/src/ZoneCodeGenerator/Parsing/C_Header/BlockType.cs
new file mode 100644
index 00000000..5dfcf4de
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/BlockType.cs
@@ -0,0 +1,11 @@
+namespace ZoneCodeGenerator.Parsing.C_Header
+{
+ enum BlockType
+ {
+ None,
+ Enum,
+ Namespace,
+ Struct,
+ Union
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/Block.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/Block.cs
new file mode 100644
index 00000000..29a9fbfa
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/Block.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ abstract class Block
+ {
+ protected readonly IHeaderParserState State;
+ public BlockType Type { get; }
+
+ protected Block(IHeaderParserState headerParserState, BlockType type)
+ {
+ State = headerParserState;
+ Type = type;
+ }
+
+ public abstract IEnumerable> GetAvailableTests();
+
+ public abstract void OnOpen();
+
+ public abstract void OnClose();
+
+ public abstract void OnChildBlockClose(Block childBlock);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockEnum.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockEnum.cs
new file mode 100644
index 00000000..f1cca5d8
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockEnum.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ class BlockEnum : Block, INameAssignable, IVariableBlock
+ {
+ private readonly ITokenTest[] tests =
+ {
+ new TestEnumMember(),
+ new TestCloseBlock(true)
+ };
+
+ public string Name { get; }
+ public string AssignedName { get; private set; }
+ public string Namespace { get; private set; }
+ public DataTypeBaseType ParentType { get; }
+ public bool IsTypedef { get; }
+ public List Members { get; }
+
+ private DataTypeEnum _enum;
+
+ public BlockEnum(IHeaderParserState headerParserState, string name, DataTypeBaseType parentType, bool isTypedef) : base(headerParserState, BlockType.Enum)
+ {
+ Name = name;
+ ParentType = parentType;
+ IsTypedef = isTypedef;
+ Members = new List();
+ }
+
+ public override IEnumerable> GetAvailableTests()
+ {
+ return tests;
+ }
+
+ public override void OnOpen()
+ {
+ Namespace = State.CurrentNamespace.ToString();
+
+ State.CurrentNamespace.Push(Name);
+ }
+
+ public override void OnClose()
+ {
+ var poppedNamespaceName = State.CurrentNamespace.Pop();
+
+ if (!Name.Equals(poppedNamespaceName))
+ throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
+
+ _enum = new DataTypeEnum(Namespace, Name, ParentType);
+
+ _enum.Members.AddRange(Members);
+
+ State.AddDataType(_enum);
+
+ if (IsTypedef)
+ {
+ var typeDeclaration = new TypeDeclaration(_enum, new List());
+ var typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
+
+ State.AddDataType(typedef);
+ }
+ }
+
+ public override void OnChildBlockClose(Block childBlock)
+ {
+
+ }
+
+ public void AssignName(string nameAssignment)
+ {
+ AssignedName = nameAssignment;
+ }
+
+ public virtual void AddMember(EnumMember enumMember)
+ {
+ Members.Add(enumMember);
+ }
+
+ public virtual EnumMember FindMember(string enumMemberName)
+ {
+ return Members.Find(member => member.Name.Equals(enumMemberName));
+ }
+
+ public virtual long GetNextEnumValue()
+ {
+ var nextValue = 0L;
+
+ if (Members.Count > 0)
+ {
+ nextValue = Members[Members.Count - 1].Value + 1;
+ }
+
+ return nextValue;
+ }
+
+ public bool DefinesVariable()
+ {
+ return !IsTypedef && !string.IsNullOrEmpty(AssignedName) && _enum != null;
+ }
+
+ public Variable GetDefinedVariable()
+ {
+ if (!DefinesVariable())
+ return null;
+
+ var typeDeclaration = new TypeDeclaration(_enum, new List());
+ return new Variable(AssignedName, typeDeclaration);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNamespace.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNamespace.cs
new file mode 100644
index 00000000..a4b81527
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNamespace.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using ZoneCodeGenerator.Parsing.C_Header.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ class BlockNamespace : Block
+ {
+ private readonly ITokenTest[] tests =
+ {
+ new TestNamespace(),
+ new TestEnum(),
+ new TestStruct(),
+ new TestUnion(),
+ new TestTypedef(),
+ new TestForwardDecl(),
+ new TestCloseBlock()
+ };
+
+ public string Name { get; }
+
+ public BlockNamespace(IHeaderParserState headerParserState, string namespaceName) : base(headerParserState, BlockType.Namespace)
+ {
+ Name = namespaceName;
+ }
+
+ public override IEnumerable> GetAvailableTests()
+ {
+ return tests;
+ }
+
+ public override void OnOpen()
+ {
+ State.CurrentNamespace.Push(Name);
+ }
+
+ public override void OnClose()
+ {
+ var poppedNamespaceName = State.CurrentNamespace.Pop();
+
+ if (!Name.Equals(poppedNamespaceName))
+ throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of namespace block '{Name}'");
+ }
+
+ public override void OnChildBlockClose(Block childBlock)
+ {
+ // Do nothing
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNone.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNone.cs
new file mode 100644
index 00000000..89274588
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockNone.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Parsing.C_Header.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ class BlockNone : Block
+ {
+ private readonly ITokenTest[] tests =
+ {
+ new TestNamespace(),
+ new TestEnum(),
+ new TestStruct(),
+ new TestUnion(),
+ new TestTypedef(),
+ new TestForwardDecl()
+ };
+
+ public BlockNone(IHeaderParserState headerParserState) : base(headerParserState, BlockType.None)
+ {
+
+ }
+
+ public override IEnumerable> GetAvailableTests()
+ {
+ return tests;
+ }
+
+ public override void OnOpen()
+ {
+ // Do nothing
+ }
+
+ public override void OnClose()
+ {
+ // Do nothing
+ }
+
+ public override void OnChildBlockClose(Block childBlock)
+ {
+ // Do nothing
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockStruct.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockStruct.cs
new file mode 100644
index 00000000..c32feabd
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockStruct.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ class BlockStruct : Block, INameAssignable, IVariableHolder, IVariableBlock
+ {
+ private readonly ITokenTest[] tests =
+ {
+ new TestStruct(),
+ new TestEnum(),
+ new TestUnion(),
+ new TestVariable(),
+ new TestCloseBlock(true)
+ };
+
+ public string Name { get; }
+ public string AssignedName { get; private set; }
+ public string Namespace { get; private set; }
+ public bool IsTypedef { get; }
+ public int? CustomAlignment { get; set; }
+ public int Pack { get; private set; }
+ public List Variables { get; }
+
+ private DataTypeStruct _struct;
+ private DataTypeTypedef typedef;
+
+ public BlockStruct(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Struct)
+ {
+ Name = name;
+ IsTypedef = isTypedef;
+ Variables = new List();
+ AssignedName = "";
+ _struct = null;
+ typedef = null;
+ }
+
+ public override IEnumerable> GetAvailableTests()
+ {
+ return tests;
+ }
+
+ public override void OnOpen()
+ {
+ Pack = State.CurrentPack;
+
+ Namespace = State.CurrentNamespace.ToString();
+
+ State.CurrentNamespace.Push(Name);
+
+ State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Struct));
+ }
+
+ public override void OnClose()
+ {
+ var poppedNamespaceName = State.CurrentNamespace.Pop();
+
+ if (!Name.Equals(poppedNamespaceName))
+ throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of struct block '{Name}'");
+
+ _struct = new DataTypeStruct(Namespace, Name, Pack);
+
+ _struct.Members.AddRange(Variables);
+
+ State.AddDataType(_struct);
+
+ if (IsTypedef)
+ {
+ var typeDeclaration = new TypeDeclaration(_struct, new List());
+ typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
+
+ State.AddDataType(typedef);
+ }
+ }
+
+ public override void OnChildBlockClose(Block childBlock)
+ {
+ if (childBlock is IVariableBlock variableBlock)
+ {
+ AddVariable(variableBlock.GetDefinedVariable());
+ }
+ }
+
+ public void AssignName(string nameAssignment)
+ {
+ AssignedName = nameAssignment;
+ }
+
+ public void AddVariable(Variable variable)
+ {
+ Variables.Add(variable);
+ }
+
+ public Variable GetDefinedVariable()
+ {
+ var name = "";
+ DataType dataType = _struct;
+
+ if (!IsTypedef)
+ name = AssignedName;
+ else
+ dataType = typedef;
+
+ var typeDeclaration = new TypeDeclaration(dataType, new List());
+ return new Variable(name, typeDeclaration);
+ }
+
+ public void Inherit(DataTypeStruct parent)
+ {
+ foreach(var variable in parent.Members)
+ AddVariable(variable);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockUnion.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockUnion.cs
new file mode 100644
index 00000000..c39e1ff9
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/BlockUnion.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ class BlockUnion : Block, INameAssignable, IVariableHolder, IVariableBlock
+ {
+ private readonly ITokenTest[] tests =
+ {
+ new TestStruct(),
+ new TestEnum(),
+ new TestUnion(),
+ new TestVariable(),
+ new TestCloseBlock(true)
+ };
+
+ public string Name { get; }
+ public string AssignedName { get; private set; }
+ public string Namespace { get; private set; }
+ public bool IsTypedef { get; }
+ public int? CustomAlignment { get; set; }
+ public int Pack { get; private set; }
+ public List Variables { get; }
+
+ private DataTypeUnion union;
+ private DataTypeTypedef typedef;
+
+ public BlockUnion(IHeaderParserState headerParserState, string name, bool isTypedef) : base(headerParserState, BlockType.Union)
+ {
+ Name = name;
+ IsTypedef = isTypedef;
+ Variables = new List();
+ CustomAlignment = null;
+ AssignedName = "";
+ union = null;
+ typedef = null;
+ }
+
+ public override IEnumerable> GetAvailableTests()
+ {
+ return tests;
+ }
+
+ public override void OnOpen()
+ {
+ Namespace = State.CurrentNamespace.ToString();
+ Pack = State.CurrentPack;
+
+ State.CurrentNamespace.Push(Name);
+
+ State.AddForwardDeclaration(new ForwardDeclaration(Namespace, Name, DataTypeType.Union));
+ }
+
+ public override void OnClose()
+ {
+ var poppedNamespaceName = State.CurrentNamespace.Pop();
+
+ if (!Name.Equals(poppedNamespaceName))
+ throw new Exception($"Popped namespace '{poppedNamespaceName}' does not equal name of union block '{Name}'");
+
+ union = new DataTypeUnion(Namespace, Name, Pack)
+ {
+ AlignmentOverride = CustomAlignment
+ };
+
+ union.Members.AddRange(Variables);
+
+ State.AddDataType(union);
+
+ if (IsTypedef)
+ {
+ var typeDeclaration = new TypeDeclaration(union, new List());
+ typedef = new DataTypeTypedef(Namespace, AssignedName, typeDeclaration);
+
+ State.AddDataType(typedef);
+ }
+ }
+
+ public override void OnChildBlockClose(Block childBlock)
+ {
+ if (childBlock is IVariableBlock variableBlock)
+ {
+ AddVariable(variableBlock.GetDefinedVariable());
+ }
+ }
+
+ public void AssignName(string nameAssignment)
+ {
+ AssignedName = nameAssignment;
+ }
+
+ public void AddVariable(Variable variable)
+ {
+ Variables.Add(variable);
+ }
+
+ public Variable GetDefinedVariable()
+ {
+ var name = "";
+ DataType dataType = union;
+
+ if (!IsTypedef)
+ name = AssignedName;
+ else
+ dataType = typedef;
+
+ var typeDeclaration = new TypeDeclaration(dataType, new List());
+ return new Variable(name, typeDeclaration);
+ }
+
+ public void Inherit(DataTypeUnion parent)
+ {
+ foreach(var variable in parent.Members)
+ AddVariable(variable);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/INameAssignable.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/INameAssignable.cs
new file mode 100644
index 00000000..81b329c5
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/INameAssignable.cs
@@ -0,0 +1,7 @@
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ interface INameAssignable
+ {
+ void AssignName(string nameAssignment);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableBlock.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableBlock.cs
new file mode 100644
index 00000000..1ec216e0
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableBlock.cs
@@ -0,0 +1,9 @@
+using ZoneCodeGenerator.Domain;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ interface IVariableBlock
+ {
+ Variable GetDefinedVariable();
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableHolder.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableHolder.cs
new file mode 100644
index 00000000..ec58b894
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Blocks/IVariableHolder.cs
@@ -0,0 +1,9 @@
+using ZoneCodeGenerator.Domain;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Blocks
+{
+ interface IVariableHolder
+ {
+ void AddVariable(Variable variable);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/HeaderReader.cs b/src/ZoneCodeGenerator/Parsing/C_Header/HeaderReader.cs
new file mode 100644
index 00000000..05e112af
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/HeaderReader.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+using System.Linq;
+using ZoneCodeGenerator.Parsing.C_Header.Impl;
+using ZoneCodeGenerator.Parsing.C_Header.PostProcessor;
+using ZoneCodeGenerator.Parsing.Impl;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.C_Header
+{
+ static class HeaderReader
+ {
+ private static readonly IDataPostProcessor[] postProcessors =
+ {
+ new PostProcessorUsages(),
+ };
+
+ public static IDataRepository ReadFile(string path)
+ {
+ try
+ {
+ using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
+ {
+ var state = new HeaderParserState();
+ IDataRepository dataRepository;
+
+ using (IParsingFileStream preprocessorStream = new Preprocessor(streamFileSystem, state))
+ {
+ var lexer = new Lexer(preprocessorStream);
+ var parser = new Parser(state, lexer);
+
+ if (!parser.Parse())
+ return null;
+
+ dataRepository = new InMemoryDataRepository();
+ try
+ {
+ state.FinishAndSaveTo(dataRepository);
+ }
+ catch (LoadingException e)
+ {
+ PrintFinishingError(e);
+ return null;
+ }
+
+ preprocessorStream.Close();
+ streamFileSystem.Close();
+
+ }
+
+ if (!PostProcessRepository(dataRepository))
+ {
+ Console.WriteLine("Postprocessing data failed.");
+ return null;
+ }
+
+ return dataRepository;
+ }
+ }
+ catch (IOException)
+ {
+ return null;
+ }
+ }
+
+ private static bool PostProcessRepository(IDataRepository repository)
+ {
+ return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
+ }
+
+ private static void PrintFinishingError(LoadingException e)
+ {
+ Console.WriteLine("Parsing failed.");
+
+ Console.WriteLine(e.Message);
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/IHeaderParserState.cs b/src/ZoneCodeGenerator/Parsing/C_Header/IHeaderParserState.cs
new file mode 100644
index 00000000..c8fede13
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/IHeaderParserState.cs
@@ -0,0 +1,28 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.C_Header
+{
+ interface IHeaderParserState : IParserState
+ {
+ Namespace CurrentNamespace { get; }
+ int CurrentPack { get; }
+ Block CurrentBlock { get; }
+ Block PreviousBlock { get; }
+
+ void PushPack(int pack);
+ int PopPack();
+
+ void PushBlock(Block block);
+ Block PopBlock();
+
+ void AddDataType(DataType dataType);
+ void AddForwardDeclaration(ForwardDeclaration forwardDeclaration);
+
+ DataType FindType(string typename);
+ EnumMember FindEnumMember(string enumMemberName);
+
+ void FinishAndSaveTo(IDataRepository dataRepository);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Impl/HeaderParserState.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Impl/HeaderParserState.cs
new file mode 100644
index 00000000..28d480af
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Impl/HeaderParserState.cs
@@ -0,0 +1,208 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Testing;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Impl
+{
+ class HeaderParserState : IHeaderParserState
+ {
+ private const int DefaultPack = 8;
+
+ private readonly Block defaultBlock;
+ private readonly Stack packStack;
+ private readonly Stack blockStack;
+
+ private readonly Dictionary dataTypes;
+ private readonly Dictionary forwardDeclarations;
+
+ public Namespace CurrentNamespace { get; }
+
+ public HeaderParserState()
+ {
+ defaultBlock = new BlockNone(this);
+ packStack = new Stack();
+ blockStack = new Stack();
+
+ dataTypes = new Dictionary();
+ forwardDeclarations = new Dictionary();
+ CurrentNamespace = new Namespace();
+ }
+
+ public int CurrentPack => packStack.Count == 0 ? DefaultPack : packStack.Peek();
+
+ public Block CurrentBlock => blockStack.Count == 0 ? defaultBlock : blockStack.Peek();
+
+ public Block PreviousBlock => blockStack.Count < 2 ? defaultBlock : blockStack.ElementAt(1);
+
+ public void PushPack(int pack)
+ {
+ packStack.Push(pack);
+ }
+
+ public int PopPack()
+ {
+ return packStack.Pop();
+ }
+
+ public void PushBlock(Block block)
+ {
+ block.OnOpen();
+ blockStack.Push(block);
+ }
+
+ public Block PopBlock()
+ {
+ var block = blockStack.Pop();
+
+ block.OnClose();
+ CurrentBlock.OnChildBlockClose(block);
+
+ return block;
+ }
+
+ public void AddDataType(DataType dataType)
+ {
+ if (dataTypes.ContainsKey(dataType.FullName))
+ throw new ParserException($"Type '{dataType.FullName}' is already defined.");
+
+ dataTypes.Add(dataType.FullName, dataType);
+ }
+
+ public void AddForwardDeclaration(ForwardDeclaration forwardDeclaration)
+ {
+ if (forwardDeclarations.ContainsKey(forwardDeclaration.FullName))
+ {
+ var existingForwardDeclaration = forwardDeclarations[forwardDeclaration.FullName];
+
+ if(existingForwardDeclaration.Type != forwardDeclaration.Type)
+ throw new ParserException($"Forward declaration of type '{forwardDeclaration.FullName}' already done with different type.");
+ }
+ else
+ {
+ forwardDeclarations.Add(forwardDeclaration.FullName, forwardDeclaration);
+ }
+ }
+
+ public DataType FindType(string typename)
+ {
+ var currentNamespaceTypename = Namespace.Combine(CurrentNamespace, typename);
+
+ var baseType = DataTypeBaseType.BASE_TYPES.FirstOrDefault(databaseBaseType => databaseBaseType.Name.Equals(typename));
+
+ if (baseType != null)
+ return baseType;
+
+ if (dataTypes.ContainsKey(typename))
+ {
+ return dataTypes[typename];
+ }
+
+ if (dataTypes.ContainsKey(currentNamespaceTypename))
+ {
+ return dataTypes[currentNamespaceTypename];
+ }
+
+ if (forwardDeclarations.ContainsKey(typename))
+ {
+ return forwardDeclarations[typename];
+ }
+
+ if (forwardDeclarations.ContainsKey(currentNamespaceTypename))
+ {
+ return forwardDeclarations[currentNamespaceTypename];
+ }
+
+ return null;
+ }
+
+ public EnumMember FindEnumMember(string enumMemberName)
+ {
+ foreach(var block in blockStack)
+ {
+ if (!(block is BlockEnum blockEnum)) continue;
+
+ var foundMember = blockEnum.FindMember(enumMemberName);
+
+ if (foundMember != null)
+ return foundMember;
+ }
+
+ foreach (var dataType in dataTypes)
+ {
+ if (!(dataType.Value is DataTypeEnum _enum))
+ continue;
+
+ var foundMember = _enum.Members.Find(member => member.Name.Equals(enumMemberName));
+
+ if (foundMember != null)
+ return foundMember;
+ }
+
+ return null;
+ }
+
+ private void ResolveForwardDeclarations()
+ {
+ foreach(var forwardDeclaration in forwardDeclarations.Values)
+ {
+ var foundType = FindType(forwardDeclaration.FullName);
+
+ if (foundType == null || foundType is ForwardDeclaration)
+ throw new ParserException($"Type {forwardDeclaration.FullName} was declared but not defined.");
+
+ forwardDeclaration.ForwardedType = foundType;
+ }
+
+ foreach (var dataType in dataTypes.Values)
+ {
+ if (!(dataType is DataTypeWithMembers dataTypeWithMembers)) continue;
+
+ foreach (var variable in dataTypeWithMembers.Members)
+ {
+ if (variable.VariableType.Type is ForwardDeclaration forwardDeclaration)
+ variable.VariableType.Type = forwardDeclaration.ForwardedType;
+ }
+ }
+ }
+
+ public void FinishAndSaveTo(IDataRepository dataRepository)
+ {
+ if(blockStack.Count > 0)
+ throw new ParserException($"Parsing finished but {blockStack.Count} blocks were not closed.");
+
+ ResolveForwardDeclarations();
+
+ foreach (var dataType in dataTypes.Values)
+ {
+ switch (dataType)
+ {
+ case DataTypeEnum _enum:
+ dataRepository.Add(_enum);
+ break;
+ case DataTypeStruct _struct:
+ _struct.FinalizeDataType();
+ dataRepository.Add(_struct);
+ break;
+ case DataTypeTypedef typedef:
+ dataRepository.Add(typedef);
+ break;
+ case DataTypeUnion union:
+ union.FinalizeDataType();
+ dataRepository.Add(union);
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(dataType));
+ }
+ }
+ }
+
+ public IEnumerable> GetTests()
+ {
+ return CurrentBlock.GetAvailableTests();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Impl/Preprocessor.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Impl/Preprocessor.cs
new file mode 100644
index 00000000..8368c60a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Impl/Preprocessor.cs
@@ -0,0 +1,127 @@
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using ZoneCodeGenerator.Parsing.Impl;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Impl
+{
+ class Preprocessor : IParsingFileStream
+ {
+ private static readonly Regex packPushRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*push\s*,\s*(\d+)\s*\)\s*$");
+ private static readonly Regex packPopRegex = new Regex(@"^\s*#pragma\s+pack\s*\(\s*pop\s*\)\s*$");
+ private static readonly Regex defineRegex = new Regex(@"^\s*#define\s*(\w+)(?:\s*(.*))?$");
+ private static readonly Regex undefRegex = new Regex(@"^\s*#undef\s*(\w+)\s*$");
+ private static readonly Regex includeRegex = new Regex(@"^\s*#include\s*(?:\""(.*)\""|\<(.*)\>)\s*$");
+
+ private readonly IIncludingParsingStream streamFileSystem;
+ private readonly IHeaderParserState state;
+ private readonly ICommentProcessor commentProcessor;
+
+ private readonly Dictionary defines;
+
+ public bool EndOfStream => streamFileSystem.EndOfStream;
+ public string Filename => streamFileSystem.Filename;
+ public int Line => streamFileSystem.Line;
+
+ public Preprocessor(IIncludingParsingStream includingParsingStream, IHeaderParserState state)
+ {
+ streamFileSystem = includingParsingStream;
+ this.state = state;
+ defines = new Dictionary();
+ commentProcessor = new CommentProcessor();
+ }
+
+ private void ParseCompilerExpression(string line)
+ {
+ Match packPush = packPushRegex.Match(line.ToLower());
+ if(packPush.Success)
+ {
+ state.PushPack(int.Parse(packPush.Groups[1].Value));
+ return;
+ }
+
+ Match packPop = packPopRegex.Match(line.ToLower());
+ if(packPop.Success)
+ {
+ state.PopPack();
+ return;
+ }
+
+ Match define = defineRegex.Match(line);
+ if (define.Success)
+ {
+ string key = define.Groups[1].Value;
+ string value = define.Groups[2].Value.Trim();
+
+ if (defines.ContainsKey(key))
+ defines[key] = value;
+ else
+ defines.Add(key, value);
+ return;
+ }
+
+ Match undef = undefRegex.Match(line);
+ if (undef.Success)
+ {
+ var key = undef.Groups[1].Value;
+
+ if(defines.ContainsKey(key))
+ defines.Remove(key);
+ return;
+ }
+
+ Match include = includeRegex.Match(line);
+ if (include.Success)
+ {
+ string filename = include.Groups[1].Success ? include.Groups[1].Value : include.Groups[2].Value;
+
+ streamFileSystem.IncludeFile(filename);
+ return;
+ }
+ }
+
+ private string Preprocess(string line)
+ {
+ bool defineMatched;
+ line = commentProcessor.RemoveComments(line);
+
+ if (line.StartsWith("#"))
+ {
+ ParseCompilerExpression(line);
+ return "";
+ }
+
+ do
+ {
+ defineMatched = false;
+ foreach (KeyValuePair define in defines)
+ {
+ Match match = Regex.Match(line, $@"^(.*\W)?{define.Key}(\W.*)?$");
+
+ if (!match.Success) continue;
+
+ line = match.Groups[1].Value + define.Value + match.Groups[2].Value;
+ defineMatched = true;
+ break;
+ }
+
+ } while (defineMatched);
+
+ return line;
+ }
+
+ public string ReadLine()
+ {
+ return Preprocess(streamFileSystem.ReadLine());
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ public void Close()
+ {
+ streamFileSystem.Close();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/PostProcessor/PostProcessorUsages.cs b/src/ZoneCodeGenerator/Parsing/C_Header/PostProcessor/PostProcessorUsages.cs
new file mode 100644
index 00000000..e1d02ffa
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/PostProcessor/PostProcessorUsages.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.PostProcessor
+{
+ class PostProcessorUsages : IDataPostProcessor
+ {
+ public bool PostProcess(IDataRepository repository)
+ {
+ foreach (var dataTypeWithMembers in repository.GetAllStructs()
+ .AsEnumerable()
+ .Concat(repository.GetAllUnions()))
+ {
+ var information = repository.GetInformationFor(dataTypeWithMembers);
+
+ foreach (var memberInformation in information.OrderedMembers)
+ {
+ if (memberInformation.StructureType == null) continue;
+
+ memberInformation.StructureType.Usages.Add(information);
+
+ if (IsNonEmbeddedReference(memberInformation.Member))
+ memberInformation.StructureType.NonEmbeddedReferenceExists = true;
+
+ if (IsPointerReference(memberInformation.Member))
+ memberInformation.StructureType.PointerReferenceExists = true;
+
+ if (IsArrayReference(memberInformation.Member))
+ memberInformation.StructureType.PointerReferenceExists = true;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool IsNonEmbeddedReference(Variable var)
+ {
+ return var.VariableType.References.Any();
+ }
+
+ private static bool IsPointerReference(Variable var)
+ {
+ return var.VariableType.References.Any()
+ && var.VariableType.References.Last() is ReferenceTypePointer;
+ }
+
+ private static bool IsArrayReference(Variable var)
+ {
+ return var.VariableType.References.Any()
+ && var.VariableType.References.Last() is ReferenceTypeArray;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs
new file mode 100644
index 00000000..ffdbf254
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestCloseBlock.cs
@@ -0,0 +1,48 @@
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestCloseBlock : AbstractTokenTest
+ {
+ private const string NameToken = "close_with_name";
+ private const string SemicolonToken = "close_with_semi_colon";
+
+ private readonly bool semicolonRequired;
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("}"),
+ new MatcherGroupOptional( new MatcherGroupAnd(
+ new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
+ new MatcherLiteral(";").WithName(SemicolonToken)
+ ))
+ };
+
+ public TestCloseBlock(bool semicolonRequired = false) : base(matchers)
+ {
+ this.semicolonRequired = semicolonRequired;
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ if (HasMatcherTokens(NameToken))
+ {
+ if (state.CurrentBlock is INameAssignable nameAssignableBlock)
+ {
+ nameAssignableBlock.AssignName(GetMatcherTokens(NameToken)[0]);
+ }
+ else
+ {
+ throw new TestFailedException($"Cannot give block '{state.CurrentBlock.Type}' a name when closing");
+ }
+ }
+
+ if (!HasMatcherTokens(SemicolonToken) && semicolonRequired)
+ throw new TestFailedException($"Block '{state.CurrentBlock.Type}' needs to be closed with a '{'}'};'");
+
+ state.PopBlock();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs
new file mode 100644
index 00000000..1b98edf0
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnum.cs
@@ -0,0 +1,57 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+using ZoneCodeGenerator.Utils;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestEnum : AbstractTokenTest
+ {
+ private const string TypedefToken = "typedef";
+ private const string NameToken = "name";
+ private const string TypenameToken = "typename";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
+ new MatcherLiteral("enum"),
+ new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
+ new MatcherGroupOptional(new MatcherGroupAnd(new MatcherLiteral(":"), new MatcherTypename().WithName(TypenameToken))),
+ new MatcherLiteral("{")
+ };
+
+ public TestEnum() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var isTypedef = HasMatcherTokens(TypedefToken);
+ var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
+ var parentType = DataTypeBaseType.INT;
+
+ if (HasMatcherTokens(TypenameToken))
+ {
+ var typeName = GetMatcherTokens(TypenameToken)[0];
+ var type = state.FindType(typeName);
+
+ if (type == null)
+ throw new TestFailedException($"Parent type '{typeName}' of enum '{name}' not found.");
+
+ while (type is DataTypeTypedef typedef)
+ {
+ if (typedef.TypeDefinition.References.Count > 0)
+ throw new TestFailedException($"Parent type of enum '{name}' cannot be a typedef that is an array or a pointer.");
+
+ type = typedef.TypeDefinition.Type;
+ }
+
+ parentType = type as DataTypeBaseType ?? throw new TestFailedException($"Parent type of enum '{name}' must be a base type.");
+ }
+
+ state.PushBlock(new BlockEnum(state, name, parentType, isTypedef));
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs
new file mode 100644
index 00000000..d1608f1b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestEnumMember.cs
@@ -0,0 +1,66 @@
+using System;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestEnumMember : AbstractTokenTest
+ {
+ private const string NameToken = "name";
+ private const string NumberValueToken = "value_number";
+ private const string EnumMemberValueToken = "value_string";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherName().WithName(NameToken),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral("="),
+ new MatcherGroupOr(
+ new MatcherNumber().WithName(NumberValueToken),
+ new MatcherName().WithName(EnumMemberValueToken)
+ ))),
+ new MatcherGroupOr(
+ new MatcherLiteral(","),
+ new MatcherLiteral("}").NonConsuming()
+ )
+ };
+
+ public TestEnumMember() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var name = GetMatcherTokens(NameToken)[0];
+ long value;
+
+ if (!(state.CurrentBlock is BlockEnum _enum))
+ throw new Exception("Excepted enum to be top block when parsing an enum member.");
+
+ if (HasMatcherTokens(NumberValueToken))
+ {
+ value = long.Parse(GetMatcherTokens(NumberValueToken)[0]);
+ }
+ else if(HasMatcherTokens(EnumMemberValueToken))
+ {
+ var stringValue = GetMatcherTokens(EnumMemberValueToken)[0];
+ var memberWithFittingName = state.FindEnumMember(stringValue);
+
+ if(memberWithFittingName == null)
+ throw new TestFailedException($"Could not find value for '{stringValue}'.");
+
+ value = memberWithFittingName.Value;
+ }
+ else
+ {
+ value = _enum.GetNextEnumValue();
+ }
+
+ var enumMember = new EnumMember(name, value);
+ _enum.AddMember(enumMember);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs
new file mode 100644
index 00000000..c3e42a45
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestForwardDecl.cs
@@ -0,0 +1,52 @@
+using System;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestForwardDecl : AbstractTokenTest
+ {
+ private const string EnumToken = "enum";
+ private const string StructToken = "struct";
+ private const string UnionToken = "union";
+ private const string NameToken = "name";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherGroupOr(
+ new MatcherLiteral("enum").WithName(EnumToken),
+ new MatcherLiteral("struct").WithName(StructToken),
+ new MatcherLiteral("union").WithName(UnionToken)
+ ),
+ new MatcherName().WithName(NameToken),
+ new MatcherLiteral(";")
+ };
+
+ public TestForwardDecl() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var name = GetMatcherTokens(NameToken)[0];
+ var _namespace = state.CurrentNamespace.ToString();
+
+ if (HasMatcherTokens(EnumToken))
+ {
+ state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Enum));
+ }
+ else if (HasMatcherTokens(StructToken))
+ {
+ state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Struct));
+ }
+ else if (HasMatcherTokens(UnionToken))
+ {
+ state.AddForwardDeclaration(new ForwardDeclaration(_namespace, name, DataTypeType.Union));
+ }
+ else
+ throw new Exception("Unknown type for forward declaration.");
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs
new file mode 100644
index 00000000..3b169bb6
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestNamespace.cs
@@ -0,0 +1,29 @@
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestNamespace : AbstractTokenTest
+ {
+ private const string NamespaceNameToken = "namespace_name";
+
+ private static readonly TokenMatcher[] matchers =
+ {
+ new MatcherLiteral("namespace"),
+ new MatcherName().WithName(NamespaceNameToken),
+ new MatcherLiteral("{")
+ };
+
+ public TestNamespace() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ state.PushBlock(new BlockNamespace(state, GetMatcherTokens(NamespaceNameToken)[0]));
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs
new file mode 100644
index 00000000..12d0295d
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestStruct.cs
@@ -0,0 +1,69 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+using ZoneCodeGenerator.Utils;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestStruct : AbstractTokenTest
+ {
+ private const string TypedefToken = "typedef";
+ private const string NameToken = "name";
+ private const string AlignToken = "align";
+ private const string ParentToken = "parent";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
+ new MatcherGroupOptional(new MatcherLiteral("const")),
+ new MatcherLiteral("struct"),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral("__declspec"),
+ new MatcherLiteral("("),
+ new MatcherLiteral("align"),
+ new MatcherLiteral("("),
+ new MatcherNumber().WithName(AlignToken),
+ new MatcherLiteral(")"),
+ new MatcherLiteral(")")
+ )),
+ new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral(":"),
+ new MatcherTypename().WithName(ParentToken)
+ )),
+ new MatcherLiteral("{")
+ };
+
+ public TestStruct() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var isTypedef = HasMatcherTokens(TypedefToken);
+ var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
+
+ var block = new BlockStruct(state, name, isTypedef);
+
+ if (HasMatcherTokens(AlignToken))
+ block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]);
+
+ if (HasMatcherTokens(ParentToken))
+ {
+ var parentDataTypeName = GetMatcherTokens(ParentToken)[0];
+ var parentDataType = state.FindType(parentDataTypeName);
+
+ if(parentDataType == null)
+ throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for struct '{name}'");
+ if(!(parentDataType is DataTypeStruct parentStruct))
+ throw new TestFailedException($"Parent data type '{parentDataTypeName}' for struct '{name}' must be a struct as well.");
+
+ block.Inherit(parentStruct);
+ }
+
+ state.PushBlock(block);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs
new file mode 100644
index 00000000..c4290a83
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestTypedef.cs
@@ -0,0 +1,96 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestTypedef : AbstractTokenTest
+ {
+ private const string PointerToArrayVariant = "pointertoarray";
+ private const string ArrayOfPointersVariant = "arrayofpointers";
+ private const string TypeNameTokens = "typename";
+ private const string PointerTokens = "pointer";
+ private const string NameToken = "name";
+ private const string ArrayTokens = "array";
+
+ private static readonly TokenMatcher[] arrayOfPointersMatchers = {
+ new MatcherLiteral("typedef"),
+ new MatcherTypename().WithName(TypeNameTokens),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
+ new MatcherName().WithName(NameToken),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
+ new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
+ };
+
+ private static readonly TokenMatcher[] pointerToArrayMatchers = {
+ new MatcherLiteral("typedef"),
+ new MatcherTypename().WithName(TypeNameTokens),
+ new MatcherLiteral("("),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
+ new MatcherName().WithName(NameToken),
+ new MatcherLiteral(")"),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
+ new MatcherLiteral(";").WithName(PointerToArrayVariant)
+ };
+
+ private static readonly TokenMatcher[] matchers =
+ {
+ new MatcherGroupOr(
+ new MatcherGroupAnd(arrayOfPointersMatchers),
+ new MatcherGroupAnd(pointerToArrayMatchers)
+ )
+ };
+
+ public TestTypedef() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var name = GetMatcherTokens(NameToken)[0];
+ var pointerDepth = GetMatcherTokens(PointerTokens).Count;
+
+ var typeName = string.Join(" ", GetMatcherTokens(TypeNameTokens));
+ var type = state.FindType(typeName);
+
+ if (type == null)
+ throw new TestFailedException($"Could not find type '{typeName}' of typedef '{name}'.");
+
+ var arrayTokens = GetMatcherTokens(ArrayTokens);
+ var arraySize = new int[arrayTokens.Count];
+
+ for(var i = 0; i < arrayTokens.Count; i++)
+ {
+ if (!int.TryParse(arrayTokens[i], out arraySize[i]))
+ throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric.");
+ }
+
+ var references = new List();
+
+ if (HasMatcherTokens(PointerToArrayVariant))
+ {
+ for (var i = 0; i < pointerDepth; i++)
+ references.Add(new ReferenceTypePointer());
+
+ foreach(var array in arraySize)
+ references.Add(new ReferenceTypeArray(array));
+ }
+ else
+ {
+ foreach(var array in arraySize)
+ references.Add(new ReferenceTypeArray(array));
+
+ for (var i = 0; i < pointerDepth; i++)
+ references.Add(new ReferenceTypePointer());
+ }
+
+ var typeDeclaration = new TypeDeclaration(type, references);
+ var typedef = new DataTypeTypedef(state.CurrentNamespace.ToString(), name, typeDeclaration);
+
+ state.AddDataType(typedef);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs
new file mode 100644
index 00000000..935ae8ec
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestUnion.cs
@@ -0,0 +1,69 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+using ZoneCodeGenerator.Utils;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestUnion : AbstractTokenTest
+ {
+ private const string TypedefToken = "typedef";
+ private const string NameToken = "name";
+ private const string AlignToken = "align";
+ private const string ParentToken = "parent";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherGroupOptional(new MatcherLiteral("typedef").WithName(TypedefToken)),
+ new MatcherGroupOptional(new MatcherLiteral("const")),
+ new MatcherLiteral("union"),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral("__declspec"),
+ new MatcherLiteral("("),
+ new MatcherLiteral("align"),
+ new MatcherLiteral("("),
+ new MatcherNumber().WithName(AlignToken),
+ new MatcherLiteral(")"),
+ new MatcherLiteral(")")
+ )),
+ new MatcherGroupOptional(new MatcherName().WithName(NameToken)),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral(":"),
+ new MatcherTypename().WithName(ParentToken)
+ )),
+ new MatcherLiteral("{")
+ };
+
+ public TestUnion() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var isTypedef = HasMatcherTokens(TypedefToken);
+ var name = HasMatcherTokens(NameToken) ? GetMatcherTokens(NameToken)[0] : RandomName.GenerateName();
+
+ var block = new BlockUnion(state, name, isTypedef);
+
+ if (HasMatcherTokens(AlignToken))
+ block.CustomAlignment = int.Parse(GetMatcherTokens(AlignToken)[0]);
+
+ if (HasMatcherTokens(ParentToken))
+ {
+ var parentDataTypeName = GetMatcherTokens(ParentToken)[0];
+ var parentDataType = state.FindType(parentDataTypeName);
+
+ if(parentDataType == null)
+ throw new TestFailedException($"Could not find parent data type '{parentDataTypeName}' for union '{name}'");
+ if(!(parentDataType is DataTypeUnion parentUnion))
+ throw new TestFailedException($"Parent data type '{parentDataTypeName}' for union '{name}' must be a union as well.");
+
+ block.Inherit(parentUnion);
+ }
+
+ state.PushBlock(block);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs
new file mode 100644
index 00000000..4b8fa6f4
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/C_Header/Tests/TestVariable.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.C_Header.Blocks;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.C_Header.Tests
+{
+ class TestVariable : AbstractTokenTest
+ {
+ private const string PointerToArrayVariant = "pointertoarray";
+ private const string ArrayOfPointersVariant = "arrayofpointers";
+ private const string TypeNameToken = "typename";
+ private const string PointerTokens = "pointer";
+ private const string NameToken = "name";
+ private const string ArrayTokens = "array";
+ private const string BitSizeToken = "bitsize";
+
+ private static readonly TokenMatcher[] arrayOfPointersMatchers = {
+ new MatcherTypename().WithName(TypeNameToken),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
+ new MatcherName().WithName(NameToken),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray().WithName(ArrayTokens)),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherLiteral(":"),
+ new MatcherNumber().WithName(BitSizeToken)
+ )),
+ new MatcherLiteral(";").WithName(ArrayOfPointersVariant)
+ };
+
+ private static readonly TokenMatcher[] pointerToArrayMatchers = {
+ new MatcherTypename().WithName(TypeNameToken),
+ new MatcherLiteral("("),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherLiteral("*").WithName(PointerTokens)),
+ new MatcherName().WithName(NameToken),
+ new MatcherLiteral(")"),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherArray().WithName(ArrayTokens)),
+ new MatcherLiteral(";").WithName(PointerToArrayVariant)
+ };
+
+ private static readonly TokenMatcher[] matchers =
+ {
+ new MatcherGroupOr(
+ new MatcherGroupAnd(arrayOfPointersMatchers),
+ new MatcherGroupAnd(pointerToArrayMatchers)
+ )
+ };
+
+ public TestVariable() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(IHeaderParserState state)
+ {
+ var name = GetMatcherTokens(NameToken)[0];
+ var typeName = GetMatcherTokens(TypeNameToken)[0];
+ var type = state.FindType(typeName);
+
+ if (type == null)
+ throw new TestFailedException($"Type '{typeName}' not found.");
+
+ var pointerDepth = GetMatcherTokens(PointerTokens).Count;
+
+ var arrayTokens = GetMatcherTokens(ArrayTokens);
+ var arraySize = new int[arrayTokens.Count];
+
+ int? bitSize = null;
+ if (HasMatcherTokens(BitSizeToken))
+ bitSize = int.Parse(GetMatcherTokens(BitSizeToken)[0]);
+
+ for(var i = 0; i < arrayTokens.Count; i++)
+ {
+ if (!int.TryParse(arrayTokens[i], out arraySize[i]))
+ throw new TestFailedException($"Array size '{arrayTokens[i]}' is not numeric.");
+ }
+
+ if (state.CurrentBlock is IVariableHolder variableHolder)
+ {
+ var references = new List();
+
+ if (HasMatcherTokens(PointerToArrayVariant))
+ {
+ for (var i = 0; i < pointerDepth; i++)
+ references.Add(new ReferenceTypePointer());
+ foreach(var array in arraySize)
+ references.Add(new ReferenceTypeArray(array));
+ }
+ else
+ {
+ foreach(var array in arraySize)
+ references.Add(new ReferenceTypeArray(array));
+
+ for (var i = 0; i < pointerDepth; i++)
+ references.Add(new ReferenceTypePointer());
+ }
+
+ var typeDeclaration = bitSize == null ? new TypeDeclaration(type, references) : new TypeDeclaration(type, bitSize.Value, references);
+
+ var variable = new Variable(name, typeDeclaration);
+
+ variableHolder.AddVariable(variable);
+ }
+ else
+ {
+ throw new Exception("Expected current block to be a variable holder when parsing variables.");
+ }
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/CommandFileReader.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/CommandFileReader.cs
new file mode 100644
index 00000000..d2898b6e
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/CommandFileReader.cs
@@ -0,0 +1,67 @@
+using System;
+using System.IO;
+using System.Linq;
+using ZoneCodeGenerator.Interface;
+using ZoneCodeGenerator.Parsing.CommandFile.Impl;
+using ZoneCodeGenerator.Parsing.CommandFile.PostProcessor;
+using ZoneCodeGenerator.Parsing.Impl;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile
+{
+ static class CommandFileReader
+ {
+ private static readonly IDataPostProcessor[] postProcessors =
+ {
+ new PostProcessorDefaultBlock(),
+ };
+
+ public static bool ReadFile(string path, CUISession session)
+ {
+ try
+ {
+ using (IIncludingParsingStream streamFileSystem = new IncludingStreamFileSystem(path))
+ {
+ var state = new CommandParserState(session.Repository);
+
+ using (IParsingFileStream preprocessorStream = new CommandFilePreprocessor(streamFileSystem))
+ {
+ var lexer = new Lexer(preprocessorStream);
+ var parser = new Parser(state, lexer);
+
+ if (!parser.Parse())
+ return false;
+
+ preprocessorStream.Close();
+ streamFileSystem.Close();
+
+ if (!state.Apply(session))
+ {
+ Console.WriteLine("Finalizing from command file failed");
+ return false;
+ }
+
+ if (!PostProcessRepository(session.Repository))
+ {
+ Console.WriteLine("Postprocessing commands failed.");
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+ catch (IOException)
+ {
+
+ }
+
+ return false;
+ }
+
+ private static bool PostProcessRepository(IDataRepository repository)
+ {
+ return postProcessors.All(postProcessor => postProcessor.PostProcess(repository));
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/ICommandParserState.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/ICommandParserState.cs
new file mode 100644
index 00000000..e4b19c61
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/ICommandParserState.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile
+{
+ interface ICommandParserState : IParserState
+ {
+ string Game { get; set; }
+ IReadOnlyDataRepository Repository { get; }
+ List FastFileBlocks { get; }
+ DataTypeWithMembers DataTypeInUse { get; set; }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandFilePreprocessor.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandFilePreprocessor.cs
new file mode 100644
index 00000000..2f1b021b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandFilePreprocessor.cs
@@ -0,0 +1,56 @@
+using System.Text.RegularExpressions;
+using ZoneCodeGenerator.Parsing.Impl;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
+{
+ class CommandFilePreprocessor : IParsingFileStream
+ {
+ private static readonly Regex includeRegex = new Regex(@"^\s*include\s*(?:\""(.*)\""|\<(.*)\>)\s*$");
+
+ private readonly IIncludingParsingStream parsingStream;
+ private readonly ICommentProcessor commentProcessor;
+
+ public CommandFilePreprocessor(IIncludingParsingStream parsingStream)
+ {
+ this.parsingStream = parsingStream;
+ commentProcessor = new CommentProcessor();
+ }
+
+ public void Dispose()
+ {
+ parsingStream.Close();
+ }
+
+ public bool EndOfStream => parsingStream.EndOfStream;
+ public string Filename => parsingStream.Filename;
+ public int Line => parsingStream.Line;
+
+ public string ReadLine()
+ {
+ return Preprocess(parsingStream.ReadLine());
+ }
+
+ public void Close()
+ {
+ parsingStream.Close();
+ }
+
+ private string Preprocess(string line)
+ {
+ line = commentProcessor.RemoveComments(line);
+
+ var includeMatch = includeRegex.Match(line);
+
+ if (includeMatch.Success)
+ {
+ var filename = includeMatch.Groups[1].Success ? includeMatch.Groups[1].Value : includeMatch.Groups[2].Value;
+
+ parsingStream.IncludeFile(filename);
+
+ return "";
+ }
+
+ return line;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs
new file mode 100644
index 00000000..9d719f4c
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs
@@ -0,0 +1,53 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Interface;
+using ZoneCodeGenerator.Parsing.CommandFile.Tests;
+using ZoneCodeGenerator.Parsing.Testing;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Impl
+{
+ class CommandParserState : ICommandParserState
+ {
+ private static readonly ITokenTest[] tests = {
+ new TestAsset(),
+ new TestBlock(),
+ new TestCondition(),
+ new TestCount(),
+ new TestGame(),
+ new TestReorder(),
+ new TestScriptString(),
+ new TestUse()
+ };
+
+ public string Game { get; set; }
+ public IReadOnlyDataRepository Repository { get; }
+ public List FastFileBlocks { get; }
+ public DataTypeWithMembers DataTypeInUse { get; set; }
+
+ public CommandParserState(IReadOnlyDataRepository repository)
+ {
+ Repository = repository;
+ FastFileBlocks = new List();
+ DataTypeInUse = null;
+ }
+
+ public IEnumerable> GetTests()
+ {
+ return tests;
+ }
+
+ public bool Apply(CUISession session)
+ {
+ session.Game = Game;
+
+ foreach (var block in FastFileBlocks)
+ {
+ session.Repository.Add(block);
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorDefaultBlock.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorDefaultBlock.cs
new file mode 100644
index 00000000..413f3b68
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/PostProcessor/PostProcessorDefaultBlock.cs
@@ -0,0 +1,33 @@
+using System.Linq;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.PostProcessor
+{
+ class PostProcessorDefaultBlock : IDataPostProcessor
+ {
+ public bool PostProcess(IDataRepository repository)
+ {
+ var memberDataTypes =
+ repository.GetAllStructs()
+ .AsEnumerable()
+ .Concat(repository.GetAllUnions());
+
+ var defaultTemp = repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Temp && block.IsDefault) ??
+ repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Temp);
+
+ var defaultNormal = repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Normal && block.IsDefault) ??
+ repository.GetAllFastFileBlocks().First(block => block.BlockType == FastFileBlock.Type.Normal);
+
+ foreach (var memberType in memberDataTypes)
+ {
+ var info = repository.GetInformationFor(memberType);
+
+ info.Block = info.IsAsset ? defaultTemp : defaultNormal;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs
new file mode 100644
index 00000000..f4d0955a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestAsset.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestAsset : AbstractTokenTest
+ {
+ private const string AssetTypeNameToken = "name";
+ private const string AssetEnumEntryToken = "enumEntry";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("asset"),
+ new MatcherTypename().WithName(AssetTypeNameToken),
+ new MatcherName().WithName(AssetEnumEntryToken),
+ new MatcherLiteral(";")
+ };
+
+ public TestAsset() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+ var assetTypeName = GetMatcherTokens(AssetTypeNameToken)[0];
+
+ var assetType = state.Repository.GetDataTypeByName(assetTypeName);
+ if (assetType == null)
+ {
+ throw new LoadingException($"Could not find type '{assetTypeName}' to mark it as an asset.");
+ }
+
+ if (!(assetType is DataTypeWithMembers assetTypeWithMembers))
+ {
+ throw new LoadingException($"Type of asset '{assetTypeName}' needs to be struct or union.");
+ }
+
+ var assetInfo = state.Repository.GetInformationFor(assetTypeWithMembers);
+ if (assetType == null)
+ {
+ throw new LoadingException($"Could not find information for type '{assetTypeName}' to mark it as an asset.");
+ }
+
+ var enumEntryName = GetMatcherTokens(AssetEnumEntryToken)[0];
+ var enumEntry = state.Repository.GetAllEnums()
+ .SelectMany(_enum => _enum.Members)
+ .FirstOrDefault(member => member.Name.Equals(enumEntryName, StringComparison.CurrentCultureIgnoreCase));
+
+ assetInfo.AssetEnumEntry = enumEntry ?? throw new LoadingException(
+ $"Could not find enum entry '{enumEntryName}' as an asset type index for asset type '{assetTypeName}'.");
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs
new file mode 100644
index 00000000..cc55bde5
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestBlock.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Linq;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestBlock : AbstractTokenTest
+ {
+ private const string BlockNumberToken = "num";
+ private const string BlockTypeToken = "type";
+ private const string BlockNameToken = "name";
+ private const string DefaultToken = "default";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("block"),
+ new MatcherNumber().WithName(BlockNumberToken),
+ new MatcherName().WithName(BlockTypeToken),
+ new MatcherName().WithName(BlockNameToken),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple,new MatcherGroupOr(
+ new MatcherLiteral("default").WithName(DefaultToken)
+ )),
+ new MatcherLiteral(";")
+ };
+
+ public TestBlock() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+ var blockName = GetMatcherTokens(BlockNameToken)[0];
+ var blockNumber = int.Parse(GetMatcherTokens(BlockNumberToken)[0]);
+
+ var blockTypeInput = GetMatcherTokens(BlockTypeToken)[0];
+ if (!Enum.TryParse(blockTypeInput, true, out FastFileBlock.Type blockType))
+ {
+ var blockTypeValues = Enum.GetValues(typeof(FastFileBlock.Type)).OfType()
+ .Select(type => type.ToString());
+
+ throw new TestFailedException($"Unknown fastfile block type '{blockTypeInput}'. Must be one of the following: {string.Join(", ", blockTypeValues)}");
+ }
+
+ var block = new FastFileBlock(blockName, blockNumber, blockType, HasMatcherTokens(DefaultToken));
+
+ state.FastFileBlocks.Add(block);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs
new file mode 100644
index 00000000..9da49f0b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCondition.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestCondition : AbstractTokenTest
+ {
+ private const string TypeNameToken = "typeName";
+ private const string ConditionStatementTag = "conditionStatement";
+ private const string ConditionChainTag = "conditionChain";
+ private const string ConditionChainLinkTag = "conditionChainLink";
+ private const string OperationTag = "operation";
+ private const string OperandTag = "operand";
+
+ private static readonly TokenMatcher operand = new MatcherGroupOr(
+ new MatcherGroupAnd(
+ new MatcherTypename(),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray())
+ ),
+ new MatcherNumber(),
+ new MatcherLiteral("true"),
+ new MatcherLiteral("false")
+ ).WithTag(OperandTag);
+
+ private static readonly TokenMatcher operation = new MatcherGroupOr(
+ new MatcherLiteral("+"),
+ new MatcherLiteral("-"),
+ new MatcherLiteral("*"),
+ new MatcherLiteral("/"),
+ new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("<")),
+ new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral(">"))
+ ).WithTag(OperationTag);
+
+ private static readonly TokenMatcher conditionStatement = new MatcherGroupOr(
+ new MatcherGroupAnd(
+ new MatcherLiteral("("),
+ new MatcherWithTag(ConditionStatementTag),
+ new MatcherLiteral(")")
+ ),
+ new MatcherGroupAnd(
+ new MatcherWithTag(OperandTag),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherWithTag(OperationTag),
+ new MatcherWithTag(OperandTag)
+ ))
+ )
+ ).WithTag(ConditionStatementTag);
+
+ private static readonly TokenMatcher conditionChainLink = new MatcherGroupOr(
+ new MatcherGroupAnd(new MatcherLiteral("="), new MatcherLiteral("=")),
+ new MatcherGroupAnd(new MatcherLiteral("!"), new MatcherLiteral("=")),
+ new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("=")),
+ new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral("=")),
+ new MatcherLiteral("<"),
+ new MatcherLiteral(">")
+ ).WithTag(ConditionChainLinkTag);
+
+ private static readonly TokenMatcher conditionChain = new MatcherGroupAnd(
+ new MatcherWithTag(ConditionStatementTag),
+ new MatcherWithTag(ConditionChainLinkTag),
+ new MatcherWithTag(ConditionStatementTag)
+ ).WithTag(ConditionChainTag);
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("set"),
+ new MatcherLiteral("condition"),
+ new MatcherTypename().WithName(TypeNameToken),
+ new MatcherGroupOr(
+ new MatcherLiteral("never"),
+ new MatcherWithTag(ConditionChainTag)
+ ),
+ new MatcherLiteral(";")
+ };
+
+ public TestCondition() : base(matchers)
+ {
+ AddTaggedMatcher(conditionChain);
+ AddTaggedMatcher(conditionChainLink);
+ AddTaggedMatcher(conditionStatement);
+ AddTaggedMatcher(operation);
+ AddTaggedMatcher(operand);
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs
new file mode 100644
index 00000000..81acb833
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestCount.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestCount : AbstractTokenTest
+ {
+ private const string TypeNameToken = "typeName";
+ private const string ConditionStatementTag = "conditionStatement";
+ private const string ConditionChainTag = "conditionChain";
+ private const string ConditionChainLinkTag = "conditionChainLink";
+ private const string OperationTag = "operation";
+ private const string OperandTag = "operand";
+
+ private static readonly TokenMatcher operand = new MatcherGroupOr(
+ new MatcherGroupAnd(
+ new MatcherTypename(),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherArray())
+ ),
+ new MatcherNumber()
+ ).WithTag(OperandTag);
+
+ private static readonly TokenMatcher operation = new MatcherGroupOr(
+ new MatcherLiteral("+"),
+ new MatcherLiteral("-"),
+ new MatcherLiteral("*"),
+ new MatcherLiteral("/"),
+ new MatcherGroupAnd(new MatcherLiteral("<"), new MatcherLiteral("<")),
+ new MatcherGroupAnd(new MatcherLiteral(">"), new MatcherLiteral(">"))
+ ).WithTag(OperationTag);
+
+ private static readonly TokenMatcher conditionStatement = new MatcherGroupOr(
+ new MatcherGroupAnd(
+ new MatcherLiteral("("),
+ new MatcherWithTag(ConditionStatementTag),
+ new MatcherLiteral(")")
+ ),
+ new MatcherGroupAnd(
+ new MatcherWithTag(OperandTag),
+ new MatcherGroupOptional(new MatcherGroupAnd(
+ new MatcherWithTag(OperationTag),
+ new MatcherWithTag(OperandTag)
+ ))
+ )
+ ).WithTag(ConditionStatementTag);
+
+ private static readonly TokenMatcher conditionChainLink = new MatcherGroupOr(
+ new MatcherGroupAnd(new MatcherLiteral("|"), new MatcherLiteral("|")),
+ new MatcherGroupAnd(new MatcherLiteral("&"), new MatcherLiteral("&"))
+ ).WithTag(ConditionChainLinkTag);
+
+ private static readonly TokenMatcher conditionChain = new MatcherGroupAnd(
+ new MatcherWithTag(ConditionStatementTag),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.ZeroOneMultiple, new MatcherGroupAnd(
+ new MatcherWithTag(ConditionChainLinkTag),
+ new MatcherWithTag(ConditionStatementTag)
+ ))
+ ).WithTag(ConditionChainTag);
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("set"),
+ new MatcherLiteral("count"),
+ new MatcherTypename().WithName(TypeNameToken),
+ new MatcherWithTag(ConditionChainTag),
+ new MatcherLiteral(";")
+ };
+
+ public TestCount() : base(matchers)
+ {
+ AddTaggedMatcher(conditionStatement);
+ AddTaggedMatcher(conditionChain);
+ AddTaggedMatcher(conditionChainLink);
+ AddTaggedMatcher(operation);
+ AddTaggedMatcher(operand);
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs
new file mode 100644
index 00000000..070d6642
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestGame.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestGame : AbstractTokenTest
+ {
+ private const string GameNameToken = "name";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("game"),
+ new MatcherName().WithName(GameNameToken),
+ new MatcherLiteral(";")
+ };
+
+ public TestGame() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+ if (!string.IsNullOrEmpty(state.Game))
+ {
+ throw new TestFailedException($"Game has already been set with value '{state.Game}'");
+ }
+
+ state.Game = GetMatcherTokens(GameNameToken)[0];
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs
new file mode 100644
index 00000000..2c327250
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestReorder.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestReorder : AbstractTokenTest
+ {
+ private const string TypeNameToken = "typeName";
+ private const string ReorderMemberNameToken = "member";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("reorder"),
+ new MatcherGroupOptional(new MatcherTypename().WithName(TypeNameToken)),
+ new MatcherLiteral(":"),
+ new MatcherGroupLoop(MatcherGroupLoop.LoopMode.OneMultiple, new MatcherName().WithName(ReorderMemberNameToken)),
+ new MatcherLiteral(";")
+ };
+
+ public TestReorder() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs
new file mode 100644
index 00000000..3063fec8
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestScriptString.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestScriptString : AbstractTokenTest
+ {
+ private const string MemberTypeNameToken = "name";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("set"),
+ new MatcherLiteral("scriptstring"),
+ new MatcherTypename().WithName(MemberTypeNameToken),
+ new MatcherLiteral(";")
+ };
+
+ public TestScriptString() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs
new file mode 100644
index 00000000..dbf30d74
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestUse.cs
@@ -0,0 +1,41 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Parsing.Matching;
+using ZoneCodeGenerator.Parsing.Matching.Matchers;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing.CommandFile.Tests
+{
+ class TestUse : AbstractTokenTest
+ {
+ private const string TypeNameToken = "typeName";
+
+ private static readonly TokenMatcher[] matchers = {
+ new MatcherLiteral("use"),
+ new MatcherTypename().WithName(TypeNameToken),
+ new MatcherLiteral(";")
+ };
+
+ public TestUse() : base(matchers)
+ {
+
+ }
+
+ protected override void ProcessMatch(ICommandParserState state)
+ {
+ var typeName = GetMatcherTokens(TypeNameToken)[0];
+ var dataTypeToUse = state.Repository.GetDataTypeByName(typeName);
+
+ if (dataTypeToUse == null)
+ {
+ throw new LoadingException($"Could not find data type '{typeName}'");
+ }
+
+ if (!(dataTypeToUse is DataTypeWithMembers dataTypeWithMembersToUse))
+ {
+ throw new LoadingException($"To use data type '{typeName}' it must either be a struct or a union.");
+ }
+
+ state.DataTypeInUse = dataTypeWithMembersToUse;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/ICommentProcessor.cs b/src/ZoneCodeGenerator/Parsing/ICommentProcessor.cs
new file mode 100644
index 00000000..d10f992e
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/ICommentProcessor.cs
@@ -0,0 +1,7 @@
+namespace ZoneCodeGenerator.Parsing
+{
+ interface ICommentProcessor
+ {
+ string RemoveComments(string line);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/IDataPostProcessor.cs b/src/ZoneCodeGenerator/Parsing/IDataPostProcessor.cs
new file mode 100644
index 00000000..cba70750
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/IDataPostProcessor.cs
@@ -0,0 +1,9 @@
+using ZoneCodeGenerator.Persistence;
+
+namespace ZoneCodeGenerator.Parsing
+{
+ interface IDataPostProcessor
+ {
+ bool PostProcess(IDataRepository repository);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/IIncludingParsingStream.cs b/src/ZoneCodeGenerator/Parsing/IIncludingParsingStream.cs
new file mode 100644
index 00000000..b53b8f17
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/IIncludingParsingStream.cs
@@ -0,0 +1,12 @@
+namespace ZoneCodeGenerator.Parsing
+{
+ interface IIncludingParsingStream : IParsingFileStream
+ {
+ ///
+ /// Pushes back current file and the position in it to read from another file now instead.
+ /// After completion returns back to the previous file.
+ ///
+ ///
+ void IncludeFile(string filename);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/ILexer.cs b/src/ZoneCodeGenerator/Parsing/ILexer.cs
new file mode 100644
index 00000000..bf722c68
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/ILexer.cs
@@ -0,0 +1,14 @@
+namespace ZoneCodeGenerator.Parsing
+{
+ interface ILexer
+ {
+ int CurrentLine { get; }
+ string CurrentFile { get; }
+ bool IsEndOfStream { get; }
+ int CachedTokenCount { get; }
+
+ string NextToken();
+ string PeekToken(int index = 0);
+ void SkipTokens(int count);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/IParserState.cs b/src/ZoneCodeGenerator/Parsing/IParserState.cs
new file mode 100644
index 00000000..1a439bfe
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/IParserState.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing
+{
+ interface IParserState where TState : IParserState
+ {
+ IEnumerable> GetTests();
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/IParsingFileStream.cs b/src/ZoneCodeGenerator/Parsing/IParsingFileStream.cs
new file mode 100644
index 00000000..32679b0a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/IParsingFileStream.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace ZoneCodeGenerator.Parsing
+{
+ interface IParsingFileStream : IDisposable
+ {
+ ///
+ /// Whether the end of the stream has been reached.
+ ///
+ bool EndOfStream { get; }
+
+ ///
+ /// The current filename.
+ ///
+ string Filename { get; }
+
+ ///
+ /// The current line in the current file.
+ ///
+ int Line { get; }
+
+ ///
+ /// Reads a line from the current header and returns it.
+ ///
+ ///
+ string ReadLine();
+
+ ///
+ /// Closes this and all underlying streams.
+ ///
+ void Close();
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Impl/CommentProcessor.cs b/src/ZoneCodeGenerator/Parsing/Impl/CommentProcessor.cs
new file mode 100644
index 00000000..fb6b5668
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Impl/CommentProcessor.cs
@@ -0,0 +1,57 @@
+using System;
+
+namespace ZoneCodeGenerator.Parsing.Impl
+{
+ class CommentProcessor : ICommentProcessor
+ {
+ private const string LineCommentStart = "//";
+ private const string BlockCommentStart = "/*";
+ private const string BlockCommentEnd = "*/";
+
+ private bool inComment;
+
+ public CommentProcessor()
+ {
+ inComment = false;
+ }
+
+ public string RemoveComments(string line)
+ {
+ if (inComment)
+ {
+ var idx = line.IndexOf(BlockCommentEnd, StringComparison.Ordinal);
+
+ if(idx == -1)
+ return "";
+
+ line = line.Substring(idx + BlockCommentEnd.Length);
+ inComment = false;
+ }
+
+ var commentIndex = line.IndexOf(LineCommentStart, StringComparison.Ordinal);
+ if (commentIndex != -1)
+ line = line.Remove(commentIndex).Trim();
+
+ while (true)
+ {
+ var indexBlockCommentBegin = line.IndexOf(BlockCommentStart, StringComparison.Ordinal);
+
+ if (indexBlockCommentBegin == -1)
+ break;
+
+ var indexBlockCommentEnd = line.IndexOf(BlockCommentEnd, indexBlockCommentBegin, StringComparison.Ordinal);
+
+ if(indexBlockCommentEnd == -1)
+ {
+ line = line.Remove(indexBlockCommentBegin).Trim();
+ inComment = true;
+ break;
+ }
+
+ line = line.Remove(indexBlockCommentBegin, indexBlockCommentEnd + BlockCommentEnd.Length - indexBlockCommentBegin).Trim();
+ }
+
+ return line;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Impl/IncludingStreamFileSystem.cs b/src/ZoneCodeGenerator/Parsing/Impl/IncludingStreamFileSystem.cs
new file mode 100644
index 00000000..b899ed9b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Impl/IncludingStreamFileSystem.cs
@@ -0,0 +1,107 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace ZoneCodeGenerator.Parsing.Impl
+{
+ class IncludingStreamFileSystem : IIncludingParsingStream
+ {
+ private class HeaderStreamState
+ {
+ private readonly StreamReader reader;
+ private readonly Stream stream;
+
+ public string Cwd { get; }
+ public string Filename { get; }
+ public int Line { get; private set; }
+
+ public HeaderStreamState(FileStream stream, string filepath)
+ {
+ this.stream = stream;
+ reader = new StreamReader(stream);
+
+ Cwd = Path.GetDirectoryName(filepath);
+ Filename = Path.GetFileName(filepath);
+ Line = 1;
+ }
+
+ public bool EndOfStream => reader.EndOfStream;
+
+ public string ReadLine()
+ {
+ Line++;
+ return reader.ReadLine();
+ }
+
+ public void Close()
+ {
+ reader.Close();
+ stream.Close();
+ }
+ }
+
+ private readonly Stack states;
+
+ public IncludingStreamFileSystem(string path)
+ {
+ states = new Stack();
+ var initialState = new HeaderStreamState(new FileStream(path, FileMode.Open), path);
+
+ states.Push(initialState);
+ }
+
+ public bool EndOfStream => states.Count == 0;
+
+ public string Filename => states.Count == 0 ? "" : State.Filename;
+
+ public int Line => states.Count == 0 ? -1 : State.Line;
+
+ private HeaderStreamState State => states.Count == 0 ? null : states.Peek();
+
+ public string ReadLine()
+ {
+ var state = State;
+
+ if (state == null)
+ return "";
+
+ var line = state.ReadLine();
+
+ if (state.EndOfStream)
+ {
+ state.Close();
+ states.Pop();
+ }
+
+ return line;
+ }
+
+ public void IncludeFile(string filename)
+ {
+ var state = State;
+
+ if (state == null)
+ return;
+
+ var path = Path.Combine(state.Cwd, filename);
+
+ if (!File.Exists(path)) return;
+
+ var newState = new HeaderStreamState(new FileStream(path, FileMode.Open), path);
+
+ states.Push(newState);
+ }
+
+ public void Close()
+ {
+ while (states.Count > 0)
+ {
+ states.Pop().Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Impl/Lexer.cs b/src/ZoneCodeGenerator/Parsing/Impl/Lexer.cs
new file mode 100644
index 00000000..bcf7ba1b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Impl/Lexer.cs
@@ -0,0 +1,160 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace ZoneCodeGenerator.Parsing.Impl
+{
+ class Lexer : ILexer
+ {
+ private class LexerToken
+ {
+ public string Token { get; set; }
+ public int Row { get; set; }
+ public string Filename { get; set; }
+ }
+
+ private static readonly char[] charTokens = {
+ ';',
+ ':',
+ '{',
+ '}',
+ ',',
+ '=',
+ '(',
+ ')',
+ '*',
+ '[',
+ ']',
+ '<',
+ '>',
+ '#',
+ '&',
+ '%',
+ '\"',
+ '?',
+ '!',
+ '+',
+ '-',
+ '/',
+ '\\'
+ };
+
+ private readonly IParsingFileStream fileStream;
+
+ private readonly List tokenCache;
+
+ public bool IsEndOfStream => fileStream.EndOfStream && tokenCache.Count == 0;
+ public int CachedTokenCount => tokenCache.Count;
+
+ public Lexer(IParsingFileStream fileStream)
+ {
+ this.fileStream = fileStream;
+ tokenCache = new List();
+ }
+
+ public int CurrentLine => tokenCache.Count == 0 ? fileStream.Line : tokenCache[0].Row;
+
+ public string CurrentFile => tokenCache.Count == 0 ? fileStream.Filename : tokenCache[0].Filename;
+
+ private static bool IsCharToken(char c)
+ {
+ return charTokens.Contains(c);
+ }
+
+ private void TokenizeLine(string filename, int lineNr, string line)
+ {
+ line = line.Trim();
+
+ while(line.Length > 0)
+ {
+ var token = "";
+
+ while (line.Length > 0)
+ {
+ var c = line[0];
+ line = line.Substring(1);
+
+ if (char.IsWhiteSpace(c))
+ break;
+
+ if (IsCharToken(c))
+ {
+ if(token == "")
+ {
+ token += c;
+ break;
+ }
+ else
+ {
+ line = c + line;
+ break;
+ }
+ }
+
+ token += c;
+ }
+
+ tokenCache.Add(new LexerToken()
+ {
+ Token = token,
+ Row = lineNr,
+ Filename = filename
+ });
+ line = line.TrimStart();
+ }
+ }
+
+ public string NextToken()
+ {
+ while(tokenCache.Count == 0)
+ {
+ if (fileStream.EndOfStream)
+ {
+ return "";
+ }
+
+ TokenizeLine(fileStream.Filename, fileStream.Line, fileStream.ReadLine());
+ }
+
+ var token = tokenCache[0].Token;
+ tokenCache.RemoveAt(0);
+ return token;
+ }
+
+ public string PeekToken(int index = 0)
+ {
+ if (index < 0)
+ return "";
+
+ while (tokenCache.Count <= index)
+ {
+ if (fileStream.EndOfStream)
+ {
+ return "";
+ }
+
+ TokenizeLine(fileStream.Filename, fileStream.Line, fileStream.ReadLine());
+ }
+
+ return tokenCache[index].Token;
+ }
+
+ public void SkipTokens(int count)
+ {
+ if (count < 0)
+ return;
+
+ while (tokenCache.Count < count)
+ {
+ if (fileStream.EndOfStream)
+ {
+ tokenCache.Clear();
+ return;
+ }
+
+ TokenizeLine(fileStream.Filename, fileStream.Line, fileStream.ReadLine());
+ }
+
+ tokenCache.RemoveRange(0, count);
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs b/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs
new file mode 100644
index 00000000..ec1a0f4b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/BaseMatcher.cs
@@ -0,0 +1,62 @@
+namespace ZoneCodeGenerator.Parsing.Matching
+{
+ abstract class BaseMatcher : TokenMatcher
+ {
+ protected class MatchingResult
+ {
+ public bool Successful { get; }
+ public int TokensConsumed { get; }
+
+ public MatchingResult(bool successful, int tokensConsumed)
+ {
+ Successful = successful;
+ TokensConsumed = tokensConsumed;
+ }
+ }
+
+ private string name;
+ private string output;
+ private bool consuming;
+
+ protected BaseMatcher()
+ {
+ name = null;
+ consuming = true;
+ output = "";
+ }
+
+ protected abstract MatchingResult Matches(MatchingContext context, int tokenOffset);
+
+ protected void SetMatcherOutput(string text)
+ {
+ output = text;
+ }
+
+ public BaseMatcher WithName(string tokenName)
+ {
+ name = tokenName;
+ return this;
+ }
+
+ public BaseMatcher NonConsuming()
+ {
+ consuming = false;
+ return this;
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ var match = Matches(context, tokenOffset);
+
+ var success = match.Successful;
+ var consumedTokens = success && consuming ? match.TokensConsumed : 0;
+
+ var result = new TokenMatchingResult(success, consumedTokens);
+
+ if (name != null && success)
+ result.AddNamedMatch(name, output);
+
+ return result;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/GroupMatcher.cs b/src/ZoneCodeGenerator/Parsing/Matching/GroupMatcher.cs
new file mode 100644
index 00000000..a02a4c59
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/GroupMatcher.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ZoneCodeGenerator.Parsing.Matching
+{
+ abstract class GroupMatcher : TokenMatcher
+ {
+ public TokenMatcher[] Matchers { get; }
+ protected GroupMatcher(TokenMatcher[] matchers)
+ {
+ Matchers = matchers;
+ }
+
+ protected abstract override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherArray.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherArray.cs
new file mode 100644
index 00000000..67f26dbc
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherArray.cs
@@ -0,0 +1,47 @@
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherArray : BaseMatcher
+ {
+ private static readonly Regex decimalNumberRegex = new Regex(@"^[0-9]+$");
+ private static readonly Regex hexNumberRegex = new Regex(@"^0x([0-9a-fA-F]+)$");
+ private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
+
+ protected override MatchingResult Matches(MatchingContext context, int tokenOffset)
+ {
+ var lexer = context.Lexer;
+
+ if (lexer.PeekToken(tokenOffset++) != "[")
+ return new MatchingResult(false, 0);
+
+ var token = lexer.PeekToken(tokenOffset++);
+
+ if (decimalNumberRegex.IsMatch(token))
+ {
+ SetMatcherOutput(token);
+ }
+ else if (hexNumberRegex.IsMatch(token))
+ {
+ SetMatcherOutput(int.Parse(hexNumberRegex.Match(token).Groups[1].Value, NumberStyles.HexNumber).ToString());
+ }
+ else if (nameRegex.IsMatch(token))
+ {
+ SetMatcherOutput(token);
+ }
+ else
+ {
+ return new MatchingResult(false, 0);
+ }
+
+ return lexer.PeekToken(tokenOffset) != "]" ? new MatchingResult(false, 0)
+ : new MatchingResult(true, 3);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "Array";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs
new file mode 100644
index 00000000..93123c69
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupAnd.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherGroupAnd : GroupMatcher
+ {
+ public MatcherGroupAnd(params TokenMatcher[] matchers) : base(matchers)
+ {
+ if(matchers.Length == 0)
+ throw new ArgumentException("A matcher group is supposed to have matchers.");
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ var result = new TokenMatchingResult(true, 0);
+
+ foreach(var matcher in Matchers)
+ {
+ var matcherResult = matcher.Test(context, tokenOffset + result.ConsumedTokenCount);
+
+ if (matcherResult.Successful)
+ {
+ matcherResult.CopyNamedMatchesTo(result);
+ result.ConsumedTokenCount += matcherResult.ConsumedTokenCount;
+ }
+ else
+ {
+ return new TokenMatchingResult(false, 0);
+ }
+ }
+
+ return result;
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "GroupAnd";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs
new file mode 100644
index 00000000..d79052cb
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupLoop.cs
@@ -0,0 +1,68 @@
+using System;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherGroupLoop : GroupMatcher
+ {
+ public enum LoopMode
+ {
+ ZeroOneMultiple,
+ OneMultiple,
+ Multiple
+ }
+
+ private readonly TokenMatcher matcher;
+ private readonly LoopMode mode;
+
+ public MatcherGroupLoop(LoopMode mode, TokenMatcher matcher) : base(new []{matcher})
+ {
+ this.mode = mode;
+ this.matcher = matcher;
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ var result = new TokenMatchingResult(false, 0);
+ var matchedTimes = 0;
+
+ while (true)
+ {
+ var matcherResult = matcher.Test(context, tokenOffset + result.ConsumedTokenCount);
+
+ if (!matcherResult.Successful)
+ break;
+
+ matcherResult.CopyNamedMatchesTo(result);
+ result.ConsumedTokenCount += matcherResult.ConsumedTokenCount;
+ matchedTimes++;
+ }
+
+ switch (mode)
+ {
+ case LoopMode.ZeroOneMultiple:
+ result.Successful = true;
+ break;
+
+ case LoopMode.OneMultiple:
+ result.Successful = matchedTimes > 0;
+ break;
+
+ case LoopMode.Multiple:
+ result.Successful = matchedTimes > 1;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (!result.Successful)
+ result.ConsumedTokenCount = 0;
+
+ return result;
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "GroupLoop";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOptional.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOptional.cs
new file mode 100644
index 00000000..6be2ac31
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOptional.cs
@@ -0,0 +1,24 @@
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherGroupOptional : GroupMatcher
+ {
+ private readonly TokenMatcher matcher;
+
+ public MatcherGroupOptional(TokenMatcher matcher) : base(new []{matcher})
+ {
+ this.matcher = matcher;
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ var result = matcher.Test(context, tokenOffset);
+
+ return !result.Successful ? new TokenMatchingResult(true, 0) : result;
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "GroupOptional";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs
new file mode 100644
index 00000000..0f71e70a
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherGroupOr.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherGroupOr : GroupMatcher
+ {
+ private readonly TokenMatcher[] matchers;
+
+ public MatcherGroupOr(params TokenMatcher[] matchers) : base(matchers)
+ {
+ if(matchers.Length == 0)
+ throw new ArgumentException("A matcher group is supposed to have matchers.");
+
+ this.matchers = matchers;
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ foreach(var matcher in matchers)
+ {
+ var matcherResult = matcher.Test(context, tokenOffset);
+
+ if (matcherResult.Successful)
+ return matcherResult;
+ }
+
+ return new TokenMatchingResult(false, 0);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "GroupOr";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs
new file mode 100644
index 00000000..8742cf97
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherLiteral.cs
@@ -0,0 +1,28 @@
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherLiteral : BaseMatcher
+ {
+ private readonly string literal;
+
+ public MatcherLiteral(string literal)
+ {
+ this.literal = literal;
+ }
+
+ protected override MatchingResult Matches(MatchingContext context, int tokenOffset)
+ {
+ var token = context.Lexer.PeekToken(tokenOffset);
+ var isMatch = string.Equals(token, literal);
+
+ if (!isMatch) return new MatchingResult(false, 0);
+
+ SetMatcherOutput(literal);
+ return new MatchingResult(true, 1);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return $"Literal(\"{literal}\")";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherName.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherName.cs
new file mode 100644
index 00000000..e444820f
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherName.cs
@@ -0,0 +1,98 @@
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherName : BaseMatcher
+ {
+ private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
+
+ private static readonly string[] reservedWords = {
+ "const",
+ "int",
+ "char",
+ "short",
+ "long",
+ "unsigned",
+ "typedef",
+ "void",
+ "static",
+ "class",
+ "struct",
+ "enum",
+ "union",
+ "namespace",
+ "using",
+ "public",
+ "protected",
+ "private",
+ "alignas",
+ "and",
+ "auto",
+ "bool",
+ "catch",
+ "concept",
+ "default",
+ "double",
+ "float",
+ "extern",
+ "for",
+ "if",
+ "mutable",
+ "noexcept",
+ "nullptr",
+ "switch",
+ "this",
+ "true",
+ "false",
+ "typeid",
+ "while",
+ "alignof",
+ "break",
+ "continue",
+ "dynamic_cast",
+ "static_cast",
+ "explicit",
+ "friend",
+ "not",
+ "operator",
+ "return",
+ "sizeof",
+ "thread_local",
+ "try",
+ "typename",
+ "volatile",
+ "asm",
+ "case",
+ "constexpr",
+ "decltype",
+ "do",
+ "else",
+ "export",
+ "goto",
+ "inline",
+ "new",
+ "reinterpret_cast",
+ "static",
+ "template",
+ "throw",
+ "virtual"
+ };
+
+ protected override MatchingResult Matches(MatchingContext context, int tokenOffset)
+ {
+ var token = context.Lexer.PeekToken(tokenOffset);
+ var isMatch = nameRegex.IsMatch(token) && !reservedWords.Contains(token);
+
+ if (!isMatch) return new MatchingResult(false, 0);
+
+ SetMatcherOutput(token);
+ return new MatchingResult(true, 1);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "Name";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherNumber.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherNumber.cs
new file mode 100644
index 00000000..2ffc6c48
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherNumber.cs
@@ -0,0 +1,36 @@
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherNumber : BaseMatcher
+ {
+ private static readonly Regex decimalNumber = new Regex(@"^\d+$");
+ private static readonly Regex hexNumber = new Regex(@"^0x([0-9a-fA-F]+)$");
+
+ protected override MatchingResult Matches(MatchingContext context, int tokenOffset)
+ {
+ var token = context.Lexer.PeekToken(tokenOffset);
+
+ var currentMatch = decimalNumber.Match(token);
+
+ if (currentMatch.Success)
+ {
+ SetMatcherOutput(token);
+ return new MatchingResult(true, 1);
+ }
+
+ currentMatch = hexNumber.Match(token);
+
+ if (!currentMatch.Success) return new MatchingResult(false, 0);
+
+ SetMatcherOutput(int.Parse( currentMatch.Groups[1].Value, NumberStyles.HexNumber).ToString());
+ return new MatchingResult(true, 1);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "Number";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs
new file mode 100644
index 00000000..ef7d1b28
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherTypename.cs
@@ -0,0 +1,80 @@
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherTypename : BaseMatcher
+ {
+ private static readonly Regex nameRegex = new Regex(@"^[a-zA-Z_$][a-zA-Z0-9_$]*$");
+
+ private static readonly string[] typenamePrefixes = {
+ "const",
+ "signed",
+ "unsigned"
+ };
+
+ private int MatchTypenameExtension(MatchingContext context, int tokenOffset)
+ {
+ if (!":".Equals(context.Lexer.PeekToken(tokenOffset++)))
+ return 0;
+ if (!":".Equals(context.Lexer.PeekToken(tokenOffset++)))
+ return 0;
+
+ return nameRegex.IsMatch(context.Lexer.PeekToken(tokenOffset)) ? 3 : 0;
+ }
+
+ protected override MatchingResult Matches(MatchingContext context, int tokenOffset)
+ {
+ var lexer = context.Lexer;
+ var typename = new StringBuilder();
+ var startTokenOffset = tokenOffset;
+
+ var currentPart = lexer.PeekToken(tokenOffset++);
+ if (!nameRegex.IsMatch(currentPart))
+ return new MatchingResult(false, 0);
+ typename.Append(currentPart);
+
+ while (typenamePrefixes.Contains(currentPart))
+ {
+ currentPart = lexer.PeekToken(tokenOffset++);
+
+ if (!nameRegex.IsMatch(currentPart))
+ return new MatchingResult(false, 0);
+ typename.Append(' ');
+ typename.Append(currentPart);
+ }
+
+ if ("long".Equals(currentPart))
+ {
+ currentPart = lexer.PeekToken(tokenOffset);
+ if (currentPart.Equals("long"))
+ {
+ tokenOffset++;
+ typename.Append(' ');
+ typename.Append(currentPart);
+ }
+ }
+
+ var extensionLength = MatchTypenameExtension(context, tokenOffset);
+ while (extensionLength > 0)
+ {
+ for (var i = 0; i < extensionLength; i++)
+ {
+ typename.Append(lexer.PeekToken(tokenOffset + i));
+ }
+
+ tokenOffset += extensionLength;
+ extensionLength = MatchTypenameExtension(context, tokenOffset);
+ }
+
+ SetMatcherOutput(typename.ToString());
+ return new MatchingResult(true, tokenOffset - startTokenOffset);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return "Typename";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherWithTag.cs b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherWithTag.cs
new file mode 100644
index 00000000..a5a934cc
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/Matchers/MatcherWithTag.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ZoneCodeGenerator.Parsing.Matching.Matchers
+{
+ class MatcherWithTag : TokenMatcher
+ {
+ private readonly string tag;
+
+ public MatcherWithTag(string tag)
+ {
+ this.tag = tag;
+ }
+
+ protected override TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset)
+ {
+ var matcherWithTag = context.GetMatcherByTag(tag);
+
+ if (matcherWithTag == null)
+ {
+ throw new Exception($"Could not find matcher with tag '{tag}'");
+ }
+
+ return matcherWithTag.Test(context, tokenOffset);
+ }
+
+ protected override string GetIdentifier()
+ {
+ return $"WithTag(\"{tag}\")";
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/MatchingContext.cs b/src/ZoneCodeGenerator/Parsing/Matching/MatchingContext.cs
new file mode 100644
index 00000000..043fd991
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/MatchingContext.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace ZoneCodeGenerator.Parsing.Matching
+{
+ class MatchingContext
+ {
+ public ILexer Lexer { get; }
+
+ public bool Verbose { get; set; }
+
+ private readonly Dictionary taggedMatchers;
+
+ public MatchingContext(ILexer lexer, Dictionary taggedMatchers)
+ {
+ Lexer = lexer;
+ this.taggedMatchers = taggedMatchers;
+
+ #if DEBUG
+ Verbose = true;
+ #else
+ Verbose = false;
+ #endif
+ }
+
+ public TokenMatcher GetMatcherByTag(string tag)
+ {
+ return taggedMatchers.ContainsKey(tag) ? taggedMatchers[tag] : null;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/TokenMatcher.cs b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatcher.cs
new file mode 100644
index 00000000..d4244a23
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatcher.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+
+namespace ZoneCodeGenerator.Parsing.Matching
+{
+ abstract class TokenMatcher
+ {
+ private const int DebugPeekMin = 3;
+
+ public string Tag { get; private set; }
+
+ protected TokenMatcher()
+ {
+ Tag = "";
+ }
+
+ public TokenMatcher WithTag(string tag)
+ {
+ Tag = tag;
+ return this;
+ }
+
+ protected abstract string GetIdentifier();
+
+ public override string ToString()
+ {
+ return string.IsNullOrEmpty(Tag) ? GetIdentifier() : Tag;
+ }
+
+ protected abstract TokenMatchingResult PerformTest(MatchingContext context, int tokenOffset);
+
+ public virtual TokenMatchingResult Test(MatchingContext context, int tokenOffset)
+ {
+ var result = PerformTest(context, tokenOffset);
+
+ if (context.Verbose)
+ {
+ if (result.Successful)
+ {
+ var matchedTokens = new List();
+
+ for (var i = 0; i < result.ConsumedTokenCount; i++)
+ {
+ matchedTokens.Add(context.Lexer.PeekToken(tokenOffset + i));
+ }
+
+ Console.WriteLine($"Matcher {ToString()} matched: {string.Join(" ", matchedTokens)}");
+ }
+ else
+ {
+ var debugPeekCount = Math.Max(context.Lexer.CachedTokenCount - tokenOffset, DebugPeekMin);
+ var nextTokens = new List();
+
+ for (var i = 0; i < debugPeekCount; i++)
+ {
+ nextTokens.Add(context.Lexer.PeekToken(tokenOffset + i));
+ }
+
+ Console.WriteLine($"Matcher {ToString()} failed @ {string.Join(" ", nextTokens)}");
+ }
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs
new file mode 100644
index 00000000..ba7e3da1
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Matching/TokenMatchingResult.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ZoneCodeGenerator.Parsing.Matching
+{
+ class TokenMatchingResult : IEnumerable>>
+ {
+ public bool Successful { get; set; }
+ public int ConsumedTokenCount { get; set; }
+
+ private readonly Dictionary> namedMatches;
+
+ public TokenMatchingResult(bool success, int consumedTokenCount)
+ {
+ if(!success && consumedTokenCount > 0)
+ throw new ArgumentException("Token Match cannot be unsuccessful and consume tokens");
+
+ if(consumedTokenCount < 0)
+ throw new ArgumentException("Consumed token count cannot be negative");
+
+ Successful = success;
+ ConsumedTokenCount = consumedTokenCount;
+
+ namedMatches = new Dictionary>();
+ }
+
+ public void AddNamedMatch(string name, string value)
+ {
+ if(!namedMatches.ContainsKey(name))
+ namedMatches.Add(name, new List());
+
+ namedMatches[name].Add(value);
+ }
+
+ public IEnumerator>> GetEnumerator()
+ {
+ return namedMatches.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return namedMatches.GetEnumerator();
+ }
+
+ public List this[string key] => namedMatches.ContainsKey(key) ? namedMatches[key] : new List();
+
+ public void CopyNamedMatchesTo(TokenMatchingResult target)
+ {
+ foreach(var namedMatchKey in namedMatches)
+ {
+ foreach (var namedMatch in namedMatchKey.Value)
+ {
+ target.AddNamedMatch(namedMatchKey.Key, namedMatch);
+ }
+ }
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Parser.cs b/src/ZoneCodeGenerator/Parsing/Parser.cs
new file mode 100644
index 00000000..53f3f6d9
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Parser.cs
@@ -0,0 +1,85 @@
+using System;
+using ZoneCodeGenerator.Parsing.Testing;
+
+namespace ZoneCodeGenerator.Parsing
+{
+ class Parser where TState : IParserState
+ {
+ // Amount of consecutive tokens that are output after a parser error to show the region where the error happened.
+ private const int ParserErrorTokenPeekCount = 3;
+
+ private readonly ILexer lexer;
+ private readonly TState state;
+
+ public Parser(TState state, ILexer lexer)
+ {
+ this.state = state;
+ this.lexer = lexer;
+ }
+
+ public bool Parse()
+ {
+ while (!lexer.IsEndOfStream)
+ {
+ var testSuccessful = false;
+
+ try
+ {
+ foreach (var test in state.GetTests())
+ {
+ switch (test.PerformTest(state, lexer))
+ {
+ case TokenTestResult.Match:
+ lexer.SkipTokens(test.ConsumedTokenCount);
+ testSuccessful = true;
+ break;
+ case TokenTestResult.NoMatch:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ if (testSuccessful)
+ break;
+ }
+ }
+ catch (LoadingException e)
+ {
+ PrintParserError(e);
+ return false;
+ }
+
+ if (!testSuccessful)
+ {
+ PrintParserError(new LoadingException("Could not parse expression"));
+ return false;
+ }
+
+ // Peek for the next token here to be able to determine if the stream is at its end or not
+ lexer.PeekToken();
+ }
+
+ return true;
+ }
+
+ private void PrintParserError(LoadingException e)
+ {
+ Console.WriteLine($"Parsing failed in file '{lexer.CurrentFile}' at line {lexer.CurrentLine}:");
+
+ Console.WriteLine(e.Message);
+
+ Console.Write(" ");
+
+ var tokenCountToShow = Math.Max(ParserErrorTokenPeekCount, lexer.CachedTokenCount);
+ for (var i = 0; i < tokenCountToShow; i++)
+ {
+ var token = lexer.PeekToken(i);
+ if (string.IsNullOrEmpty(token))
+ break;
+ Console.Write($"{token} ");
+ }
+ Console.WriteLine();
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/ParserException.cs b/src/ZoneCodeGenerator/Parsing/ParserException.cs
new file mode 100644
index 00000000..a1b1e9ff
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/ParserException.cs
@@ -0,0 +1,9 @@
+namespace ZoneCodeGenerator.Parsing
+{
+ class ParserException : LoadingException
+ {
+ public ParserException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs b/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs
new file mode 100644
index 00000000..b65a3538
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Testing/AbstractTokenTest.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ZoneCodeGenerator.Parsing.Matching;
+
+namespace ZoneCodeGenerator.Parsing.Testing
+{
+ abstract class AbstractTokenTest : ITokenTest where TState : IParserState
+ {
+ public int ConsumedTokenCount { get; private set; }
+
+ private readonly TokenMatcher[] matcherEntryPoint;
+ private readonly Dictionary> matchedEntries;
+ private readonly Dictionary taggedMatchers;
+ private bool tested;
+
+ protected AbstractTokenTest(TokenMatcher[] matcherEntryPoint)
+ {
+ this.matcherEntryPoint = matcherEntryPoint;
+ matchedEntries = new Dictionary>();
+ taggedMatchers = new Dictionary();
+ tested = false;
+
+ BuildTaggedMatcherList(matcherEntryPoint);
+ }
+
+ private void BuildTaggedMatcherList(IEnumerable matchersWithTags)
+ {
+ foreach (var tokenMatcher in matchersWithTags)
+ {
+ if (!string.IsNullOrEmpty(tokenMatcher.Tag))
+ {
+ taggedMatchers[tokenMatcher.Tag] = tokenMatcher;
+ }
+
+ if (tokenMatcher is GroupMatcher groupMatcher)
+ {
+ BuildTaggedMatcherList(groupMatcher.Matchers);
+ }
+ }
+ }
+
+ protected void AddTaggedMatcher(params TokenMatcher[] taggedMatcher)
+ {
+ BuildTaggedMatcherList(taggedMatcher);
+ }
+
+ protected ReadOnlyCollection GetMatcherTokens(string matcherName)
+ {
+ return tested && matchedEntries.ContainsKey(matcherName) ? matchedEntries[matcherName].AsReadOnly() : new List().AsReadOnly();
+ }
+
+ protected bool HasMatcherTokens(string matcherName)
+ {
+ return tested && matchedEntries.ContainsKey(matcherName);
+ }
+
+ protected abstract void ProcessMatch(TState state);
+
+ public TokenTestResult PerformTest(TState state, ILexer lexer)
+ {
+ var tokenOffset = 0;
+ matchedEntries.Clear();
+
+ ConsumedTokenCount = 0;
+ tested = true;
+
+ var context = new MatchingContext(lexer, taggedMatchers);
+
+ if (context.Verbose)
+ {
+ Console.WriteLine($"Test {GetType().Name} start");
+ }
+
+ foreach(var matcher in matcherEntryPoint)
+ {
+ var result = matcher.Test(context, tokenOffset);
+
+ if (!result.Successful)
+ {
+ if (context.Verbose)
+ {
+ Console.WriteLine($"Test {GetType().Name} failed");
+ }
+
+ return TokenTestResult.NoMatch;
+ }
+
+ tokenOffset += result.ConsumedTokenCount;
+
+ foreach (var entry in result)
+ {
+ matchedEntries.Add(entry.Key, entry.Value);
+ }
+ }
+
+ ConsumedTokenCount = tokenOffset;
+
+ ProcessMatch(state);
+
+ if (context.Verbose)
+ {
+ Console.WriteLine($"Test {GetType().Name} successful");
+ }
+
+ return TokenTestResult.Match;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Testing/ITokenTest.cs b/src/ZoneCodeGenerator/Parsing/Testing/ITokenTest.cs
new file mode 100644
index 00000000..996c89e7
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Testing/ITokenTest.cs
@@ -0,0 +1,9 @@
+namespace ZoneCodeGenerator.Parsing.Testing
+{
+ interface ITokenTest where TState : IParserState
+ {
+ int ConsumedTokenCount { get; }
+
+ TokenTestResult PerformTest(TState state, ILexer lexer);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Testing/TestFailedException.cs b/src/ZoneCodeGenerator/Parsing/Testing/TestFailedException.cs
new file mode 100644
index 00000000..edf61ca7
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Testing/TestFailedException.cs
@@ -0,0 +1,9 @@
+namespace ZoneCodeGenerator.Parsing.Testing
+{
+ class TestFailedException : LoadingException
+ {
+ public TestFailedException(string message) : base(message)
+ {
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Parsing/Testing/TokenTestResult.cs b/src/ZoneCodeGenerator/Parsing/Testing/TokenTestResult.cs
new file mode 100644
index 00000000..47d7e654
--- /dev/null
+++ b/src/ZoneCodeGenerator/Parsing/Testing/TokenTestResult.cs
@@ -0,0 +1,8 @@
+namespace ZoneCodeGenerator.Parsing.Testing
+{
+ enum TokenTestResult
+ {
+ Match,
+ NoMatch
+ }
+}
diff --git a/src/ZoneCodeGenerator/Persistence/IDataRepository.cs b/src/ZoneCodeGenerator/Persistence/IDataRepository.cs
new file mode 100644
index 00000000..98ada481
--- /dev/null
+++ b/src/ZoneCodeGenerator/Persistence/IDataRepository.cs
@@ -0,0 +1,14 @@
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+
+namespace ZoneCodeGenerator.Persistence
+{
+ interface IDataRepository : IReadOnlyDataRepository
+ {
+ void Add(DataTypeEnum data);
+ void Add(DataTypeStruct data);
+ void Add(DataTypeUnion data);
+ void Add(DataTypeTypedef data);
+ void Add(FastFileBlock block);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Persistence/IReadOnlyDataRepository.cs b/src/ZoneCodeGenerator/Persistence/IReadOnlyDataRepository.cs
new file mode 100644
index 00000000..bc65ce3c
--- /dev/null
+++ b/src/ZoneCodeGenerator/Persistence/IReadOnlyDataRepository.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Domain.StructureInformation;
+
+namespace ZoneCodeGenerator.Persistence
+{
+ interface IReadOnlyDataRepository
+ {
+ IEnumerable GetAllEnums();
+ IEnumerable GetAllStructs();
+ IEnumerable GetAllUnions();
+ IEnumerable GetAllTypedefs();
+ IEnumerable GetAllStructureInformation();
+ IEnumerable GetAllFastFileBlocks();
+
+ DataType GetDataTypeByName(string name);
+ StructureInformation GetInformationFor(DataTypeWithMembers dataTypeWithMembers);
+ }
+}
diff --git a/src/ZoneCodeGenerator/Persistence/InMemoryDataRepository.cs b/src/ZoneCodeGenerator/Persistence/InMemoryDataRepository.cs
new file mode 100644
index 00000000..9d74ef55
--- /dev/null
+++ b/src/ZoneCodeGenerator/Persistence/InMemoryDataRepository.cs
@@ -0,0 +1,127 @@
+using System.Collections.Generic;
+using System.Linq;
+using ZoneCodeGenerator.Domain;
+using ZoneCodeGenerator.Domain.FastFileStructure;
+using ZoneCodeGenerator.Domain.StructureInformation;
+
+namespace ZoneCodeGenerator.Persistence
+{
+ class InMemoryDataRepository : IDataRepository
+ {
+ private readonly List typedefs;
+ private readonly List enums;
+ private readonly List structs;
+ private readonly List unions;
+ private readonly List structureInformationList;
+ private readonly List blocks;
+
+ public InMemoryDataRepository()
+ {
+ typedefs = new List();
+ enums = new List();
+ structs = new List();
+ unions = new List();
+ structureInformationList = new List();
+ blocks = new List();
+ }
+
+ public void Add(DataTypeEnum data)
+ {
+ enums.Add(data);
+ }
+
+ public void Add(DataTypeTypedef data)
+ {
+ typedefs.Add(data);
+ }
+
+ public void Add(FastFileBlock block)
+ {
+ blocks.Add(block);
+ }
+
+ public void Add(DataTypeStruct data)
+ {
+ structs.Add(data);
+ }
+
+ public void Add(DataTypeUnion data)
+ {
+ unions.Add(data);
+ }
+
+ public IEnumerable GetAllEnums()
+ {
+ return enums.AsEnumerable();
+ }
+
+ public IEnumerable GetAllStructs()
+ {
+ return structs.AsEnumerable();
+ }
+
+ public IEnumerable GetAllTypedefs()
+ {
+ return typedefs.AsEnumerable();
+ }
+
+ public IEnumerable GetAllStructureInformation()
+ {
+ return structureInformationList.AsEnumerable();
+ }
+
+ public IEnumerable GetAllFastFileBlocks()
+ {
+ return blocks.AsEnumerable();
+ }
+
+ public IEnumerable GetAllUnions()
+ {
+ return unions.AsEnumerable();
+ }
+
+ public DataType GetDataTypeByName(string name)
+ {
+ DataType data = enums.Find(_enum => _enum.FullName.Equals(name));
+ if (data != null)
+ return data;
+
+ data = structs.Find(_struct => _struct.FullName.Equals(name));
+ if (data != null)
+ return data;
+
+ data = unions.Find(_struct => _struct.FullName.Equals(name));
+ if (data != null)
+ return data;
+
+ data = typedefs.Find(typeDef => typeDef.FullName.Equals(name));
+
+ return data;
+ }
+
+ public StructureInformation GetInformationFor(DataTypeWithMembers dataTypeWithMembers)
+ {
+ var information = structureInformationList.Find(listEntry => listEntry.Type == dataTypeWithMembers);
+
+ if (information == null)
+ {
+ information = new StructureInformation(dataTypeWithMembers);
+ structureInformationList.Add(information);
+
+ foreach (var member in dataTypeWithMembers.Members)
+ {
+ StructureInformation memberStructureInformation = null;
+
+ if (member.VariableType.Type is DataTypeWithMembers memberType)
+ {
+ memberStructureInformation = GetInformationFor(memberType);
+ }
+
+ information.OrderedMembers.Add(new MemberInformation(member, memberStructureInformation));
+ }
+ }
+
+ return information;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Program.cs b/src/ZoneCodeGenerator/Program.cs
new file mode 100644
index 00000000..eb75603d
--- /dev/null
+++ b/src/ZoneCodeGenerator/Program.cs
@@ -0,0 +1,37 @@
+using System;
+using ZoneCodeGenerator.Interface;
+using ZoneCodeGenerator.Parsing.C_Header;
+
+namespace ZoneCodeGenerator
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static int Main(string[] args)
+ {
+ var cui = new CUI();
+
+ return cui.Start(args) ? 0 : 1;
+ }
+
+ private static bool CreateDatabase(string[] args)
+ {
+ var storage = HeaderReader.ReadFile(args[0]);
+
+ var prettyPrinter = new PrettyPrinter(storage);
+
+ prettyPrinter.PrintAll();
+
+ return true;
+ }
+
+ private static bool PrintDatabase(string[] args)
+ {
+ Console.WriteLine("Printing");
+ return true;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Properties/AssemblyInfo.cs b/src/ZoneCodeGenerator/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..c41f146b
--- /dev/null
+++ b/src/ZoneCodeGenerator/Properties/AssemblyInfo.cs
@@ -0,0 +1,39 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("ZoneCodeGenerator")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("ZoneCodeGenerator")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d1c20c32-9cb8-44b8-9df7-f0cf8fb304d3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+
+[assembly: InternalsVisibleTo("ZoneCodeGeneratorTests")]
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/Utils/AlignmentExtension.cs b/src/ZoneCodeGenerator/Utils/AlignmentExtension.cs
new file mode 100644
index 00000000..05d0bfa0
--- /dev/null
+++ b/src/ZoneCodeGenerator/Utils/AlignmentExtension.cs
@@ -0,0 +1,15 @@
+namespace ZoneCodeGenerator.Utils
+{
+ static class AlignmentExtension
+ {
+ public static int Align(this int valueToAlign, int alignment)
+ {
+ return (valueToAlign + alignment - 1) / alignment * alignment;
+ }
+
+ public static long Align(this long valueToAlign, long alignment)
+ {
+ return (valueToAlign + alignment - 1) / alignment * alignment;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Utils/KeyValueExtension.cs b/src/ZoneCodeGenerator/Utils/KeyValueExtension.cs
new file mode 100644
index 00000000..8f05d826
--- /dev/null
+++ b/src/ZoneCodeGenerator/Utils/KeyValueExtension.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+
+namespace ZoneCodeGenerator.Utils
+{
+ public static class KeyValueExtension
+ {
+ public static void Deconstruct(this KeyValuePair keyValuePair, out T1 m1, out T2 m2)
+ {
+ m1 = keyValuePair.Key;
+ m2 = keyValuePair.Value;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/Utils/RandomName.cs b/src/ZoneCodeGenerator/Utils/RandomName.cs
new file mode 100644
index 00000000..428c91a1
--- /dev/null
+++ b/src/ZoneCodeGenerator/Utils/RandomName.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace ZoneCodeGenerator.Utils
+{
+ static class RandomName
+ {
+ private const int NameLen = 32;
+
+ private static readonly Random random = new Random();
+ private static readonly char[] generatorChars = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+ };
+
+ public static string GenerateName()
+ {
+ var name = "";
+ for (var i = 0; i < NameLen; i++)
+ name += generatorChars[random.Next(generatorChars.Length)];
+
+ return name;
+ }
+ }
+}
diff --git a/src/ZoneCodeGenerator/ZoneCodeGenerator.csproj b/src/ZoneCodeGenerator/ZoneCodeGenerator.csproj
new file mode 100644
index 00000000..05701fdb
--- /dev/null
+++ b/src/ZoneCodeGenerator/ZoneCodeGenerator.csproj
@@ -0,0 +1,171 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {D1C20C32-9CB8-44B8-9DF7-F0CF8FB304D3}
+ Exe
+ ZoneCodeGenerator
+ ZoneCodeGenerator
+ v4.6.1
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\..\packages\Antlr3.Runtime.3.5.1\lib\net40-client\Antlr3.Runtime.dll
+
+
+ ..\..\packages\StringTemplate4.4.0.8\lib\net35-client\Antlr4.StringTemplate.dll
+
+
+ ..\..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ZoneCodeGenerator/packages.config b/src/ZoneCodeGenerator/packages.config
new file mode 100644
index 00000000..9dcd9366
--- /dev/null
+++ b/src/ZoneCodeGenerator/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/IGame.h b/src/ZoneCommon/Game/IGame.h
new file mode 100644
index 00000000..2155c9f0
--- /dev/null
+++ b/src/ZoneCommon/Game/IGame.h
@@ -0,0 +1,12 @@
+#pragma once
+#include "Zone/Zone.h"
+#include
+
+class Zone;
+
+class IGame
+{
+public:
+ virtual void AddZone(Zone* zone) = 0;
+ virtual std::vector GetZones() = 0;
+};
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp
new file mode 100644
index 00000000..9926082f
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.cpp
@@ -0,0 +1,337 @@
+#include "GameAssetPoolT6.h"
+#include "Pool/AssetPoolStatic.h"
+#include "Pool/AssetPoolDynamic.h"
+#include
+
+using namespace T6;
+
+GameAssetPoolT6::GameAssetPoolT6(const int priority)
+{
+ m_priority = priority;
+
+ m_phys_preset = nullptr;
+ m_phys_constraints = nullptr;
+ m_destructible_def = nullptr;
+ m_xanim_parts = nullptr;
+ m_xmodel = nullptr;
+ m_material = nullptr;
+ m_technique_set = nullptr;
+ m_image = nullptr;
+ m_sound_bank = nullptr;
+ m_sound_patch = nullptr;
+ m_clip_map = nullptr;
+ m_com_world = nullptr;
+ m_game_world_sp = nullptr;
+ m_game_world_mp = nullptr;
+ m_map_ents = nullptr;
+ m_gfx_world = nullptr;
+ m_gfx_light_def = nullptr;
+ m_font = nullptr;
+ m_font_icon = nullptr;
+ m_menu_list = nullptr;
+ m_menu_def = nullptr;
+ m_localize = nullptr;
+ m_weapon = nullptr;
+ m_attachment = nullptr;
+ m_attachment_unique = nullptr;
+ m_camo = nullptr;
+ m_snd_driver_globals = nullptr;
+ m_fx = nullptr;
+ m_fx_impact_table = nullptr;
+ m_raw_file = nullptr;
+ m_string_table = nullptr;
+ m_leaderboard = nullptr;
+ m_xglobals = nullptr;
+ m_ddl = nullptr;
+ m_glasses = nullptr;
+ m_emblem_set = nullptr;
+ m_script = nullptr;
+ m_key_value_pairs = nullptr;
+ m_vehicle = nullptr;
+ m_memory_block = nullptr;
+ m_addon_map_ents = nullptr;
+ m_tracer = nullptr;
+ m_skinned_verts = nullptr;
+ m_qdb = nullptr;
+ m_slug = nullptr;
+ m_footstep_table = nullptr;
+ m_footstep_fx_table = nullptr;
+ m_zbarrier = nullptr;
+}
+
+GameAssetPoolT6::~GameAssetPoolT6()
+{
+#define DELETE_POOL(poolName) \
+ delete (poolName); (poolName) = nullptr;
+
+ DELETE_POOL(m_phys_preset);
+ DELETE_POOL(m_phys_constraints);
+ DELETE_POOL(m_destructible_def);
+ DELETE_POOL(m_xanim_parts);
+ DELETE_POOL(m_xmodel);
+ DELETE_POOL(m_material);
+ DELETE_POOL(m_technique_set);
+ DELETE_POOL(m_image);
+ DELETE_POOL(m_sound_bank);
+ DELETE_POOL(m_sound_patch);
+ DELETE_POOL(m_clip_map);
+ DELETE_POOL(m_com_world);
+ DELETE_POOL(m_game_world_sp);
+ DELETE_POOL(m_game_world_mp);
+ DELETE_POOL(m_map_ents);
+ DELETE_POOL(m_gfx_world);
+ DELETE_POOL(m_gfx_light_def);
+ DELETE_POOL(m_font);
+ DELETE_POOL(m_font_icon);
+ DELETE_POOL(m_menu_list);
+ DELETE_POOL(m_menu_def);
+ DELETE_POOL(m_localize);
+ DELETE_POOL(m_weapon);
+ DELETE_POOL(m_attachment);
+ DELETE_POOL(m_attachment_unique);
+ DELETE_POOL(m_camo);
+ DELETE_POOL(m_snd_driver_globals);
+ DELETE_POOL(m_fx);
+ DELETE_POOL(m_fx_impact_table);
+ DELETE_POOL(m_raw_file);
+ DELETE_POOL(m_string_table);
+ DELETE_POOL(m_leaderboard);
+ DELETE_POOL(m_xglobals);
+ DELETE_POOL(m_ddl);
+ DELETE_POOL(m_glasses);
+ DELETE_POOL(m_emblem_set);
+ DELETE_POOL(m_script);
+ DELETE_POOL(m_key_value_pairs);
+ DELETE_POOL(m_vehicle);
+ DELETE_POOL(m_memory_block);
+ DELETE_POOL(m_addon_map_ents);
+ DELETE_POOL(m_tracer);
+ DELETE_POOL(m_skinned_verts);
+ DELETE_POOL(m_qdb);
+ DELETE_POOL(m_slug);
+ DELETE_POOL(m_footstep_table);
+ DELETE_POOL(m_footstep_fx_table);
+ DELETE_POOL(m_zbarrier);
+
+#undef DELETE_POOL
+}
+
+void GameAssetPoolT6::InitPoolStatic(const asset_type_t type, const size_t capacity)
+{
+#define CASE_INIT_POOL_STATIC(assetType, poolName, poolType) \
+ case assetType: \
+ { \
+ if((poolName) == nullptr && capacity > 0) \
+ { \
+ (poolName) = new AssetPoolStatic(capacity, m_priority); \
+ } \
+ break; \
+ }
+
+ switch(type)
+ {
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_PHYSPRESET, m_phys_preset, PhysPreset);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, PhysConstraints);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, DestructibleDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_XANIMPARTS, m_xanim_parts, XAnimParts);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_XMODEL, m_xmodel, XModel);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_MATERIAL, m_material, Material);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, MaterialTechniqueSet);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_IMAGE, m_image, GfxImage);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SOUND, m_sound_bank, SndBank);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SOUND_PATCH, m_sound_patch, SndPatch);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap_t);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap_t);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_COMWORLD, m_com_world, ComWorld);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, GameWorldSp);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, GameWorldMp);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_MAP_ENTS, m_map_ents, MapEnts);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_GFXWORLD, m_gfx_world, GfxWorld);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, GfxLightDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_FONT, m_font, Font_s);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_FONTICON, m_font_icon, FontIcon);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_MENULIST, m_menu_list, MenuList);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_MENU, m_menu_def, menuDef_t);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, LocalizeEntry);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_WEAPON, m_weapon, WeaponVariantDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_ATTACHMENT, m_attachment, WeaponAttachment);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, WeaponAttachmentUnique);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_WEAPON_CAMO, m_camo, WeaponCamo);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, SndDriverGlobals);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_FX, m_fx, FxEffectDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, FxImpactTable);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_RAWFILE, m_raw_file, RawFile);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_STRINGTABLE, m_string_table, StringTable);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_LEADERBOARD, m_leaderboard, LeaderboardDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_XGLOBALS, m_xglobals, XGlobals);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_DDL, m_ddl, ddlRoot_t);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_GLASSES, m_glasses, Glasses);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_EMBLEMSET, m_emblem_set, EmblemSet);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SCRIPTPARSETREE, m_script, ScriptParseTree);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, KeyValuePairs);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_VEHICLEDEF, m_vehicle, VehicleDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_MEMORYBLOCK, m_memory_block, MemoryBlock);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, AddonMapEnts);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_TRACER, m_tracer, TracerDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, SkinnedVertsDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_QDB, m_qdb, Qdb);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_SLUG, m_slug, Slug);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, FootstepTableDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, FootstepFXTableDef);
+ CASE_INIT_POOL_STATIC(ASSET_TYPE_ZBARRIER, m_zbarrier, ZBarrierDef);
+
+ default:
+ assert(type >= 0 && type < ASSET_TYPE_COUNT);
+ break;
+ }
+
+#undef CASE_INIT_POOL_STATIC
+}
+
+void GameAssetPoolT6::InitPoolDynamic(const asset_type_t type)
+{
+#define CASE_INIT_POOL_DYNAMIC(assetType, poolName, poolType) \
+ case assetType: \
+ { \
+ if((poolName) == nullptr) \
+ { \
+ (poolName) = new AssetPoolDynamic(m_priority); \
+ } \
+ break; \
+ }
+
+ switch(type)
+ {
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_PHYSPRESET, m_phys_preset, PhysPreset);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, PhysConstraints);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, DestructibleDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XANIMPARTS, m_xanim_parts, XAnimParts);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XMODEL, m_xmodel, XModel);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MATERIAL, m_material, Material);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, MaterialTechniqueSet);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_IMAGE, m_image, GfxImage);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SOUND, m_sound_bank, SndBank);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SOUND_PATCH, m_sound_patch, SndPatch);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap_t);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap_t);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_COMWORLD, m_com_world, ComWorld);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, GameWorldSp);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, GameWorldMp);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MAP_ENTS, m_map_ents, MapEnts);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GFXWORLD, m_gfx_world, GfxWorld);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, GfxLightDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FONT, m_font, Font_s);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FONTICON, m_font_icon, FontIcon);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MENULIST, m_menu_list, MenuList);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MENU, m_menu_def, menuDef_t);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, LocalizeEntry);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_WEAPON, m_weapon, WeaponVariantDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ATTACHMENT, m_attachment, WeaponAttachment);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, WeaponAttachmentUnique);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_WEAPON_CAMO, m_camo, WeaponCamo);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, SndDriverGlobals);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FX, m_fx, FxEffectDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, FxImpactTable);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_RAWFILE, m_raw_file, RawFile);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_STRINGTABLE, m_string_table, StringTable);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_LEADERBOARD, m_leaderboard, LeaderboardDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_XGLOBALS, m_xglobals, XGlobals);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_DDL, m_ddl, ddlRoot_t);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_GLASSES, m_glasses, Glasses);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_EMBLEMSET, m_emblem_set, EmblemSet);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SCRIPTPARSETREE, m_script, ScriptParseTree);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, KeyValuePairs);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_VEHICLEDEF, m_vehicle, VehicleDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_MEMORYBLOCK, m_memory_block, MemoryBlock);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, AddonMapEnts);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_TRACER, m_tracer, TracerDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, SkinnedVertsDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_QDB, m_qdb, Qdb);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_SLUG, m_slug, Slug);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, FootstepTableDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, FootstepFXTableDef);
+ CASE_INIT_POOL_DYNAMIC(ASSET_TYPE_ZBARRIER, m_zbarrier, ZBarrierDef);
+
+ default:
+ assert(type >= 0 && type < ASSET_TYPE_COUNT);
+ break;
+ }
+
+#undef CASE_INIT_POOL_STATIC
+}
+
+void* GameAssetPoolT6::AddAsset(asset_type_t type, std::string name, void* asset, std::vector& scriptStrings, std::vector& dependencies)
+{
+ XAsset xAsset{};
+
+ xAsset.type = static_cast(type);
+ xAsset.header.data = asset;
+
+#define CASE_ADD_TO_POOL(assetType, poolName, headerName) \
+ case assetType: \
+ { \
+ assert((poolName) != nullptr); \
+ return (poolName)->AddAsset(std::move(name), xAsset.header.headerName, scriptStrings, dependencies)->m_asset; \
+ }
+
+ switch(xAsset.type)
+ {
+ CASE_ADD_TO_POOL(ASSET_TYPE_PHYSPRESET, m_phys_preset, physPreset);
+ CASE_ADD_TO_POOL(ASSET_TYPE_PHYSCONSTRAINTS, m_phys_constraints, physConstraints);
+ CASE_ADD_TO_POOL(ASSET_TYPE_DESTRUCTIBLEDEF, m_destructible_def, destructibleDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_XANIMPARTS, m_xanim_parts, parts);
+ CASE_ADD_TO_POOL(ASSET_TYPE_XMODEL, m_xmodel, model);
+ CASE_ADD_TO_POOL(ASSET_TYPE_MATERIAL, m_material, material);
+ CASE_ADD_TO_POOL(ASSET_TYPE_TECHNIQUE_SET, m_technique_set, techniqueSet);
+ CASE_ADD_TO_POOL(ASSET_TYPE_IMAGE, m_image, image);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SOUND, m_sound_bank, sound);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SOUND_PATCH, m_sound_patch, soundPatch);
+ CASE_ADD_TO_POOL(ASSET_TYPE_CLIPMAP, m_clip_map, clipMap);
+ CASE_ADD_TO_POOL(ASSET_TYPE_CLIPMAP_PVS, m_clip_map, clipMap);
+ CASE_ADD_TO_POOL(ASSET_TYPE_COMWORLD, m_com_world, comWorld);
+ CASE_ADD_TO_POOL(ASSET_TYPE_GAMEWORLD_SP, m_game_world_sp, gameWorldSp);
+ CASE_ADD_TO_POOL(ASSET_TYPE_GAMEWORLD_MP, m_game_world_mp, gameWorldMp);
+ CASE_ADD_TO_POOL(ASSET_TYPE_MAP_ENTS, m_map_ents, mapEnts);
+ CASE_ADD_TO_POOL(ASSET_TYPE_GFXWORLD, m_gfx_world, gfxWorld);
+ CASE_ADD_TO_POOL(ASSET_TYPE_LIGHT_DEF, m_gfx_light_def, lightDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_FONT, m_font, font);
+ CASE_ADD_TO_POOL(ASSET_TYPE_FONTICON, m_font_icon, fontIcon);
+ CASE_ADD_TO_POOL(ASSET_TYPE_MENULIST, m_menu_list, menuList);
+ CASE_ADD_TO_POOL(ASSET_TYPE_MENU, m_menu_def, menu);
+ CASE_ADD_TO_POOL(ASSET_TYPE_LOCALIZE_ENTRY, m_localize, localize);
+ CASE_ADD_TO_POOL(ASSET_TYPE_WEAPON, m_weapon, weapon);
+ CASE_ADD_TO_POOL(ASSET_TYPE_ATTACHMENT, m_attachment, attachment);
+ CASE_ADD_TO_POOL(ASSET_TYPE_ATTACHMENT_UNIQUE, m_attachment_unique, attachmentUnique);
+ CASE_ADD_TO_POOL(ASSET_TYPE_WEAPON_CAMO, m_camo, weaponCamo);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SNDDRIVER_GLOBALS, m_snd_driver_globals, sndDriverGlobals);
+ CASE_ADD_TO_POOL(ASSET_TYPE_FX, m_fx, fx);
+ CASE_ADD_TO_POOL(ASSET_TYPE_IMPACT_FX, m_fx_impact_table, impactFx);
+ CASE_ADD_TO_POOL(ASSET_TYPE_RAWFILE, m_raw_file, rawfile);
+ CASE_ADD_TO_POOL(ASSET_TYPE_STRINGTABLE, m_string_table, stringTable);
+ CASE_ADD_TO_POOL(ASSET_TYPE_LEADERBOARD, m_leaderboard, leaderboardDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_XGLOBALS, m_xglobals, xGlobals);
+ CASE_ADD_TO_POOL(ASSET_TYPE_DDL, m_ddl, ddlRoot);
+ CASE_ADD_TO_POOL(ASSET_TYPE_GLASSES, m_glasses, glasses);
+ CASE_ADD_TO_POOL(ASSET_TYPE_EMBLEMSET, m_emblem_set, emblemSet);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SCRIPTPARSETREE, m_script, scriptParseTree);
+ CASE_ADD_TO_POOL(ASSET_TYPE_KEYVALUEPAIRS, m_key_value_pairs, keyValuePairs);
+ CASE_ADD_TO_POOL(ASSET_TYPE_VEHICLEDEF, m_vehicle, vehicleDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_MEMORYBLOCK, m_memory_block, memoryBlock);
+ CASE_ADD_TO_POOL(ASSET_TYPE_ADDON_MAP_ENTS, m_addon_map_ents, addonMapEnts);
+ CASE_ADD_TO_POOL(ASSET_TYPE_TRACER, m_tracer, tracerDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SKINNEDVERTS, m_skinned_verts, skinnedVertsDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_QDB, m_qdb, qdb);
+ CASE_ADD_TO_POOL(ASSET_TYPE_SLUG, m_slug, slug);
+ CASE_ADD_TO_POOL(ASSET_TYPE_FOOTSTEP_TABLE, m_footstep_table, footstepTableDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_FOOTSTEPFX_TABLE, m_footstep_fx_table, footstepFXTableDef);
+ CASE_ADD_TO_POOL(ASSET_TYPE_ZBARRIER, m_zbarrier, zbarrierDef);
+
+ default:
+ assert(false);
+ break;
+ }
+
+ return nullptr;
+
+#undef CASE_ADD_TO_POOL
+}
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/T6/GameAssetPoolT6.h b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h
new file mode 100644
index 00000000..3cbfcd66
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/GameAssetPoolT6.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "Pool/AssetPool.h"
+#include "Pool/IZoneAssetPools.h"
+#include "T6.h"
+
+class GameAssetPoolT6 final : public IZoneAssetPools
+{
+ int m_priority;
+
+public:
+ AssetPool* m_phys_preset;
+ AssetPool* m_phys_constraints;
+ AssetPool* m_destructible_def;
+ AssetPool* m_xanim_parts;
+ AssetPool* m_xmodel;
+ AssetPool* m_material;
+ AssetPool* m_technique_set;
+ AssetPool* m_image;
+ AssetPool* m_sound_bank;
+ AssetPool* m_sound_patch;
+ AssetPool* m_clip_map;
+ AssetPool* m_com_world;
+ AssetPool* m_game_world_sp;
+ AssetPool* m_game_world_mp;
+ AssetPool* m_map_ents;
+ AssetPool* m_gfx_world;
+ AssetPool* m_gfx_light_def;
+ AssetPool* m_font;
+ AssetPool* m_font_icon;
+ AssetPool* m_menu_list;
+ AssetPool* m_menu_def;
+ AssetPool* m_localize;
+ AssetPool* m_weapon;
+ AssetPool* m_attachment;
+ AssetPool* m_attachment_unique;
+ AssetPool* m_camo;
+ AssetPool* m_snd_driver_globals;
+ AssetPool* m_fx;
+ AssetPool* m_fx_impact_table;
+ AssetPool* m_raw_file;
+ AssetPool* m_string_table;
+ AssetPool* m_leaderboard;
+ AssetPool* m_xglobals;
+ AssetPool* m_ddl;
+ AssetPool* m_glasses;
+ AssetPool* m_emblem_set;
+ AssetPool* m_script;
+ AssetPool* m_key_value_pairs;
+ AssetPool* m_vehicle;
+ AssetPool* m_memory_block;
+ AssetPool* m_addon_map_ents;
+ AssetPool* m_tracer;
+ AssetPool* m_skinned_verts;
+ AssetPool* m_qdb;
+ AssetPool* m_slug;
+ AssetPool* m_footstep_table;
+ AssetPool* m_footstep_fx_table;
+ AssetPool* m_zbarrier;
+
+ explicit GameAssetPoolT6(int priority);
+ ~GameAssetPoolT6() override;
+
+ void InitPoolStatic(asset_type_t type, size_t capacity) override;
+ void InitPoolDynamic(asset_type_t type) override;
+
+ void* AddAsset(asset_type_t type, std::string name, void* asset, std::vector& scriptStrings, std::vector& dependencies) override;
+};
diff --git a/src/ZoneCommon/Game/T6/GameT6.cpp b/src/ZoneCommon/Game/T6/GameT6.cpp
new file mode 100644
index 00000000..5a3e37ec
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/GameT6.cpp
@@ -0,0 +1,16 @@
+#include "GameT6.h"
+#include "T6.h"
+
+using namespace T6;
+
+GameT6 game_t6;
+
+void GameT6::AddZone(Zone* zone)
+{
+ m_zones.push_back(zone);
+}
+
+std::vector GameT6::GetZones()
+{
+ return m_zones;
+}
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/T6/GameT6.h b/src/ZoneCommon/Game/T6/GameT6.h
new file mode 100644
index 00000000..f5c9fe42
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/GameT6.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "Game/IGame.h"
+
+class GameT6 : public IGame
+{
+ std::vector m_zones;
+
+public:
+ void AddZone(Zone* zone) override;
+ std::vector GetZones() override;
+};
+
+extern GameT6 game_t6;
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/T6/T6.h b/src/ZoneCommon/Game/T6/T6.h
new file mode 100644
index 00000000..ac0a89b4
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/T6.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include
+
+namespace T6
+{
+#include "T6_Assets.h"
+
+ enum XFileBlock
+ {
+ XFILE_BLOCK_TEMP,
+ XFILE_BLOCK_RUNTIME_VIRTUAL,
+ XFILE_BLOCK_RUNTIME_PHYSICAL,
+ XFILE_BLOCK_DELAY_VIRTUAL,
+ XFILE_BLOCK_DELAY_PHYSICAL,
+ XFILE_BLOCK_VIRTUAL,
+ XFILE_BLOCK_PHYSICAL,
+ XFILE_BLOCK_STREAMER_RESERVE,
+ MAX_XFILE_COUNT,
+ };
+
+ struct ScriptStringList
+ {
+ int count;
+ const char **strings;
+ };
+
+ struct XAsset
+ {
+ XAssetType type;
+ XAssetHeader header;
+ };
+
+
+ struct XAssetList
+ {
+ ScriptStringList stringList;
+ int dependCount;
+ const char **depends;
+ int assetCount;
+ XAsset *assets;
+ };
+
+}
\ No newline at end of file
diff --git a/src/ZoneCommon/Game/T6/T6_Assets.h b/src/ZoneCommon/Game/T6/T6_Assets.h
new file mode 100644
index 00000000..d9596fe6
--- /dev/null
+++ b/src/ZoneCommon/Game/T6/T6_Assets.h
@@ -0,0 +1,5725 @@
+#define __int8 char
+#define __int16 short
+#define __int32 int
+#define __int64 long long
+
+struct dvar_t;
+struct MenuCell;
+struct cplane_s;
+struct cbrushside_t;
+struct MaterialVertexDeclaration;
+struct MaterialVertexShader;
+struct MaterialPixelShader;
+struct MaterialShaderArgument;
+struct MaterialTechnique;
+struct MaterialTechniqueSet;
+struct GfxImageLoadDef;
+struct GfxImage;
+struct MaterialTextureDef;
+struct MaterialConstantDef;
+struct GfxStateBits;
+struct Material;
+struct MenuRow;
+struct Glyph;
+struct KerningPairs;
+struct Font_s;
+struct BrushWrapper;
+struct multiDef_s;
+struct XModelCollTri_s;
+struct PhysConstraints;
+struct ScriptCondition;
+struct listBoxDef_s;
+struct expressionRpn;
+struct GenericEventScript;
+struct GenericEventHandler;
+struct animParamsDef_t;
+struct enumDvarDef_s;
+struct PhysPreset;
+struct profileMultiDef_s;
+struct PhysGeomInfo;
+struct XModelCollSurf_s;
+struct gameMsgDef_s;
+struct SndAlias;
+struct SndAliasList;
+struct XBoneInfo;
+struct editFieldDef_s;
+struct WeaponCamoMaterial;
+struct PhysGeomList;
+struct textExp_s;
+struct ItemKeyHandler;
+struct focusItemDef_s;
+struct textDef_s;
+struct imageDef_s;
+struct ownerDrawDef_s;
+struct menuDef_t;
+struct rectData_s;
+struct UIAnimInfo;
+struct itemDef_s;
+struct WeaponCamoMaterialSet;
+struct Collmap;
+struct TracerDef;
+struct WeaponAttachment;
+struct DObjAnimMat;
+struct GfxPackedVertex;
+struct XSurfaceCollisionNode;
+struct XSurfaceCollisionLeaf;
+struct XSurfaceCollisionTree;
+struct XRigidVertList;
+struct XSurface;
+struct XModel;
+struct flameTable;
+struct cStaticModel_s;
+struct FxElemVelStateSample;
+struct FxElemVisStateSample;
+struct FxElemMarkVisuals;
+struct FxEffectDef;
+struct GfxLightDef;
+union FxElemVisuals;
+struct FxTrailVertex;
+struct FxTrailDef;
+struct FxSpotLightDef;
+struct FxElemDef;
+struct WeaponCamoSet;
+struct WeaponCamo;
+struct WeaponDef;
+struct WeaponAttachmentUnique;
+struct WeaponVariantDef;
+struct cLeafBrushNode_s;
+struct cbrush_t;
+struct ClipMaterial;
+struct Bounds;
+struct cLeaf_s;
+struct cmodel_t;
+struct CollisionAabbTree;
+struct pathlink_s;
+struct pathnode_t;
+struct DestructiblePiece;
+struct DestructibleDef;
+struct GraphFloat;
+struct VehicleDef;
+struct XAnimNotifyInfo;
+struct XAnimPartTrans;
+struct XAnimDeltaPartQuat2;
+struct XAnimDeltaPartQuat;
+struct XAnimDeltaPart;
+struct XAnimParts;
+struct ZBarrierDef;
+struct GfxLight;
+struct ddlHash_t;
+struct ddlEnumDef_t;
+struct SndVolumeGroup;
+struct XModelPiece;
+struct XModelPieces;
+struct DynEntityDef;
+struct CollisionPartition;
+struct ddlMemberDef_t;
+struct ddlStructDef_t;
+struct ddlDef_t;
+struct GlassDef;
+struct Glass;
+struct GfxAabbTree;
+struct FxImpactEntry;
+struct StringTableCell;
+struct ddlRoot_t;
+struct StringTable;
+struct FxImpactTable;
+struct SndIndexEntry;
+struct SndRadverb;
+struct SndDuck;
+struct SndAssetBankEntry;
+struct SndDialogScriptIdLookup;
+struct SndBank;
+struct SndPatch;
+struct cNode_t;
+struct TriggerModel;
+struct TriggerHull;
+struct TriggerSlab;
+struct MapEnts;
+struct DynEntityPose;
+struct DynEntityClient;
+struct DynEntityServer;
+struct DynEntityColl;
+struct rope_t;
+struct clipMap_t;
+struct ComPrimaryLight;
+struct ComWorld;
+struct pathbasenode_t;
+struct pathnode_tree_t;
+struct GameWorldSp;
+struct GameWorldMp;
+struct GfxStreamingAabbTree;
+struct GfxLightCorona;
+struct GfxShadowMapVolume;
+struct GfxVolumePlane;
+struct GfxExposureVolume;
+struct GfxWorldFogVolume;
+struct GfxWorldFogModifierVolume;
+struct GfxLutVolume;
+struct GfxPortal;
+struct GfxCell;
+struct GfxReflectionProbeVolumeData;
+struct GfxReflectionProbe;
+struct GfxLightmapArray;
+struct GfxLightGridEntry;
+struct GfxCompressedLightGridColors;
+struct GfxCompressedLightGridCoeffs;
+struct GfxSkyGridVolume;
+struct GfxBrushModel;
+struct MaterialMemory;
+struct GfxSceneDynModel;
+struct GfxSceneDynBrush;
+struct SSkinShaders;
+struct SSkinVert;
+struct SSkinModel;
+struct SSkinAnim;
+struct SSkinInstance;
+struct GfxShadowGeometry;
+struct GfxLightRegionAxis;
+struct GfxLightRegionHull;
+struct GfxLightRegion;
+struct GfxStaticModelInst;
+struct GfxSurface;
+struct GfxStaticModelDrawInst;
+struct Occluder;
+struct GfxOutdoorBounds;
+struct GfxHeroLight;
+struct GfxHeroLightTree;
+struct GfxWorld;
+struct FontIconEntry;
+struct FontIconAlias;
+struct FontIcon;
+struct MenuList;
+struct LocalizeEntry;
+struct SndCurve;
+struct SndPan;
+struct SndDuckGroup;
+struct SndContext;
+struct SndMaster;
+struct SndSidechainDuck;
+struct SndFutz;
+struct SndDriverGlobals;
+struct RawFile;
+struct LbColumnDef;
+struct LeaderboardDef;
+struct XGlobals;
+struct Glasses;
+struct EmblemSet;
+struct ScriptParseTree;
+struct KeyValuePair;
+struct KeyValuePairs;
+struct MemoryBlock;
+struct AddonMapEnts;
+struct SkinnedVertsDef;
+struct Qdb;
+struct Slug;
+struct FootstepTableDef;
+struct FootstepFXTableDef;
+
+enum XAssetType
+{
+ ASSET_TYPE_XMODELPIECES = 0x0,
+ ASSET_TYPE_PHYSPRESET = 0x1,
+ ASSET_TYPE_PHYSCONSTRAINTS = 0x2,
+ ASSET_TYPE_DESTRUCTIBLEDEF = 0x3,
+ ASSET_TYPE_XANIMPARTS = 0x4,
+ ASSET_TYPE_XMODEL = 0x5,
+ ASSET_TYPE_MATERIAL = 0x6,
+ ASSET_TYPE_TECHNIQUE_SET = 0x7,
+ ASSET_TYPE_IMAGE = 0x8,
+ ASSET_TYPE_SOUND = 0x9,
+ ASSET_TYPE_SOUND_PATCH = 0xA,
+ ASSET_TYPE_CLIPMAP = 0xB,
+ ASSET_TYPE_CLIPMAP_PVS = 0xC,
+ ASSET_TYPE_COMWORLD = 0xD,
+ ASSET_TYPE_GAMEWORLD_SP = 0xE,
+ ASSET_TYPE_GAMEWORLD_MP = 0xF,
+ ASSET_TYPE_MAP_ENTS = 0x10,
+ ASSET_TYPE_GFXWORLD = 0x11,
+ ASSET_TYPE_LIGHT_DEF = 0x12,
+ ASSET_TYPE_UI_MAP = 0x13,
+ ASSET_TYPE_FONT = 0x14,
+ ASSET_TYPE_FONTICON = 0x15,
+ ASSET_TYPE_MENULIST = 0x16,
+ ASSET_TYPE_MENU = 0x17,
+ ASSET_TYPE_LOCALIZE_ENTRY = 0x18,
+ ASSET_TYPE_WEAPON = 0x19,
+ ASSET_TYPE_WEAPONDEF = 0x1A,
+ ASSET_TYPE_WEAPON_VARIANT = 0x1B,
+ ASSET_TYPE_WEAPON_FULL = 0x1C,
+ ASSET_TYPE_ATTACHMENT = 0x1D,
+ ASSET_TYPE_ATTACHMENT_UNIQUE = 0x1E,
+ ASSET_TYPE_WEAPON_CAMO = 0x1F,
+ ASSET_TYPE_SNDDRIVER_GLOBALS = 0x20,
+ ASSET_TYPE_FX = 0x21,
+ ASSET_TYPE_IMPACT_FX = 0x22,
+ ASSET_TYPE_AITYPE = 0x23,
+ ASSET_TYPE_MPTYPE = 0x24,
+ ASSET_TYPE_MPBODY = 0x25,
+ ASSET_TYPE_MPHEAD = 0x26,
+ ASSET_TYPE_CHARACTER = 0x27,
+ ASSET_TYPE_XMODELALIAS = 0x28,
+ ASSET_TYPE_RAWFILE = 0x29,
+ ASSET_TYPE_STRINGTABLE = 0x2A,
+ ASSET_TYPE_LEADERBOARD = 0x2B,
+ ASSET_TYPE_XGLOBALS = 0x2C,
+ ASSET_TYPE_DDL = 0x2D,
+ ASSET_TYPE_GLASSES = 0x2E,
+ ASSET_TYPE_EMBLEMSET = 0x2F,
+ ASSET_TYPE_SCRIPTPARSETREE = 0x30,
+ ASSET_TYPE_KEYVALUEPAIRS = 0x31,
+ ASSET_TYPE_VEHICLEDEF = 0x32,
+ ASSET_TYPE_MEMORYBLOCK = 0x33,
+ ASSET_TYPE_ADDON_MAP_ENTS = 0x34,
+ ASSET_TYPE_TRACER = 0x35,
+ ASSET_TYPE_SKINNEDVERTS = 0x36,
+ ASSET_TYPE_QDB = 0x37,
+ ASSET_TYPE_SLUG = 0x38,
+ ASSET_TYPE_FOOTSTEP_TABLE = 0x39,
+ ASSET_TYPE_FOOTSTEPFX_TABLE = 0x3A,
+ ASSET_TYPE_ZBARRIER = 0x3B,
+ ASSET_TYPE_COUNT = 0x3C,
+ ASSET_TYPE_STRING = 0x3C,
+ ASSET_TYPE_ASSETLIST = 0x3D,
+ ASSET_TYPE_REPORT = 0x3E,
+ ASSET_TYPE_DEPEND = 0x3F,
+ ASSET_TYPE_FULL_COUNT = 0x40,
+};
+
+union XAssetHeader
+{
+ //XModelPieces *xmodelPieces; // Not an asset
+ PhysPreset *physPreset;
+ PhysConstraints *physConstraints;
+ DestructibleDef *destructibleDef;
+ XAnimParts *parts;
+ XModel *model;
+ Material *material;
+ //MaterialPixelShader *pixelShader; // Not an asset
+ //MaterialVertexShader *vertexShader; // Not an asset
+ MaterialTechniqueSet *techniqueSet;
+ GfxImage *image;
+ SndBank *sound;
+ SndPatch *soundPatch;
+ clipMap_t *clipMap;
+ ComWorld *comWorld;
+ GameWorldSp *gameWorldSp;
+ GameWorldMp *gameWorldMp;
+ MapEnts *mapEnts;
+ GfxWorld *gfxWorld;
+ GfxLightDef *lightDef;
+ Font_s *font;
+ FontIcon *fontIcon;
+ MenuList *menuList;
+ menuDef_t *menu;
+ LocalizeEntry *localize;
+ WeaponVariantDef *weapon;
+ WeaponAttachment *attachment;
+ WeaponAttachmentUnique *attachmentUnique;
+ WeaponCamo *weaponCamo;
+ SndDriverGlobals *sndDriverGlobals;
+ FxEffectDef *fx;
+ FxImpactTable *impactFx;
+ RawFile *rawfile;
+ StringTable *stringTable;
+ LeaderboardDef *leaderboardDef;
+ XGlobals *xGlobals;
+ ddlRoot_t *ddlRoot;
+ Glasses *glasses;
+ //TextureList *textureList; // Does not exist in this game
+ EmblemSet *emblemSet;
+ ScriptParseTree *scriptParseTree;
+ KeyValuePairs *keyValuePairs;
+ VehicleDef *vehicleDef;
+ MemoryBlock *memoryBlock;
+ AddonMapEnts *addonMapEnts;
+ TracerDef *tracerDef;
+ SkinnedVertsDef *skinnedVertsDef;
+ Qdb *qdb;
+ Slug *slug;
+ FootstepTableDef *footstepTableDef;
+ FootstepFXTableDef *footstepFXTableDef;
+ ZBarrierDef *zbarrierDef;
+ void *data;
+};
+
+struct XModelPieces
+{
+ const char *name;
+ int numpieces;
+ XModelPiece *pieces;
+};
+
+union vec3_t
+{
+ struct
+ {
+ float x;
+ float y;
+ float z;
+ };
+ float v[3];
+};
+
+struct PhysPreset
+{
+ const char *name;
+ int flags;
+ float mass;
+ float bounce;
+ float friction;
+ float bulletForceScale;
+ float explosiveForceScale;
+ const char *sndAliasPrefix;
+ float piecesSpreadFraction;
+ float piecesUpwardVelocity;
+ int canFloat;
+ float gravityScale;
+ vec3_t centerOfMassOffset;
+ vec3_t buoyancyBoxMin;
+ vec3_t buoyancyBoxMax;
+};
+
+enum ConstraintType
+{
+ CONSTRAINT_NONE = 0x0,
+ CONSTRAINT_POINT = 0x1,
+ CONSTRAINT_DISTANCE = 0x2,
+ CONSTRAINT_HINGE = 0x3,
+ CONSTRAINT_JOINT = 0x4,
+ CONSTRAINT_ACTUATOR = 0x5,
+ CONSTRAINT_FAKE_SHAKE = 0x6,
+ CONSTRAINT_LAUNCH = 0x7,
+ CONSTRAINT_ROPE = 0x8,
+ CONSTRAINT_LIGHT = 0x9,
+ NUM_CONSTRAINT_TYPES = 0xA,
+};
+
+enum AttachPointType
+{
+ ATTACH_POINT_WORLD = 0x0,
+ ATTACH_POINT_DYNENT = 0x1,
+ ATTACH_POINT_ENT = 0x2,
+ ATTACH_POINT_BONE = 0x3,
+};
+
+struct PhysConstraint
+{
+ unsigned __int16 targetname;
+ ConstraintType type;
+ AttachPointType attach_point_type1;
+ int target_index1;
+ unsigned __int16 target_ent1;
+ const char *target_bone1;
+ AttachPointType attach_point_type2;
+ int target_index2;
+ unsigned __int16 target_ent2;
+ const char *target_bone2;
+ vec3_t offset;
+ vec3_t pos;
+ vec3_t pos2;
+ vec3_t dir;
+ int flags;
+ int timeout;
+ int min_health;
+ int max_health;
+ float distance;
+ float damp;
+ float power;
+ vec3_t scale;
+ float spin_scale;
+ float minAngle;
+ float maxAngle;
+ Material *material;
+ int constraintHandle;
+ int rope_index;
+ int centity_num[4];
+};
+
+struct PhysConstraints
+{
+ const char *name;
+ unsigned int count;
+ PhysConstraint data[16];
+};
+
+struct DestructibleDef
+{
+ const char *name;
+ XModel *model;
+ XModel *pristineModel;
+ int numPieces;
+ DestructiblePiece *pieces;
+ int clientOnly;
+};
+
+union XAnimIndices
+{
+ char *_1;
+ unsigned __int16 *_2;
+ void *data;
+};
+
+struct XAnimParts
+{
+ const char *name;
+ unsigned __int16 dataByteCount;
+ unsigned __int16 dataShortCount;
+ unsigned __int16 dataIntCount;
+ unsigned __int16 randomDataByteCount;
+ unsigned __int16 randomDataIntCount;
+ unsigned __int16 numframes;
+ bool bLoop;
+ bool bDelta;
+ bool bDelta3D;
+ bool bLeftHandGripIK;
+ unsigned int streamedFileSize;
+ char boneCount[10];
+ char notifyCount;
+ char assetType;
+ bool isDefault;
+ unsigned int randomDataShortCount;
+ unsigned int indexCount;
+ float framerate;
+ float frequency;
+ float primedLength;
+ float loopEntryTime;
+ unsigned __int16 *names;
+ char *dataByte;
+ __int16 *dataShort;
+ int *dataInt;
+ __int16 *randomDataShort;
+ char *randomDataByte;
+ int *randomDataInt;
+ XAnimIndices indices;
+ XAnimNotifyInfo *notify;
+ XAnimDeltaPart *deltaPart;
+};
+
+struct XModelLodInfo
+{
+ float dist;
+ unsigned __int16 numsurfs;
+ unsigned __int16 surfIndex;
+ int partBits[5];
+};
+
+struct XModel
+{
+ const char *name;
+ char numBones;
+ char numRootBones;
+ char numsurfs;
+ char lodRampType;
+ unsigned __int16 *boneNames;
+ char *parentList;
+ __int16 *quats;
+ float *trans;
+ char *partClassification;
+ DObjAnimMat *baseMat;
+ XSurface *surfs;
+ Material **materialHandles;
+ XModelLodInfo lodInfo[4];
+ XModelCollSurf_s *collSurfs;
+ int numCollSurfs;
+ int contents;
+ XBoneInfo *boneInfo;
+ float radius;
+ vec3_t mins;
+ vec3_t maxs;
+ __int16 numLods;
+ __int16 collLod;
+ float *himipInvSqRadii;
+ int memUsage;
+ int flags;
+ bool bad;
+ PhysPreset *physPreset;
+ char numCollmaps;
+ Collmap *collmaps;
+ PhysConstraints *physConstraints;
+ vec3_t lightingOriginOffset;
+ float lightingOriginRange;
+};
+
+struct GfxDrawSurfFields
+{
+ unsigned __int64 objectId : 16;
+ unsigned __int64 customIndex : 9;
+ unsigned __int64 reflectionProbeIndex : 5;
+ unsigned __int64 dlightMask : 2;
+ unsigned __int64 materialSortedIndex : 12;
+ unsigned __int64 primaryLightIndex : 8;
+ unsigned __int64 surfType : 4;
+ unsigned __int64 prepass : 2;
+ unsigned __int64 primarySortKey : 6;
+};
+
+union GfxDrawSurf
+{
+ GfxDrawSurfFields fields;
+ unsigned __int64 packed;
+};
+
+struct __declspec(align(8)) MaterialInfo
+{
+ const char *name;
+ unsigned int gameFlags;
+ char pad;
+ char sortKey;
+ char textureAtlasRowCount;
+ char textureAtlasColumnCount;
+ GfxDrawSurf drawSurf;
+ unsigned int surfaceTypeBits;
+ unsigned int layeredSurfaceTypes;
+ unsigned __int16 hashIndex;
+ int surfaceFlags;
+ int contents;
+};
+
+struct Material
+{
+ MaterialInfo info;
+ char stateBitsEntry[36];
+ char textureCount;
+ char constantCount;
+ char stateBitsCount;
+ char stateFlags;
+ char cameraRegion;
+ char probeMipBits;
+ MaterialTechniqueSet *techniqueSet;
+ MaterialTextureDef *textureTable;
+ MaterialConstantDef *constantTable;
+ GfxStateBits *stateBitsTable;
+ Material *thermalMaterial;
+};
+
+struct GfxPixelShaderLoadDef
+{
+ char *program;
+ unsigned int programSize;
+};
+
+struct MaterialPixelShaderProgram
+{
+ ID3D11PixelShader *ps;
+ GfxPixelShaderLoadDef loadDef;
+};
+
+struct MaterialPixelShader
+{
+ const char *name;
+ MaterialPixelShaderProgram prog;
+};
+
+struct GfxVertexShaderLoadDef
+{
+ char *program;
+ unsigned int programSize;
+};
+
+struct MaterialVertexShaderProgram
+{
+ ID3D11VertexShader *vs;
+ GfxVertexShaderLoadDef loadDef;
+};
+
+struct MaterialVertexShader
+{
+ const char *name;
+ MaterialVertexShaderProgram prog;
+};
+
+struct MaterialTechniqueSet
+{
+ const char *name;
+ char worldVertFormat;
+ MaterialTechnique *techniques[36];
+};
+
+union GfxTexture
+{
+ ID3D11ShaderResourceView *basemap;
+ GfxImageLoadDef *loadDef;
+};
+
+struct Picmip
+{
+ char platform[2];
+};
+
+struct CardMemory
+{
+ int platform[2];
+};
+
+struct GfxStreamedPartInfo
+{
+ unsigned int levelCountAndSize;
+ unsigned int hash;
+ unsigned __int16 width;
+ unsigned __int16 height;
+ unsigned __int32 offset : 32;
+ unsigned __int32 size : 28;
+ unsigned __int32 ipakIndex : 4;
+ unsigned __int32 adjacentLeft : 15;
+ unsigned __int32 adjacentRight : 15;
+ unsigned __int32 compressed : 1;
+ unsigned __int32 valid : 1;
+};
+
+struct GfxImage
+{
+ GfxTexture texture;
+ char mapType;
+ char semantic;
+ char category;
+ bool delayLoadPixels;
+ Picmip picmip;
+ bool noPicmip;
+ char track;
+ CardMemory cardMemory;
+ unsigned __int16 width;
+ unsigned __int16 height;
+ unsigned __int16 depth;
+ char levelCount;
+ char streaming;
+ unsigned int baseSize;
+ char *pixels;
+ GfxStreamedPartInfo streamedParts[1];
+ char streamedPartCount;
+ unsigned int loadedSize;
+ char skippedMipLevels;
+ const char *name;
+ unsigned int hash;
+};
+
+struct SndAssetBankHeader
+{
+ unsigned int magic;
+ unsigned int version;
+ unsigned int entrySize;
+ unsigned int checksumSize;
+ unsigned int dependencySize;
+ unsigned int entryCount;
+ unsigned int dependencyCount;
+ unsigned int pad32;
+ __int64 fileSize;
+ __int64 entryOffset;
+ __int64 checksumOffset;
+ char checksumChecksum[16];
+ char dependencies[512];
+ char padding[1464];
+};
+
+#pragma pack(push, 1)
+struct __declspec(align(2)) SndRuntimeAssetBank
+{
+ const char *zone;
+ const char *language;
+ int fileHandle;
+ SndAssetBankHeader header;
+ unsigned int entryOffset;
+ char linkTimeChecksum[16];
+ char filename[256];
+ bool indicesLoaded;
+ bool indicesAllocated;
+};
+#pragma pack(pop)
+
+struct SndLoadedAssets
+{
+ const char *zone;
+ const char *language;
+ unsigned int loadedCount;
+ unsigned int entryCount;
+ SndAssetBankEntry *entries;
+ unsigned int dataSize;
+ char *data;
+};
+
+enum SndBankState
+{
+ SND_BANK_STATE_NEW = 0x0,
+ SND_BANK_STATE_STREAM_HEADER = 0x1,
+ SND_BANK_STATE_STREAM_TOC = 0x2,
+ SND_BANK_STATE_LOADED_HEADER = 0x3,
+ SND_BANK_STATE_LOADED_TOC = 0x4,
+ SND_BANK_STATE_LOADED_ASSET_WAIT = 0x5,
+ SND_BANK_STATE_LOADED_ASSETS = 0x6,
+ SND_BANK_STATE_READY_TO_USE = 0x7,
+ SND_BANK_STATE_ERROR = 0x8,
+};
+
+struct __declspec(align(2)) SndBank
+{
+ const char *name;
+ unsigned int aliasCount;
+ SndAliasList *alias;
+ SndIndexEntry *aliasIndex;
+ unsigned int radverbCount;
+ SndRadverb *radverbs;
+ unsigned int duckCount;
+ SndDuck *ducks;
+ SndRuntimeAssetBank streamAssetBank;
+ SndRuntimeAssetBank loadAssetBank;
+ SndLoadedAssets loadedAssets;
+ unsigned int scriptIdLookupCount;
+ SndDialogScriptIdLookup *scriptIdLookups;
+ SndBankState state;
+ int streamRequestId;
+ bool pendingIo;
+ bool ioError;
+ bool runtimeAssetLoad;
+};
+
+struct SndPatch
+{
+ char *name;
+ unsigned int elementCount;
+ unsigned int *elements;
+};
+
+struct ClipInfo
+{
+ int planeCount;
+ cplane_s *planes;
+ unsigned int numMaterials;
+ ClipMaterial *materials;
+ unsigned int numBrushSides;
+ cbrushside_t *brushsides;
+ unsigned int leafbrushNodesCount;
+ cLeafBrushNode_s *leafbrushNodes;
+ unsigned int numLeafBrushes;
+ unsigned __int16 *leafbrushes;
+ unsigned int numBrushVerts;
+ vec3_t *brushVerts;
+ unsigned int nuinds;
+ unsigned __int16 *uinds;
+ unsigned __int16 numBrushes;
+ cbrush_t *brushes;
+ Bounds *brushBounds;
+ int *brushContents;
+};
+
+struct __declspec(align(4)) cLeaf_s
+{
+ unsigned __int16 firstCollAabbIndex;
+ unsigned __int16 collAabbCount;
+ int brushContents;
+ int terrainContents;
+ vec3_t mins;
+ vec3_t maxs;
+ int leafBrushNode;
+ __int16 cluster;
+};
+
+struct cmodel_t
+{
+ vec3_t mins;
+ vec3_t maxs;
+ float radius;
+ ClipInfo *info;
+ cLeaf_s leaf;
+};
+
+struct clipMap_t
+{
+ const char *name;
+ int isInUse;
+ ClipInfo info;
+ ClipInfo *pInfo;
+ unsigned int numStaticModels;
+ cStaticModel_s *staticModelList;
+ unsigned int numNodes;
+ cNode_t *nodes;
+ unsigned int numLeafs;
+ cLeaf_s *leafs;
+ unsigned int vertCount;
+ vec3_t *verts;
+ int triCount;
+ unsigned __int16 *triIndices;
+ char *triEdgeIsWalkable;
+ int partitionCount;
+ CollisionPartition *partitions;
+ int aabbTreeCount;
+ CollisionAabbTree *aabbTrees;
+ unsigned int numSubModels;
+ cmodel_t *cmodels;
+ int numClusters;
+ int clusterBytes;
+ char *visibility;
+ int vised;
+ MapEnts *mapEnts;
+ cbrush_t *box_brush;
+ cmodel_t box_model;
+ unsigned __int16 originalDynEntCount;
+ unsigned __int16 dynEntCount[4];
+ DynEntityDef *dynEntDefList[2];
+ DynEntityPose *dynEntPoseList[2];
+ DynEntityClient *dynEntClientList[2];
+ DynEntityServer *dynEntServerList[2];
+ DynEntityColl *dynEntCollList[4];
+ int num_constraints;
+ PhysConstraint *constraints;
+ int max_ropes;
+ rope_t *ropes;
+ unsigned int checksum;
+};
+
+struct ComWorld
+{
+ const char *name;
+ int isInUse;
+ unsigned int primaryLightCount;
+ ComPrimaryLight *primaryLights;
+};
+
+struct PathData
+{
+ unsigned int nodeCount;
+ unsigned int originalNodeCount;
+ pathnode_t *nodes;
+ pathbasenode_t *basenodes;
+ int visBytes;
+ char *pathVis;
+ int smoothBytes;
+ char *smoothCache;
+ int nodeTreeCount;
+ pathnode_tree_t *nodeTree;
+};
+
+struct GameWorldSp
+{
+ const char *name;
+ PathData path;
+};
+
+struct GameWorldMp
+{
+ const char *name;
+ PathData path;
+};
+
+struct MapTriggers
+{
+ unsigned int count;
+ TriggerModel *models;
+ unsigned int hullCount;
+ TriggerHull *hulls;
+ unsigned int slabCount;
+ TriggerSlab *slabs;
+};
+
+struct MapEnts
+{
+ const char *name;
+ char *entityString;
+ int numEntityChars;
+ MapTriggers trigger;
+};
+
+struct GfxWorldStreamInfo
+{
+ int aabbTreeCount;
+ GfxStreamingAabbTree *aabbTrees;
+ int leafRefCount;
+ int *leafRefs;
+};
+
+union vec4_t
+{
+ float v[4];
+ struct
+ {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+ struct
+ {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+};
+
+struct GfxWorldSun
+{
+ unsigned int control;
+ vec3_t angles;
+ vec4_t ambientColor;
+ vec4_t sunCd;
+ vec4_t sunCs;
+ vec4_t skyColor;
+ float exposure;
+};
+
+struct GfxWorldFog
+{
+ float baseDist;
+ float halfDist;
+ float baseHeight;
+ float halfHeight;
+ float sunFogPitch;
+ float sunFogYaw;
+ float sunFogInner;
+ float sunFogOuter;
+ vec3_t fogColor;
+ float fogOpacity;
+ vec3_t sunFogColor;
+ float sunFogOpacity;
+};
+
+struct SunLightParseParams
+{
+ char name[64];
+ GfxWorldSun initWorldSun[1];
+ float fogTransitionTime;
+ GfxWorldFog initWorldFog[1];
+};
+
+struct GfxSkyDynamicIntensity
+{
+ float angle0;
+ float angle1;
+ float factor0;
+ float factor1;
+};
+
+struct GfxWorldDpvsPlanes
+{
+ int cellCount;
+ cplane_s *planes;
+ unsigned __int16 *nodes;
+ unsigned int *sceneEntCellBits;
+};
+
+struct GfxWorldVertexData0
+{
+ char *data;
+ ID3D11Buffer *vb;
+};
+
+struct GfxWorldVertexData1
+{
+ char *data;
+ ID3D11Buffer *vb;
+};
+
+struct GfxWorldDraw
+{
+ unsigned int reflectionProbeCount;
+ GfxReflectionProbe *reflectionProbes;
+ GfxTexture *reflectionProbeTextures;
+ int lightmapCount;
+ GfxLightmapArray *lightmaps;
+ GfxTexture *lightmapPrimaryTextures;
+ GfxTexture *lightmapSecondaryTextures;
+ unsigned int vertexCount;
+ unsigned int vertexDataSize0;
+ GfxWorldVertexData0 vd0;
+ unsigned int vertexDataSize1;
+ GfxWorldVertexData1 vd1;
+ int indexCount;
+ unsigned __int16 *indices;
+ ID3D11Buffer *indexBuffer;
+};
+
+struct GfxLightGrid
+{
+ unsigned int sunPrimaryLightIndex;
+ unsigned __int16 mins[3];
+ unsigned __int16 maxs[3];
+ float offset;
+ unsigned int rowAxis;
+ unsigned int colAxis;
+ unsigned __int16 *rowDataStart;
+ unsigned int rawRowDataSize;
+ char *rawRowData;
+ unsigned int entryCount;
+ GfxLightGridEntry *entries;
+ unsigned int colorCount;
+ GfxCompressedLightGridColors *colors;
+ unsigned int coeffCount;
+ GfxCompressedLightGridCoeffs *coeffs;
+ unsigned int skyGridVolumeCount;
+ GfxSkyGridVolume *skyGridVolumes;
+};
+
+struct sunflare_t
+{
+ bool hasValidData;
+ Material *spriteMaterial;
+ Material *flareMaterial;
+ float spriteSize;
+ float flareMinSize;
+ float flareMinDot;
+ float flareMaxSize;
+ float flareMaxDot;
+ float flareMaxAlpha;
+ int flareFadeInTime;
+ int flareFadeOutTime;
+ float blindMinDot;
+ float blindMaxDot;
+ float blindMaxDarken;
+ int blindFadeInTime;
+ int blindFadeOutTime;
+ float glareMinDot;
+ float glareMaxDot;
+ float glareMaxLighten;
+ int glareFadeInTime;
+ int glareFadeOutTime;
+ vec3_t sunFxPosition;
+};
+
+struct GfxWorldDpvsStatic
+{
+ unsigned int smodelCount;
+ unsigned int staticSurfaceCount;
+ unsigned int litSurfsBegin;
+ unsigned int litSurfsEnd;
+ unsigned int litTransSurfsBegin;
+ unsigned int litTransSurfsEnd;
+ unsigned int emissiveOpaqueSurfsBegin;
+ unsigned int emissiveOpaqueSurfsEnd;
+ unsigned int emissiveTransSurfsBegin;
+ unsigned int emissiveTransSurfsEnd;
+ unsigned int smodelVisDataCount;
+ unsigned int surfaceVisDataCount;
+ char *smodelVisData[3];
+ char *surfaceVisData[3];
+ char *smodelVisDataCameraSaved;
+ char *surfaceVisDataCameraSaved;
+ unsigned __int16 *sortedSurfIndex;
+ GfxStaticModelInst *smodelInsts;
+ GfxSurface *surfaces;
+ GfxStaticModelDrawInst *smodelDrawInsts;
+ GfxDrawSurf *surfaceMaterials;
+ char *surfaceCastsSunShadow;
+ char *surfaceCastsShadow;
+ char *smodelCastsShadow;
+ volatile int usageCount;
+};
+
+struct GfxWorldDpvsDynamic
+{
+ unsigned int dynEntClientWordCount[2];
+ unsigned int dynEntClientCount[2];
+ unsigned int *dynEntCellBits[2];
+ char *dynEntVisData[2][3];
+ volatile int usageCount;
+};
+
+struct GfxWaterBuffer
+{
+ unsigned int bufferSize;
+ vec4_t *buffer;
+};
+
+struct GfxWorld
+{
+ const char *name;
+ const char *baseName;
+ int planeCount;
+ int nodeCount;
+ int surfaceCount;
+ GfxWorldStreamInfo streamInfo;
+ const char *skyBoxModel;
+ SunLightParseParams sunParse;
+ GfxLight *sunLight;
+ unsigned int sunPrimaryLightIndex;
+ unsigned int primaryLightCount;
+ unsigned int coronaCount;
+ GfxLightCorona *coronas;
+ unsigned int shadowMapVolumeCount;
+ GfxShadowMapVolume *shadowMapVolumes;
+ unsigned int shadowMapVolumePlaneCount;
+ GfxVolumePlane *shadowMapVolumePlanes;
+ unsigned int exposureVolumeCount;
+ GfxExposureVolume *exposureVolumes;
+ unsigned int exposureVolumePlaneCount;
+ GfxVolumePlane *exposureVolumePlanes;
+ unsigned int worldFogVolumeCount;
+ GfxWorldFogVolume *worldFogVolumes;
+ unsigned int worldFogVolumePlaneCount;
+ GfxVolumePlane *worldFogVolumePlanes;
+ unsigned int worldFogModifierVolumeCount;
+ GfxWorldFogModifierVolume *worldFogModifierVolumes;
+ unsigned int worldFogModifierVolumePlaneCount;
+ GfxVolumePlane *worldFogModifierVolumePlanes;
+ unsigned int lutVolumeCount;
+ GfxLutVolume *lutVolumes;
+ unsigned int lutVolumePlaneCount;
+ GfxVolumePlane *lutVolumePlanes;
+ GfxSkyDynamicIntensity skyDynIntensity;
+ GfxWorldDpvsPlanes dpvsPlanes;
+ int cellBitsCount;
+ GfxCell *cells;
+ GfxWorldDraw draw;
+ GfxLightGrid lightGrid;
+ int modelCount;
+ GfxBrushModel *models;
+ vec3_t mins;
+ vec3_t maxs;
+ unsigned int checksum;
+ int materialMemoryCount;
+ MaterialMemory *materialMemory;
+ sunflare_t sun;
+ vec4_t outdoorLookupMatrix[4];
+ GfxImage *outdoorImage;
+ unsigned int *cellCasterBits;
+ GfxSceneDynModel *sceneDynModel;
+ GfxSceneDynBrush *sceneDynBrush;
+ unsigned int *primaryLightEntityShadowVis;
+ unsigned int *primaryLightDynEntShadowVis[2];
+ unsigned int numSiegeSkinInsts;
+ SSkinInstance *siegeSkinInsts;
+ GfxShadowGeometry *shadowGeom;
+ GfxLightRegion *lightRegion;
+ GfxWorldDpvsStatic dpvs;
+ GfxWorldDpvsDynamic dpvsDyn;
+ float waterDirection;
+ GfxWaterBuffer waterBuffers[2];
+ Material *waterMaterial;
+ Material *coronaMaterial;
+ Material *ropeMaterial;
+ Material *lutMaterial;
+ unsigned int numOccluders;
+ Occluder *occluders;
+ unsigned int numOutdoorBounds;
+ GfxOutdoorBounds *outdoorBounds;
+ unsigned int heroLightCount;
+ unsigned int heroLightTreeCount;
+ GfxHeroLight *heroLights;
+ GfxHeroLightTree *heroLightTree;
+ unsigned int lightingFlags;
+ int lightingQuality;
+};
+
+struct __declspec(align(4)) GfxLightImage
+{
+ GfxImage *image;
+ char samplerState;
+};
+
+struct GfxLightDef
+{
+ const char *name;
+ GfxLightImage attenuation;
+ int lmapLookupStart;
+};
+
+struct Font_s
+{
+ const char *fontName;
+ int pixelHeight;
+ int isScalingAllowed;
+ int glyphCount;
+ int kerningPairsCount;
+ Material *material;
+ Material *glowMaterial;
+ Glyph *glyphs;
+ KerningPairs *kerningPairs;
+};
+
+struct FontIcon
+{
+ const char *name;
+ int numEntries;
+ int numAliasEntries;
+ FontIconEntry *fontIconEntry;
+ FontIconAlias *fontIconAlias;
+};
+
+struct MenuList
+{
+ const char *name;
+ int menuCount;
+ menuDef_t **menus;
+};
+
+struct rectDef_s
+{
+ float x;
+ float y;
+ float w;
+ float h;
+ int horzAlign;
+ int vertAlign;
+};
+
+struct windowDef_t
+{
+ const char *name;
+ rectDef_s rect;
+ rectDef_s rectClient;
+ const char *group;
+ char style;
+ char border;
+ char modal;
+ char frameSides;
+ float frameTexSize;
+ float frameSize;
+ int ownerDraw;
+ int ownerDrawFlags;
+ float borderSize;
+ int staticFlags;
+ int dynamicFlags[1];
+ int nextTime;
+ vec4_t foreColor;
+ vec4_t backColor;
+ vec4_t borderColor;
+ vec4_t outlineColor;
+ float rotation;
+ Material *background;
+};
+
+struct ExpressionStatement
+{
+ char *filename;
+ int line;
+ int numRpn;
+ expressionRpn *rpn;
+};
+
+struct __declspec(align(8)) menuDef_t
+{
+ windowDef_t window;
+ const char *font;
+ int fullScreen;
+ int ui3dWindowId;
+ int itemCount;
+ int fontIndex;
+ int cursorItem[1];
+ int fadeCycle;
+ int priority;
+ float fadeClamp;
+ float fadeAmount;
+ float fadeInAmount;
+ float blurRadius;
+ int openSlideSpeed;
+ int closeSlideSpeed;
+ int openSlideDirection;
+ int closeSlideDirection;
+ rectDef_s initialRectInfo;
+ int openFadingTime;
+ int closeFadingTime;
+ int fadeTimeCounter;
+ int slideTimeCounter;
+ GenericEventHandler *onEvent;
+ ItemKeyHandler *onKey;
+ ExpressionStatement visibleExp;
+ unsigned __int64 showBits;
+ unsigned __int64 hideBits;
+ const char *allowedBinding;
+ const char *soundName;
+ int imageTrack;
+ int control;
+ vec4_t focusColor;
+ vec4_t disableColor;
+ ExpressionStatement rectXExp;
+ ExpressionStatement rectYExp;
+ itemDef_s **items;
+};
+
+struct LocalizeEntry
+{
+ const char *value;
+ const char *name;
+};
+
+enum weaponIconRatioType_t
+{
+ WEAPON_ICON_RATIO_1TO1 = 0x0,
+ WEAPON_ICON_RATIO_2TO1 = 0x1,
+ WEAPON_ICON_RATIO_4TO1 = 0x2,
+ WEAPON_ICON_RATIO_COUNT = 0x3,
+};
+
+struct WeaponVariantDef
+{
+ const char *szInternalName;
+ int iVariantCount;
+ WeaponDef *weapDef;
+ const char *szDisplayName;
+ const char *szAltWeaponName;
+ const char *szAttachmentUnique;
+ WeaponAttachment **attachments;
+ WeaponAttachmentUnique **attachmentUniques;
+ const char **szXAnims;
+ unsigned __int16 *hideTags;
+ XModel **attachViewModel;
+ XModel **attachWorldModel;
+ const char **attachViewModelTag;
+ const char **attachWorldModelTag;
+ float attachViewModelOffsets[24];
+ float attachWorldModelOffsets[24];
+ float attachViewModelRotations[24];
+ float attachWorldModelRotations[24];
+ vec3_t stowedModelOffsets;
+ vec3_t stowedModelRotations;
+ unsigned int altWeaponIndex;
+ int iAttachments;
+ bool bIgnoreAttachments;
+ int iClipSize;
+ int iReloadTime;
+ int iReloadEmptyTime;
+ int iReloadQuickTime;
+ int iReloadQuickEmptyTime;
+ int iAdsTransInTime;
+ int iAdsTransOutTime;
+ int iAltRaiseTime;
+ const char *szAmmoDisplayName;
+ const char *szAmmoName;
+ int iAmmoIndex;
+ const char *szClipName;
+ int iClipIndex;
+ float fAimAssistRangeAds;
+ float fAdsSwayHorizScale;
+ float fAdsSwayVertScale;
+ float fAdsViewKickCenterSpeed;
+ float fHipViewKickCenterSpeed;
+ float fAdsZoomFov1;
+ float fAdsZoomFov2;
+ float fAdsZoomFov3;
+ float fAdsZoomInFrac;
+ float fAdsZoomOutFrac;
+ float fOverlayAlphaScale;
+ float fOOPosAnimLength[2];
+ bool bSilenced;
+ bool bDualMag;
+ bool bInfraRed;
+ bool bTVGuided;
+ unsigned int perks[2];
+ bool bAntiQuickScope;
+ Material *overlayMaterial;
+ Material *overlayMaterialLowRes;
+ Material *dpadIcon;
+ weaponIconRatioType_t dpadIconRatio;
+ bool noAmmoOnDpadIcon;
+ bool mmsWeapon;
+ bool mmsInScope;
+ float mmsFOV;
+ float mmsAspect;
+ float mmsMaxDist;
+ vec3_t ikLeftHandIdlePos;
+ vec3_t ikLeftHandOffset;
+ vec3_t ikLeftHandRotation;
+ bool bUsingLeftHandProneIK;
+ vec3_t ikLeftHandProneOffset;
+ vec3_t ikLeftHandProneRotation;
+ vec3_t ikLeftHandUiViewerOffset;
+ vec3_t ikLeftHandUiViewerRotation;
+};
+
+enum eAttachment
+{
+ ATTACHMENT_NONE = 0x0,
+ ATTACHMENT_ACOG = 0x1,
+ ATTACHMENT_DUALCLIP = 0x2,
+ ATTACHMENT_DUALOPTIC = 0x3,
+ ATTACHMENT_DW = 0x4,
+ ATTACHMENT_EXTBARREL = 0x5,
+ ATTACHMENT_EXTCLIP = 0x6,
+ ATTACHMENT_EXTRAMAGS = 0x7,
+ ATTACHMENT_FASTADS = 0x8,
+ ATTACHMENT_FASTRELOAD = 0x9,
+ ATTACHMENT_FMJ = 0xA,
+ ATTACHMENT_GL = 0xB,
+ ATTACHMENT_GRIP = 0xC,
+ ATTACHMENT_HOLO = 0xD,
+ ATTACHMENT_IR = 0xE,
+ ATTACHMENT_IRONSIGHTS = 0xF,
+ ATTACHMENT_LONGBREATH = 0x10,
+ ATTACHMENT_MK = 0x11,
+ ATTACHMENT_MMS = 0x12,
+ ATTACHMENT_RANGEFINDER = 0x13,
+ ATTACHMENT_REFLEX = 0x14,
+ ATTACHMENT_RF = 0x15,
+ ATTACHMENT_SELECTFIRE = 0x16,
+ ATTACHMENT_SILENCER = 0x17,
+ ATTACHMENT_STACKFIRE = 0x18,
+ ATTACHMENT_STALKER = 0x19,
+ ATTACHMENT_STEADYAIM = 0x1A,
+ ATTACHMENT_SWAYREDUC = 0x1B,
+ ATTACHMENT_TACKNIFE = 0x1C,
+ ATTACHMENT_VZOOM = 0x1D,
+ ATTACHMENT_TYPE_COUNT = 0x1E,
+ ATTACHMENT_INVALID = 0x1E,
+};
+
+enum eAttachmentPoint
+{
+ ATTACHMENT_POINT_NONE = 0x0,
+ ATTACHMENT_POINT_TOP = 0x1,
+ ATTACHMENT_POINT_FIRST = 0x1,
+ ATTACHMENT_POINT_BOTTOM = 0x2,
+ ATTACHMENT_POINT_TRIGGER = 0x3,
+ ATTACHMENT_POINT_MUZZLE = 0x4,
+ ATTACHMENT_POINT_GUNPERK = 0x5,
+ ATTACHMENT_POINT_COUNT = 0x6,
+ ATTACHMENT_POINT_INVALID = 0x6,
+};
+
+enum PenetrateType
+{
+ PENETRATE_TYPE_NONE = 0x0,
+ PENETRATE_TYPE_SMALL = 0x1,
+ PENETRATE_TYPE_MEDIUM = 0x2,
+ PENETRATE_TYPE_LARGE = 0x3,
+ PENETRATE_TYPE_COUNT = 0x4,
+};
+
+enum weapFireType_t
+{
+ WEAPON_FIRETYPE_FULLAUTO = 0x0,
+ WEAPON_FIRETYPE_SINGLESHOT = 0x1,
+ WEAPON_FIRETYPE_BURSTFIRE2 = 0x2,
+ WEAPON_FIRETYPE_BURSTFIRE3 = 0x3,
+ WEAPON_FIRETYPE_BURSTFIRE4 = 0x4,
+ WEAPON_FIRETYPE_BURSTFIRE5 = 0x5,
+ WEAPON_FIRETYPE_STACKED = 0x6,
+ WEAPON_FIRETYPE_MINIGUN = 0x7,
+ WEAPON_FIRETYPE_CHARGESHOT = 0x8,
+ WEAPON_FIRETYPE_JETGUN = 0x9,
+ WEAPON_FIRETYPECOUNT = 0xA,
+};
+
+struct WeaponAttachment
+{
+ const char *szInternalName;
+ const char *szDisplayName;
+ eAttachment attachmentType;
+ eAttachmentPoint attachmentPoint;
+ PenetrateType penetrateType;
+ weapFireType_t fireType;
+ int firstRaisePriority;
+ float fHipIdleAmount;
+ bool bAltWeaponAdsOnly;
+ bool bAltWeaponDisableSwitching;
+ float altScopeADSTransInTime;
+ float altScopeADSTransOutTime;
+ bool bSilenced;
+ bool bDualMag;
+ bool laserSight;
+ bool bInfraRed;
+ bool bUseAsMelee;
+ bool bDualWield;
+ bool sharedAmmo;
+ float fDamageRangeScale;
+ float fAdsZoomFov1;
+ float fAdsZoomFov2;
+ float fAdsZoomFov3;
+ float fAdsZoomInFrac;
+ float fAdsZoomOutFrac;
+ float fAdsTransInTimeScale;
+ float fAdsTransOutTimeScale;
+ float fAdsRecoilReductionRate;
+ float fAdsRecoilReductionLimit;
+ float fAdsViewKickCenterSpeedScale;
+ float fAdsIdleAmountScale;
+ bool swayOverride;
+ float swayMaxAngle;
+ float swayLerpSpeed;
+ float swayPitchScale;
+ float swayYawScale;
+ float swayHorizScale;
+ float swayVertScale;
+ bool adsSwayOverride;
+ float adsSwayMaxAngle;
+ float adsSwayLerpSpeed;
+ float adsSwayPitchScale;
+ float adsSwayYawScale;
+ float fAdsSwayHorizScale;
+ float fAdsSwayVertScale;
+ float adsMoveSpeedScale;
+ float fHipSpreadMinScale;
+ float fHipSpreadMaxScale;
+ float strafeRotR;
+ float standMoveF;
+ vec3_t vStandRot;
+ float fFireTimeScale;
+ float fReloadTimeScale;
+ float fReloadEmptyTimeScale;
+ float fReloadAddTimeScale;
+ float fReloadQuickTimeScale;
+ float fReloadQuickEmptyTimeScale;
+ float fReloadQuickAddTimeScale;
+ bool mmsWeapon;
+ bool mmsInScope;
+ float mmsFOV;
+ float mmsAspect;
+ float mmsMaxDist;
+ float clipSizeScale;
+ int iClipSize;
+ unsigned int stackFire;
+ float stackFireSpread;
+ float stackFireAccuracyDecay;
+ unsigned int perks[2];
+ float customFloat0;
+ float customFloat1;
+ float customFloat2;
+ int customBool0;
+ int customBool1;
+ int customBool2;
+};
+
+enum weapOverlayReticle_t
+{
+ WEAPOVERLAYRETICLE_NONE = 0x0,
+ WEAPOVERLAYRETICLE_CROSSHAIR = 0x1,
+ WEAPOVERLAYRETICLE_NUM = 0x2,
+};
+
+struct WeaponAttachmentUnique
+{
+ const char *szInternalName;
+ eAttachment attachmentType;
+ int siblingLink;
+ int childLink;
+ int combinedAttachmentTypeMask;
+ const char *szAltWeaponName;
+ unsigned int altWeaponIndex;
+ const char *szDualWieldWeaponName;
+ unsigned int dualWieldWeaponIndex;
+ unsigned __int16 *hideTags;
+ XModel *viewModel;
+ XModel *viewModelAdditional;
+ XModel *viewModelADS;
+ XModel *worldModel;
+ XModel *worldModelAdditional;
+ const char *viewModelTag;
+ const char *worldModelTag;
+ vec3_t viewModelOffsets;
+ vec3_t worldModelOffsets;
+ vec3_t viewModelRotations;
+ vec3_t worldModelRotations;
+ vec3_t viewModelAddOffsets;
+ vec3_t worldModelAddOffsets;
+ vec3_t viewModelAddRotations;
+ vec3_t worldModelAddRotations;
+ WeaponCamo *weaponCamo;
+ bool disableBaseWeaponAttachment;
+ bool disableBaseWeaponClip;
+ bool overrideBaseWeaponAttachmentOffsets;
+ vec3_t viewModelOffsetBaseAttachment;
+ vec3_t worldModelOffsetBaseAttachment;
+ Material *overlayMaterial;
+ Material *overlayMaterialLowRes;
+ weapOverlayReticle_t overlayReticle;
+ int iFirstRaiseTime;
+ int iAltRaiseTime;
+ int iAltDropTime;
+ int iReloadAmmoAdd;
+ int iReloadStartAdd;
+ bool bSegmentedReload;
+ const char **szXAnims;
+ int animationOverrides[3];
+ float *locationDamageMultipliers;
+ int soundOverrides;
+ const char *fireSound;
+ const char *fireSoundPlayer;
+ const char *fireLoopSound;
+ const char *fireLoopSoundPlayer;
+ const char *fireLoopEndSound;
+ const char *fireLoopEndSoundPlayer;
+ const char *fireStartSound;
+ const char *fireStopSound;
+ const char *fireStartSoundPlayer;
+ const char *fireStopSoundPlayer;
+ const char *fireLastSound;
+ const char *fireLastSoundPlayer;
+ const char *fireKillcamSound;
+ const char *fireKillcamSoundPlayer;
+ int effectOverrides;
+ FxEffectDef *viewFlashEffect;
+ FxEffectDef *worldFlashEffect;
+ TracerDef *tracerType;
+ TracerDef *enemyTracerType;
+ float adsDofStart;
+ float adsDofEnd;
+ int iAmmoIndex;
+ int iClipIndex;
+ bool bOverrideLeftHandIK;
+ bool bOverrideLeftHandProneIK;
+ vec3_t ikLeftHandOffset;
+ vec3_t ikLeftHandRotation;
+ vec3_t ikLeftHandProneOffset;
+ vec3_t ikLeftHandProneRotation;
+ float customFloat0;
+ float customFloat1;
+ float customFloat2;
+ int customBool0;
+ int customBool1;
+ int customBool2;
+};
+
+struct WeaponCamo
+{
+ const char *name;
+ GfxImage *solidBaseImage;
+ GfxImage *patternBaseImage;
+ WeaponCamoSet *camoSets;
+ unsigned int numCamoSets;
+ WeaponCamoMaterialSet *camoMaterials;
+ unsigned int numCamoMaterials;
+};
+
+struct SndDriverGlobals
+{
+ const char *name;
+ unsigned int groupCount;
+ SndVolumeGroup *groups;
+ unsigned int curveCount;
+ SndCurve *curves;
+ unsigned int panCount;
+ SndPan *pans;
+ unsigned int duckGroupCount;
+ SndDuckGroup *duckGroups;
+ unsigned int contextCount;
+ SndContext *contexts;
+ unsigned int masterCount;
+ SndMaster *masters;
+ unsigned int voiceDuckCount;
+ SndSidechainDuck *voiceDucks;
+ unsigned int futzCount;
+ SndFutz *futzes;
+};
+
+struct FxFloatRange
+{
+ float base;
+ float amplitude;
+};
+
+const struct FxEffectDef
+{
+ const char *name;
+ unsigned __int16 flags;
+ char efPriority;
+ __int16 elemDefCountLooping;
+ __int16 elemDefCountOneShot;
+ __int16 elemDefCountEmission;
+ int totalSize;
+ int msecLoopingLife;
+ int msecNonLoopingLife;
+ FxElemDef *elemDefs;
+ vec3_t boundingBoxDim;
+ vec3_t boundingBoxCentre;
+ float occlusionQueryDepthBias;
+ int occlusionQueryFadeIn;
+ int occlusionQueryFadeOut;
+ FxFloatRange occlusionQueryScaleRange;
+};
+
+struct FxImpactTable
+{
+ const char *name;
+ FxImpactEntry *table;
+};
+
+struct RawFile
+{
+ const char *name;
+ int len;
+ const char *buffer;
+};
+
+struct StringTable
+{
+ const char *name;
+ int columnCount;
+ int rowCount;
+ StringTableCell *values;
+ __int16 *cellIndex;
+};
+
+enum LbUpdateType
+{
+ LBUPDATE_TYPE_NORMAL = 0x0,
+ LBUPDATE_TYPE_RANK = 0x1,
+ LBUPDATE_TYPE_COMBINE = 0x2,
+ LBUPDATE_TYPE_COUNT = 0x3,
+};
+
+struct LeaderboardDef
+{
+ const char *name;
+ unsigned int id;
+ int columnCount;
+ int dwColumnCount;
+ int xpColId;
+ int prestigeColId;
+ LbColumnDef *columns;
+ LbUpdateType updateType;
+ int trackTypes;
+};
+
+struct gump_info_t
+{
+ char *name;
+ int size;
+};
+
+struct overlay_info_t
+{
+ char *name;
+ int size;
+};
+
+struct XGlobals
+{
+ const char *name;
+ int xanimStreamBufferSize;
+ int cinematicMaxWidth;
+ int cinematicMaxHeight;
+ int extracamResolution;
+ vec4_t screenClearColor;
+ int bigestGumpSize;
+ int gumpsCount;
+ gump_info_t gumps[32];
+ int bigestOverlaySize;
+ int overlayCount;
+ overlay_info_t overlays[32];
+};
+
+struct ddlRoot_t
+{
+ const char *name;
+ ddlDef_t *ddlDef;
+};
+
+struct Glasses
+{
+ const char *name;
+ unsigned int numGlasses;
+ Glass *glasses;
+ char *workMemory;
+ unsigned int workMemorySize;
+ unsigned int smallAllocatorBlocks;
+ unsigned int maxGroups;
+ unsigned int maxShards;
+ unsigned int maxPhysics;
+ unsigned int shardMemorySize;
+ unsigned int maxFreeCmd;
+ unsigned int numSlots;
+ unsigned int numVerts;
+ unsigned int numIndices;
+};
+
+struct EmblemLayer
+{
+ int cost;
+ int unlockLevel;
+ int unlockPLevel;
+};
+
+struct EmblemCategory
+{
+ const char *name;
+ const char *description;
+};
+
+struct EmblemIconType
+{
+ const char *name;
+ const char *description;
+};
+
+struct EmblemBGCategory
+{
+ const char *name;
+ const char *description;
+};
+
+struct EmblemIcon
+{
+ GfxImage *image;
+ const char *description;
+ float outlineSize;
+ int cost;
+ int unlockLevel;
+ int unlockPLevel;
+ int unclassifyAt;
+ int sortKey;
+ unsigned __int16 iconType;
+ unsigned __int16 category;
+};
+
+struct EmblemBackground
+{
+ Material *material;
+ const char *description;
+ int cost;
+ int unlockLevel;
+ int unlockPLevel;
+ int unclassifyAt;
+ int sortKey;
+ unsigned __int16 bgCategory;
+ int mtxIndex;
+};
+
+struct EmblemSet
+{
+ int colorCount;
+ int layerCount;
+ EmblemLayer layers[32];
+ int categoryCount;
+ EmblemCategory categories[16];
+ int iconTypeCount;
+ EmblemIconType iconTypes[16];
+ int bgCategoryCount;
+ EmblemBGCategory bgCategories[16];
+ int iconCount;
+ EmblemIcon icons[1024];
+ int backgroundCount;
+ EmblemBackground backgrounds[550];
+ int backgroundLookupCount;
+ __int16 backgroundLookup[550];
+};
+
+struct ScriptParseTree
+{
+ const char *name;
+ int len;
+ char *buffer;
+};
+
+struct KeyValuePairs
+{
+ const char *name;
+ int numVariables;
+ KeyValuePair *keyValuePairs;
+};
+
+struct view_limits_t
+{
+ float horizSpanLeft;
+ float horizSpanRight;
+ float vertSpanUp;
+ float vertSpanDown;
+ float horizResistLeft;
+ float horizResistRight;
+ float vertResistUp;
+ float vertResistDown;
+};
+
+union vec2_t
+{
+ float v[2];
+ struct
+ {
+ float x;
+ float y;
+ };
+};
+
+enum TractionType
+{
+ TRACTION_TYPE_FRONT = 0x0,
+ TRACTION_TYPE_BACK = 0x1,
+ TRACTION_TYPE_ALL_WD = 0x2,
+ NUM_TRACTION_TYPES = 0x3,
+};
+
+struct VehicleParameter
+{
+ float m_speed_max;
+ float m_accel_max;
+ float m_reverse_scale;
+ float m_steer_angle_max;
+ float m_steer_angle_speed_scale;
+ float m_steer_speed;
+ float m_wheel_radius;
+ float m_susp_spring_k;
+ float m_susp_damp_k;
+ float m_susp_adj;
+ float m_susp_hard_limit;
+ float m_susp_min_height;
+ float m_tire_fric_fwd;
+ float m_tire_fric_side;
+ float m_tire_fric_brake;
+ float m_tire_fric_hand_brake;
+ float m_body_mass;
+ float m_roll_stability;
+ float m_pitch_stability;
+ float m_pitch_roll_resistance;
+ float m_yaw_resistance;
+ float m_upright_strength;
+ float m_tilt_fakey;
+ float m_peel_out_max_speed;
+ float m_tire_damp_coast;
+ float m_tire_damp_brake;
+ float m_tire_damp_hand;
+ float m_auto_hand_brake_min_speed;
+ TractionType m_traction_type;
+ const char *m_name;
+ vec3_t m_bbox_min;
+ vec3_t m_bbox_max;
+ vec3_t m_mass_center_offset;
+ vec3_t m_buoyancybox_min;
+ vec3_t m_buoyancybox_max;
+ float m_water_speed_max;
+ float m_water_accel_max;
+ float m_water_turn_accel;
+ float m_water_turn_speed_max;
+ float m_water_ebrake_power;
+ vec3_t m_boat_motor_offset;
+ float m_boat_speed_rise;
+ float m_boat_speed_tilt;
+ float m_boat_side_fric_scale;
+ float m_boat_forward_fric_scale;
+ float m_boat_vertical_fric_scale;
+ float m_jump_force;
+ float m_tire_fric_side_max;
+ bool m_drive_on_walls;
+ float m_linear_drag_scale;
+ float m_angular_drag_scale;
+};
+
+struct VehicleDriveBySound
+{
+ int apex;
+ const char *name;
+ unsigned int alias;
+};
+
+struct VehicleEngineSound
+{
+ const char *name;
+ unsigned int alias;
+ float params[5];
+};
+
+struct VehicleGearData
+{
+ float minRPM;
+ float maxRPM;
+ float ratio;
+};
+
+struct VehicleEngine
+{
+ float idleRpms;
+ float maxRpms;
+ float maxTorque;
+ float brakingCoeff;
+ vec4_t loadFadeParams;
+ float loadScale;
+ float loadSmoothing;
+ float throttleLag;
+ float pitchScale;
+ VehicleEngineSound onload[5];
+ VehicleEngineSound offload[5];
+ int numGears;
+ int loopLastGear;
+ VehicleGearData gears[10];
+};
+
+struct VehicleAntenna
+{
+ float springK;
+ float damp;
+ float length;
+ float gravity;
+};
+
+const struct VehicleDef
+{
+ const char *name;
+ __int16 type;
+ int remoteControl;
+ int bulletDamage;
+ int armorPiercingDamage;
+ int grenadeDamage;
+ int projectileDamage;
+ int projectileSplashDamage;
+ int heavyExplosiveDamage;
+ __int16 cameraMode;
+ int autoRecenterOnAccel;
+ int thirdPersonDriver;
+ int thirdPersonUseVehicleRoll;
+ int thirdPersonCameraPitchVehicleRelative;
+ int thirdPersonCameraHeightWorldRelative;
+ float thirdPersonCameraRange;
+ float thirdPersonCameraMinPitchClamp;
+ float thirdPersonCameraMaxPitchClamp;
+ float thirdPersonCameraHeight[2];
+ float thirdPersonCameraPitch[2];
+ int cameraAlwaysAutoCenter;
+ float cameraAutoCenterLerpRate;
+ float cameraAutoCenterMaxLerpRate;
+ float thirdPersonCameraSpringDistance;
+ float thirdPersonCameraSpringTime;
+ float thirdPersonCameraHandbrakeTurnRateInc;
+ float cameraFOV;
+ float cameraRollFraction;
+ vec3_t tagPlayerOffset;
+ int killcamCollision;
+ float killcamDist;
+ float killcamZDist;
+ float killcamMinDist;
+ float killcamZTargetOffset;
+ float killcamFOV;
+ float killcamNearBlur;
+ float killcamNearBlurStart;
+ float killcamNearBlurEnd;
+ float killcamFarBlur;
+ float killcamFarBlurStart;
+ float killcamFarBlurEnd;
+ int isDrivable;
+ int numberOfSeats;
+ int numberOfGunners;
+ int seatSwitchOrder[11];
+ int driverControlledGunPos;
+ float entryPointRadius[5];
+ float texScrollScale;
+ float wheelRotRate;
+ float extraWheelRotScale;
+ int wheelChildTakesSteerYaw;
+ float maxSpeed;
+ float maxSpeedVertical;
+ float accel;
+ float accelVertical;
+ float rotRate;
+ float rotAccel;
+ float maxBodyPitch;
+ float maxBodyRoll;
+ float collisionDamage;
+ float collisionSpeed;
+ float suspensionTravel;
+ float heliCollisionScalar;
+ float viewPitchOffset;
+ float viewInfluence;
+ float tiltFromAcceleration[2];
+ float tiltFromDeceleration[2];
+ float tiltFromVelocity[2];
+ float tiltSpeed[2];
+ const char *turretWeapon;
+ view_limits_t turretViewLimits;
+ float turretRotRate;
+ int turretClampPlayerView;
+ int turretLockTurretToPlayerView;
+ const char *gunnerWeapon[4];
+ unsigned __int16 gunnerWeaponIndex[4];
+ float gunnerRotRate;
+ vec2_t gunnerRestAngles[4];
+ view_limits_t passengerViewLimits[6];
+ const char *sndNames[2];
+ unsigned int sndIndices[2];
+ const char *sndMaterialNames[3];
+ float skidSpeedMin;
+ float skidSpeedMax;
+ const char *futzName;
+ float futzBlend;
+ int animType;
+ const char *animSet;
+ int scriptedAnimationEntry;
+ float mantleAngles[4];
+ unsigned __int16 extraWheelTags[4];
+ unsigned __int16 driverHideTag;
+ XModel *attachmentModels[4];
+ unsigned __int16 attachmentTags[4];
+ XModel *deathAttachmentModels[4];
+ unsigned __int16 deathAttachmentTags[4];
+ float tracerOffset[2];
+ XModel *model;
+ XModel *viewModel;
+ XModel *deathModel;
+ XModel *enemyModel;
+ float modelSwapDelay;
+ FxEffectDef *exhaustFx;
+ int oneExhaust;
+ FxEffectDef *treadFx[32];
+ FxEffectDef *deathFx;
+ unsigned __int16 deathFxTag;
+ const char *deathFxSound;
+ FxEffectDef *lightFx[4];
+ unsigned __int16 lightFxTag[4];
+ FxEffectDef *friendlyLightFx;
+ unsigned __int16 friendlyLightFxTag;
+ FxEffectDef *enemyLightFx;
+ unsigned __int16 enemyLightFxTag;
+ float radiusDamageMin;
+ float radiusDamageMax;
+ float radiusDamageRadius;
+ const char *shootShock;
+ const char *shootRumble;
+ float deathQuakeScale;
+ float deathQuakeDuration;
+ float deathQuakeRadius;
+ const char *rumbleType;
+ float rumbleScale;
+ float rumbleDuration;
+ float rumbleRadius;
+ float rumbleBaseTime;
+ float rumbleAdditionalTime;
+ int healthDefault;
+ int healthMin;
+ int healthMax;
+ int eTeam;
+ int boostAccelMultiplier;
+ float boostDuration;
+ float boostSpeedIncrease;
+ int addToCompass;
+ int addToCompassEnemy;
+ const char *compassIcon;
+ Material *compassIconMaterial;
+ const char *gasButtonName;
+ int gasButton;
+ const char *reverseBrakeButtonName;
+ int reverseBrakeButton;
+ const char *handBrakeButtonName;
+ int handBrakeButton;
+ const char *attackButtonName;
+ int attackButton;
+ const char *attackSecondaryButtonName;
+ int attackSecondaryButton;
+ const char *boostButtonName;
+ int boostButton;
+ const char *moveUpButtonName;
+ int moveUpButton;
+ const char *moveDownButtonName;
+ int moveDownButton;
+ const char *switchSeatButtonName;
+ int switchSeatButton;
+ const char *steerGraphName;
+ GraphFloat *steerGraph;
+ const char *accelGraphName;
+ GraphFloat *accelGraph;
+ int isNitrous;
+ int isFourWheelSteering;
+ int useCollmap;
+ float radius;
+ float minHeight;
+ float maxHeight;
+ float max_fric_tilt_angle;
+ float max_fric_tilt;
+ int noDirectionalDamage;
+ int fakeBodyStabilizer;
+ float vehHelicopterBoundsRadius;
+ float vehHelicopterDecelerationFwd;
+ float vehHelicopterDecelerationSide;
+ float vehHelicopterDecelerationUp;
+ float vehHelicopterTiltFromControllerAxes;
+ float vehHelicopterTiltFromFwdAndYaw;
+ float vehHelicopterTiltFromFwdAndYaw_VelAtMaxTilt;
+ float vehHelicopterTiltMomentum;
+ int vehHelicopterQuadRotor;
+ int vehHelicopterAccelTwardsView;
+ float maxRotorArmMovementAngle;
+ float maxRotorArmRotationAngle;
+ int vehHelicopterMaintainHeight;
+ int vehHelicopterMaintainMaxHeight;
+ float vehHelicopterMaintainHeightLimit;
+ float vehHelicopterMaintainHeightAccel;
+ float vehHelicopterMaintainHeightMinimum;
+ float vehHelicopterMaintainHeightMaximum;
+ float vehHelicopterMaintainCeilingMinimum;
+ int joltVehicle;
+ int joltVehicleDriver;
+ float joltMaxTime;
+ float joltTime;
+ float joltWaves;
+ float joltIntensity;
+ VehicleParameter nitrousVehParams;
+ float driveBySoundRadius[2];
+ VehicleDriveBySound driveBySounds[40];
+ int doFootSteps;
+ int isSentient;
+ VehicleEngine engine;
+ VehicleAntenna antenna[2];
+ char *csvInclude;
+ float customFloat0;
+ float customFloat1;
+ float customFloat2;
+ int customBool0;
+ int customBool1;
+ int customBool2;
+};
+
+struct MemoryBlock
+{
+ const char *name;
+ bool mainMem;
+ bool videoMem;
+ bool streamMem;
+ unsigned int size;
+ unsigned int alignment;
+ char *data;
+};
+
+struct AddonMapEnts
+{
+ const char *name;
+ char *entityString;
+ int numEntityChars;
+ MapTriggers trigger;
+ ClipInfo *info;
+ unsigned int numSubModels;
+ cmodel_t *cmodels;
+ GfxBrushModel *models;
+};
+
+enum tracerType_t
+{
+ TRACERTYPE_LASER = 0x0,
+ TRACERTYPE_SMOKE = 0x1,
+ TRACERTYPE_NUM = 0x2,
+};
+
+struct TracerDef
+{
+ const char *name;
+ tracerType_t type;
+ Material *material;
+ unsigned int drawInterval;
+ float speed;
+ float beamLength;
+ float beamWidth;
+ float screwRadius;
+ float screwDist;
+ float fadeTime;
+ float fadeScale;
+ float texRepeatRate;
+ vec4_t colors[5];
+};
+
+struct SkinnedVertsDef
+{
+ const char *name;
+ unsigned int maxSkinnedVerts;
+};
+
+struct Qdb
+{
+ const char *name;
+ int len;
+ char *buffer;
+};
+
+struct Slug
+{
+ const char *name;
+ int len;
+ char *buffer;
+};
+
+struct FootstepTableDef
+{
+ const char *name;
+ unsigned int sndAliasTable[32][7];
+};
+
+struct FootstepFXTableDef
+{
+ const char *name;
+ FxEffectDef *footstepFX[32];
+};
+
+struct ZBarrierBoard
+{
+ XModel *pBoardModel;
+ XModel *pAlternateBoardModel;
+ XModel *pUpgradedBoardModel;
+ const char *pTearAnim;
+ const char *pBoardAnim;
+ FxEffectDef *repairEffect1;
+ FxEffectDef *repairEffect2;
+ vec3_t repairEffect1Offset;
+ vec3_t repairEffect2Offset;
+ unsigned int boardRepairSound;
+ unsigned int boardRepairHoverSound;
+ unsigned int pauseAndRepeatRepSound;
+ float minPause;
+ float maxPause;
+ unsigned __int16 zombieBoardTearStateName;
+ unsigned __int16 zombieBoardTearSubStateName;
+ unsigned int numRepsToPullProBoard;
+};
+
+struct ZBarrierDef
+{
+ const char *name;
+ unsigned int generalRepairSound1;
+ unsigned int generalRepairSound2;
+ unsigned int upgradedGeneralRepairSound1;
+ unsigned int upgradedGeneralRepairSound2;
+ unsigned int delayBetweenRepSounds;
+ float delayBetweenRepSoundsDuration;
+ unsigned int earthquakeOnRepair;
+ float earthquakeMinScale;
+ float earthquakeMaxScale;
+ float earthquakeMinDuration;
+ float earthquakeMaxDuration;
+ float earthquakeRadius;
+ int numBoardsInBarrier;
+ unsigned int autoHideOpenPieces;
+ unsigned int taunts;
+ unsigned int reachThroughAttacks;
+ unsigned __int16 zombieTauntAnimState;
+ unsigned __int16 zombieReachThroughAnimState;
+ int numAttackSlots;
+ float attackSpotHorzOffset;
+ ZBarrierBoard boards[6];
+};
+
+struct XModelPiece
+{
+ XModel *model;
+ vec3_t offset;
+};
+
+struct DestructibleStage
+{
+ unsigned __int16 showBone;
+ float breakHealth;
+ float maxTime;
+ unsigned int flags;
+ FxEffectDef *breakEffect;
+ const char *breakSound;
+ const char *breakNotify;
+ const char *loopSound;
+ XModel *spawnModel[3];
+ PhysPreset *physPreset;
+};
+
+struct DestructiblePiece
+{
+ DestructibleStage stages[5];
+ char parentPiece;
+ float parentDamagePercent;
+ float bulletDamageScale;
+ float explosiveDamageScale;
+ float meleeDamageScale;
+ float impactDamageScale;
+ float entityDamageTransfer;
+ PhysConstraints *physConstraints;
+ int health;
+ const char *damageSound;
+ FxEffectDef *burnEffect;
+ const char *burnSound;
+ unsigned __int16 enableLabel;
+ int hideBones[5];
+};
+
+struct XAnimNotifyInfo
+{
+ unsigned __int16 name;
+ float time;
+};
+
+struct XAnimDeltaPart
+{
+ XAnimPartTrans *trans;
+ XAnimDeltaPartQuat2 *quat2;
+ XAnimDeltaPartQuat *quat;
+};
+
+struct DObjAnimMat
+{
+ vec4_t quat;
+ vec3_t trans;
+ float transWeight;
+};
+
+struct XSurfaceVertexInfo
+{
+ __int16 vertCount[4];
+ unsigned __int16 *vertsBlend;
+ float *tensionData;
+};
+
+struct __declspec(align(16)) XSurface
+{
+ char tileMode;
+ char vertListCount;
+ unsigned __int16 flags;
+ unsigned __int16 vertCount;
+ unsigned __int16 triCount;
+ unsigned __int16 baseVertIndex;
+ unsigned __int16 *triIndices;
+ XSurfaceVertexInfo vertInfo;
+ GfxPackedVertex *verts0;
+ ID3D11Buffer *vb0;
+ XRigidVertList *vertList;
+ ID3D11Buffer *indexBuffer;
+ int partBits[5];
+};
+
+struct XModelCollSurf_s
+{
+ XModelCollTri_s *collTris;
+ int numCollTris;
+ vec3_t mins;
+ vec3_t maxs;
+ int boneIdx;
+ int contents;
+ int surfFlags;
+};
+
+struct __declspec(align(4)) XBoneInfo
+{
+ vec3_t bounds[2];
+ vec3_t offset;
+ float radiusSquared;
+ char collmap;
+};
+
+struct Collmap
+{
+ PhysGeomList *geomList;
+};
+
+struct MaterialTextureDef
+{
+ unsigned int nameHash;
+ char nameStart;
+ char nameEnd;
+ char samplerState;
+ char semantic;
+ char isMatureContent;
+ char pad[3];
+ GfxImage *image;
+};
+
+struct MaterialConstantDef
+{
+ unsigned int nameHash;
+ char name[12];
+ vec4_t literal;
+};
+
+struct GfxStateBits
+{
+ unsigned int loadBits[2];
+ ID3D11BlendState *blendState;
+ ID3D11DepthStencilState *depthStencilState;
+ ID3D11RasterizerState *rasterizerState;
+};
+
+/*struct IUnknown
+{
+ IUnknownVtbl *vfptr;
+};*/
+
+/*struct __cppobj ID3D11DeviceChild : IUnknown
+{
+};*/
+
+/*struct __cppobj ID3D11PixelShader : ID3D11DeviceChild
+{
+};*/
+
+/*struct __cppobj ID3D11VertexShader : ID3D11DeviceChild
+{
+};*/
+
+struct MaterialPass
+{
+ MaterialVertexDeclaration *vertexDecl;
+ MaterialVertexShader *vertexShader;
+ MaterialPixelShader *pixelShader;
+ char perPrimArgCount;
+ char perObjArgCount;
+ char stableArgCount;
+ char customSamplerFlags;
+ char precompiledIndex;
+ char materialType;
+ MaterialShaderArgument *args;
+};
+
+struct MaterialTechnique
+{
+ const char *name;
+ unsigned __int16 flags;
+ unsigned __int16 passCount;
+ MaterialPass passArray[1];
+};
+
+/*struct __cppobj ID3D11View : ID3D11DeviceChild
+{
+};*/
+
+/*struct __cppobj ID3D11ShaderResourceView : ID3D11View
+{
+};*/
+
+struct __declspec(align(4)) GfxImageLoadDef
+{
+ char levelCount;
+ char flags;
+ int format;
+ int resourceSize;
+ char data[1];
+};
+
+struct SndAliasList
+{
+ const char *name;
+ unsigned int id;
+ SndAlias *head;
+ int count;
+ int sequence;
+};
+
+struct SndIndexEntry
+{
+ unsigned __int16 value;
+ unsigned __int16 next;
+};
+
+struct SndRadverb
+{
+ char name[32];
+ unsigned int id;
+ float smoothing;
+ float earlyTime;
+ float lateTime;
+ float earlyGain;
+ float lateGain;
+ float returnGain;
+ float earlyLpf;
+ float lateLpf;
+ float inputLpf;
+ float dampLpf;
+ float wallReflect;
+ float dryGain;
+ float earlySize;
+ float lateSize;
+ float diffusion;
+ float returnHighpass;
+};
+
+struct SndDuck
+{
+ char name[32];
+ unsigned int id;
+ float fadeIn;
+ float fadeOut;
+ float startDelay;
+ float distance;
+ float length;
+ unsigned int fadeInCurve;
+ unsigned int fadeOutCurve;
+ float *attenuation;
+ float *filter;
+ int updateWhilePaused;
+};
+
+struct SndAssetBankEntry
+{
+ unsigned int id;
+ unsigned int size;
+ unsigned int offset;
+ unsigned int frameCount;
+ char frameRateIndex;
+ char channelCount;
+ char looping;
+ char format;
+};
+
+struct SndDialogScriptIdLookup
+{
+ unsigned int scriptId;
+ unsigned int aliasId;
+};
+
+struct cplane_s
+{
+ vec3_t normal;
+ float dist;
+ char type;
+ char signbits;
+ char pad[2];
+};
+
+struct ClipMaterial
+{
+ const char *name;
+ int surfaceFlags;
+ int contentFlags;
+};
+
+struct cbrushside_t
+{
+ cplane_s *plane;
+ int cflags;
+ int sflags;
+};
+
+struct cLeafBrushNodeLeaf_t
+{
+ unsigned __int16 *brushes;
+};
+
+struct cLeafBrushNodeChildren_t
+{
+ float dist;
+ float range;
+ unsigned __int16 childOffset[2];
+};
+
+union cLeafBrushNodeData_t
+{
+ cLeafBrushNodeLeaf_t leaf;
+ cLeafBrushNodeChildren_t children;
+};
+
+struct cLeafBrushNode_s
+{
+ char axis;
+ __int16 leafBrushCount;
+ int contents;
+ cLeafBrushNodeData_t data;
+};
+
+struct __declspec(align(8)) cbrush_t
+{
+ vec3_t mins;
+ int contents;
+ vec3_t maxs;
+ unsigned int numsides;
+ cbrushside_t *sides;
+ int axial_cflags[2][3];
+ int axial_sflags[2][3];
+ unsigned int numverts;
+ vec3_t *verts;
+};
+
+struct Bounds
+{
+ vec3_t midPoint;
+ vec3_t halfSize;
+};
+
+struct cStaticModelWritable
+{
+ unsigned __int16 nextModelInWorldSector;
+};
+
+struct cStaticModel_s
+{
+ cStaticModelWritable writable;
+ XModel *xmodel;
+ int contents;
+ vec3_t origin;
+ vec3_t invScaledAxis[3];
+ vec3_t absmin;
+ vec3_t absmax;
+};
+
+struct cNode_t
+{
+ cplane_s *plane;
+ __int16 children[2];
+};
+
+const struct CollisionPartition
+{
+ char triCount;
+ int firstTri;
+ int nuinds;
+ int fuind;
+};
+
+union CollisionAabbTreeIndex
+{
+ int firstChildIndex;
+ int partitionIndex;
+};
+
+struct CollisionAabbTree
+{
+ vec3_t origin;
+ unsigned __int16 materialIndex;
+ unsigned __int16 childCount;
+ vec3_t halfSize;
+ CollisionAabbTreeIndex u;
+};
+
+enum DynEntityType
+{
+ DYNENT_TYPE_INVALID = 0x0,
+ DYNENT_TYPE_CLUTTER = 0x1,
+ DYNENT_TYPE_DESTRUCT = 0x2,
+ DYNENT_TYPE_COUNT = 0x3,
+};
+
+struct GfxPlacement
+{
+ vec4_t quat;
+ vec3_t origin;
+};
+
+struct DynEntityDef
+{
+ DynEntityType type;
+ GfxPlacement pose;
+ XModel *xModel;
+ XModel *destroyedxModel;
+ unsigned __int16 brushModel;
+ unsigned __int16 physicsBrushModel;
+ FxEffectDef *destroyFx;
+ unsigned int destroySound;
+ XModelPieces *destroyPieces;
+ PhysPreset *physPreset;
+ __int16 physConstraints[4];
+ int health;
+ int flags;
+ int contents;
+ unsigned __int16 targetname;
+ unsigned __int16 target;
+};
+
+struct DynEntityPose
+{
+ GfxPlacement pose;
+ float radius;
+};
+
+struct DynEntityClient
+{
+ int physObjId;
+ unsigned __int16 flags;
+ unsigned __int16 lightingHandle;
+ int health;
+ unsigned __int16 burnTime;
+ unsigned __int16 fadeTime;
+ int physicsStartTime;
+};
+
+struct DynEntityServer
+{
+ unsigned __int16 flags;
+ int health;
+};
+
+struct DynEntityColl
+{
+ unsigned __int16 sector;
+ unsigned __int16 nextEntInSector;
+ vec3_t linkMins;
+ vec3_t linkMaxs;
+ int contents;
+};
+
+struct par_t
+{
+ vec3_t p;
+ vec3_t p0;
+ vec3_t p_prev;
+ int flags;
+};
+
+enum rope_constraint_e
+{
+ ROPE_PAIR_CONSTRAINT = 0x0,
+ ROPE_WORLD_CONSTRAINT = 0x1,
+ ROPE_DENTITY_CONSTRAINT = 0x2,
+ ROPE_CENTITY_CONSTRAINT = 0x3,
+};
+
+struct __declspec(align(4)) constraint_t
+{
+ vec3_t p;
+ rope_constraint_e type;
+ int entity_index;
+ int bone_name_hash;
+ char pi1;
+ char pi2;
+};
+
+struct rope_frame_verts_t
+{
+ int num_verts;
+ vec3_t v[50];
+};
+
+struct rope_client_verts_t
+{
+ rope_frame_verts_t frame_verts[2];
+ unsigned int frame_index;
+};
+
+struct __declspec(align(4)) rope_t
+{
+ par_t m_particles[25];
+ constraint_t m_constraints[30];
+ int m_entity_anchors[3];
+ int m_num_particles;
+ int m_num_constraints;
+ int m_num_entity_anchors;
+ int m_num_draw_verts;
+ rope_client_verts_t m_client_verts;
+ vec3_t m_min;
+ vec3_t m_max;
+ vec3_t m_start;
+ vec3_t m_end;
+ int m_in_use;
+ int m_visible;
+ int m_dist_constraint;
+ int m_flags;
+ Material *m_material;
+ float m_seglen;
+ float m_length;
+ float m_width;
+ float m_scale;
+ float m_force_scale;
+ int m_health;
+ int m_frame;
+ int m_stable_count;
+ int m_static_rope;
+ unsigned __int16 m_lightingHandle;
+};
+
+struct ComPrimaryLight
+{
+ char type;
+ char canUseShadowMap;
+ char exponent;
+ char priority;
+ __int16 cullDist;
+ char useCookie;
+ char shadowmapVolume;
+ vec3_t color;
+ vec3_t dir;
+ vec3_t origin;
+ float radius;
+ float cosHalfFovOuter;
+ float cosHalfFovInner;
+ float cosHalfFovExpanded;
+ float rotationLimit;
+ float translationLimit;
+ float mipDistance;
+ float dAttenuation;
+ float roundness;
+ vec4_t diffuseColor;
+ vec4_t falloff;
+ vec4_t angle;
+ vec4_t aAbB;
+ vec4_t cookieControl0;
+ vec4_t cookieControl1;
+ vec4_t cookieControl2;
+ const char *defName;
+};
+
+enum nodeType
+{
+ NODE_BADNODE = 0x0,
+ NODE_PATHNODE = 0x1,
+ NODE_COVER_STAND = 0x2,
+ NODE_COVER_CROUCH = 0x3,
+ NODE_COVER_CROUCH_WINDOW = 0x4,
+ NODE_COVER_PRONE = 0x5,
+ NODE_COVER_RIGHT = 0x6,
+ NODE_COVER_LEFT = 0x7,
+ NODE_COVER_PILLAR = 0x8,
+ NODE_AMBUSH = 0x9,
+ NODE_EXPOSED = 0xA,
+ NODE_CONCEALMENT_STAND = 0xB,
+ NODE_CONCEALMENT_CROUCH = 0xC,
+ NODE_CONCEALMENT_PRONE = 0xD,
+ NODE_REACQUIRE = 0xE,
+ NODE_BALCONY = 0xF,
+ NODE_SCRIPTED = 0x10,
+ NODE_NEGOTIATION_BEGIN = 0x11,
+ NODE_NEGOTIATION_END = 0x12,
+ NODE_TURRET = 0x13,
+ NODE_GUARD = 0x14,
+ NODE_NUMTYPES = 0x15,
+ NODE_DONTLINK = 0x15,
+};
+
+struct pathnode_constant_t
+{
+ nodeType type;
+ int spawnflags;
+ unsigned __int16 targetname;
+ unsigned __int16 script_linkName;
+ unsigned __int16 script_noteworthy;
+ unsigned __int16 target;
+ unsigned __int16 animscript;
+ int animscriptfunc;
+ vec3_t vOrigin;
+ float fAngle;
+ vec2_t forward;
+ float fRadius;
+ float minUseDistSq;
+ __int16 wOverlapNode[2];
+ unsigned __int16 totalLinkCount;
+ pathlink_s *Links;
+};
+
+struct SentientHandle
+{
+ unsigned __int16 number;
+ unsigned __int16 infoIndex;
+};
+
+struct __declspec(align(4)) pathnode_dynamic_t
+{
+ SentientHandle pOwner;
+ int iFreeTime;
+ int iValidTime[3];
+ int dangerousNodeTime[3];
+ int inPlayerLOSTime;
+ __int16 wLinkCount;
+ __int16 wOverlapCount;
+ __int16 turretEntNumber;
+ __int16 userCount;
+ bool hasBadPlaceLink;
+};
+
+struct pathnode_transient_t
+{
+ int iSearchFrame;
+ pathnode_t *pNextOpen;
+ pathnode_t *pPrevOpen;
+ pathnode_t *pParent;
+ float fCost;
+ float fHeuristic;
+ union
+ {
+ float nodeCost;
+ int linkIndex;
+ };
+};
+
+struct pathnode_t
+{
+ pathnode_constant_t constant;
+ pathnode_dynamic_t dynamic;
+ pathnode_transient_t transient;
+};
+
+struct pathbasenode_t
+{
+ vec3_t vOrigin;
+ unsigned int type;
+};
+
+struct pathnode_tree_nodes_t
+{
+ int nodeCount;
+ unsigned __int16 *nodes;
+};
+
+union pathnode_tree_info_t
+{
+ pathnode_tree_t *child[2];
+ pathnode_tree_nodes_t s;
+};
+
+struct pathnode_tree_t
+{
+ int axis;
+ float dist;
+ pathnode_tree_info_t u;
+};
+
+struct TriggerModel
+{
+ int contents;
+ unsigned __int16 hullCount;
+ unsigned __int16 firstHull;
+};
+
+struct TriggerHull
+{
+ Bounds bounds;
+ int contents;
+ unsigned __int16 slabCount;
+ unsigned __int16 firstSlab;
+};
+
+struct TriggerSlab
+{
+ vec3_t dir;
+ float midPoint;
+ float halfSize;
+};
+
+struct GfxStreamingAabbTree
+{
+ vec4_t mins;
+ vec4_t maxs;
+ float maxStreamingDistance;
+ unsigned __int16 firstItem;
+ unsigned __int16 itemCount;
+ unsigned __int16 firstChild;
+ unsigned __int16 childCount;
+ unsigned __int16 smodelCount;
+ unsigned __int16 surfaceCount;
+};
+
+struct float44
+{
+ union
+ {
+ vec4_t m[4];
+ float member[16];
+ };
+};
+
+struct GfxLight
+{
+ char type;
+ char canUseShadowMap;
+ char shadowmapVolume;
+ __int16 cullDist;
+ vec3_t color;
+ vec3_t dir;
+ vec3_t origin;
+ float radius;
+ float cosHalfFovOuter;
+ float cosHalfFovInner;
+ int exponent;
+ unsigned int spotShadowIndex;
+ float dAttenuation;
+ float roundness;
+ vec3_t angles;
+ float spotShadowHiDistance;
+ vec4_t diffuseColor;
+ vec4_t shadowColor;
+ vec4_t falloff;
+ vec4_t aAbB;
+ vec4_t cookieControl0;
+ vec4_t cookieControl1;
+ vec4_t cookieControl2;
+ /*__declspec(align(16))*/ float44 viewMatrix;
+ float44 projMatrix;
+ GfxLightDef *def;
+};
+
+struct GfxLightCorona
+{
+ vec3_t origin;
+ float radius;
+ vec3_t color;
+ float intensity;
+};
+
+struct GfxShadowMapVolume
+{
+ unsigned int control;
+ unsigned int padding1;
+ unsigned int padding2;
+ unsigned int padding3;
+};
+
+struct GfxVolumePlane
+{
+ vec4_t plane;
+};
+
+struct GfxExposureVolume
+{
+ unsigned int control;
+ float exposure;
+ float luminanceIncreaseScale;
+ float luminanceDecreaseScale;
+ float featherRange;
+ float featherAdjust;
+};
+
+struct GfxWorldFogVolume
+{
+ vec3_t mins;
+ unsigned int control;
+ vec3_t maxs;
+ float fogTransitionTime;
+ unsigned int controlEx;
+ GfxWorldFog volumeWorldFog[1];
+};
+
+struct GfxWorldFogModifierVolume
+{
+ unsigned int control;
+ unsigned __int16 minX;
+ unsigned __int16 minY;
+ unsigned __int16 minZ;
+ unsigned __int16 maxX;
+ unsigned __int16 maxY;
+ unsigned __int16 maxZ;
+ unsigned int controlEx;
+ float transitionTime;
+ float depthScale;
+ float heightScale;
+ vec4_t colorAdjust;
+};
+
+struct GfxLutVolume
+{
+ vec3_t mins;
+ unsigned int control;
+ vec3_t maxs;
+ float lutTransitionTime;
+ unsigned int lutIndex;
+};
+
+struct GfxCell
+{
+ vec3_t mins;
+ vec3_t maxs;
+ int aabbTreeCount;
+ GfxAabbTree *aabbTree;
+ int portalCount;
+ GfxPortal *portals;
+ char reflectionProbeCount;
+ char *reflectionProbes;
+};
+
+struct GfxLightingSH
+{
+ vec4_t V0;
+ vec4_t V1;
+ vec4_t V2;
+};
+
+struct GfxReflectionProbe
+{
+ vec3_t origin;
+ GfxLightingSH lightingSH;
+ GfxImage *reflectionImage;
+ GfxReflectionProbeVolumeData *probeVolumes;
+ unsigned int probeVolumeCount;
+ float mipLodBias;
+};
+
+struct GfxLightmapArray
+{
+ GfxImage *primary;
+ GfxImage *secondary;
+};
+
+/*struct __cppobj ID3D11Resource : ID3D11DeviceChild
+{
+};*/
+
+/*struct __cppobj ID3D11Buffer : ID3D11Resource
+{
+};*/
+
+struct GfxLightGridEntry
+{
+ unsigned __int16 colorsIndex;
+ char primaryLightIndex;
+ char visibility;
+};
+
+struct GfxCompressedLightGridColors
+{
+ char rgb[56][3];
+};
+
+struct GfxCompressedLightGridCoeffs
+{
+ unsigned __int16 coeffs[9][3];
+};
+
+struct GfxSkyGridVolume
+{
+ vec3_t mins;
+ vec3_t maxs;
+ vec3_t lightingOrigin;
+ unsigned __int16 colorsIndex;
+ char primaryLightIndex;
+ char visibility;
+};
+
+struct GfxBrushModelWritable
+{
+ vec3_t mins;
+ float padding1;
+ vec3_t maxs;
+ float padding2;
+};
+
+struct GfxBrushModel
+{
+ GfxBrushModelWritable writable;
+ vec3_t bounds[2];
+ unsigned int surfaceCount;
+ unsigned int startSurfIndex;
+};
+
+struct MaterialMemory
+{
+ Material *material;
+ int memory;
+};
+
+union XModelDrawInfo
+{
+ struct
+ {
+ char state;
+ char lod;
+ unsigned __int16 surfId;
+ };
+ unsigned int packed;
+};
+
+struct GfxSceneDynModel
+{
+ XModelDrawInfo info;
+ unsigned __int16 dynEntId;
+ char primaryLightIndex;
+ char reflectionProbeIndex;
+};
+
+struct BModelDrawInfo
+{
+ unsigned __int16 surfId;
+};
+
+struct GfxSceneDynBrush
+{
+ BModelDrawInfo info;
+ unsigned __int16 dynEntId;
+};
+
+union __m128
+{
+ float m128_f32[4];
+ unsigned __int64 m128_u64[2];
+ char m128_i8[16];
+ __int16 m128_i16[8];
+ int m128_i32[4];
+ __int64 m128_i64[2];
+ char m128_u8[16];
+ unsigned __int16 m128_u16[8];
+ unsigned int m128_u32[4];
+};
+
+struct vector3
+{
+ __m128 x;
+ __m128 y;
+ __m128 z;
+};
+
+struct vector4 : vector3
+{
+ __m128 w;
+};
+
+struct SSkinInstance
+{
+ union
+ {
+ vector4 mat;
+ float disk_mat[16];
+ };
+ SSkinShaders *shaders;
+ SSkinModel *model;
+ SSkinAnim *anim;
+ SSkinVert *instVerts;
+ float frame;
+ int pad1;
+ int pad2;
+ int pad3;
+};
+
+struct GfxShadowGeometry
+{
+ unsigned __int16 surfaceCount;
+ unsigned __int16 smodelCount;
+ unsigned __int16 *sortedSurfIndex;
+ unsigned __int16 *smodelIndex;
+};
+
+struct GfxLightRegion
+{
+ unsigned int hullCount;
+ GfxLightRegionHull *hulls;
+};
+
+struct GfxStaticModelInst
+{
+ vec3_t mins;
+ vec3_t maxs;
+ vec3_t lightingOrigin;
+};
+
+struct srfTriangles_t
+{
+ vec3_t mins;
+ int vertexDataOffset0;
+ vec3_t maxs;
+ int vertexDataOffset1;
+ int firstVertex;
+ float himipRadiusInvSq;
+ unsigned __int16 vertexCount;
+ unsigned __int16 triCount;
+ int baseIndex;
+};
+
+struct GfxSurface
+{
+ srfTriangles_t tris;
+ Material *material;
+ char lightmapIndex;
+ char reflectionProbeIndex;
+ char primaryLightIndex;
+ char flags;
+ vec3_t bounds[2];
+};
+
+struct GfxPackedPlacement
+{
+ vec3_t origin;
+ vec3_t axis[3];
+ float scale;
+};
+
+struct GfxLightingSHQuantized
+{
+ unsigned __int16 V0[4];
+ unsigned __int16 V1[4];
+ unsigned __int16 V2[4];
+};
+
+struct __declspec(align(4)) GfxStaticModelLmapVertexInfo
+{
+ unsigned int *lmapVertexColors;
+ ID3D11Buffer *lmapVertexColorsVB;
+ unsigned __int16 numLmapVertexColors;
+};
+
+struct GfxStaticModelDrawInst
+{
+ float cullDist;
+ GfxPackedPlacement placement;
+ XModel *model;
+ int flags;
+ float invScaleSq;
+ unsigned __int16 lightingHandle;
+ unsigned __int16 colorsIndex;
+ GfxLightingSHQuantized lightingSH;
+ char primaryLightIndex;
+ char visibility;
+ char reflectionProbeIndex;
+ unsigned int smid;
+ GfxStaticModelLmapVertexInfo lmapVertexInfo[4];
+};
+
+struct Occluder
+{
+ unsigned int flags;
+ char name[16];
+ vec3_t points[4];
+};
+
+struct GfxOutdoorBounds
+{
+ vec3_t bounds[2];
+};
+
+struct GfxHeroLight
+{
+ char type;
+ char unused[3];
+ vec3_t color;
+ vec3_t dir;
+ vec3_t origin;
+ float radius;
+ float cosHalfFovOuter;
+ float cosHalfFovInner;
+ int exponent;
+};
+
+struct GfxHeroLightTree
+{
+ vec3_t mins;
+ vec3_t maxs;
+ int leftNode;
+ int rightNode;
+};
+
+struct Glyph
+{
+ unsigned __int16 letter;
+ char x0;
+ char y0;
+ char dx;
+ char pixelWidth;
+ char pixelHeight;
+ float s0;
+ float t0;
+ float s1;
+ float t1;
+};
+
+struct KerningPairs
+{
+ unsigned __int16 wFirst;
+ unsigned __int16 wSecond;
+ int iKernAmount;
+};
+
+struct FontIconName
+{
+ const char *string;
+ int hash;
+};
+
+struct FontIconEntry
+{
+ FontIconName fontIconName;
+ Material *fontIconMaterialHandle;
+ int fontIconSize;
+ float xScale;
+ float yScale;
+};
+
+struct FontIconAlias
+{
+ int aliasHash;
+ int buttonHash;
+};
+
+struct GenericEventHandler
+{
+ const char *name;
+ GenericEventScript *eventScript;
+ GenericEventHandler *next;
+};
+
+struct ItemKeyHandler
+{
+ int key;
+ GenericEventScript *keyScript;
+ ItemKeyHandler *next;
+};
+
+enum expDataType
+{
+ VAL_INT = 0x0,
+ VAL_FLOAT = 0x1,
+ VAL_STRING = 0x2,
+ VAL_ADDRESS = 0x3,
+ VAL_DVAR = 0x4,
+};
+
+union operandInternalDataUnion
+{
+ int intVal;
+ float floatVal;
+ const char *string;
+ dvar_t *dvar;
+};
+
+struct Operand
+{
+ expDataType dataType;
+ operandInternalDataUnion internals;
+};
+
+union expressionRpnDataUnion
+{
+ Operand constant;
+ void *cmd;
+ int cmdIdx;
+};
+
+struct expressionRpn
+{
+ int type;
+ expressionRpnDataUnion data;
+};
+
+union itemDefData_t
+{
+ textDef_s *textDef;
+ imageDef_s *imageDef;
+ focusItemDef_s *blankButtonDef;
+ ownerDrawDef_s *ownerDrawDef;
+ void *data;
+};
+
+struct __declspec(align(8)) itemDef_s
+{
+ windowDef_t window;
+ int type;
+ int dataType;
+ int imageTrack;
+ const char *dvar;
+ const char *profileVar;
+ const char *dvarTest;
+ const char *enableDvar;
+ int dvarFlags;
+ itemDefData_t typeData;
+ menuDef_t *parent;
+ rectData_s *rectExpData;
+ ExpressionStatement visibleExp;
+ unsigned __int64 showBits;
+ unsigned __int64 hideBits;
+ ExpressionStatement forecolorAExp;
+ int ui3dWindowId;
+ GenericEventHandler *onEvent;
+ UIAnimInfo *animInfo;
+};
+
+enum weapType_t
+{
+ WEAPTYPE_BULLET = 0x0,
+ WEAPTYPE_GRENADE = 0x1,
+ WEAPTYPE_PROJECTILE = 0x2,
+ WEAPTYPE_BINOCULARS = 0x3,
+ WEAPTYPE_GAS = 0x4,
+ WEAPTYPE_BOMB = 0x5,
+ WEAPTYPE_MINE = 0x6,
+ WEAPTYPE_MELEE = 0x7,
+ WEAPTYPE_RIOTSHIELD = 0x8,
+ WEAPTYPE_NUM = 0x9,
+};
+
+enum weapClass_t
+{
+ WEAPCLASS_RIFLE = 0x0,
+ WEAPCLASS_MG = 0x1,
+ WEAPCLASS_SMG = 0x2,
+ WEAPCLASS_SPREAD = 0x3,
+ WEAPCLASS_PISTOL = 0x4,
+ WEAPCLASS_GRENADE = 0x5,
+ WEAPCLASS_ROCKETLAUNCHER = 0x6,
+ WEAPCLASS_TURRET = 0x7,
+ WEAPCLASS_NON_PLAYER = 0x8,
+ WEAPCLASS_GAS = 0x9,
+ WEAPCLASS_ITEM = 0xA,
+ WEAPCLASS_MELEE = 0xB,
+ WEAPCLASS_KILLSTREAK_ALT_STORED_WEAPON = 0xC,
+ WEAPCLASS_PISTOL_SPREAD = 0xD,
+ WEAPCLASS_NUM = 0xE,
+};
+
+enum ImpactType
+{
+ IMPACT_TYPE_NONE = 0x0,
+ IMPACT_TYPE_BULLET_SMALL = 0x1,
+ IMPACT_TYPE_BULLET_LARGE = 0x2,
+ IMPACT_TYPE_BULLET_AP = 0x3,
+ IMPACT_TYPE_BULLET_XTREME = 0x4,
+ IMPACT_TYPE_SHOTGUN = 0x5,
+ IMPACT_TYPE_GRENADE_BOUNCE = 0x6,
+ IMPACT_TYPE_GRENADE_EXPLODE = 0x7,
+ IMPACT_TYPE_RIFLE_GRENADE = 0x8,
+ IMPACT_TYPE_ROCKET_EXPLODE = 0x9,
+ IMPACT_TYPE_ROCKET_EXPLODE_XTREME = 0xA,
+ IMPACT_TYPE_PROJECTILE_DUD = 0xB,
+ IMPACT_TYPE_MORTAR_SHELL = 0xC,
+ IMPACT_TYPE_TANK_SHELL = 0xD,
+ IMPACT_TYPE_BOLT = 0xE,
+ IMPACT_TYPE_BLADE = 0xF,
+ IMPACT_TYPE_COUNT = 0x10,
+};
+
+enum weapInventoryType_t
+{
+ WEAPINVENTORY_PRIMARY = 0x0,
+ WEAPINVENTORY_OFFHAND = 0x1,
+ WEAPINVENTORY_ITEM = 0x2,
+ WEAPINVENTORY_ALTMODE = 0x3,
+ WEAPINVENTORY_MELEE = 0x4,
+ WEAPINVENTORY_DWLEFTHAND = 0x5,
+ WEAPINVENTORYCOUNT = 0x6,
+};
+
+enum weapClipType_t
+{
+ WEAPON_CLIPTYPE_BOTTOM = 0x0,
+ WEAPON_CLIPTYPE_TOP = 0x1,
+ WEAPON_CLIPTYPE_LEFT = 0x2,
+ WEAPON_CLIPTYPE_DP28 = 0x3,
+ WEAPON_CLIPTYPE_PTRS = 0x4,
+ WEAPON_CLIPTYPE_LMG = 0x5,
+ WEAPON_CLIPTYPECOUNT = 0x6,
+};
+
+enum barrelType_t
+{
+ BARREL_TYPE_SINGLE = 0x0,
+ BARREL_TYPE_DUAL = 0x1,
+ BARREL_TYPE_DUAL_ALTERNATE = 0x2,
+ BARREL_TYPE_QUAD = 0x3,
+ BARREL_TYPE_QUAD_ALTERNATE = 0x4,
+ BARREL_TYPE_QUAD_DOUBLE_ALTERNATE = 0x5,
+ BARREL_TYPE_COUNT = 0x6,
+};
+
+enum OffhandClass
+{
+ OFFHAND_CLASS_NONE = 0x0,
+ OFFHAND_CLASS_FRAG_GRENADE = 0x1,
+ OFFHAND_CLASS_SMOKE_GRENADE = 0x2,
+ OFFHAND_CLASS_FLASH_GRENADE = 0x3,
+ OFFHAND_CLASS_GEAR = 0x4,
+ OFFHAND_CLASS_SUPPLYDROP_MARKER = 0x5,
+ OFFHAND_CLASS_COUNT = 0x6,
+};
+
+enum OffhandSlot
+{
+ OFFHAND_SLOT_NONE = 0x0,
+ OFFHAND_SLOT_LETHAL_GRENADE = 0x1,
+ OFFHAND_SLOT_TACTICAL_GRENADE = 0x2,
+ OFFHAND_SLOT_EQUIPMENT = 0x3,
+ OFFHAND_SLOT_SPECIFIC_USE = 0x4,
+ OFFHAND_SLOT_COUNT = 0x5,
+};
+
+enum weapStance_t
+{
+ WEAPSTANCE_STAND = 0x0,
+ WEAPSTANCE_DUCK = 0x1,
+ WEAPSTANCE_PRONE = 0x2,
+ WEAPSTANCE_NUM = 0x3,
+};
+
+enum activeReticleType_t
+{
+ VEH_ACTIVE_RETICLE_NONE = 0x0,
+ VEH_ACTIVE_RETICLE_PIP_ON_A_STICK = 0x1,
+ VEH_ACTIVE_RETICLE_BOUNCING_DIAMOND = 0x2,
+ VEH_ACTIVE_RETICLE_MISSILE_LOCK = 0x3,
+ VEH_ACTIVE_RETICLE_COUNT = 0x4,
+};
+
+enum ammoCounterClipType_t
+{
+ AMMO_COUNTER_CLIP_NONE = 0x0,
+ AMMO_COUNTER_CLIP_MAGAZINE = 0x1,
+ AMMO_COUNTER_CLIP_SHORTMAGAZINE = 0x2,
+ AMMO_COUNTER_CLIP_SHOTGUN = 0x3,
+ AMMO_COUNTER_CLIP_ROCKET = 0x4,
+ AMMO_COUNTER_CLIP_BELTFED = 0x5,
+ AMMO_COUNTER_CLIP_ALTWEAPON = 0x6,
+ AMMO_COUNTER_CLIP_COUNT = 0x7,
+};
+
+enum WeapOverlayInteface_t
+{
+ WEAPOVERLAYINTERFACE_NONE = 0x0,
+ WEAPOVERLAYINTERFACE_JAVELIN = 0x1,
+ WEAPOVERLAYINTERFACE_TURRETSCOPE = 0x2,
+ WEAPOVERLAYINTERFACECOUNT = 0x3,
+};
+
+enum weapProjExposion_t
+{
+ WEAPPROJEXP_GRENADE = 0x0,
+ WEAPPROJEXP_ROCKET = 0x1,
+ WEAPPROJEXP_FLASHBANG = 0x2,
+ WEAPPROJEXP_NONE = 0x3,
+ WEAPPROJEXP_DUD = 0x4,
+ WEAPPROJEXP_SMOKE = 0x5,
+ WEAPPROJEXP_HEAVY = 0x6,
+ WEAPPROJEXP_FIRE = 0x7,
+ WEAPPROJEXP_NAPALMBLOB = 0x8,
+ WEAPPROJEXP_BOLT = 0x9,
+ WEAPPROJEXP_SHRAPNELSPAN = 0xA,
+ WEAPPROJEXP_NUM = 0xB,
+};
+
+enum WeapStickinessType
+{
+ WEAPSTICKINESS_NONE = 0x0,
+ WEAPSTICKINESS_ALL = 0x1,
+ WEAPSTICKINESS_ALL_NO_SENTIENTS = 0x2,
+ WEAPSTICKINESS_GROUND = 0x3,
+ WEAPSTICKINESS_GROUND_WITH_YAW = 0x4,
+ WEAPSTICKINESS_FLESH = 0x5,
+ WEAPSTICKINESS_COUNT = 0x6,
+};
+
+enum WeapRotateType
+{
+ WEAPROTATE_GRENADE_ROTATE = 0x0,
+ WEAPROTATE_BLADE_ROTATE = 0x1,
+ WEAPROTATE_CYLINDER_ROTATE = 0x2,
+ WEAPROTATE_COUNT = 0x3,
+};
+
+enum guidedMissileType_t
+{
+ MISSILE_GUIDANCE_NONE = 0x0,
+ MISSILE_GUIDANCE_SIDEWINDER = 0x1,
+ MISSILE_GUIDANCE_HELLFIRE = 0x2,
+ MISSILE_GUIDANCE_JAVELIN = 0x3,
+ MISSILE_GUIDANCE_BALLISTIC = 0x4,
+ MISSILE_GUIDANCE_WIREGUIDED = 0x5,
+ MISSILE_GUIDANCE_TVGUIDED = 0x6,
+ MISSILE_GUIDANCE_DRONE = 0x7,
+ MISSILE_GUIDANCE_HEATSEEKING = 0x8,
+ MISSILE_GUIDANCE_COUNT = 0x9,
+};
+
+struct WeaponDef
+{
+ const char *szOverlayName;
+ XModel **gunXModel;
+ XModel *handXModel;
+ const char *szModeName;
+ unsigned __int16 *notetrackSoundMapKeys;
+ unsigned __int16 *notetrackSoundMapValues;
+ int playerAnimType;
+ weapType_t weapType;
+ weapClass_t weapClass;
+ PenetrateType penetrateType;
+ ImpactType impactType;
+ weapInventoryType_t inventoryType;
+ weapFireType_t fireType;
+ weapClipType_t clipType;
+ barrelType_t barrelType;
+ int itemIndex;
+ const char *parentWeaponName;
+ int iJamFireTime;
+ int overheatWeapon;
+ float overheatRate;
+ float cooldownRate;
+ float overheatEndVal;
+ bool coolWhileFiring;
+ bool fuelTankWeapon;
+ int iTankLifeTime;
+ OffhandClass offhandClass;
+ OffhandSlot offhandSlot;
+ weapStance_t stance;
+ FxEffectDef *viewFlashEffect;
+ FxEffectDef *worldFlashEffect;
+ FxEffectDef *barrelCooldownEffect;
+ int barrelCooldownMinCount;
+ vec3_t vViewFlashOffset;
+ vec3_t vWorldFlashOffset;
+ const char *pickupSound;
+ const char *pickupSoundPlayer;
+ const char *ammoPickupSound;
+ const char *ammoPickupSoundPlayer;
+ const char *projectileSound;
+ const char *pullbackSound;
+ const char *pullbackSoundPlayer;
+ const char *fireSound;
+ const char *fireSoundPlayer;
+ const char *fireLoopSound;
+ const char *fireLoopSoundPlayer;
+ const char *fireLoopEndSound;
+ const char *fireLoopEndSoundPlayer;
+ const char *fireStartSound;
+ const char *fireStopSound;
+ const char *fireKillcamSound;
+ const char *fireStartSoundPlayer;
+ const char *fireStopSoundPlayer;
+ const char *fireKillcamSoundPlayer;
+ const char *fireLastSound;
+ const char *fireLastSoundPlayer;
+ const char *emptyFireSound;
+ const char *emptyFireSoundPlayer;
+ const char *crackSound;
+ const char *whizbySound;
+ const char *meleeSwipeSound;
+ const char *meleeSwipeSoundPlayer;
+ const char *meleeHitSound;
+ const char *meleeMissSound;
+ const char *rechamberSound;
+ const char *rechamberSoundPlayer;
+ const char *reloadSound;
+ const char *reloadSoundPlayer;
+ const char *reloadEmptySound;
+ const char *reloadEmptySoundPlayer;
+ const char *reloadStartSound;
+ const char *reloadStartSoundPlayer;
+ const char *reloadEndSound;
+ const char *reloadEndSoundPlayer;
+ const char *rotateLoopSound;
+ const char *rotateLoopSoundPlayer;
+ const char *rotateStopSound;
+ const char *rotateStopSoundPlayer;
+ const char *deploySound;
+ const char *deploySoundPlayer;
+ const char *finishDeploySound;
+ const char *finishDeploySoundPlayer;
+ const char *breakdownSound;
+ const char *breakdownSoundPlayer;
+ const char *finishBreakdownSound;
+ const char *finishBreakdownSoundPlayer;
+ const char *detonateSound;
+ const char *detonateSoundPlayer;
+ const char *nightVisionWearSound;
+ const char *nightVisionWearSoundPlayer;
+ const char *nightVisionRemoveSound;
+ const char *nightVisionRemoveSoundPlayer;
+ const char *altSwitchSound;
+ const char *altSwitchSoundPlayer;
+ const char *raiseSound;
+ const char *raiseSoundPlayer;
+ const char *firstRaiseSound;
+ const char *firstRaiseSoundPlayer;
+ const char *adsRaiseSoundPlayer;
+ const char *adsLowerSoundPlayer;
+ const char *putawaySound;
+ const char *putawaySoundPlayer;
+ const char *overheatSound;
+ const char *overheatSoundPlayer;
+ const char *adsZoomSound;
+ const char *shellCasing;
+ const char *shellCasingPlayer;
+ const char **bounceSound;
+ const char *standMountedWeapdef;
+ const char *crouchMountedWeapdef;
+ const char *proneMountedWeapdef;
+ int standMountedIndex;
+ int crouchMountedIndex;
+ int proneMountedIndex;
+ FxEffectDef *viewShellEjectEffect;
+ FxEffectDef *worldShellEjectEffect;
+ FxEffectDef *viewLastShotEjectEffect;
+ FxEffectDef *worldLastShotEjectEffect;
+ vec3_t vViewShellEjectOffset;
+ vec3_t vWorldShellEjectOffset;
+ vec3_t vViewShellEjectRotation;
+ vec3_t vWorldShellEjectRotation;
+ Material *reticleCenter;
+ Material *reticleSide;
+ int iReticleCenterSize;
+ int iReticleSideSize;
+ int iReticleMinOfs;
+ activeReticleType_t activeReticleType;
+ vec3_t vStandMove;
+ vec3_t vStandRot;
+ vec3_t vDuckedOfs;
+ vec3_t vDuckedMove;
+ vec3_t vDuckedSprintOfs;
+ vec3_t vDuckedSprintRot;
+ vec2_t vDuckedSprintBob;
+ float fDuckedSprintCycleScale;
+ vec3_t vSprintOfs;
+ vec3_t vSprintRot;
+ vec2_t vSprintBob;
+ float fSprintCycleScale;
+ vec3_t vLowReadyOfs;
+ vec3_t vLowReadyRot;
+ vec3_t vRideOfs;
+ vec3_t vRideRot;
+ vec3_t vDtpOfs;
+ vec3_t vDtpRot;
+ vec2_t vDtpBob;
+ float fDtpCycleScale;
+ vec3_t vMantleOfs;
+ vec3_t vMantleRot;
+ vec3_t vSlideOfs;
+ vec3_t vSlideRot;
+ vec3_t vDuckedRot;
+ vec3_t vProneOfs;
+ vec3_t vProneMove;
+ vec3_t vProneRot;
+ vec3_t vStrafeMove;
+ vec3_t vStrafeRot;
+ float fPosMoveRate;
+ float fPosProneMoveRate;
+ float fStandMoveMinSpeed;
+ float fDuckedMoveMinSpeed;
+ float fProneMoveMinSpeed;
+ float fPosRotRate;
+ float fPosProneRotRate;
+ float fStandRotMinSpeed;
+ float fDuckedRotMinSpeed;
+ float fProneRotMinSpeed;
+ XModel **worldModel;
+ XModel *worldClipModel;
+ XModel *rocketModel;
+ XModel *mountedModel;
+ XModel *additionalMeleeModel;
+ Material *fireTypeIcon;
+ Material *hudIcon;
+ weaponIconRatioType_t hudIconRatio;
+ Material *indicatorIcon;
+ weaponIconRatioType_t indicatorIconRatio;
+ Material *ammoCounterIcon;
+ weaponIconRatioType_t ammoCounterIconRatio;
+ ammoCounterClipType_t ammoCounterClip;
+ int iStartAmmo;
+ int iMaxAmmo;
+ int shotCount;
+ const char *szSharedAmmoCapName;
+ int iSharedAmmoCapIndex;
+ int iSharedAmmoCap;
+ bool unlimitedAmmo;
+ bool ammoCountClipRelative;
+ int damage[6];
+ float damageRange[6];
+ int minPlayerDamage;
+ float damageDuration;
+ float damageInterval;
+ int playerDamage;
+ int iMeleeDamage;
+ int iDamageType;
+ unsigned __int16 explosionTag;
+ int iFireDelay;
+ int iMeleeDelay;
+ int meleeChargeDelay;
+ int iDetonateDelay;
+ int iSpinUpTime;
+ int iSpinDownTime;
+ float spinRate;
+ const char *spinLoopSound;
+ const char *spinLoopSoundPlayer;
+ const char *startSpinSound;
+ const char *startSpinSoundPlayer;
+ const char *stopSpinSound;
+ const char *stopSpinSoundPlayer;
+ bool applySpinPitch;
+ int iFireTime;
+ int iLastFireTime;
+ int iRechamberTime;
+ int iRechamberBoltTime;
+ int iHoldFireTime;
+ int iDetonateTime;
+ int iMeleeTime;
+ int iBurstDelayTime;
+ int meleeChargeTime;
+ int iReloadTimeRight;
+ int iReloadTimeLeft;
+ int reloadShowRocketTime;
+ int iReloadEmptyTimeLeft;
+ int iReloadAddTime;
+ int iReloadEmptyAddTime;
+ int iReloadQuickAddTime;
+ int iReloadQuickEmptyAddTime;
+ int iReloadStartTime;
+ int iReloadStartAddTime;
+ int iReloadEndTime;
+ int iDropTime;
+ int iRaiseTime;
+ int iAltDropTime;
+ int quickDropTime;
+ int quickRaiseTime;
+ int iFirstRaiseTime;
+ int iEmptyRaiseTime;
+ int iEmptyDropTime;
+ int sprintInTime;
+ int sprintLoopTime;
+ int sprintOutTime;
+ int lowReadyInTime;
+ int lowReadyLoopTime;
+ int lowReadyOutTime;
+ int contFireInTime;
+ int contFireLoopTime;
+ int contFireOutTime;
+ int dtpInTime;
+ int dtpLoopTime;
+ int dtpOutTime;
+ int crawlInTime;
+ int crawlForwardTime;
+ int crawlBackTime;
+ int crawlRightTime;
+ int crawlLeftTime;
+ int crawlOutFireTime;
+ int crawlOutTime;
+ int slideInTime;
+ int deployTime;
+ int breakdownTime;
+ int iFlourishTime;
+ int nightVisionWearTime;
+ int nightVisionWearTimeFadeOutEnd;
+ int nightVisionWearTimePowerUp;
+ int nightVisionRemoveTime;
+ int nightVisionRemoveTimePowerDown;
+ int nightVisionRemoveTimeFadeInStart;
+ int fuseTime;
+ int aiFuseTime;
+ int lockOnRadius;
+ int lockOnSpeed;
+ bool requireLockonToFire;
+ bool noAdsWhenMagEmpty;
+ bool avoidDropCleanup;
+ unsigned int stackFire;
+ float stackFireSpread;
+ float stackFireAccuracyDecay;
+ const char *stackSound;
+ float autoAimRange;
+ float aimAssistRange;
+ bool mountableWeapon;
+ float aimPadding;
+ float enemyCrosshairRange;
+ bool crosshairColorChange;
+ float moveSpeedScale;
+ float adsMoveSpeedScale;
+ float sprintDurationScale;
+ weapOverlayReticle_t overlayReticle;
+ WeapOverlayInteface_t overlayInterface;
+ float overlayWidth;
+ float overlayHeight;
+ float fAdsBobFactor;
+ float fAdsViewBobMult;
+ bool bHoldBreathToSteady;
+ float fHipSpreadStandMin;
+ float fHipSpreadDuckedMin;
+ float fHipSpreadProneMin;
+ float hipSpreadStandMax;
+ float hipSpreadDuckedMax;
+ float hipSpreadProneMax;
+ float fHipSpreadDecayRate;
+ float fHipSpreadFireAdd;
+ float fHipSpreadTurnAdd;
+ float fHipSpreadMoveAdd;
+ float fHipSpreadDuckedDecay;
+ float fHipSpreadProneDecay;
+ float fHipReticleSidePos;
+ float fAdsIdleAmount;
+ float fHipIdleAmount;
+ float adsIdleSpeed;
+ float hipIdleSpeed;
+ float fIdleCrouchFactor;
+ float fIdleProneFactor;
+ float fGunMaxPitch;
+ float fGunMaxYaw;
+ float swayMaxAngle;
+ float swayLerpSpeed;
+ float swayPitchScale;
+ float swayYawScale;
+ float swayHorizScale;
+ float swayVertScale;
+ float swayShellShockScale;
+ float adsSwayMaxAngle;
+ float adsSwayLerpSpeed;
+ float adsSwayPitchScale;
+ float adsSwayYawScale;
+ bool sharedAmmo;
+ bool bRifleBullet;
+ bool armorPiercing;
+ bool bAirburstWeapon;
+ bool bBoltAction;
+ bool bUseAltTagFlash;
+ bool bUseAntiLagRewind;
+ bool bIsCarriedKillstreakWeapon;
+ bool aimDownSight;
+ bool bRechamberWhileAds;
+ bool bReloadWhileAds;
+ float adsViewErrorMin;
+ float adsViewErrorMax;
+ bool bCookOffHold;
+ bool bClipOnly;
+ bool bCanUseInVehicle;
+ bool bNoDropsOrRaises;
+ bool adsFireOnly;
+ bool cancelAutoHolsterWhenEmpty;
+ bool suppressAmmoReserveDisplay;
+ bool laserSight;
+ bool laserSightDuringNightvision;
+ bool bHideThirdPerson;
+ bool bHasBayonet;
+ bool bDualWield;
+ bool bExplodeOnGround;
+ bool bThrowBack;
+ bool bRetrievable;
+ bool bDieOnRespawn;
+ bool bNoThirdPersonDropsOrRaises;
+ bool bContinuousFire;
+ bool bNoPing;
+ bool bForceBounce;
+ bool bUseDroppedModelAsStowed;
+ bool bNoQuickDropWhenEmpty;
+ bool bKeepCrosshairWhenADS;
+ bool bUseOnlyAltWeaoponHideTagsInAltMode;
+ bool bAltWeaponAdsOnly;
+ bool bAltWeaponDisableSwitching;
+ Material *killIcon;
+ weaponIconRatioType_t killIconRatio;
+ bool flipKillIcon;
+ bool bNoPartialReload;
+ bool bSegmentedReload;
+ bool bNoADSAutoReload;
+ int iReloadAmmoAdd;
+ int iReloadStartAdd;
+ const char *szSpawnedGrenadeWeaponName;
+ const char *szDualWieldWeaponName;
+ unsigned int dualWieldWeaponIndex;
+ int iDropAmmoMin;
+ int iDropAmmoMax;
+ int iDropClipAmmoMin;
+ int iDropClipAmmoMax;
+ int iShotsBeforeRechamber;
+ bool blocksProne;
+ bool bShowIndicator;
+ int isRollingGrenade;
+ int useBallisticPrediction;
+ int isValuable;
+ int isTacticalInsertion;
+ bool isReviveWeapon;
+ bool bUseRigidBodyOnVehicle;
+ int iExplosionRadius;
+ int iExplosionRadiusMin;
+ int iIndicatorRadius;
+ int iExplosionInnerDamage;
+ int iExplosionOuterDamage;
+ float damageConeAngle;
+ int iProjectileSpeed;
+ int iProjectileSpeedUp;
+ int iProjectileSpeedRelativeUp;
+ int iProjectileSpeedForward;
+ float fProjectileTakeParentVelocity;
+ int iProjectileActivateDist;
+ float projLifetime;
+ float timeToAccelerate;
+ float projectileCurvature;
+ XModel *projectileModel;
+ weapProjExposion_t projExplosion;
+ FxEffectDef *projExplosionEffect;
+ bool projExplosionEffectForceNormalUp;
+ FxEffectDef *projExplosionEffect2;
+ bool projExplosionEffect2ForceNormalUp;
+ FxEffectDef *projExplosionEffect3;
+ bool projExplosionEffect3ForceNormalUp;
+ FxEffectDef *projExplosionEffect4;
+ bool projExplosionEffect4ForceNormalUp;
+ FxEffectDef *projExplosionEffect5;
+ bool projExplosionEffect5ForceNormalUp;
+ FxEffectDef *projDudEffect;
+ const char *projExplosionSound;
+ const char *projDudSound;
+ const char *mortarShellSound;
+ const char *tankShellSound;
+ bool bProjImpactExplode;
+ bool bProjSentientImpactExplode;
+ bool bProjExplodeWhenStationary;
+ bool bBulletImpactExplode;
+ WeapStickinessType stickiness;
+ WeapRotateType rotateType;
+ bool plantable;
+ bool hasDetonator;
+ bool timedDetonation;
+ bool bNoCrumpleMissile;
+ bool rotate;
+ bool bKeepRolling;
+ bool holdButtonToThrow;
+ bool offhandHoldIsCancelable;
+ bool freezeMovementWhenFiring;
+ float lowAmmoWarningThreshold;
+ bool bDisallowAtMatchStart;
+ float meleeChargeRange;
+ bool bUseAsMelee;
+ bool isCameraSensor;
+ bool isAcousticSensor;
+ bool isLaserSensor;
+ bool isHoldUseGrenade;
+ float *parallelBounce;
+ float *perpendicularBounce;
+ FxEffectDef *projTrailEffect;
+ vec3_t vProjectileColor;
+ guidedMissileType_t guidedMissileType;
+ float maxSteeringAccel;
+ int projIgnitionDelay;
+ FxEffectDef *projIgnitionEffect;
+ const char *projIgnitionSound;
+ float fAdsAimPitch;
+ float fAdsCrosshairInFrac;
+ float fAdsCrosshairOutFrac;
+ int adsGunKickReducedKickBullets;
+ float adsGunKickReducedKickPercent;
+ float fAdsGunKickPitchMin;
+ float fAdsGunKickPitchMax;
+ float fAdsGunKickYawMin;
+ float fAdsGunKickYawMax;
+ float fAdsGunKickAccel;
+ float fAdsGunKickSpeedMax;
+ float fAdsGunKickSpeedDecay;
+ float fAdsGunKickStaticDecay;
+ float fAdsViewKickPitchMin;
+ float fAdsViewKickPitchMax;
+ float fAdsViewKickMinMagnitude;
+ float fAdsViewKickYawMin;
+ float fAdsViewKickYawMax;
+ float fAdsRecoilReductionRate;
+ float fAdsRecoilReductionLimit;
+ float fAdsRecoilReturnRate;
+ float fAdsViewScatterMin;
+ float fAdsViewScatterMax;
+ float fAdsSpread;
+ int hipGunKickReducedKickBullets;
+ float hipGunKickReducedKickPercent;
+ float fHipGunKickPitchMin;
+ float fHipGunKickPitchMax;
+ float fHipGunKickYawMin;
+ float fHipGunKickYawMax;
+ float fHipGunKickAccel;
+ float fHipGunKickSpeedMax;
+ float fHipGunKickSpeedDecay;
+ float fHipGunKickStaticDecay;
+ float fHipViewKickPitchMin;
+ float fHipViewKickPitchMax;
+ float fHipViewKickMinMagnitude;
+ float fHipViewKickYawMin;
+ float fHipViewKickYawMax;
+ float fHipViewScatterMin;
+ float fHipViewScatterMax;
+ float fAdsViewKickCenterDuckedScale;
+ float fAdsViewKickCenterProneScale;
+ float fAntiQuickScopeTime;
+ float fAntiQuickScopeScale;
+ float fAntiQuickScopeSpreadMultiplier;
+ float fAntiQuickScopeSpreadMax;
+ float fAntiQuickScopeSwayFactor;
+ float fightDist;
+ float maxDist;
+ const char *accuracyGraphName[2];
+ vec2_t *accuracyGraphKnots[2];
+ vec2_t *originalAccuracyGraphKnots[2];
+ int accuracyGraphKnotCount[2];
+ int originalAccuracyGraphKnotCount[2];
+ int iPositionReloadTransTime;
+ float leftArc;
+ float rightArc;
+ float topArc;
+ float bottomArc;
+ float accuracy;
+ float aiSpread;
+ float playerSpread;
+ float minTurnSpeed[2];
+ float maxTurnSpeed[2];
+ float pitchConvergenceTime;
+ float yawConvergenceTime;
+ float suppressTime;
+ float maxRange;
+ float fAnimHorRotateInc;
+ float fPlayerPositionDist;
+ const char *szUseHintString;
+ const char *dropHintString;
+ int iUseHintStringIndex;
+ int dropHintStringIndex;
+ float horizViewJitter;
+ float vertViewJitter;
+ float cameraShakeScale;
+ int cameraShakeDuration;
+ int cameraShakeRadius;
+ float explosionCameraShakeScale;
+ int explosionCameraShakeDuration;
+ int explosionCameraShakeRadius;
+ const char *szScript;
+ float destabilizationRateTime;
+ float destabilizationCurvatureMax;
+ int destabilizeDistance;
+ float *locationDamageMultipliers;
+ const char *fireRumble;
+ const char *meleeImpactRumble;
+ const char *reloadRumble;
+ const char *explosionRumble;
+ TracerDef *tracerType;
+ TracerDef *enemyTracerType;
+ float adsDofStart;
+ float adsDofEnd;
+ float hipDofStart;
+ float hipDofEnd;
+ float scanSpeed;
+ float scanAccel;
+ int scanPauseTime;
+ const char *flameTableFirstPerson;
+ const char *flameTableThirdPerson;
+ flameTable *flameTableFirstPersonPtr;
+ flameTable *flameTableThirdPersonPtr;
+ FxEffectDef *tagFx_preparationEffect;
+ FxEffectDef *tagFlash_preparationEffect;
+ bool doGibbing;
+ float maxGibDistance;
+ float altScopeADSTransInTime;
+ float altScopeADSTransOutTime;
+ int iIntroFireTime;
+ int iIntroFireLength;
+ FxEffectDef *meleeSwipeEffect;
+ FxEffectDef *meleeImpactEffect;
+ FxEffectDef *meleeImpactNoBloodEffect;
+ const char *throwBackType;
+ WeaponCamo *weaponCamo;
+ float customFloat0;
+ float customFloat1;
+ float customFloat2;
+ int customBool0;
+ int customBool1;
+ int customBool2;
+};
+
+struct WeaponCamoSet
+{
+ GfxImage *solidCamoImage;
+ GfxImage *patternCamoImage;
+ vec2_t patternOffset;
+ float patternScale;
+};
+
+struct WeaponCamoMaterialSet
+{
+ unsigned int numMaterials;
+ WeaponCamoMaterial *materials;
+};
+
+enum SndMenuCategory
+{
+ SND_CATEGORY_SFX = 0x0,
+ SND_CATEGORY_MUSIC = 0x1,
+ SND_CATEGORY_VOICE = 0x2,
+ SND_CATEGORY_UI = 0x3,
+ SND_CATEGORY_CINEMATIC = 0x4,
+ SND_CATEGORY_COUNT = 0x5,
+};
+
+struct SndVolumeGroup
+{
+ char name[32];
+ char parentName[32];
+ unsigned int id;
+ int parentIndex;
+ SndMenuCategory category;
+ unsigned __int16 attenuationSp;
+ unsigned __int16 attenuationMp;
+};
+
+struct SndCurve
+{
+ char name[32];
+ unsigned int id;
+ vec2_t points[8];
+};
+
+struct SndPan
+{
+ char name[32];
+ unsigned int id;
+ float front;
+ float back;
+ float center;
+ float lfe;
+ float left;
+ float right;
+};
+
+struct SndDuckGroup
+{
+ char name[32];
+ unsigned int id;
+};
+
+struct SndContext
+{
+ unsigned int type;
+ unsigned int values[8];
+};
+
+struct SndMaster
+{
+ char name[32];
+ unsigned int id;
+ int lowE;
+ float lowG;
+ float lowF;
+ float lowQ;
+ int peak1E;
+ float peak1G;
+ float peak1F;
+ float peak1Q;
+ int peak2E;
+ float peak2G;
+ float peak2F;
+ float peak2Q;
+ int hiE;
+ float hiG;
+ float hiF;
+ float hiQ;
+ float eqG;
+ int compE;
+ float compPG;
+ float compMG;
+ float compT;
+ float compR;
+ float compTA;
+ float compTR;
+ int limitE;
+ float limitPG;
+ float limitMG;
+ float limitT;
+ float limitR;
+ float limitTA;
+ float limitTR;
+ float busReverbG;
+ float busFxG;
+ float busVoiceG;
+ float busPfutzG;
+ float busHdrfxG;
+ float busUiG;
+ float busMusicG;
+ float busMovieG;
+ float busVcsG;
+ int busReverbE;
+ int busFxE;
+ int busVoiceE;
+ int busPfutzE;
+ int busHdrfxE;
+ int busUiE;
+ int busMusicE;
+ int busMovieE;
+ int hdrfxCompE;
+ int voiceEqE;
+ int voiceCompE;
+};
+
+struct SndSidechainDuck
+{
+ char name[32];
+ unsigned int id;
+ float g;
+ float f;
+ float q;
+ float ta;
+ float tr;
+ float tf;
+};
+
+struct SndFutz
+{
+ char name[32];
+ unsigned int id;
+ float bpfF;
+ float bpfQ;
+ float lsG;
+ float lsF;
+ float lsQ;
+ float dist;
+ float preG;
+ float postG;
+ float th;
+ float tg;
+ float clippre;
+ float clippost;
+ float blend;
+ unsigned int startAliasId;
+ unsigned int stopAliasId;
+ unsigned int loopAliasId;
+};
+
+struct FxSpawnDefLooping
+{
+ int intervalMsec;
+ int count;
+};
+
+struct FxIntRange
+{
+ int base;
+ int amplitude;
+};
+
+struct FxSpawnDefOneShot
+{
+ FxIntRange count;
+};
+
+union FxSpawnDef
+{
+ FxSpawnDefLooping looping;
+ FxSpawnDefOneShot oneShot;
+};
+
+struct FxElemAtlas
+{
+ char behavior;
+ char index;
+ char fps;
+ char loopCount;
+ char colIndexBits;
+ char rowIndexBits;
+ unsigned __int16 entryCountAndIndexRange;
+};
+
+union FxEffectDefRef
+{
+ FxEffectDef *handle;
+ const char *name;
+};
+
+union FxElemVisuals
+{
+ void *anonymous;
+ Material *material;
+ XModel *model;
+ FxEffectDefRef effectDef;
+ const char *soundName;
+ GfxLightDef *lightDef;
+};
+
+union FxElemDefVisuals
+{
+ FxElemMarkVisuals *markArray;
+ FxElemVisuals *array;
+ FxElemVisuals instance;
+};
+
+union FxElemExtendedDefPtr
+{
+ FxTrailDef *localTrailDef;
+ FxTrailDef *trailDef;
+ FxSpotLightDef *localSpotLightDef;
+ FxSpotLightDef *spotLightDef;
+ void *unknownDef;
+};
+
+struct FxBillboardTrim
+{
+ float topWidth;
+ float bottomWidth;
+};
+
+union FxElemDefUnion
+{
+ FxBillboardTrim billboard;
+ FxIntRange cloudDensityRange;
+};
+
+struct FxElemSpawnSound
+{
+ const char *spawnSound;
+};
+
+const struct FxElemDef
+{
+ int flags;
+ FxSpawnDef spawn;
+ FxFloatRange spawnRange;
+ FxFloatRange fadeInRange;
+ FxFloatRange fadeOutRange;
+ float spawnFrustumCullRadius;
+ FxIntRange spawnDelayMsec;
+ FxIntRange lifeSpanMsec;
+ FxFloatRange spawnOrigin[3];
+ FxFloatRange spawnOffsetRadius;
+ FxFloatRange spawnOffsetHeight;
+ FxFloatRange spawnAngles[3];
+ FxFloatRange angularVelocity[3];
+ FxFloatRange initialRotation;
+ unsigned int rotationAxis;
+ FxFloatRange gravity;
+ FxFloatRange reflectionFactor;
+ FxElemAtlas atlas;
+ float windInfluence;
+ char elemType;
+ char visualCount;
+ char velIntervalCount;
+ char visStateIntervalCount;
+ FxElemVelStateSample *velSamples;
+ FxElemVisStateSample *visSamples;
+ FxElemDefVisuals visuals;
+ vec3_t collMins;
+ vec3_t collMaxs;
+ FxEffectDefRef effectOnImpact;
+ FxEffectDefRef effectOnDeath;
+ FxEffectDefRef effectEmitted;
+ FxFloatRange emitDist;
+ FxFloatRange emitDistVariance;
+ FxEffectDefRef effectAttached;
+ FxElemExtendedDefPtr extended;
+ char sortOrder;
+ char lightingFrac;
+ char unused[2];
+ unsigned __int16 alphaFadeTimeMsec;
+ unsigned __int16 maxWindStrength;
+ unsigned __int16 spawnIntervalAtMaxWind;
+ unsigned __int16 lifespanAtMaxWind;
+ FxElemDefUnion u;
+ FxElemSpawnSound spawnSound;
+ vec2_t billboardPivot;
+};
+
+struct FxImpactEntry
+{
+ FxEffectDef *nonflesh[32];
+ FxEffectDef *flesh[4];
+};
+
+struct StringTableCell
+{
+ const char *string;
+ int hash;
+};
+
+enum LbColType
+{
+ LBCOL_TYPE_NUMBER = 0x0,
+ LBCOL_TYPE_TIME = 0x1,
+ LBCOL_TYPE_LEVELXP = 0x2,
+ LBCOL_TYPE_PRESTIGE = 0x3,
+ LBCOL_TYPE_BIGNUMBER = 0x4,
+ LBCOL_TYPE_PERCENT = 0x5,
+ LBCOL_TYPE_TIME_FULL = 0x6,
+ LBCOL_TYPE_COUNT = 0x7,
+};
+
+enum LbAggType
+{
+ LBAGG_TYPE_MIN = 0x0,
+ LBAGG_TYPE_MAX = 0x1,
+ LBAGG_TYPE_ADD = 0x2,
+ LBAGG_TYPE_REPLACE = 0x3,
+ LBAGG_TYPE_COUNT = 0x4,
+};
+
+struct LbColumnDef
+{
+ const char *name;
+ int colId;
+ int dwColIndex;
+ bool hidden;
+ const char *statName;
+ LbColType type;
+ int precision;
+ LbAggType agg;
+ const char *localization;
+ int uiCalColX;
+ int uiCalColY;
+};
+
+struct ddlDef_t
+{
+ int version;
+ int size;
+ ddlStructDef_t *structList;
+ int structCount;
+ ddlEnumDef_t *enumList;
+ int enumCount;
+ ddlDef_t *next;
+};
+
+struct Glass
+{
+ unsigned int numCellIndices;
+ unsigned __int16 cellIndices[6];
+ GlassDef *glassDef;
+ unsigned int index;
+ unsigned int brushModel;
+ vec3_t origin;
+ vec3_t angles;
+ vec3_t absmin;
+ vec3_t absmax;
+ bool isPlanar;
+ char numOutlineVerts;
+ char binormalSign;
+ vec2_t *outline;
+ vec3_t outlineAxis[3];
+ vec3_t outlineOrigin;
+ float uvScale;
+ float thickness;
+};
+
+struct KeyValuePair
+{
+ int keyHash;
+ int namespaceHash;
+ const char *value;
+};
+
+enum DevEventType
+{
+ EVENT_ACTIVATE = 0x0,
+ EVENT_DEACTIVATE = 0x1,
+ EVENT_ACCEPT = 0x2,
+ EVENT_UPDATE = 0x3,
+ EVENT_DRAW = 0x4,
+ EVENT_SAVE = 0x5,
+};
+
+enum LocalClientNum_t
+{
+ INVALID_LOCAL_CLIENT = 0xFFFFFFFF,
+ LOCAL_CLIENT_FIRST = 0x0,
+ LOCAL_CLIENT_0 = 0x0,
+ ONLY_LOCAL_CLIENT = 0x0,
+ LOCAL_CLIENT_COUNT = 0x1,
+};
+
+struct __declspec(align(4)) DevGraph
+{
+ vec2_t *knots;
+ int *knotCount;
+ int knotCountMax;
+ int selectedKnot;
+ void* eventCallback; //void (__cdecl *eventCallback)(DevGraph *, DevEventType, LocalClientNum_t);
+ void* textCallback; //void (__cdecl *textCallback)(DevGraph *, const float, const float, char *, const int);
+ void *data;
+ bool disableEditingEndPoints;
+};
+
+struct GraphFloat
+{
+ char name[64];
+ vec2_t knots[32];
+ int knotCount;
+ float scale;
+ DevGraph devguiGraph;
+};
+
+union XAnimDynamicFrames
+{
+ char (*_1)[3];
+ unsigned __int16 (*_2)[3];
+};
+
+union XAnimDynamicIndices
+{
+ char _1[1];
+ unsigned __int16 _2[1];
+};
+
+struct __declspec(align(4)) XAnimPartTransFrames
+{
+ vec3_t mins;
+ vec3_t size;
+ XAnimDynamicFrames frames;
+ XAnimDynamicIndices indices;
+};
+
+union XAnimPartTransData
+{
+ XAnimPartTransFrames frames;
+ vec3_t frame0;
+};
+
+struct XAnimPartTrans
+{
+ unsigned __int16 size;
+ char smallTrans;
+ XAnimPartTransData u;
+};
+
+struct __declspec(align(4)) XAnimDeltaPartQuatDataFrames2
+{
+ __int16 (*frames)[2];
+ XAnimDynamicIndices indices;
+};
+
+union XAnimDeltaPartQuatData2
+{
+ XAnimDeltaPartQuatDataFrames2 frames;
+ __int16 frame0[2];
+};
+
+struct XAnimDeltaPartQuat2
+{
+ unsigned __int16 size;
+ XAnimDeltaPartQuatData2 u;
+};
+
+struct __declspec(align(4)) XAnimDeltaPartQuatDataFrames
+{
+ __int16 (*frames)[4];
+ XAnimDynamicIndices indices;
+};
+
+union XAnimDeltaPartQuatData
+{
+ XAnimDeltaPartQuatDataFrames frames;
+ __int16 frame0[4];
+};
+
+struct XAnimDeltaPartQuat
+{
+ unsigned __int16 size;
+ XAnimDeltaPartQuatData u;
+};
+
+union GfxColor
+{
+ unsigned int packed;
+ char array[4];
+};
+
+union PackedTexCoords
+{
+ unsigned int packed;
+};
+
+union PackedUnitVec
+{
+ unsigned int packed;
+};
+
+struct GfxPackedVertex
+{
+ vec3_t xyz;
+ float binormalSign;
+ GfxColor color;
+ PackedTexCoords texCoord;
+ PackedUnitVec normal;
+ PackedUnitVec tangent;
+};
+
+struct XRigidVertList
+{
+ unsigned __int16 boneOffset;
+ unsigned __int16 vertCount;
+ unsigned __int16 triOffset;
+ unsigned __int16 triCount;
+ XSurfaceCollisionTree *collisionTree;
+};
+
+struct XModelCollTri_s
+{
+ vec4_t plane;
+ vec4_t svec;
+ vec4_t tvec;
+};
+
+struct PhysGeomList
+{
+ unsigned int count;
+ PhysGeomInfo *geoms;
+ int contents;
+};
+
+/*struct __cppobj ID3D11BlendState : ID3D11DeviceChild
+{
+};*/
+
+/*struct __cppobj ID3D11DepthStencilState : ID3D11DeviceChild
+{
+};*/
+
+/*struct __cppobj ID3D11RasterizerState : ID3D11DeviceChild
+{
+};*/
+
+/*struct IUnknownVtbl
+{
+ HRESULT (__stdcall *QueryInterface)(IUnknown *this, _GUID *, void **);
+ unsigned int (__stdcall *AddRef)(IUnknown *this);
+ unsigned int (__stdcall *Release)(IUnknown *this);
+};*/
+
+struct MaterialStreamRouting
+{
+ char source;
+ char dest;
+};
+
+struct MaterialVertexStreamRouting
+{
+ MaterialStreamRouting data[16];
+ ID3D11InputLayout *decl[20];
+};
+
+struct MaterialVertexDeclaration
+{
+ char streamCount;
+ bool hasOptionalSource;
+ bool isLoaded;
+ MaterialVertexStreamRouting routing;
+};
+
+union MaterialArgumentLocation
+{
+ unsigned __int16 offset;
+ struct
+ {
+ char textureIndex;
+ char samplerIndex;
+ };
+};
+
+struct MaterialArgumentCodeConst
+{
+ unsigned __int16 index;
+ char firstRow;
+ char rowCount;
+};
+
+union MaterialArgumentDef
+{
+ /*const*/ float *literalConst;
+ MaterialArgumentCodeConst codeConst;
+ unsigned int codeSampler;
+ unsigned int nameHash;
+};
+
+struct MaterialShaderArgument
+{
+ unsigned __int16 type;
+ MaterialArgumentLocation location;
+ unsigned __int16 size;
+ unsigned __int16 buffer;
+ MaterialArgumentDef u;
+};
+
+struct SndAlias
+{
+ const char *name;
+ unsigned int id;
+ const char *subtitle;
+ const char *secondaryname;
+ unsigned int assetId;
+ const char *assetFileName;
+ unsigned int flags0;
+ unsigned int flags1;
+ unsigned int duck;
+ unsigned int contextType;
+ unsigned int contextValue;
+ unsigned int stopOnPlay;
+ unsigned int futzPatch;
+ unsigned __int16 fluxTime;
+ unsigned __int16 startDelay;
+ unsigned __int16 reverbSend;
+ unsigned __int16 centerSend;
+ unsigned __int16 volMin;
+ unsigned __int16 volMax;
+ unsigned __int16 pitchMin;
+ unsigned __int16 pitchMax;
+ unsigned __int16 distMin;
+ unsigned __int16 distMax;
+ unsigned __int16 distReverbMax;
+ unsigned __int16 envelopMin;
+ unsigned __int16 envelopMax;
+ unsigned __int16 envelopPercentage;
+ __int16 fadeIn;
+ __int16 fadeOut;
+ __int16 dopplerScale;
+ char minPriorityThreshold;
+ char maxPriorityThreshold;
+ char probability;
+ char occlusionLevel;
+ char minPriority;
+ char maxPriority;
+ char pan;
+ char limitCount;
+ char entityLimitCount;
+ char duckGroup;
+};
+
+struct __declspec(align(4)) pathlink_s
+{
+ float fDist;
+ unsigned __int16 nodeNum;
+ char disconnectCount;
+ char negotiationLink;
+ char flags;
+ char ubBadPlaceCount[5];
+};
+
+struct GfxAabbTree
+{
+ vec3_t mins;
+ vec3_t maxs;
+ unsigned __int16 childCount;
+ unsigned __int16 surfaceCount;
+ unsigned __int16 startSurfIndex;
+ unsigned __int16 smodelIndexCount;
+ unsigned __int16 *smodelIndexes;
+ int childrenOffset;
+};
+
+struct GfxPortalWritable
+{
+ bool isQueued;
+ bool isAncestor;
+ char recursionDepth;
+ char hullPointCount;
+ vec2_t *hullPoints;
+ GfxPortal *queuedParent;
+};
+
+struct DpvsPlane
+{
+ vec4_t coeffs;
+ char side[3];
+ char pad;
+};
+
+struct GfxPortal
+{
+ GfxPortalWritable writable;
+ DpvsPlane plane;
+ GfxCell *cell;
+ vec3_t *vertices;
+ char vertexCount;
+ vec3_t hullAxis[2];
+ vec3_t bounds[2];
+};
+
+struct GfxReflectionProbeVolumeData
+{
+ vec4_t volumePlanes[6];
+};
+
+struct SSkinShaders
+{
+ char *pixelShaderAlign;
+ char *pixelShader;
+ char *vertexShader;
+ int pixelShaderSize;
+ int vertexShaderSize;
+};
+
+struct SSkinModel
+{
+ int numVerts;
+ int numTris;
+ SSkinVert *verts;
+ unsigned __int16 *tris;
+};
+
+struct SSkinAnim
+{
+ int bones;
+ int width;
+ int frames;
+ float *data;
+};
+
+struct half
+{
+ unsigned __int16 v;
+};
+
+union half4
+{
+ struct
+ {
+ half x;
+ half y;
+ half z;
+ half w;
+ };
+ unsigned __int64 v;
+};
+
+union half2
+{
+ struct
+ {
+ half x;
+ half y;
+ };
+ unsigned int v;
+};
+
+struct SSkinVert
+{
+ half4 pos_bone;
+ PackedUnitVec normal;
+ half2 uv;
+};
+
+struct GfxLightRegionHull
+{
+ float kdopMidPoint[9];
+ float kdopHalfSize[9];
+ unsigned int axisCount;
+ GfxLightRegionAxis *axis;
+};
+
+struct GenericEventScript
+{
+ ScriptCondition *prerequisites;
+ ExpressionStatement condition;
+ int type;
+ bool fireOnTrue;
+ const char *action;
+ int blockID;
+ int constructID;
+ GenericEventScript *next;
+};
+
+enum dvarType_t
+{
+ DVAR_TYPE_INVALID = 0x0,
+ DVAR_TYPE_BOOL = 0x1,
+ DVAR_TYPE_FLOAT = 0x2,
+ DVAR_TYPE_FLOAT_2 = 0x3,
+ DVAR_TYPE_FLOAT_3 = 0x4,
+ DVAR_TYPE_FLOAT_4 = 0x5,
+ DVAR_TYPE_INT = 0x6,
+ DVAR_TYPE_ENUM = 0x7,
+ DVAR_TYPE_STRING = 0x8,
+ DVAR_TYPE_COLOR = 0x9,
+ DVAR_TYPE_INT64 = 0xA,
+ DVAR_TYPE_LINEAR_COLOR_RGB = 0xB,
+ DVAR_TYPE_COLOR_XYZ = 0xC,
+ DVAR_TYPE_COUNT = 0xD,
+};
+
+union DvarValue
+{
+ bool enabled;
+ int integer;
+ unsigned int unsignedInt;
+ __int64 integer64;
+ unsigned __int64 unsignedInt64;
+ float value;
+ vec4_t vector;
+ const char *string;
+ char color[4];
+};
+
+union DvarLimits
+{
+ struct
+ {
+ int stringCount;
+ const char **strings;
+ } enumeration;
+
+ struct
+ {
+ int min;
+ int max;
+ } integer;
+
+ struct
+ {
+ __int64 min;
+ __int64 max;
+ } integer64;
+
+ struct
+ {
+ float min;
+ float max;
+ } value;
+
+ struct
+ {
+ float min;
+ float max;
+ } vector;
+};
+
+struct __declspec(align(8)) dvar_t
+{
+ const char *name;
+ const char *description;
+ int hash;
+ unsigned int flags;
+ dvarType_t type;
+ bool modified;
+ DvarValue current;
+ DvarValue latched;
+ DvarValue reset;
+ DvarLimits domain;
+ dvar_t *hashNext;
+};
+
+union textDefData_t
+{
+ focusItemDef_s *focusItemDef;
+ gameMsgDef_s *gameMsgDef;
+ void *data;
+};
+
+struct textDef_s
+{
+ rectDef_s textRect[1];
+ int alignment;
+ int fontEnum;
+ int itemFlags;
+ int textAlignMode;
+ float textalignx;
+ float textaligny;
+ float textscale;
+ float textpadding;
+ int textStyle;
+ vec4_t fontColor;
+ vec4_t glowColor;
+ vec4_t shadowColor;
+ float fontBlur;
+ float glowSize;
+ float shadowSize;
+ vec2_t shadowOffset;
+ const char *text;
+ textExp_s *textExpData;
+ textDefData_t textTypeData;
+};
+
+struct imageDef_s
+{
+ ExpressionStatement materialExp;
+};
+
+union focusDefData_t
+{
+ listBoxDef_s *listBox;
+ multiDef_s *multi;
+ profileMultiDef_s *profileMulti;
+ editFieldDef_s *editField;
+ enumDvarDef_s *enumDvar;
+ void *data;
+};
+
+struct focusItemDef_s
+{
+ const char *mouseEnterText;
+ const char *mouseExitText;
+ const char *mouseEnter;
+ const char *mouseExit;
+ ItemKeyHandler *onKey;
+ focusDefData_t focusTypeData;
+};
+
+struct ownerDrawDef_s
+{
+ ExpressionStatement dataExp;
+};
+
+struct rectData_s
+{
+ ExpressionStatement rectXExp;
+ ExpressionStatement rectYExp;
+ ExpressionStatement rectWExp;
+ ExpressionStatement rectHExp;
+};
+
+struct animParamsDef_t
+{
+ const char *name;
+ rectDef_s rectClient;
+ float borderSize;
+ vec4_t foreColor;
+ vec4_t backColor;
+ vec4_t borderColor;
+ vec4_t outlineColor;
+ float textScale;
+ float rotation;
+ GenericEventHandler *onEvent;
+};
+
+struct UIAnimInfo
+{
+ int animStateCount;
+ animParamsDef_t **animStates;
+ animParamsDef_t currentAnimState;
+ animParamsDef_t nextAnimState;
+ int animating;
+ int animStartTime;
+ int animDuration;
+};
+
+struct flameTable
+{
+ float flameVar_streamChunkGravityStart;
+ float flameVar_streamChunkGravityEnd;
+ float flameVar_streamChunkMaxSize;
+ float flameVar_streamChunkStartSize;
+ float flameVar_streamChunkEndSize;
+ float flameVar_streamChunkStartSizeRand;
+ float flameVar_streamChunkEndSizeRand;
+ float flameVar_streamChunkDistScalar;
+ float flameVar_streamChunkDistSwayScale;
+ float flameVar_streamChunkDistSwayVelMax;
+ float flameVar_streamChunkSpeed;
+ float flameVar_streamChunkDecel;
+ float flameVar_streamChunkVelocityAddScale;
+ float flameVar_streamChunkDuration;
+ float flameVar_streamChunkDurationScaleMaxVel;
+ float flameVar_streamChunkDurationVelScalar;
+ float flameVar_streamChunkSizeSpeedScale;
+ float flameVar_streamChunkSizeAgeScale;
+ float flameVar_streamChunkSpawnFireIntervalStart;
+ float flameVar_streamChunkSpawnFireIntervalEnd;
+ float flameVar_streamChunkSpawnFireMinLifeFrac;
+ float flameVar_streamChunkSpawnFireMaxLifeFrac;
+ float flameVar_streamChunkFireMinLifeFrac;
+ float flameVar_streamChunkFireMinLifeFracStart;
+ float flameVar_streamChunkFireMinLifeFracEnd;
+ float flameVar_streamChunkDripsMinLifeFrac;
+ float flameVar_streamChunkDripsMinLifeFracStart;
+ float flameVar_streamChunkDripsMinLifeFracEnd;
+ float flameVar_streamChunkRotationRange;
+ float flameVar_streamSizeRandSinWave;
+ float flameVar_streamSizeRandCosWave;
+ float flameVar_streamDripsChunkInterval;
+ float flameVar_streamDripsChunkMinFrac;
+ float flameVar_streamDripsChunkRandFrac;
+ float flameVar_streamSmokeChunkInterval;
+ float flameVar_streamSmokeChunkMinFrac;
+ float flameVar_streamSmokeChunkRandFrac;
+ float flameVar_streamChunkCullDistSizeFrac;
+ float flameVar_streamChunkCullMinLife;
+ float flameVar_streamChunkCullMaxLife;
+ float flameVar_streamFuelSizeStart;
+ float flameVar_streamFuelSizeEnd;
+ float flameVar_streamFuelLength;
+ float flameVar_streamFuelNumSegments;
+ float flameVar_streamFuelAnimLoopTime;
+ float flameVar_streamFlameSizeStart;
+ float flameVar_streamFlameSizeEnd;
+ float flameVar_streamFlameLength;
+ float flameVar_streamFlameNumSegments;
+ float flameVar_streamFlameAnimLoopTime;
+ float flameVar_streamPrimaryLightRadius;
+ float flameVar_streamPrimaryLightRadiusFlutter;
+ float flameVar_streamPrimaryLightR;
+ float flameVar_streamPrimaryLightG;
+ float flameVar_streamPrimaryLightB;
+ float flameVar_streamPrimaryLightFlutterR;
+ float flameVar_streamPrimaryLightFlutterG;
+ float flameVar_streamPrimaryLightFlutterB;
+ float flameVar_fireLife;
+ float flameVar_fireLifeRand;
+ float flameVar_fireSpeedScale;
+ float flameVar_fireSpeedScaleRand;
+ float flameVar_fireVelocityAddZ;
+ float flameVar_fireVelocityAddZRand;
+ float flameVar_fireVelocityAddSideways;
+ float flameVar_fireGravity;
+ float flameVar_fireGravityEnd;
+ float flameVar_fireMaxRotVel;
+ float flameVar_fireFriction;
+ float flameVar_fireEndSizeAdd;
+ float flameVar_fireStartSizeScale;
+ float flameVar_fireEndSizeScale;
+ float flameVar_fireBrightness;
+ float flameVar_dripsLife;
+ float flameVar_dripsLifeRand;
+ float flameVar_dripsSpeedScale;
+ float flameVar_dripsSpeedScaleRand;
+ float flameVar_dripsVelocityAddZ;
+ float flameVar_dripsVelocityAddZRand;
+ float flameVar_dripsVelocityAddSideways;
+ float flameVar_dripsGravity;
+ float flameVar_dripsGravityEnd;
+ float flameVar_dripsMaxRotVel;
+ float flameVar_dripsFriction;
+ float flameVar_dripsEndSizeAdd;
+ float flameVar_dripsStartSizeScale;
+ float flameVar_dripsEndSizeScale;
+ float flameVar_dripsBrightness;
+ float flameVar_smokeLife;
+ float flameVar_smokeLifeRand;
+ float flameVar_smokeSpeedScale;
+ float flameVar_smokeVelocityAddZ;
+ float flameVar_smokeGravity;
+ float flameVar_smokeGravityEnd;
+ float flameVar_smokeMaxRotation;
+ float flameVar_smokeMaxRotVel;
+ float flameVar_smokeFriction;
+ float flameVar_smokeEndSizeAdd;
+ float flameVar_smokeStartSizeAdd;
+ float flameVar_smokeOriginSizeOfsZScale;
+ float flameVar_smokeOriginOfsZ;
+ float flameVar_smokeFadein;
+ float flameVar_smokeFadeout;
+ float flameVar_smokeMaxAlpha;
+ float flameVar_smokeBrightness;
+ float flameVar_smokeOriginOffset;
+ float flameVar_collisionSpeedScale;
+ float flameVar_collisionVolumeScale;
+ const char *name;
+ Material *fire;
+ Material *smoke;
+ Material *heat;
+ Material *drips;
+ Material *streamFuel;
+ Material *streamFuel2;
+ Material *streamFlame;
+ Material *streamFlame2;
+ const char *flameOffLoopSound;
+ const char *flameIgniteSound;
+ const char *flameOnLoopSound;
+ const char *flameCooldownSound;
+};
+
+struct WeaponCamoMaterial
+{
+ unsigned __int16 replaceFlags;
+ unsigned __int16 numBaseMaterials;
+ Material **baseMaterials;
+ Material **camoMaterials;
+ float shaderConsts[8];
+};
+
+struct FxElemVec3Range
+{
+ vec3_t base;
+ vec3_t amplitude;
+};
+
+struct FxElemVelStateInFrame
+{
+ FxElemVec3Range velocity;
+ FxElemVec3Range totalDelta;
+};
+
+const struct FxElemVelStateSample
+{
+ FxElemVelStateInFrame local;
+ FxElemVelStateInFrame world;
+};
+
+struct FxElemVisualState
+{
+ char color[4];
+ float rotationDelta;
+ float rotationTotal;
+ float size[2];
+ float scale;
+};
+
+const struct FxElemVisStateSample
+{
+ FxElemVisualState base;
+ FxElemVisualState amplitude;
+};
+
+struct FxElemMarkVisuals
+{
+ Material *materials[2];
+};
+
+struct FxTrailDef
+{
+ int scrollTimeMsec;
+ int repeatDist;
+ int splitDist;
+ int vertCount;
+ FxTrailVertex *verts;
+ int indCount;
+ unsigned __int16 *inds;
+};
+
+struct FxSpotLightDef
+{
+ float fovInnerFraction;
+ float startRadius;
+ float endRadius;
+};
+
+struct ddlStructDef_t
+{
+ const char *name;
+ int size;
+ int memberCount;
+ ddlMemberDef_t *members;
+ ddlHash_t *hashTable;
+};
+
+struct ddlEnumDef_t
+{
+ const char *name;
+ int memberCount;
+ const char **members;
+ ddlHash_t *hashTable;
+};
+
+struct GlassDef
+{
+ const char *name;
+ int maxHealth;
+ float thickness;
+ float minShardSize;
+ float maxShardSize;
+ float shardLifeProbablility;
+ int maxShards;
+ Material *pristineMaterial;
+ Material *crackedMaterial;
+ Material *shardMaterial;
+ const char *crackSound;
+ const char *shatterShound;
+ const char *autoShatterShound;
+ FxEffectDef *crackEffect;
+ FxEffectDef *shatterEffect;
+};
+
+struct XSurfaceCollisionTree
+{
+ vec3_t trans;
+ vec3_t scale;
+ unsigned int nodeCount;
+ XSurfaceCollisionNode *nodes;
+ unsigned int leafCount;
+ XSurfaceCollisionLeaf *leafs;
+};
+
+struct PhysGeomInfo
+{
+ BrushWrapper *brush;
+ int type;
+ vec3_t orientation[3];
+ vec3_t offset;
+ vec3_t halfLengths;
+};
+
+/*struct __cppobj ID3D11InputLayout : ID3D11DeviceChild
+{
+};*/
+
+struct GfxLightRegionAxis
+{
+ vec3_t dir;
+ float midPoint;
+ float halfSize;
+};
+
+struct ScriptCondition
+{
+ bool fireOnTrue;
+ int constructID;
+ int blockID;
+ ScriptCondition *next;
+};
+
+struct textExp_s
+{
+ ExpressionStatement textExp;
+};
+
+struct gameMsgDef_s
+{
+ int gameMsgWindowIndex;
+ int gameMsgWindowMode;
+};
+
+struct columnInfo_s
+{
+ int elementStyle;
+ int maxChars;
+ rectDef_s rect;
+};
+
+struct listBoxDef_s
+{
+ int mousePos;
+ int cursorPos[1];
+ int startPos[1];
+ int endPos[1];
+ int drawPadding;
+ float elementWidth;
+ float elementHeight;
+ int numColumns;
+ float special;
+ columnInfo_s columnInfo[16];
+ int notselectable;
+ int noScrollBars;
+ int usePaging;
+ vec4_t selectBorder;
+ vec4_t disableColor;
+ vec4_t focusColor;
+ vec4_t elementHighlightColor;
+ vec4_t elementBackgroundColor;
+ Material *selectIcon;
+ Material *backgroundItemListbox;
+ Material *highlightTexture;
+ int noBlinkingHighlight;
+ MenuRow *rows;
+ int maxRows;
+ int rowCount;
+};
+
+struct multiDef_s
+{
+ const char *dvarList[32];
+ const char *dvarStr[32];
+ float dvarValue[32];
+ int count;
+ int actionOnEnterPressOnly;
+ int strDef;
+};
+
+struct profileMultiDef_s
+{
+ const char *profileVarList[32];
+ const char *profileVarStr[32];
+ float profileVarValue[32];
+ int count;
+ int actionOnEnterPressOnly;
+ int strDef;
+};
+
+struct editFieldDef_s
+{
+ int cursorPos[1];
+ float minVal;
+ float maxVal;
+ float defVal;
+ float range;
+ int maxChars;
+ int maxCharsGotoNext;
+ int maxPaintChars;
+ int paintOffset;
+};
+
+struct enumDvarDef_s
+{
+ const char *enumDvarName;
+};
+
+struct FxTrailVertex
+{
+ vec2_t pos;
+ vec2_t normal;
+ float texCoord;
+};
+
+struct ddlMemberDef_t
+{
+ const char *name;
+ int size;
+ int offset;
+ int type;
+ int externalIndex;
+ unsigned int rangeLimit;
+ unsigned int serverDelta;
+ unsigned int clientDelta;
+ int arraySize;
+ int enumIndex;
+ int permission;
+};
+
+struct ddlHash_t
+{
+ int hash;
+ int index;
+};
+
+struct XSurfaceCollisionAabb
+{
+ unsigned __int16 mins[3];
+ unsigned __int16 maxs[3];
+};
+
+struct XSurfaceCollisionNode
+{
+ XSurfaceCollisionAabb aabb;
+ unsigned __int16 childBeginIndex;
+ unsigned __int16 childCount;
+};
+
+struct XSurfaceCollisionLeaf
+{
+ unsigned __int16 triangleBeginIndex;
+};
+
+struct BrushWrapper
+{
+ vec3_t mins;
+ int contents;
+ vec3_t maxs;
+ unsigned int numsides;
+ cbrushside_t *sides;
+ int axial_cflags[2][3];
+ int axial_sflags[2][3];
+ unsigned int numverts;
+ vec3_t *verts;
+ cplane_s *planes;
+};
+
+struct MenuRow
+{
+ MenuCell *cells;
+ char *eventName;
+ char *onFocusEventName;
+ bool disableArg;
+ int status;
+ int name;
+};
+
+struct MenuCell
+{
+ int type;
+ int maxChars;
+ char *stringValue;
+};
+
diff --git a/src/ZoneCommon/Pool/AssetPool.h b/src/ZoneCommon/Pool/AssetPool.h
new file mode 100644
index 00000000..f654ffcd
--- /dev/null
+++ b/src/ZoneCommon/Pool/AssetPool.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include "XAssetInfo.h"
+#include
+#include