Compare commits

...

33 Commits

Author SHA1 Message Date
6632149f42 Merge pull request 'Enhanced Feature Implementation and Cleanup' (#1) from feature/icon_factory into main
Reviewed-on: https://git.redline.llc/njohnson/XPlor/pulls/1
2025-06-04 22:40:19 -04:00
=
2eaaa87b72 Add lzo files. 2025-06-04 22:35:10 -04:00
=
c005d19fa8 Add compro tool. 2025-06-04 22:34:49 -04:00
=
b5595d9855 Add temp icon psd. 2025-06-04 22:34:32 -04:00
=
aef7c2657d Add compro tool to project. 2025-06-04 22:34:07 -04:00
=
ecd897b4ac Add experimental method to xcompress header. 2025-06-04 22:33:49 -04:00
=
2eb0ee39fb Update autotests. 2025-06-04 22:33:31 -04:00
=
130814d206 Update autotests. 2025-06-04 22:33:19 -04:00
=
0576fb5bd4 Switch all to fastfile factory. 2025-06-04 22:33:02 -04:00
=
298d5e9848 Add color utilities. 2025-06-04 22:32:34 -04:00
=
3ac572edeb Add highlightings to project. 2025-06-04 22:32:14 -04:00
=
ac33cd4524 Remove unused lzo source. 2025-06-04 22:31:53 -04:00
=
ea39199201 Add XMem functions (in progress) and LZO, fix ZLib. 2025-06-04 22:31:22 -04:00
=
b204858a90 Add XMem functions (in progress) and LZO, fix ZLib. 2025-06-04 22:31:11 -04:00
=
f3427e77ba Remove unused files from resource. 2025-06-04 22:30:03 -04:00
=
7b0fe25650 Add search, remove column, update zone viewer. 2025-06-04 22:29:43 -04:00
=
af82d9a78a Add category support to XTreeWidget with TREE_CATEGORY enum and sorting improvements 2025-06-04 22:29:01 -04:00
=
3e311e5aec Fix data compression, byte order handling, and tag parsing in COD Wii zonefile 2025-06-04 22:25:32 -04:00
=
95349eaa5b Fix data compression, byte order handling, and tag parsing in COD Wii fastfile. 2025-06-04 22:25:12 -04:00
=
22062c2a6e Removed unused header files. 2025-06-04 22:19:47 -04:00
=
72846f4733 Update mainwindow, add highlighting, and fix viewer logic. 2025-06-04 22:14:24 -04:00
=
c056b45184 Add tabs for rumble and shock file viewing. 2025-06-04 22:13:13 -04:00
=
9dd0bd9897 Fix LocalStrViewer entry count and rename group box. 2025-06-04 22:11:50 -04:00
=
4dd68a06e8 Added rumble file viewer. 2025-06-04 22:11:12 -04:00
=
db9165295f Add syntax highlighting for gsc, rmb, and shock files. 2025-06-04 22:10:49 -04:00
=
8fe0e02e64 Added rumble file viewer. 2025-06-04 22:10:14 -04:00
=
20964df102 Remove temp user file. 2025-06-04 22:09:55 -04:00
=
2495fbfdef Only keep non-generated png files. 2025-06-04 22:09:30 -04:00
=
6e7a83d473 Remove png files. 2025-06-04 22:08:44 -04:00
=
87cbdeeefc feat(XPlor): Add dependencies for libs in app, tests and tools projects
Added dependencies for the libs in the app, tests and tools projects. This change ensures that these components depend on the correct libraries.
2025-05-17 23:42:30 -04:00
=
a90f1017f7 add fastfile and zonefile support for all cods 2025-05-17 22:56:57 -04:00
=
588d03ad8f Unify test factory methods and add Wii support 2025-05-17 22:54:28 -04:00
=
b58561eb78 add some bo3 ff processing logic. 2025-05-03 09:57:47 -04:00
281 changed files with 54069 additions and 4807 deletions

View File

@ -4,3 +4,7 @@ SUBDIRS += libs \
app \ app \
tools \ tools \
tests tests
tests.depends = libs
app.depends = libs
tools.depends = libs

View File

@ -1,625 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 15.0.0, 2025-04-04T21:57:41. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
<value type="QByteArray">{40d992cb-ac11-4385-a22b-016f1b4251a7}</value>
</data>
<data>
<variable>ProjectExplorer.Project.ActiveTarget</variable>
<value type="qlonglong">0</value>
</data>
<data>
<variable>ProjectExplorer.Project.EditorSettings</variable>
<valuemap type="QVariantMap">
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
<value type="QString" key="language">Cpp</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
</valuemap>
</valuemap>
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
<value type="QString" key="language">QmlJS</value>
<valuemap type="QVariantMap" key="value">
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
</valuemap>
</valuemap>
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
<value type="int" key="EditorConfiguration.IndentSize">4</value>
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
<value type="int" key="EditorConfiguration.TabSize">8</value>
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.PluginSettings</variable>
<valuemap type="QVariantMap">
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
<value type="bool" key="AutoTest.Framework.Boost">true</value>
<value type="bool" key="AutoTest.Framework.CTest">false</value>
<value type="bool" key="AutoTest.Framework.Catch">true</value>
<value type="bool" key="AutoTest.Framework.GTest">true</value>
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
</valuemap>
<value type="bool" key="AutoTest.ApplyFilter">false</value>
<valuemap type="QVariantMap" key="AutoTest.CheckStates">
<value type="Qt::CheckState" key="1@G:/Projects/Qt/XPlor/tests/autotest_cod.h:AutoTest_COD">Unchecked</value>
</valuemap>
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
<value type="int" key="AutoTest.RunAfterBuild">0</value>
<value type="bool" key="AutoTest.UseGlobal">true</value>
<valuemap type="QVariantMap" key="ClangTools">
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
<value type="int" key="ClangTools.ParallelJobs">16</value>
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
</valuemap>
<valuemap type="QVariantMap" key="CppEditor.QuickFix">
<value type="bool" key="UseGlobalSettings">true</value>
</valuemap>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.0</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.8.2 MSVC2022 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.8.2 MSVC2022 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.682.win64_msvc2022_64_kit</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="SeparateDebugInfo">0</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/app/app.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug/app</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/tests/tests.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug/tests</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.1</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.8.2 llvm-mingw 64-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.8.2 llvm-mingw 64-bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.682.win64_llvm_mingw_kit</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Profile</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Profile</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
<value type="int" key="SeparateDebugInfo">0</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/app/app.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/tests/tests.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.Target.2</variable>
<valuemap type="QVariantMap">
<value type="QString" key="DeviceType">Desktop</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 6.8.1 MSVC2022 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.8.1 MSVC2022 64bit</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.681.win64_msvc2022_64_kit</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="int" key="EnableQmlDebugging">0</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_1_MSVC2022_64bit-Debug</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_1_MSVC2022_64bit-Release</value>
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Release</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
<valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
<value type="int" key="QtQuickCompiler">0</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
</valuemap>
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/app/app.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug/app</value>
</valuemap>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
<valuelist type="QVariantList" key="CustomOutputParsers"/>
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">G:/Projects/Qt/XPlor/tests/tests.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
<value type="QString" key="RunConfiguration.WorkingDirectory.default">G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug/tests</value>
</valuemap>
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
</valuemap>
</data>
<data>
<variable>ProjectExplorer.Project.TargetCount</variable>
<value type="qlonglong">3</value>
</data>
<data>
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
<value type="int">22</value>
</data>
<data>
<variable>Version</variable>
<value type="int">22</value>
</data>
</qtcreator>

View File

@ -19,6 +19,8 @@ SOURCES += \
preferenceeditor.cpp \ preferenceeditor.cpp \
soundviewer.cpp \ soundviewer.cpp \
stringtableviewer.cpp \ stringtableviewer.cpp \
rumblegraphviewer.cpp \
rumblefileviewer.cpp \
techsetviewer.cpp \ techsetviewer.cpp \
xtreewidget.cpp \ xtreewidget.cpp \
xtreewidgetitem.cpp \ xtreewidgetitem.cpp \
@ -37,6 +39,8 @@ HEADERS += \
preferenceeditor.h \ preferenceeditor.h \
soundviewer.h \ soundviewer.h \
stringtableviewer.h \ stringtableviewer.h \
rumblegraphviewer.h \
rumblefileviewer.h \
techsetviewer.h \ techsetviewer.h \
xtreewidget.h \ xtreewidget.h \
xtreewidgetitem.h \ xtreewidgetitem.h \
@ -55,21 +59,13 @@ FORMS += \
preferenceeditor.ui \ preferenceeditor.ui \
soundviewer.ui \ soundviewer.ui \
stringtableviewer.ui \ stringtableviewer.ui \
rumblegraphviewer.ui \
rumblefileviewer.ui \
techsetviewer.ui \ techsetviewer.ui \
zonefileviewer.ui zonefileviewer.ui
RESOURCES += ../data/data.qrc RESOURCES += ../data/data.qrc
app.depends += \
libs/core \
libs/compression \
libs/encryption \
libs/fastfile \
libs/ddsfile \
libs/ipakfile \
libs/iwifile \
libs/zonefile
LIBS += \ LIBS += \
-L$$PWD/../third_party/devil_sdk/lib/ -lDevIL -lILU -lILUT \ -L$$PWD/../third_party/devil_sdk/lib/ -lDevIL -lILU -lILUT \
-L$$PWD/../third_party/zlib/lib/ -lzlib \ -L$$PWD/../third_party/zlib/lib/ -lzlib \

View File

@ -18,7 +18,7 @@ FastFileViewer::~FastFileViewer()
void FastFileViewer::SetFastFile(std::shared_ptr<FastFile> aFastFile) { void FastFileViewer::SetFastFile(std::shared_ptr<FastFile> aFastFile) {
mFastFile.swap(aFastFile); mFastFile.swap(aFastFile);
ui->label_Title->setText(mFastFile->GetStem() + ".ff"); ui->label_Title->setText(mFastFile->GetStem());
ui->comboBox_Company->setCurrentIndex(mFastFile->GetCompany()); ui->comboBox_Company->setCurrentIndex(mFastFile->GetCompany());
ui->comboBox_FileType->setCurrentIndex(mFastFile->GetType()); ui->comboBox_FileType->setCurrentIndex(mFastFile->GetType());
ui->checkBox_Signed->setChecked(mFastFile->GetSignage() == SIGNAGE_SIGNED); ui->checkBox_Signed->setChecked(mFastFile->GetSignage() == SIGNAGE_SIGNED);

View File

@ -10,6 +10,7 @@ LocalStringViewer::LocalStringViewer(QWidget *parent)
ui->setupUi(this); ui->setupUi(this);
ui->tableWidget_Strings->setColumnCount(2); ui->tableWidget_Strings->setColumnCount(2);
ui->tableWidget_Strings->setRowCount(0);
ui->tableWidget_Strings->setColumnWidth(0, 200); ui->tableWidget_Strings->setColumnWidth(0, 200);
ui->tableWidget_Strings->horizontalHeader()->setStretchLastSection(true); ui->tableWidget_Strings->horizontalHeader()->setStretchLastSection(true);
} }
@ -37,10 +38,12 @@ void LocalStringViewer::SetFileNotes(const QString aFileNotes) {
} }
void LocalStringViewer::AddLocalString(LocalString aLocalString) { void LocalStringViewer::AddLocalString(LocalString aLocalString) {
mLocalStrings << aLocalString; mLocalStrings.append(aLocalString);
ui->tableWidget_Strings->setRowCount(mLocalStrings.size()); ui->tableWidget_Strings->setRowCount(mLocalStrings.size());
ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(mLocalStrings.size()));
QTableWidgetItem *aliasItem = new QTableWidgetItem(aLocalString.alias); QTableWidgetItem *aliasItem = new QTableWidgetItem(aLocalString.alias);
QTableWidgetItem *stringItem = new QTableWidgetItem(aLocalString.string); QTableWidgetItem *stringItem = new QTableWidgetItem(aLocalString.string);
@ -53,7 +56,7 @@ void LocalStringViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
ui->tableWidget_Strings->clear(); ui->tableWidget_Strings->clear();
ui->label_Title->setText(aZoneFile->GetStem().section('.', 0, 0) + ".str"); ui->label_Title->setText(aZoneFile->GetStem().section('.', 0, 0) + ".str");
for (LocalString localStr : aZoneFile->GetAssetMap().localStrings) { for (const LocalString &localStr : aZoneFile->GetAssetMap().localStrings) {
AddLocalString(localStr); AddLocalString(localStr);
} }
} }

View File

@ -142,7 +142,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QGroupBox" name="groupBox_2"> <widget class="QGroupBox" name="groupBox_LocalStrViewer">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>400</width> <width>400</width>

View File

@ -1,13 +1,19 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "aboutdialog.h" #include "aboutdialog.h"
#include "fastfile.h" #include "fastfile.h"
#include "highlighter_gsc.h"
#include "highlighter_cfg.h"
#include "highlighter_shock.h"
#include "highlighter_rumble.h"
#include "materialviewer.h" #include "materialviewer.h"
#include "preferenceeditor.h" #include "preferenceeditor.h"
#include "rumblefileviewer.h"
#include "rumblegraphviewer.h"
#include "soundviewer.h" #include "soundviewer.h"
#include "stringtableviewer.h" #include "stringtableviewer.h"
#include "techsetviewer.h" #include "techsetviewer.h"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "compression.h" #include "fastfile_factory.h"
#include "iwifile.h" #include "iwifile.h"
#include "ddsfile.h" #include "ddsfile.h"
#include "statusbarmanager.h" #include "statusbarmanager.h"
@ -143,9 +149,13 @@ MainWindow::MainWindow(QWidget *parent)
}); });
connect(mTreeWidget, &XTreeWidget::RawFileSelected, this, [this](std::shared_ptr<RawFile> rawFile, const QString aParentName) { connect(mTreeWidget, &XTreeWidget::RawFileSelected, this, [this](std::shared_ptr<RawFile> rawFile, const QString aParentName) {
QPlainTextEdit *scriptEditor = new QPlainTextEdit(this); QTabWidget *rawTabWidget = new QTabWidget(this);
rawTabWidget->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
QPlainTextEdit *scriptEditor = new QPlainTextEdit(rawTabWidget);
scriptEditor->setAcceptDrops(false); scriptEditor->setAcceptDrops(false);
scriptEditor->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); scriptEditor->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
scriptEditor->setFont(QFont("Consolas"));
if (rawFile->contents.isEmpty()) { if (rawFile->contents.isEmpty()) {
scriptEditor->setPlainText("EMPTY"); scriptEditor->setPlainText("EMPTY");
@ -156,15 +166,52 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = rawFile->path.split('/').last(); QString fileStem = rawFile->path.split('/').last();
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete scriptEditor;
return; return;
} }
} }
QScrollArea *scrollArea = new QScrollArea(ui->tabWidget); const int tabStopSpaces = 4;
scrollArea->layout()->addWidget(scriptEditor); QFontMetrics metrics(scriptEditor->font());
scriptEditor->setTabStopDistance(tabStopSpaces * metrics.horizontalAdvance(' '));
ui->tabWidget->addTab(scrollArea, fileStem); QSyntaxHighlighter *highlighter;
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_GSCFile.png")); if (fileStem.contains(".gsc")) {
highlighter = new Highlighter_GSC(scriptEditor->document());
} else if (fileStem.contains(".cfg")) {
highlighter = new Highlighter_CFG(scriptEditor->document());
} else if (fileStem.contains(".rmb")) {
highlighter = new Highlighter_Rumble(scriptEditor->document());
RumbleGraphViewer *rmbGraphViewer = new RumbleGraphViewer(this);
rmbGraphViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
rmbGraphViewer->SetRumbleGraphFile(rawFile);
rawTabWidget->addTab(rmbGraphViewer, "UI Editor");
rawTabWidget->addTab(scriptEditor, "Text Editor");
ui->tabWidget->addTab(rawTabWidget, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RUMBLE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
return;
} else if (fileStem.contains(".shock")) {
highlighter = new Highlighter_Shock(scriptEditor->document());
} else if (rawFile->contents.left(6) == "RUMBLE") {
RumbleFileViewer *rmbFileViewer = new RumbleFileViewer(this);
rmbFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
rmbFileViewer->SetRumbleFile(rawFile);
rawTabWidget->addTab(rmbFileViewer, "UI Editor");
rawTabWidget->addTab(scriptEditor, "Text Editor");
ui->tabWidget->addTab(rawTabWidget, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RUMBLE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
return;
}
ui->tabWidget->addTab(scriptEditor, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RAW_FILE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -177,12 +224,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = image->materialName; QString fileStem = image->materialName;
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete mImageWidget;
return; return;
} }
} }
ui->tabWidget->addTab(mImageWidget, fileStem); ui->tabWidget->addTab(mImageWidget, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Image.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -190,24 +238,6 @@ MainWindow::MainWindow(QWidget *parent)
Q_UNUSED(menu); Q_UNUSED(menu);
}); });
connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](std::shared_ptr<DDSFile> ddsFile, const QString aParentName) {
DDSViewer *ddsViewer = new DDSViewer(this);
ddsViewer->setAcceptDrops(false);
ddsViewer->SetDDSFile(ddsFile);
ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
QString fileStem = ddsFile->fileStem + ".dds";
for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) {
return;
}
}
ui->tabWidget->addTab(ddsViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_DDSFile.png"));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
});
connect(mTreeWidget, &XTreeWidget::MaterialSelected, this, [this](std::shared_ptr<Material> material, const QString aParentName) { connect(mTreeWidget, &XTreeWidget::MaterialSelected, this, [this](std::shared_ptr<Material> material, const QString aParentName) {
MaterialViewer *matViewer = new MaterialViewer(this); MaterialViewer *matViewer = new MaterialViewer(this);
matViewer->setAcceptDrops(false); matViewer->setAcceptDrops(false);
@ -217,12 +247,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = material->name; QString fileStem = material->name;
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete matViewer;
return; return;
} }
} }
ui->tabWidget->addTab(matViewer, fileStem); ui->tabWidget->addTab(matViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Material.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_MATERIAL));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -235,12 +266,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = ddsFile->fileStem + ".dds"; QString fileStem = ddsFile->fileStem + ".dds";
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete ddsViewer;
return; return;
} }
} }
ui->tabWidget->addTab(ddsViewer, fileStem); ui->tabWidget->addTab(ddsViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_DDSFile.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -253,12 +285,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = iwiFile->fileStem + ".iwi"; QString fileStem = iwiFile->fileStem + ".iwi";
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete iwiViewer;
return; return;
} }
} }
ui->tabWidget->addTab(iwiViewer, fileStem); ui->tabWidget->addTab(iwiViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_IWIFile.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -268,15 +301,16 @@ MainWindow::MainWindow(QWidget *parent)
fastFileViewer->SetFastFile(aFastFile); fastFileViewer->SetFastFile(aFastFile);
fastFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); fastFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
QString fileStem = aFastFile->GetStem() + ".ff"; QString fileStem = aFastFile->GetStem();
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete fastFileViewer;
return; return;
} }
} }
ui->tabWidget->addTab(fastFileViewer, fileStem); ui->tabWidget->addTab(fastFileViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_FastFile.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_FAST_FILE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -286,9 +320,10 @@ MainWindow::MainWindow(QWidget *parent)
zoneFileViewer->SetZoneFile(aZoneFile); zoneFileViewer->SetZoneFile(aZoneFile);
zoneFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); zoneFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName));
QString fileStem = aZoneFile->GetStem() + ".zone"; QString fileStem = aZoneFile->GetBaseStem() + ".zone";
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete zoneFileViewer;
return; return;
} }
} }
@ -306,7 +341,7 @@ MainWindow::MainWindow(QWidget *parent)
scrollArea->setWidget(containerWidget); scrollArea->setWidget(containerWidget);
ui->tabWidget->addTab(scrollArea, fileStem); ui->tabWidget->addTab(scrollArea, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_ZoneFile.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_ZONE_FILE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -319,12 +354,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = aZoneFile->GetStem() + ".str"; QString fileStem = aZoneFile->GetStem() + ".str";
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete localStrViewer;
return; return;
} }
} }
ui->tabWidget->addTab(localStrViewer, fileStem); ui->tabWidget->addTab(localStrViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_String.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_LOCAL_STRING));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -337,12 +373,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = aTechSet->name; QString fileStem = aTechSet->name;
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete techSetViewer;
return; return;
} }
} }
ui->tabWidget->addTab(techSetViewer, aTechSet->name); ui->tabWidget->addTab(techSetViewer, aTechSet->name);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_TechSetFile.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_TECH_SET));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -355,12 +392,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = aStrTable->name; QString fileStem = aStrTable->name;
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete strTableViewer;
return; return;
} }
} }
ui->tabWidget->addTab(strTableViewer, fileStem); ui->tabWidget->addTab(strTableViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_StringTable.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_STRING_TABLE));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -373,12 +411,13 @@ MainWindow::MainWindow(QWidget *parent)
QString fileStem = aSound->path.split('/').last(); QString fileStem = aSound->path.split('/').last();
for (int i = 0; i < ui->tabWidget->count(); i++) { for (int i = 0; i < ui->tabWidget->count(); i++) {
if (ui->tabWidget->tabText(i) == fileStem) { if (ui->tabWidget->tabText(i) == fileStem) {
delete soundViewer;
return; return;
} }
} }
ui->tabWidget->addTab(soundViewer, fileStem); ui->tabWidget->addTab(soundViewer, fileStem);
ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Sound.png")); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_SOUND));
ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1);
}); });
@ -475,13 +514,13 @@ void MainWindow::Reset() {
and opens the selected file. and opens the selected file.
*/ */
bool MainWindow::OpenFastFile(const QString aFastFilePath) { bool MainWindow::OpenFastFile(const QString aFastFilePath) {
const QString fastFileStem = aFastFilePath.section("/", -1, -1).section('.', 0, 0); const QString fastFileStem = aFastFilePath.section("/", -1, -1);
if (mTreeWidget->HasFastFile(fastFileStem)) { if (mTreeWidget->HasFastFile(fastFileStem)) {
LogManager::instance().addError("Can't add duplicate file!"); LogManager::instance().addError("Can't add duplicate file!");
return false; return false;
} }
std::shared_ptr<FastFile> fastFile = FastFile::Open(aFastFilePath); std::shared_ptr<FastFile> fastFile = FastFileFactory::Create(aFastFilePath);
fastFile->SetStem(fastFileStem); fastFile->SetStem(fastFileStem);
mTreeWidget->AddFastFile(fastFile); mTreeWidget->AddFastFile(fastFile);

View File

@ -20,18 +20,11 @@ void MaterialViewer::SetMaterial(std::shared_ptr<Material> aMaterial) {
ui->lineEdit_Name->setText(aMaterial->name); ui->lineEdit_Name->setText(aMaterial->name);
ui->lineEdit_RefPtr->setText(ToHexStr(aMaterial->refNamePtr)); ui->lineEdit_RefPtr->setText(ToHexStr(aMaterial->refNamePtr));
ui->lineEdit_RefName->setText(aMaterial->refName); ui->lineEdit_RefName->setText(aMaterial->refName);
ui->lineEdit_Unknowns->setText(ToHexStr(aMaterial->unknownA[0]) QString unknownStr = "";
+ ToHexStr(aMaterial->unknownA[1]) foreach (quint32 unknownPtr, aMaterial->pointers) {
+ ToHexStr(aMaterial->unknownA[2]) unknownStr += ToHexStr(unknownPtr) + "\n";
+ ToHexStr(aMaterial->unknownA[3]) }
+ ToHexStr(aMaterial->unknownA[4]) ui->lineEdit_Unknowns->setText(unknownStr);
+ ToHexStr(aMaterial->unknownA[5])
+ ToHexStr(aMaterial->unknownA[6])
+ ToHexStr(aMaterial->unknownA[7])
+ ToHexStr(aMaterial->unknownA[8])
+ ToHexStr(aMaterial->unknownA[9])
+ ToHexStr(aMaterial->unknownA[10])
+ ToHexStr(aMaterial->unknownA[11]));
ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[0])); ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[0]));
ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[1])); ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[1]));
ui->spinBox_TextureCount->setValue(aMaterial->textureCount); ui->spinBox_TextureCount->setValue(aMaterial->textureCount);

58
app/rumblefileviewer.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "rumblefileviewer.h"
#include "ui_rumblefileviewer.h"
RumbleFileViewer::RumbleFileViewer(QWidget *parent)
: QWidget(parent)
, ui(new Ui::RumbleFileViewer)
, mPropertyCount()
, mRumbleFile(nullptr) {
ui->setupUi(this);
ui->tableWidget_Properties->setColumnCount(2);
ui->tableWidget_Properties->setRowCount(0);
ui->tableWidget_Properties->setColumnWidth(0, 200);
ui->tableWidget_Properties->horizontalHeader()->setStretchLastSection(true);
}
RumbleFileViewer::~RumbleFileViewer() {
delete ui;
}
void RumbleFileViewer::SetRumbleFile(std::shared_ptr<RawFile> aRumbleFile) {
mRumbleFile = aRumbleFile;
ui->tableWidget_Properties->clear();
const QString magic = aRumbleFile->contents.left(6);
if (magic != "RUMBLE") {
qDebug() << "Rumble file has invalid magic: " << magic;
return;
}
int firstIndex = 0;
int secondIndex = 0;
int thirdIndex = 0;
int startIndex = 0;
for (int i = 0; i < aRumbleFile->contents.count("\\") / 2; i++) {
ui->tableWidget_Properties->setRowCount(i + 1);
ui->spinBox_Entries->setValue(i + 1);
firstIndex = aRumbleFile->contents.indexOf("\\", startIndex);
secondIndex = aRumbleFile->contents.indexOf("\\", firstIndex + 1);
thirdIndex = aRumbleFile->contents.indexOf("\\", secondIndex + 1);
if (thirdIndex == -1) {
thirdIndex = aRumbleFile->contents.size();
}
const QString keyStr = aRumbleFile->contents.mid(firstIndex + 1, secondIndex - firstIndex - 1);
QTableWidgetItem *keyItem = new QTableWidgetItem(keyStr);
ui->tableWidget_Properties->setItem(i, 0, keyItem);
const QString valStr = aRumbleFile->contents.mid(secondIndex + 1, thirdIndex - secondIndex - 1);
QTableWidgetItem *valueItem = new QTableWidgetItem(valStr);
ui->tableWidget_Properties->setItem(i, 1, valueItem);
startIndex = thirdIndex;
}
}

28
app/rumblefileviewer.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef RUMBLEFILEVIEWER_H
#define RUMBLEFILEVIEWER_H
#include "asset_structs.h"
#include "zonefile.h"
#include <QWidget>
namespace Ui {
class RumbleFileViewer;
}
class RumbleFileViewer : public QWidget
{
Q_OBJECT
public:
explicit RumbleFileViewer(QWidget *parent = nullptr);
~RumbleFileViewer();
void SetRumbleFile(std::shared_ptr<RawFile> aRumbleFile);
private:
Ui::RumbleFileViewer *ui;
quint32 mPropertyCount;
std::shared_ptr<RawFile> mRumbleFile;
};
#endif // RUMBLEFILEVIEWER_H

153
app/rumblefileviewer.ui Normal file
View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RumbleFileViewer</class>
<widget class="QWidget" name="RumbleFileViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>841</width>
<height>457</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>841</width>
<height>457</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_Title">
<property name="font">
<font>
<family>Roboto</family>
<pointsize>16</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Rumble File Viewer</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="minimumSize">
<size>
<width>325</width>
<height>398</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>325</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Roboto</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="title">
<string>Header</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" colspan="2">
<widget class="QSpinBox" name="spinBox_Entries">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>1</number>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Entries:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_LocalStrViewer">
<property name="minimumSize">
<size>
<width>400</width>
<height>400</height>
</size>
</property>
<property name="font">
<font>
<family>Roboto</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="title">
<string>Properties</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTableWidget" name="tableWidget_Properties">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

54
app/rumblegraphviewer.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "rumblegraphviewer.h"
#include "ui_rumblegraphviewer.h"
RumbleGraphViewer::RumbleGraphViewer(QWidget *parent)
: QWidget(parent)
, ui(new Ui::RumbleGraphViewer),
mEntryCount(),
mRumbleGraphFile(nullptr) {
ui->setupUi(this);
ui->tableWidget_Entries->setColumnCount(2);
ui->tableWidget_Entries->setHorizontalHeaderLabels({ "X", "Y" });
ui->tableWidget_Entries->setRowCount(0);
ui->tableWidget_Entries->setColumnWidth(0, 200);
ui->tableWidget_Entries->horizontalHeader()->setStretchLastSection(true);
}
RumbleGraphViewer::~RumbleGraphViewer() {
delete ui;
}
void RumbleGraphViewer::SetRumbleGraphFile(const std::shared_ptr<RawFile> aRawFile) {
mRumbleGraphFile = aRawFile;
QDataStream rawFileStream(mRumbleGraphFile->contents.toLatin1());
QByteArray magic(15, Qt::Uninitialized);
rawFileStream.readRawData(magic.data(), 15);
rawFileStream.skipRawData(4);
char sectionChar;
rawFileStream >> sectionChar;
int sectionCount = sectionChar - '0';
ui->tableWidget_Entries->setRowCount(sectionCount);
ui->spinBox_Entries->setValue(sectionCount);
ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(sectionCount));
rawFileStream.skipRawData(2);
for (int i = 0; i < sectionCount; i++) {
QByteArray xVal(6, Qt::Uninitialized), yVal(6, Qt::Uninitialized);
rawFileStream.readRawData(xVal.data(), 6);
rawFileStream.skipRawData(1);
rawFileStream.readRawData(yVal.data(), 6);
rawFileStream.skipRawData(2);
QTableWidgetItem *xItem = new QTableWidgetItem(xVal);
QTableWidgetItem *yItem = new QTableWidgetItem(yVal);
ui->tableWidget_Entries->setItem(i, 0, xItem);
ui->tableWidget_Entries->setItem(i, 1, yItem);
}
}

30
app/rumblegraphviewer.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef RUMBLEGRAPHVIEWER_H
#define RUMBLEGRAPHVIEWER_H
#include "asset_structs.h"
#include "zonefile.h"
#include <QWidget>
namespace Ui {
class RumbleGraphViewer;
}
class RumbleGraphViewer : public QWidget
{
Q_OBJECT
public:
explicit RumbleGraphViewer(QWidget *parent = nullptr);
~RumbleGraphViewer();
void SetEntryCount(quint32 aCount);
void SetRumbleGraphFile(const std::shared_ptr<RawFile> aRawFile);
void SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile);
private:
Ui::RumbleGraphViewer *ui;
quint32 mEntryCount;
std::shared_ptr<RawFile> mRumbleGraphFile;
};
#endif // RUMBLEGRAPHVIEWER_H

153
app/rumblegraphviewer.ui Normal file
View File

@ -0,0 +1,153 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RumbleGraphViewer</class>
<widget class="QWidget" name="RumbleGraphViewer">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>841</width>
<height>457</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>841</width>
<height>457</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_Title">
<property name="font">
<font>
<family>Roboto</family>
<pointsize>16</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Rumble Graph File </string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="minimumSize">
<size>
<width>325</width>
<height>398</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>325</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Roboto</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="title">
<string>Header</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Entry Count: </string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QSpinBox" name="spinBox_Entries">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_LocalStrViewer">
<property name="minimumSize">
<size>
<width>400</width>
<height>400</height>
</size>
</property>
<property name="font">
<font>
<family>Roboto</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="title">
<string>Entries</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTableWidget" name="tableWidget_Entries">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -16,6 +16,7 @@ XTreeWidget::XTreeWidget(QWidget *parent)
header()->hide(); header()->hide();
setMinimumWidth(350); setMinimumWidth(350);
setSortingEnabled(true); setSortingEnabled(true);
setIconSize(QSize(16, 16));
header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
@ -38,36 +39,44 @@ XTreeWidget::~XTreeWidget() {
void XTreeWidget::AddFastFile(std::shared_ptr<FastFile> aFastFile) { void XTreeWidget::AddFastFile(std::shared_ptr<FastFile> aFastFile) {
XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this); XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this);
fastFileItem->setText(0, aFastFile->GetStem() + ".ff"); fastFileItem->setText(0, aFastFile->GetStem());
fastFileItem->setIcon(0, QIcon(":/icons/icons/Icon_FastFile.png")); fastFileItem->setIcon(0, Utils::CreateAssetIcon("FF"));
if (aFastFile->GetPlatform() == "PC") { if (aFastFile->GetPlatform() == "PC") {
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_PC.png")); fastFileItem->setIcon(1, Utils::CreateAssetIcon("PC"));
} else if (aFastFile->GetPlatform() == "360") { } else if (aFastFile->GetPlatform() == "360") {
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Xbox.png")); fastFileItem->setIcon(1, Utils::CreateAssetIcon("360"));
} else if (aFastFile->GetPlatform() == "PS3") {
fastFileItem->setIcon(1, Utils::CreateAssetIcon("PS3"));
} else if (aFastFile->GetPlatform() == "Wii") { } else if (aFastFile->GetPlatform() == "Wii") {
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Wii.png")); fastFileItem->setIcon(1, Utils::CreateAssetIcon("WII"));
} else if (aFastFile->GetPlatform() == "WiiU") { } else if (aFastFile->GetPlatform() == "WiiU") {
fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_WiiU.png")); fastFileItem->setIcon(1, Utils::CreateAssetIcon("WU"));
} }
if (aFastFile->GetGame() == "COD2") { if (aFastFile->GetGame() == "COD2") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD2.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(2));
} if (aFastFile->GetGame() == "COD4") { } if (aFastFile->GetGame() == "COD4") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD4.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(4));
} else if (aFastFile->GetGame() == "COD5") { } else if (aFastFile->GetGame() == "COD5") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD5.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(5));
} else if (aFastFile->GetGame() == "COD6") { } else if (aFastFile->GetGame() == "COD6") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD6.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(6));
} else if (aFastFile->GetGame() == "COD7") { } else if (aFastFile->GetGame() == "COD7") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD7.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(7));
} else if (aFastFile->GetGame() == "COD8") { } else if (aFastFile->GetGame() == "COD8") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD8.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(8));
} else if (aFastFile->GetGame() == "COD9") { } else if (aFastFile->GetGame() == "COD9") {
fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD9.png")); fastFileItem->setIcon(2, Utils::CreateGameIcon(9));
} else if (aFastFile->GetGame() == "COD10") {
fastFileItem->setIcon(2, Utils::CreateGameIcon(10));
} else if (aFastFile->GetGame() == "COD11") {
fastFileItem->setIcon(2, Utils::CreateGameIcon(11));
} else if (aFastFile->GetGame() == "COD12") {
fastFileItem->setIcon(2, Utils::CreateGameIcon(12));
} }
AddZoneFile(aFastFile->GetZoneFile(), fastFileItem); AddZoneFile(aFastFile->GetZoneFile(), fastFileItem);
mFastFiles[aFastFile->GetStem().section(".", 0, 0)] = aFastFile; mFastFiles[aFastFile->GetStem()] = aFastFile;
resizeColumnToContents(1); resizeColumnToContents(1);
setSortingEnabled(true); setSortingEnabled(true);
@ -81,42 +90,52 @@ void XTreeWidget::AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetIt
} else { } else {
zoneItem = new XTreeWidgetItem(this); zoneItem = new XTreeWidgetItem(this);
} }
zoneItem->setIcon(0, QIcon(":/icons/icons/Icon_ZoneFile.png")); zoneItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_ZONE_FILE));
zoneItem->setText(0, aZoneFile->GetStem() + ".zone"); zoneItem->setText(0, aZoneFile->GetBaseStem() + ".zone");
auto assetMap = aZoneFile->GetAssetMap(); auto assetMap = aZoneFile->GetAssetMap();
if (!assetMap.localStrings.isEmpty()) { if (!assetMap.localStrings.isEmpty()) {
QIcon localStrIcon = ZoneFile::AssetTypeToIcon(ASSET_LOCAL_STRING);
XTreeWidgetItem *localStrRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *localStrRoot = new XTreeWidgetItem(zoneItem);
localStrRoot->setText(0, "String Files"); localStrRoot->setText(0, "String Files");
localStrRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png")); localStrRoot->setIcon(0, localStrIcon);
localStrRoot->SetCategory(CATEGORY_TYPE);
XTreeWidgetItem *localStrItem = new XTreeWidgetItem(localStrRoot); XTreeWidgetItem *localStrItem = new XTreeWidgetItem(localStrRoot);
localStrItem->setText(0, aZoneFile->GetStem().section('.', 0, 0) + ".str"); localStrItem->setText(0, aZoneFile->GetStem().section('.', 0, 0) + ".str");
localStrItem->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png")); localStrItem->setIcon(0, localStrIcon);
} }
if (!assetMap.techSets.isEmpty()) { if (!assetMap.techSets.isEmpty()) {
QIcon techSetIcon = ZoneFile::AssetTypeToIcon(ASSET_TECH_SET);
XTreeWidgetItem *techSetRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *techSetRoot = new XTreeWidgetItem(zoneItem);
techSetRoot->setText(0, "Tech Sets"); techSetRoot->setText(0, "Tech Sets");
techSetRoot->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png")); techSetRoot->setIcon(0, techSetIcon);
techSetRoot->SetCategory(CATEGORY_TYPE);
for (TechSet techSet : assetMap.techSets) { for (TechSet techSet : assetMap.techSets) {
XTreeWidgetItem *techSetItem = new XTreeWidgetItem(techSetRoot); XTreeWidgetItem *techSetItem = new XTreeWidgetItem(techSetRoot);
techSetItem->setText(0, techSet.name); techSetItem->setText(0, techSet.name);
techSetItem->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png")); techSetItem->setIcon(0, techSetIcon);
} }
} }
if (!assetMap.rawFiles.isEmpty()) { if (!assetMap.rawFiles.isEmpty()) {
QIcon rawFileIcon = ZoneFile::AssetTypeToIcon(ASSET_RAW_FILE);
XTreeWidgetItem *rawFileRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *rawFileRoot = new XTreeWidgetItem(zoneItem);
rawFileRoot->setText(0, "Raw Files"); rawFileRoot->setText(0, "Raw Files");
rawFileRoot->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png")); rawFileRoot->setIcon(0, rawFileIcon);
rawFileRoot->SetCategory(CATEGORY_TYPE);
for (RawFile rawFile : assetMap.rawFiles) { for (RawFile rawFile : assetMap.rawFiles) {
if (!rawFile.length) { continue; } if (!rawFile.length) { continue; }
XTreeWidgetItem *tempItem = rawFileRoot; XTreeWidgetItem *tempItem = rawFileRoot;
for (const QString &pathPart : rawFile.path.split('/')) { const QStringList pathParts = rawFile.path.split('/');
for (const QString &pathPart : pathParts) {
bool childFound = false; bool childFound = false;
for (int i = 0; i < tempItem->childCount(); i++) { for (int i = 0; i < tempItem->childCount(); i++) {
QTreeWidgetItem *rawChildItem = tempItem->child(i); QTreeWidgetItem *rawChildItem = tempItem->child(i);
@ -129,25 +148,30 @@ void XTreeWidget::AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetIt
} }
} }
if (pathPart.contains(".gsc")) { const QString rawFileStr = QString("%1 [%2-%3]").arg(pathPart).arg(rawFile.startPos).arg(rawFile.endPos);
//rawFileStr = pathPart;
if (pathPart == pathParts.last()) {
XTreeWidgetItem *rawFileItem = new XTreeWidgetItem(tempItem); XTreeWidgetItem *rawFileItem = new XTreeWidgetItem(tempItem);
rawFileItem->setText(0, pathPart); rawFileItem->setText(0, rawFileStr);
tempItem = rawFileItem; tempItem = rawFileItem;
} else if (!childFound) { } else if (!childFound) {
tempItem = new XTreeWidgetItem(tempItem); tempItem = new XTreeWidgetItem(tempItem);
tempItem->setText(0, pathPart); tempItem->setText(0, rawFileStr);
} }
} }
tempItem->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png")); tempItem->setIcon(0, rawFileIcon);
} }
} }
if (!assetMap.menuFiles.isEmpty()) { if (!assetMap.menuFiles.isEmpty()) {
QIcon menuFileIcon = ZoneFile::AssetTypeToIcon(ASSET_MENU);
XTreeWidgetItem *menuRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *menuRoot = new XTreeWidgetItem(zoneItem);
menuRoot->setText(0, "Menu Files"); menuRoot->setText(0, "Menu Files");
menuRoot->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png")); menuRoot->setIcon(0, menuFileIcon);
menuRoot->SetCategory(CATEGORY_TYPE);
int menuIndex = 1; int menuIndex = 1;
for (MenuFile menuFile : assetMap.menuFiles) { for (MenuFile menuFile : assetMap.menuFiles) {
@ -155,65 +179,80 @@ void XTreeWidget::AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetIt
menuFileRoot->setText(0, QString("Menu %1").arg(menuIndex)); menuFileRoot->setText(0, QString("Menu %1").arg(menuIndex));
for (Menu menu : menuFile.menuDefs) { for (Menu menu : menuFile.menuDefs) {
XTreeWidgetItem *menuItem = new XTreeWidgetItem(menuFileRoot); XTreeWidgetItem *menuItem = new XTreeWidgetItem(menuFileRoot);
menuItem->setText(0, menu.name); menuItem->setText(0, menu.filePath);
menuItem->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png")); menuItem->setIcon(0, menuFileIcon);
} }
menuIndex++; menuIndex++;
} }
} }
if (!assetMap.images.isEmpty()) { if (!assetMap.images.isEmpty()) {
QIcon imageIcon = ZoneFile::AssetTypeToIcon(ASSET_IMAGE);
XTreeWidgetItem *imageRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *imageRoot = new XTreeWidgetItem(zoneItem);
imageRoot->setText(0, "Images"); imageRoot->setText(0, "Images");
imageRoot->setIcon(0, QIcon(":/icons/icons/Icon_Image.png")); imageRoot->setIcon(0, imageIcon);
imageRoot->SetCategory(CATEGORY_TYPE);
for (Image image : assetMap.images) { for (Image image : assetMap.images) {
XTreeWidgetItem *imageItem = new XTreeWidgetItem(imageRoot); XTreeWidgetItem *imageItem = new XTreeWidgetItem(imageRoot);
imageItem->setText(0, image.materialName); imageItem->setText(0, image.materialName);
imageItem->setIcon(0, QIcon(":/icons/icons/Icon_Image.png")); imageItem->setIcon(0, imageIcon);
} }
} }
if (!assetMap.models.isEmpty()) { if (!assetMap.models.isEmpty()) {
QIcon modelIcon = ZoneFile::AssetTypeToIcon(ASSET_MODEL);
XTreeWidgetItem *modelsRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *modelsRoot = new XTreeWidgetItem(zoneItem);
modelsRoot->setText(0, "Models"); modelsRoot->setText(0, "Models");
modelsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Model.png")); modelsRoot->setIcon(0, modelIcon);
modelsRoot->SetCategory(CATEGORY_TYPE);
for (Model model: assetMap.models) { for (Model model: assetMap.models) {
XTreeWidgetItem *modelItem = new XTreeWidgetItem(modelsRoot); XTreeWidgetItem *modelItem = new XTreeWidgetItem(modelsRoot);
modelItem->setText(0, model.modelName); modelItem->setText(0, model.modelName);
modelItem->setIcon(0, QIcon(":/icons/icons/Icon_Model.png")); modelItem->setIcon(0, modelIcon);
} }
} }
if (!assetMap.materials.isEmpty()) { if (!assetMap.materials.isEmpty()) {
QIcon materialIcon = ZoneFile::AssetTypeToIcon(ASSET_MATERIAL);
XTreeWidgetItem *materialsRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *materialsRoot = new XTreeWidgetItem(zoneItem);
materialsRoot->setText(0, "Materials"); materialsRoot->setText(0, "Materials");
materialsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Material.png")); materialsRoot->setIcon(0, materialIcon);
materialsRoot->SetCategory(CATEGORY_TYPE);
for (Material material: assetMap.materials) { for (Material material: assetMap.materials) {
XTreeWidgetItem *materialItem = new XTreeWidgetItem(materialsRoot); XTreeWidgetItem *materialItem = new XTreeWidgetItem(materialsRoot);
materialItem->setText(0, material.name); materialItem->setText(0, material.name);
materialItem->setIcon(0, QIcon(":/icons/icons/Icon_Material.png")); materialItem->setIcon(0, materialIcon);
} }
} }
if (!assetMap.stringTables.isEmpty()) { if (!assetMap.stringTables.isEmpty()) {
QIcon stringTableIcon = ZoneFile::AssetTypeToIcon(ASSET_STRING_TABLE);
XTreeWidgetItem *strTableRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *strTableRoot = new XTreeWidgetItem(zoneItem);
strTableRoot->setText(0, "String Tables"); strTableRoot->setText(0, "String Tables");
strTableRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png")); strTableRoot->setIcon(0, stringTableIcon);
strTableRoot->SetCategory(CATEGORY_TYPE);
for (StringTable strTable: assetMap.stringTables) { for (StringTable strTable: assetMap.stringTables) {
XTreeWidgetItem *modelItem = new XTreeWidgetItem(strTableRoot); XTreeWidgetItem *modelItem = new XTreeWidgetItem(strTableRoot);
modelItem->setText(0, strTable.name); modelItem->setText(0, strTable.name);
modelItem->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png")); modelItem->setIcon(0, stringTableIcon);
} }
} }
if (!assetMap.sounds.isEmpty()) { if (!assetMap.sounds.isEmpty()) {
QIcon soundIcon = ZoneFile::AssetTypeToIcon(ASSET_SOUND);
XTreeWidgetItem *soundsRoot = new XTreeWidgetItem(zoneItem); XTreeWidgetItem *soundsRoot = new XTreeWidgetItem(zoneItem);
soundsRoot->setText(0, "Sounds"); soundsRoot->setText(0, "Sounds");
soundsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png")); soundsRoot->setIcon(0, soundIcon);
soundsRoot->SetCategory(CATEGORY_TYPE);
for (SoundAsset soundAsset : assetMap.sounds) { for (SoundAsset soundAsset : assetMap.sounds) {
for (Sound sound : soundAsset.sounds) { for (Sound sound : soundAsset.sounds) {
XTreeWidgetItem *tempItem = soundsRoot; XTreeWidgetItem *tempItem = soundsRoot;
@ -245,16 +284,16 @@ void XTreeWidget::AddZoneFile(std::shared_ptr<ZoneFile> aZoneFile, XTreeWidgetIt
} }
} }
tempItem->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png")); tempItem->setIcon(0, soundIcon);
} }
} }
} }
mZoneFiles[aZoneFile->GetStem().section(".", 0, 0)] = aZoneFile; mZoneFiles[aZoneFile->GetBaseStem() + ".zone"] = aZoneFile;
} }
void XTreeWidget::CloseFastFile(const QString aFFName) { void XTreeWidget::CloseFastFile(const QString aFFName) {
const QString fileStem = aFFName.section(".", 0, 0); const QString fileStem = aFFName;
emit ItemClosed(fileStem); emit ItemClosed(fileStem);
} }
@ -355,7 +394,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
iwiFile->SaveJPG(); iwiFile->SaveJPG();
}); });
} else if (activeText.contains(".ff")) { } else if (activeText.contains(".ff")) {
const QString fileStem = activeText.replace(".zone", ""); const QString fileStem = activeText;
QMenu *closeMultipleAction = new QMenu("Close Multiple Tabs"); QMenu *closeMultipleAction = new QMenu("Close Multiple Tabs");
@ -379,7 +418,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
auto childItem = invisibleRootItem()->child(i); auto childItem = invisibleRootItem()->child(i);
if (childItem == activeItem) { continue; } if (childItem == activeItem) { continue; }
const QString fileStem = childItem->text(0).replace(".ff", ""); const QString fileStem = childItem->text(0);
if (!mFastFiles.contains(fileStem)) { if (!mFastFiles.contains(fileStem)) {
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
return; return;
@ -401,7 +440,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
auto childItem = invisibleRootItem()->child(i); auto childItem = invisibleRootItem()->child(i);
if (childItem == activeItem) { return; } if (childItem == activeItem) { return; }
const QString fileStem = childItem->text(0).replace(".ff", ""); const QString fileStem = childItem->text(0);
if (!mFastFiles.contains(fileStem)) { if (!mFastFiles.contains(fileStem)) {
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
return; return;
@ -428,7 +467,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
continue; continue;
} }
const QString fileStem = childItem->text(0).replace(".ff", ""); const QString fileStem = childItem->text(0);
if (!mFastFiles.contains(fileStem)) { if (!mFastFiles.contains(fileStem)) {
qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; qDebug() << "Error: Could not find " << fileStem << " in Fast File map!";
return; return;
@ -448,7 +487,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
connect(closeAction, &QAction::triggered, this, [this, &activeItem, &activeText](bool checked) { connect(closeAction, &QAction::triggered, this, [this, &activeItem, &activeText](bool checked) {
Q_UNUSED(checked); Q_UNUSED(checked);
const QString fileStem = activeItem->text(0).replace(".ff", ""); const QString fileStem = activeItem->text(0);
mFastFiles.remove(fileStem); mFastFiles.remove(fileStem);
CloseFastFile(activeText); CloseFastFile(activeText);
@ -482,7 +521,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) {
fastFile->GetZoneFile()->SaveZoneFile(zoneFilePath); fastFile->GetZoneFile()->SaveZoneFile(zoneFilePath);
}); });
} else if (activeText.contains(".zone")) { } else if (activeText.contains(".zone")) {
const QString fileStem = activeText.replace(".zone", ""); const QString fileStem = activeText;
if (!mZoneFiles.contains(fileStem)) { if (!mZoneFiles.contains(fileStem)) {
qDebug() << "Error: Could not find " << fileStem << " in Zone File map!"; qDebug() << "Error: Could not find " << fileStem << " in Zone File map!";
return; return;
@ -612,63 +651,39 @@ void XTreeWidget::ItemSelectionChanged() {
QString selectedText = selectedItem->text(0); QString selectedText = selectedItem->text(0);
emit ItemSelected(selectedText); emit ItemSelected(selectedText);
const QString fileStem = selectedText.section(".", 0, 0);
XTreeWidgetItem *parentItem = dynamic_cast<XTreeWidgetItem*>(selectedItem->parent()); XTreeWidgetItem *parentItem = dynamic_cast<XTreeWidgetItem*>(selectedItem->parent());
if (selectedText.contains(".dds")) { if (selectedText.contains(".dds")) {
if (!mDDSFiles.contains(fileStem)) { if (!mDDSFiles.contains(selectedText)) {
LogManager::instance().addError("Could not find " + fileStem + " in DDS map!"); LogManager::instance().addError("Could not find " + selectedText + " in DDS map!");
return; return;
} }
std::shared_ptr<DDSFile> ddsFile = mDDSFiles[fileStem]; std::shared_ptr<DDSFile> ddsFile = mDDSFiles[selectedText];
emit DDSFileSelected(ddsFile, fileStem); emit DDSFileSelected(ddsFile, selectedText);
} else if (selectedText.contains(".iwi")) { } else if (selectedText.contains(".iwi")) {
if (!mIWIFiles.contains(fileStem)) { if (!mIWIFiles.contains(selectedText)) {
LogManager::instance().addError("Could not find " + fileStem + " in IWI map!"); LogManager::instance().addError("Could not find " + selectedText + " in IWI map!");
return; return;
} }
emit IWIFileSelected(mIWIFiles[fileStem], fileStem); emit IWIFileSelected(mIWIFiles[selectedText], selectedText);
} else if (selectedText.contains(".ff")) { } else if (selectedText.contains(".ff")) {
if (!mFastFiles.contains(fileStem)) { if (!mFastFiles.contains(selectedText)) {
LogManager::instance().addError("Could not find " + fileStem + " in Fast File map!"); LogManager::instance().addError("Could not find " + selectedText + " in Fast File map!");
return; return;
} }
emit FastFileSelected(mFastFiles[fileStem], fileStem); emit FastFileSelected(mFastFiles[selectedText], selectedText);
} else if (selectedText.contains(".zone")) { } else if (selectedText.contains(".zone")) {
if (!mZoneFiles.contains(fileStem)) { if (!mZoneFiles.contains(selectedText)) {
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!");
return; return;
} }
emit ZoneFileSelected(mZoneFiles[fileStem], fileStem); emit ZoneFileSelected(mZoneFiles[selectedText], selectedText);
} else if (selectedText.contains(".str")) { } else if (selectedText.contains(".str")) {
if (!mZoneFiles.contains(fileStem)) { if (!mZoneFiles.contains(selectedText.replace(".str", ".zone"))) {
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!");
return; return;
} }
emit LocalStringSelected(mZoneFiles[fileStem], fileStem); emit LocalStringSelected(mZoneFiles[selectedText], selectedText);
} else if (selectedText.contains(".gsc")) {
XTreeWidgetItem *zoneRoot = selectedItem;
if (!zoneRoot) { return; }
while (!zoneRoot->text(0).contains(".zone")) {
zoneRoot = dynamic_cast<XTreeWidgetItem*>(zoneRoot->parent());
if (!zoneRoot) { return; }
}
const QString fileStem = zoneRoot->text(0).section('.', 0, 0);
if (!mZoneFiles.contains(fileStem)) {
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!");
return;
}
QVector<RawFile> rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles;
for (RawFile rawFile : rawFiles) {
if (rawFile.path.contains(selectedText)) {
emit RawFileSelected(std::make_shared<RawFile>(rawFile), fileStem);
return;
}
}
} else if (parentItem && (parentItem->text(0) == "Images")) { } else if (parentItem && (parentItem->text(0) == "Images")) {
XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent()); XTreeWidgetItem *grandpaItem = dynamic_cast<XTreeWidgetItem*>(parentItem->parent());
if (grandpaItem && grandpaItem->text(0).contains(".zone")) { if (grandpaItem && grandpaItem->text(0).contains(".zone")) {
@ -738,6 +753,32 @@ void XTreeWidget::ItemSelectionChanged() {
} }
} }
} }
} else if (selectedItem->GetCategory() != CATEGORY_TYPE) {
XTreeWidgetItem *zoneRoot = selectedItem;
bool zoneChild = false;
while (zoneRoot) {
zoneRoot = dynamic_cast<XTreeWidgetItem*>(zoneRoot->parent());
if (zoneRoot->text(0).contains("Raw Files")) {
zoneChild = true;
break;
}
}
if (!zoneChild) { return; }
const QString fileStem = zoneRoot->parent()->text(0);
if (!mZoneFiles.contains(fileStem)) {
LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!");
return;
}
QVector<RawFile> rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles;
for (RawFile rawFile : rawFiles) {
if (rawFile.path.split('/').last() == selectedText) {
emit RawFileSelected(std::make_shared<RawFile>(rawFile), fileStem);
return;
}
}
} }
} }
@ -778,7 +819,7 @@ void XTreeWidget::AddIWIFile(std::shared_ptr<IWIFile> aIWIFile) {
} }
XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this); XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this);
iwiItem->setIcon(0, QIcon(":/icons/icons/Icon_IWIFile.png")); iwiItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_IMAGE));
iwiItem->setText(0, iwiFileName); iwiItem->setText(0, iwiFileName);
mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile; mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile;
} }
@ -794,7 +835,7 @@ void XTreeWidget::AddDDSFile(std::shared_ptr<DDSFile> aDDSFile) {
} }
XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this); XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this);
ddsItem->setIcon(0, QIcon(":/icons/icons/Icon_DDSFile.png")); ddsItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_IMAGE));
ddsItem->setText(0, ddsFileName); ddsItem->setText(0, ddsFileName);
mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile; mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile;
} }

View File

@ -8,8 +8,10 @@
#include "fastfile.h" #include "fastfile.h"
#include "xtreewidgetitem.h" #include "xtreewidgetitem.h"
#include "zonefile.h" #include "zonefile.h"
#include "utils.h"
#include <QTreeWidget> #include <QTreeWidget>
#include <QFileDialog>
class XTreeWidget : public QTreeWidget class XTreeWidget : public QTreeWidget
{ {

View File

@ -1,15 +1,29 @@
#include "xtreewidgetitem.h" #include "xtreewidgetitem.h"
XTreeWidgetItem::XTreeWidgetItem(QTreeWidget *parent, bool group) XTreeWidgetItem::XTreeWidgetItem(QTreeWidget *parent, bool group)
: QTreeWidgetItem(parent), isGroup(group) { : QTreeWidgetItem(parent)
, isGroup(group)
, mCategory(CATEGORY_NONE) {
} }
XTreeWidgetItem::XTreeWidgetItem(QTreeWidgetItem *parent, bool group) XTreeWidgetItem::XTreeWidgetItem(QTreeWidgetItem *parent, bool group)
: QTreeWidgetItem(parent), isGroup(group) { : QTreeWidgetItem(parent)
, isGroup(group)
, mCategory(CATEGORY_NONE) {
} }
void XTreeWidgetItem::SetCategory(TREE_CATEGORY category)
{
mCategory = category;
}
TREE_CATEGORY XTreeWidgetItem::GetCategory()
{
return mCategory;
}
bool XTreeWidgetItem::operator<(const QTreeWidgetItem &other) const { bool XTreeWidgetItem::operator<(const QTreeWidgetItem &other) const {
// Attempt to cast the other item to our custom type. // Attempt to cast the other item to our custom type.
const XTreeWidgetItem* otherItem = dynamic_cast<const XTreeWidgetItem*>(&other); const XTreeWidgetItem* otherItem = dynamic_cast<const XTreeWidgetItem*>(&other);

View File

@ -4,6 +4,12 @@
#include <QTreeWidget> #include <QTreeWidget>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
enum TREE_CATEGORY {
CATEGORY_NONE = 0x00,
CATEGORY_FILE = 0x01,
CATEGORY_TYPE = 0x02
};
// Custom item class // Custom item class
class XTreeWidgetItem : public QTreeWidgetItem class XTreeWidgetItem : public QTreeWidgetItem
{ {
@ -15,9 +21,15 @@ public:
XTreeWidgetItem(QTreeWidget *parent, bool group = false); XTreeWidgetItem(QTreeWidget *parent, bool group = false);
XTreeWidgetItem(QTreeWidgetItem *parent, bool group = false); XTreeWidgetItem(QTreeWidgetItem *parent, bool group = false);
void SetCategory(TREE_CATEGORY category);
TREE_CATEGORY GetCategory();
// Override the less-than operator to customize sorting. // Override the less-than operator to customize sorting.
bool operator<(const QTreeWidgetItem &other) const override; bool operator<(const QTreeWidgetItem &other) const override;
XTreeWidgetItem &operator =(const XTreeWidgetItem &other); XTreeWidgetItem &operator =(const XTreeWidgetItem &other);
private:
TREE_CATEGORY mCategory;
}; };

View File

@ -1,34 +1,86 @@
#include "zonefileviewer.h" #include "zonefileviewer.h"
#include "ui_zonefileviewer.h" #include "ui_zonefileviewer.h"
#include "statusbarmanager.h"
ZoneFileViewer::ZoneFileViewer(QWidget *parent) ZoneFileViewer::ZoneFileViewer(QWidget *parent)
: QWidget(parent) : QWidget(parent)
, ui(new Ui::ZoneFileViewer) { , ui(new Ui::ZoneFileViewer) {
ui->setupUi(this); ui->setupUi(this);
aZoneFile = nullptr; mZoneFile = nullptr;
ui->tableWidget_RecordCounts->setColumnCount(4); ui->tableWidget_RecordCounts->setColumnCount(3);
ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" }); ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count" });
ui->tableWidget_RecordCounts->horizontalHeader()->setStretchLastSection(true); ui->tableWidget_RecordCounts->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget_RecordOrder->setColumnCount(4); ui->tableWidget_RecordOrder->setColumnCount(3);
ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" }); ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count" });
ui->tableWidget_RecordOrder->horizontalHeader()->setStretchLastSection(true); ui->tableWidget_RecordOrder->horizontalHeader()->setStretchLastSection(true);
connect(ui->lineEdit_TagSearch, &QLineEdit::textChanged, this, &ZoneFileViewer::SortTags);
connect(ui->tableWidget_RecordCounts, &QTableWidget::itemSelectionChanged, this, &ZoneFileViewer::HighlightRecordInOrder);
connect(ui->listWidget_Tags, &QListWidget::currentTextChanged, this, [this](const QString &aCurrentText) {
StatusBarManager::instance().updateStatus(QString("Selected tag '%1' with index %2").arg(aCurrentText).arg(mZoneFile->GetTags().indexOf(aCurrentText)));
});
} }
ZoneFileViewer::~ZoneFileViewer() { ZoneFileViewer::~ZoneFileViewer() {
delete ui; delete ui;
} }
void ZoneFileViewer::HighlightRecordInOrder() {
ui->tableWidget_RecordOrder->clearSelection();
foreach (auto selectedItem, ui->tableWidget_RecordCounts->selectedItems()) {
int selectedRow = selectedItem->row();
const QString assetId = ui->tableWidget_RecordCounts->item(selectedRow, 0)->text();
for (int i = 0; i < ui->tableWidget_RecordOrder->rowCount(); i++) {
const QString testAssetId = ui->tableWidget_RecordOrder->item(i, 0)->text();
if (testAssetId != assetId) { continue; }
ui->tableWidget_RecordOrder->selectRow(i);
ui->tableWidget_RecordOrder->item(i, 0)->setSelected(true);
ui->tableWidget_RecordOrder->item(i, 1)->setSelected(true);
ui->tableWidget_RecordOrder->item(i, 2)->setSelected(true);
ui->tableWidget_RecordOrder->item(i, 3)->setSelected(true);
}
}
}
void ZoneFileViewer::SortTags(const QString &aSearchText) {
ui->listWidget_Tags->clear();
const QStringList tags = mZoneFile->GetTags();
if (aSearchText.isEmpty()) {
ui->listWidget_Tags->addItems(tags);
return;
}
QStringList sortedTags;
foreach (const QString tag, tags) {
if (tag.contains(aSearchText)) {
sortedTags << tag;
}
}
StatusBarManager::instance().updateStatus(QString("Found %1 tags.").arg(sortedTags.size()));
ui->listWidget_Tags->addItems(sortedTags);
}
void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) { void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
mZoneFile = aZoneFile;
ui->tableWidget_RecordCounts->clearContents(); ui->tableWidget_RecordCounts->clearContents();
ui->tableWidget_RecordOrder->clearContents(); ui->tableWidget_RecordOrder->clearContents();
ui->listWidget_Tags->clear(); ui->listWidget_Tags->clear();
const QStringList tags = aZoneFile->GetTags(); const QStringList tags = mZoneFile->GetTags();
ui->listWidget_Tags->addItems(tags); ui->listWidget_Tags->addItems(tags);
ui->label_Title->setText(aZoneFile->GetStem() + ".zone"); ui->label_Title->setText(mZoneFile->GetBaseStem() + ".zone");
ui->groupBox_Tags->setTitle(QString("Tags (%1)").arg(tags.size()));
if (tags.isEmpty()) { if (tags.isEmpty()) {
ui->groupBox_Tags->hide(); ui->groupBox_Tags->hide();
@ -36,88 +88,67 @@ void ZoneFileViewer::SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile) {
ui->groupBox_Tags->show(); ui->groupBox_Tags->show();
} }
QString lastAsset = "";
QString lastRecord = "";
QIcon assetIcon;
int consecutiveCount = 1;
int consecutiveIndex = 0;
const QStringList records = aZoneFile->GetRecords();
QMap<QString, int> recordCounts = QMap<QString, int>(); QMap<QString, int> recordCounts = QMap<QString, int>();
for (const QString &record : records) { QVector<QPair<QString, int>> assetOccurances = QVector<QPair<QString, int>>();
lastRecord = record; for (const QString &record : mZoneFile->GetRecords()) {
if (record == "ffffffff") { break; }
if (!recordCounts.contains(record)) { if (!recordCounts.contains(record)) {
recordCounts[record] = 0; recordCounts[record] = 0;
} }
recordCounts[record]++; recordCounts[record]++;
QString assetType = aZoneFile->AssetTypeToString(record); if (!assetOccurances.isEmpty() && assetOccurances.last().first == record) {
assetOccurances.last().second++;
continue;
}
QPair<QString, int> assetOccurance(record, 1);
assetOccurances << assetOccurance;
}
ui->tableWidget_RecordOrder->setRowCount(assetOccurances.size());
int assetIndex = 0;
foreach (auto assetOccurance, assetOccurances) {
const QString record = assetOccurance.first;
AssetType assetType = mZoneFile->AssetStrToEnum(record);
int assetCount = assetOccurance.second;
QIcon assetIcon = mZoneFile->AssetTypeToIcon(assetType);
if (assetIcon.isNull()) { if (assetIcon.isNull()) {
qDebug() << "Icon is null for record: " << record; qDebug() << "Icon is null for record: " << record;
} }
if (lastAsset.isEmpty()) { QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper());
lastAsset = assetType; QTableWidgetItem *recordStrItem = new QTableWidgetItem(mZoneFile->AssetEnumToStr(assetType));
lastRecord = record; QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(assetCount));
} else if (lastAsset == assetType) { recordItem->setIcon(assetIcon);
consecutiveCount++;
} else {
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper()); ui->tableWidget_RecordOrder->setItem(assetIndex, 0, recordItem);
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset); ui->tableWidget_RecordOrder->setItem(assetIndex, 1, recordStrItem);
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount)); ui->tableWidget_RecordOrder->setItem(assetIndex, 2, recordCountItem);
QTableWidgetItem *recordIconItem = new QTableWidgetItem();
assetIcon = aZoneFile->AssetStrToIcon(lastAsset);
recordIconItem->setIcon(assetIcon);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem); assetIndex++;
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem);
consecutiveCount = 1;
consecutiveIndex++;
lastAsset = assetType;
lastRecord = record;
}
} }
ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1);
QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper());
QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset);
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount));
QTableWidgetItem *recordIconItem = new QTableWidgetItem();
assetIcon = aZoneFile->AssetStrToIcon(lastAsset);
recordIconItem->setIcon(assetIcon);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem);
ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem);
int recordIndex = 0; int recordIndex = 0;
for (const QString &record : recordCounts.keys()) { for (const QString &record : recordCounts.keys()) {
int recordCount = recordCounts[record]; int recordCount = recordCounts[record];
QString assetType = aZoneFile->AssetTypeToString(record); AssetType assetType = mZoneFile->AssetStrToEnum(record);
assetIcon = aZoneFile->AssetStrToIcon(assetType); QIcon assetIcon = mZoneFile->AssetTypeToIcon(assetType);
if (assetIcon.isNull()) { if (assetIcon.isNull()) {
qDebug() << "Icon is null for record: " << record; qDebug() << "Icon is null for record: " << record;
} }
ui->tableWidget_RecordCounts->setRowCount(recordIndex + 1); ui->tableWidget_RecordCounts->setRowCount(recordIndex + 1);
QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(assetType);
QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper()); QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper());
QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(mZoneFile->AssetEnumToStr(assetType));
QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(recordCount)); QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(recordCount));
QTableWidgetItem *recordIconItem = new QTableWidgetItem(); recordItem->setIcon(assetIcon);
recordIconItem->setIcon(assetIcon);
ui->tableWidget_RecordCounts->setItem(recordIndex, 0, recordItem); ui->tableWidget_RecordCounts->setItem(recordIndex, 0, recordItem);
ui->tableWidget_RecordCounts->setItem(recordIndex, 1, recordCountStrItem); ui->tableWidget_RecordCounts->setItem(recordIndex, 1, recordCountStrItem);
ui->tableWidget_RecordCounts->setItem(recordIndex, 2, recordCountItem); ui->tableWidget_RecordCounts->setItem(recordIndex, 2, recordCountItem);
ui->tableWidget_RecordCounts->setItem(recordIndex, 3, recordIconItem);
recordIndex++; recordIndex++;
} }

View File

@ -19,9 +19,15 @@ public:
~ZoneFileViewer(); ~ZoneFileViewer();
void SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile); void SetZoneFile(std::shared_ptr<ZoneFile> aZoneFile);
public slots:
void SortTags(const QString &aSearchText);
void HighlightRecordInOrder();
private: private:
Ui::ZoneFileViewer *ui; Ui::ZoneFileViewer *ui;
std::shared_ptr<ZoneFile> aZoneFile; std::shared_ptr<ZoneFile> mZoneFile;
}; };
#endif // ZONEFILEVIEWER_H #endif // ZONEFILEVIEWER_H

View File

@ -61,7 +61,14 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QListWidget" name="listWidget_Tags"/> <widget class="QListWidget" name="listWidget_Tags">
<property name="editTriggers">
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -73,7 +80,20 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QTableWidget" name="tableWidget_RecordCounts"/> <widget class="QTableWidget" name="tableWidget_RecordCounts">
<property name="editTriggers">
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SelectionMode::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectionBehavior::SelectRows</enum>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -85,7 +105,17 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<widget class="QTableWidget" name="tableWidget_RecordOrder"/> <widget class="QTableWidget" name="tableWidget_RecordOrder">
<property name="editTriggers">
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SelectionMode::NoSelection</enum>
</property>
</widget>
</item> </item>
</layout> </layout>
</widget> </widget>

396
bink.h
View File

@ -1,396 +0,0 @@
/* xoreos - A reimplementation of BioWare's Aurora engine
*
* xoreos is the legal property of its developers, whose names
* can be found in the AUTHORS file distributed with this source
* distribution.
*
* xoreos is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* xoreos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with xoreos. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file
* Decoding RAD Game Tools' Bink videos.
*/
/* Based on the Bink implementation in FFmpeg (<https://ffmpeg.org/)>,
* which is released under the terms of version 2 or later of the GNU
* Lesser General Public License.
*
* The original copyright notes in the files
* - libavformat/bink.c
* - libavcodec/bink.c
* - libavcodec/binkdata.h
* - libavcodec/binkdsp.c
* - libavcodec/binkdsp.h
* - libavcodec/binkaudio.c
* read as follows:
*
* Bink demuxer
* Copyright (c) 2008-2010 Peter Ross (pross@xvid.org)
* Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
*
* Bink video decoder
* Copyright (c) 2009 Konstantin Shishkov
* Copyright (C) 2011 Peter Ross <pross@xvid.org>
*
* Bink video decoder
* Copyright (C) 2009 Konstantin Shishkov
*
* Bink DSP routines
* Copyright (c) 2009 Konstantin Shishkov
*
* Bink Audio decoder
* Copyright (c) 2007-2011 Peter Ross (pross@xvid.org)
* Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu)
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef VIDEO_BINK_H
#define VIDEO_BINK_H
#include <vector>
#include <memory>
#include "src/common/types.h"
#include "src/common/rational.h"
#include "src/video/decoder.h"
namespace Common {
class SeekableReadStream;
class BitStream;
class Huffman;
class RDFT;
class DCT;
}
namespace Sound {
class PacketizedAudioStream;
}
namespace Video {
/** A decoder for RAD Game Tools' Bink videos. */
class Bink : public VideoDecoder {
public:
Bink(Common::SeekableReadStream *bink);
~Bink();
protected:
void decodeNextTrackFrame(VideoTrack &track);
void checkAudioBuffer(AudioTrack &track, const Common::Timestamp &endTime);
private:
static const int kAudioChannelsMax = 2;
static const int kAudioBlockSizeMax = (kAudioChannelsMax << 11);
enum AudioCodec {
kAudioCodecDCT,
kAudioCodecRDFT
};
/** An audio track. */
struct AudioInfo {
uint16_t flags;
uint32_t sampleRate;
uint8_t channels;
uint32_t outSampleRate;
uint8_t outChannels;
AudioCodec codec;
bool first;
uint32_t frameLen;
uint32_t overlapLen;
uint32_t blockSize;
uint32_t bandCount;
uint32_t *bands;
float root;
float coeffs[16 * kAudioBlockSizeMax];
int16_t prevCoeffs[kAudioBlockSizeMax];
float *coeffsPtr[kAudioChannelsMax];
Common::RDFT *rdft;
Common::DCT *dct;
AudioInfo();
AudioInfo(const AudioInfo &audioInfo) = default;
~AudioInfo();
};
/** A video frame. */
struct VideoFrame {
bool keyFrame;
uint32_t offset;
uint32_t size;
Common::BitStream *bits;
VideoFrame();
VideoFrame(const VideoFrame &videoFrame) = default;
~VideoFrame();
};
std::unique_ptr<Common::SeekableReadStream> _bink;
std::vector<AudioInfo> _audioTracks; ///< All audio tracks.
std::vector<VideoFrame> _frames; ///< All video frames.
uint32_t _audioTrack; ///< Audio track to use.
/** Load a Bink file. */
void load();
class BinkVideoTrack : public FixedRateVideoTrack {
public:
BinkVideoTrack(uint32_t width, uint32_t height, uint32_t frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32_t id);
uint32_t getWidth() const { return _width; }
uint32_t getHeight() const { return _height; }
int getCurFrame() const { return _curFrame; }
int getFrameCount() const { return _frameCount; }
/** Decode a video packet. */
void decodePacket(Graphics::Surface &surface, VideoFrame &frame);
protected:
Common::Rational getFrameRate() const { return _frameRate; }
private:
/** A decoder state. */
struct DecodeContext {
VideoFrame *video;
uint32_t planeIdx;
uint32_t blockX;
uint32_t blockY;
byte *dest;
byte *prev;
byte *destStart, *destEnd;
byte *prevStart, *prevEnd;
uint32_t pitch;
int coordMap[64];
int coordScaledMap1[64];
int coordScaledMap2[64];
int coordScaledMap3[64];
int coordScaledMap4[64];
};
/** IDs for different data types used in Bink video codec. */
enum Source {
kSourceBlockTypes = 0, ///< 8x8 block types.
kSourceSubBlockTypes , ///< 16x16 block types (a subset of 8x8 block types).
kSourceColors , ///< Pixel values used for different block types.
kSourcePattern , ///< 8-bit values for 2-color pattern fill.
kSourceXOff , ///< X components of motion value.
kSourceYOff , ///< Y components of motion value.
kSourceIntraDC , ///< DC values for intrablocks with DCT.
kSourceInterDC , ///< DC values for interblocks with DCT.
kSourceRun , ///< Run lengths for special fill block.
kSourceMAX
};
/** Bink video block types. */
enum BlockType {
kBlockSkip = 0, ///< Skipped block.
kBlockScaled , ///< Block has size 16x16.
kBlockMotion , ///< Block is copied from previous frame with some offset.
kBlockRun , ///< Block is composed from runs of colors with custom scan order.
kBlockResidue , ///< Motion block with some difference added.
kBlockIntra , ///< Intra DCT block.
kBlockFill , ///< Block is filled with single color.
kBlockInter , ///< Motion block with DCT applied to the difference.
kBlockPattern , ///< Block is filled with two colors following custom pattern.
kBlockRaw ///< Uncoded 8x8 block.
};
/** Data structure for decoding and translating Huffman'd data. */
struct Huffman {
int index; ///< Index of the Huffman codebook to use.
byte symbols[16]; ///< Huffman symbol => Bink symbol translation list.
Huffman();
};
/** Data structure used for decoding a single Bink data type. */
struct Bundle {
int countLengths[2]; ///< Lengths of number of entries to decode (in bits).
int countLength; ///< Length of number of entries to decode (in bits) for the current plane.
Huffman huffman; ///< Huffman codebook.
std::unique_ptr<byte[]> data; ///< Buffer for decoded symbols.
byte *dataEnd; ///< Pointer to the data end end.
byte *curDec; ///< Pointer to the data that wasn't yet decoded.
byte *curPtr; ///< Pointer to the data that wasn't yet read.
Bundle();
};
uint32_t _width;
uint32_t _height;
int _curFrame; ///< Current Frame.
int _frameCount;
Common::Rational _frameRate; ///< The frame rate of the video.
bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV?
bool _hasAlpha; ///< Do video frames have alpha?
uint32_t _id; ///< The BIK FourCC.
Bundle _bundles[kSourceMAX]; ///< Bundles for decoding all data types.
std::unique_ptr<Common::Huffman> _huffman[16]; ///< The 16 Huffman codebooks used in Bink decoding.
/** Huffman codebooks to use for decoding high nibbles in color data types. */
Huffman _colHighHuffman[16];
/** Value of the last decoded high nibble in color data types. */
int _colLastVal;
std::unique_ptr<byte[]> _curPlanes[4]; ///< The 4 color planes, YUVA, current frame.
std::unique_ptr<byte[]> _oldPlanes[4]; ///< The 4 color planes, YUVA, last frame.
/** Initialize the bundles. */
void initBundles();
/** Initialize the Huffman decoders. */
void initHuffman();
/** Decode a video packet. */
void videoPacket(VideoFrame &video);
/** Decode a plane. */
void decodePlane(VideoFrame &video, int planeIdx, bool isChroma);
/** Read/Initialize a bundle for decoding a plane. */
void readBundle(VideoFrame &video, Source source);
/** Read the symbols for a Huffman code. */
void readHuffman(VideoFrame &video, Huffman &huffman);
/** Merge two Huffman symbol lists. */
void mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size);
/** Read and translate a symbol out of a Huffman code. */
byte getHuffmanSymbol(VideoFrame &video, Huffman &huffman);
/** Get a direct value out of a bundle. */
int32_t getBundleValue(Source source);
/** Read a count value out of a bundle. */
uint32_t readBundleCount(VideoFrame &video, Bundle &bundle);
// Handle the block types
void blockSkip (DecodeContext &ctx);
void blockScaledSkip (DecodeContext &ctx);
void blockScaledRun (DecodeContext &ctx);
void blockScaledIntra (DecodeContext &ctx);
void blockScaledFill (DecodeContext &ctx);
void blockScaledPattern(DecodeContext &ctx);
void blockScaledRaw (DecodeContext &ctx);
void blockScaled (DecodeContext &ctx);
void blockMotion (DecodeContext &ctx);
void blockRun (DecodeContext &ctx);
void blockResidue (DecodeContext &ctx);
void blockIntra (DecodeContext &ctx);
void blockFill (DecodeContext &ctx);
void blockInter (DecodeContext &ctx);
void blockPattern (DecodeContext &ctx);
void blockRaw (DecodeContext &ctx);
// Read the bundles
void readRuns (VideoFrame &video, Bundle &bundle);
void readMotionValues(VideoFrame &video, Bundle &bundle);
void readBlockTypes (VideoFrame &video, Bundle &bundle);
void readPatterns (VideoFrame &video, Bundle &bundle);
void readColors (VideoFrame &video, Bundle &bundle);
void readDCS (VideoFrame &video, Bundle &bundle, int startBits, bool hasSign);
void readDCTCoeffs (VideoFrame &video, int16_t *block, bool isIntra);
void readResidue (VideoFrame &video, int16_t *block, int masksCount);
// Bink video IDCT
void IDCT(int16_t *block);
void IDCTPut(DecodeContext &ctx, int16_t *block);
void IDCTAdd(DecodeContext &ctx, int16_t *block);
};
class BinkAudioTrack : public AudioTrack {
public:
BinkAudioTrack(size_t index, AudioInfo &audio);
~BinkAudioTrack();
bool canBufferData() const;
/** Decode audio data up to endTime. */
void decodeAudio(Common::SeekableReadStream& bink, const std::vector<VideoFrame>& frames, const std::vector<AudioInfo>& audioTracks, const Common::Timestamp& endTime);
protected:
Sound::AudioStream *getAudioStream() const;
private:
size_t _index;
AudioInfo &_info;
Sound::PacketizedAudioStream *_audioStream;
uint32_t _curFrame;
Common::Timestamp _audioBuffered;
float getFloat(Common::BitStream &bits);
/** Decode an audio block. */
void audioBlock(Common::BitStream &bits, int16_t *out);
/** Decode a DCT'd audio block. */
void audioBlockDCT(Common::BitStream &bits);
/** Decode a RDFT'd audio block. */
void audioBlockRDFT(Common::BitStream &bits);
void readAudioCoeffs(Common::BitStream &bits, float *coeffs);
static void floatToInt16Interleave(int16_t *dst, const float **src, uint32_t length, uint8_t channels);
};
void initAudioTrack(AudioInfo &audio);
};
} // End of namespace Video
#endif // VIDEO_BINK_H

View File

@ -1,26 +1,4 @@
<RCC> <RCC>
<qresource prefix="/obj">
<file>obj/defaultactor_LOD0.XMODEL_BIN</file>
<file>obj/defaultactor_LOD0.XMODEL_EXPORT</file>
<file>obj/defaultactor_LOD0.bin</file>
<file>obj/defaultactor_LOD0.cast</file>
<file>obj/defaultactor_LOD0.gltf</file>
<file>obj/defaultactor_LOD0.ma</file>
<file>obj/defaultactor_LOD0.mesh.ascii</file>
<file>obj/defaultactor_LOD0.obj</file>
<file>obj/defaultactor_LOD0.semodel</file>
<file>obj/defaultactor_LOD0.smd</file>
<file>obj/defaultactor_LOD0_BIND.mel</file>
<file>obj/defaultactor_LOD0_cosmetics.mel</file>
<file>obj/diffusemap.png</file>
<file>obj/mtl_body_default_character.mtl</file>
<file>obj/mtl_body_default_character_images.txt</file>
<file>obj/normalmap.png</file>
</qresource>
<qresource prefix="/d3dbsp">
<file>d3dbsp/asset_viewer.d3dbsp</file>
<file>d3dbsp/barebones.d3dbsp</file>
</qresource>
<qresource prefix="/images"> <qresource prefix="/images">
<file>images/XPlor.png</file> <file>images/XPlor.png</file>
<file>images/copy.svg</file> <file>images/copy.svg</file>
@ -34,28 +12,6 @@
<file>images/save.svg</file> <file>images/save.svg</file>
</qresource> </qresource>
<qresource prefix="/icons"> <qresource prefix="/icons">
<file>icons/Icon_COD4.png</file>
<file>icons/Icon_COD5.png</file>
<file>icons/Icon_COD6.png</file>
<file>icons/Icon_COD7.png</file>
<file>icons/Icon_COD8.png</file>
<file>icons/Icon_COD9.png</file>
<file>icons/Icon_DDSFile.png</file>
<file>icons/Icon_FastFile.png</file>
<file>icons/Icon_IWIFile.png</file>
<file>icons/Icon_PC.png</file>
<file>icons/Icon_Playstation.png</file>
<file>icons/Icon_Xbox.png</file>
<file>icons/Icon_ZoneFile.png</file>
<file>icons/Icon_GSCFile.png</file>
<file>icons/Icon_StringFile.png</file>
<file>icons/Icon_TechSetFile.png</file>
<file>icons/Icon_WAVFile.png</file>
<file>icons/Icon_MenuFile.png</file>
<file>icons/Icon_Image.png</file>
<file>icons/Icon_Model.png</file>
<file>icons/Icon_StringTable.png</file>
<file>icons/Icon_Sound.png</file>
<file>icons/Icon_Pause.png</file> <file>icons/Icon_Pause.png</file>
<file>icons/Icon_Play.png</file> <file>icons/Icon_Play.png</file>
<file>icons/Icon_SkipBack.png</file> <file>icons/Icon_SkipBack.png</file>
@ -71,21 +27,5 @@
<file>icons/Icon_Paste.png</file> <file>icons/Icon_Paste.png</file>
<file>icons/Icon_Save.png</file> <file>icons/Icon_Save.png</file>
<file>icons/Icon_OpenFile.png</file> <file>icons/Icon_OpenFile.png</file>
<file>icons/Icon_COD2.png</file>
<file>icons/Icon_Material.png</file>
<file>icons/Icon_Animation.png</file>
<file>icons/Icon_BSP.png</file>
<file>icons/Icon_ColMapSp.png</file>
<file>icons/Icon_Effect.png</file>
<file>icons/Icon_GameMapSp.png</file>
<file>icons/Icon_Font.png</file>
<file>icons/Icon_FXMap.png</file>
<file>icons/Icon_LightDef.png</file>
<file>icons/Icon_Weapon.png</file>
<file>icons/Icon_RawFile.png</file>
<file>icons/Icon_Destructible.png</file>
<file>icons/Icon_PhysPreset.png</file>
<file>icons/Icon_Wii.png</file>
<file>icons/Icon_WiiU.png</file>
</qresource> </qresource>
</RCC> </RCC>

BIN
data/icons/Icon.psd Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 855 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -234,7 +234,7 @@
"WEIGHTS_0": 6 "WEIGHTS_0": 6
}, },
"indices": 1, "indices": 1,
"material": 0, ASSET_MATERIAL: 0,
"mode": 4 "mode": 4
} }
] ]
@ -250,7 +250,7 @@
"WEIGHTS_0": 12 "WEIGHTS_0": 12
}, },
"indices": 7, "indices": 7,
"material": 0, ASSET_MATERIAL: 0,
"mode": 4 "mode": 4
} }
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 B

670
enums.h
View File

@ -1,670 +0,0 @@
#ifndef ENUMS_H
#define ENUMS_H
#include "qtypes.h"
enum LUMP_TYPE
{
LUMP_MATERIALS = 0x0,
LUMP_LIGHTBYTES = 0x1,
LUMP_LIGHTGRIDENTRIES = 0x2,
LUMP_LIGHTGRIDCOLORS = 0x3,
LUMP_PLANES = 0x4,
LUMP_BRUSHSIDES = 0x5,
LUMP_BRUSHSIDEEDGECOUNTS = 0x6,
LUMP_BRUSHEDGES = 0x7,
LUMP_BRUSHES = 0x8,
LUMP_TRIANGLES = 0x9,
LUMP_DRAWVERTS = 0xA,
LUMP_DRAWINDICES = 0xB,
LUMP_CULLGROUPS = 0xC,
LUMP_CULLGROUPINDICES = 0xD,
LUMP_OBSOLETE_1 = 0xE,
LUMP_OBSOLETE_2 = 0xF,
LUMP_OBSOLETE_3 = 0x10,
LUMP_OBSOLETE_4 = 0x11,
LUMP_OBSOLETE_5 = 0x12,
LUMP_PORTALVERTS = 0x13,
LUMP_OBSOLETE_6 = 0x14,
LUMP_UINDS = 0x15,
LUMP_BRUSHVERTSCOUNTS = 0x16,
LUMP_BRUSHVERTS = 0x17,
LUMP_AABBTREES = 0x18,
LUMP_CELLS = 0x19,
LUMP_PORTALS = 0x1A,
LUMP_NODES = 0x1B,
LUMP_LEAFS = 0x1C,
LUMP_LEAFBRUSHES = 0x1D,
LUMP_LEAFSURFACES = 0x1E,
LUMP_COLLISIONVERTS = 0x1F,
LUMP_COLLISIONTRIS = 0x20,
LUMP_COLLISIONEDGEWALKABLE = 0x21,
LUMP_COLLISIONBORDERS = 0x22,
LUMP_COLLISIONPARTITIONS = 0x23,
LUMP_COLLISIONAABBS = 0x24,
LUMP_MODELS = 0x25,
LUMP_VISIBILITY = 0x26,
LUMP_ENTITIES = 0x27,
LUMP_PATHCONNECTIONS = 0x28,
LUMP_REFLECTION_PROBES = 0x29,
LUMP_VERTEX_LAYER_DATA = 0x2A,
LUMP_PRIMARY_LIGHTS = 0x2B,
LUMP_LIGHTGRIDHEADER = 0x2C,
LUMP_LIGHTGRIDROWS = 0x2D,
LUMP_OBSOLETE_10 = 0x2E,
//Obsolete in BO1/////////////////
LUMP_UNLAYERED_TRIANGLES = 0x2F,
LUMP_UNLAYERED_DRAWVERTS = 0x30,
LUMP_UNLAYERED_DRAWINDICES = 0x31,
LUMP_UNLAYERED_CULLGROUPS = 0x32,
LUMP_UNLAYERED_AABBTREES = 0x33,
//////////////////////////////////
LUMP_WATERHEADER = 0x34,
LUMP_WATERCELLS = 0x35,
LUMP_WATERCELLDATA = 0x36,
LUMP_BURNABLEHEADER = 0x37,
LUMP_BURNABLECELLS = 0x38,
LUMP_BURNABLECELLDATA = 0x39,
LUMP_SIMPLELIGHTMAPBYTES = 0x3A,
LUMP_LODCHAINS = 0x3B,
LUMP_LODINFOS = 0x3C,
LUMP_LODSURFACES = 0x3D,
LUMP_LIGHTREGIONS = 0x3E,
LUMP_LIGHTREGION_HULLS = 0x3F,
LUMP_LIGHTREGION_AXES = 0x40,
LUMP_WIILIGHTGRID = 0x41,
LUMP_LIGHTGRID2D_LIGHTS = 0x42,
LUMP_LIGHTGRID2D_INDICES = 0x43,
LUMP_LIGHTGRID2D_POINTS = 0x44,
LUMP_LIGHTGRID2D_CELLS = 0x45,
LUMP_LIGHT_CORONAS = 0x46,
//BO Specific/////////////////////////
LUMP_SHADOWMAP_VOLUMES = 0x47,
LUMP_SHADOWMAP_VOLUME_PLANES = 0x48,
LUMP_EXPOSURE_VOLUMES = 0x49,
LUMP_EXPOSURE_VOLUME_PLANES = 0x4A,
LUMP_OCCLUDERS = 0x4B,
LUMP_OUTDOORBOUNDS = 0x4C,
LUMP_HERO_ONLY_LIGHTS = 0x4D,
//////////////////////////////////////
INFO_LUMP_TYPE_COUNT
};
enum BSPVERSION_TYPE
{
BSPVERSION_COD_WAW = 31,
BSPVERSION_COD_BO = 45
};
enum MENU_ITEM_TYPE {
ITEM_TYPE_TEXT = 0, // simple text
ITEM_TYPE_BUTTON = 1, // button, basically text with a border
ITEM_TYPE_RADIOBUTTON = 2, // toggle button, may be grouped
ITEM_TYPE_CHECKBOX = 3, // check box
ITEM_TYPE_EDITFIELD = 4, // editable text, associated with a dvar
ITEM_TYPE_COMBO = 5, // drop down list
ITEM_TYPE_LISTBOX = 6, // scrollable list
ITEM_TYPE_MODEL = 7, // model
ITEM_TYPE_OWNERDRAW = 8, // owner draw, name specs what it is
ITEM_TYPE_NUMERICFIELD = 9, // editable text, associated with a dvar
ITEM_TYPE_SLIDER = 10, // mouse speed, volume, etc.
ITEM_TYPE_YESNO = 11, // yes no dvar setting
ITEM_TYPE_MULTI = 12, // multiple list setting, enumerated
ITEM_TYPE_DVARENUM = 13, // multiple list setting, enumerated from a dvar
ITEM_TYPE_BIND = 14, // bind
ITEM_TYPE_MENUMODEL = 15, // special menu model
ITEM_TYPE_VALIDFILEFIELD = 16, // text must be valid for use in a dos filename
ITEM_TYPE_DECIMALFIELD = 17, // editable text, associated with a dvar, which allows decimal input
ITEM_TYPE_UPREDITFIELD = 18, // editable text, associated with a dvar
ITEM_TYPE_GAME_MESSAGE_WINDOW = 19, // game message window
ITEM_TYPE_SCALEFORM = 20, // Flash movie for Scaleform GFx
ITEM_TYPE_BIND2 = 21, // bind2
};
enum MENU_ITEM_H_ALIGN {
ITEM_ALIGN_LEFT = 0, // aligns left of text to left of containing rectangle
ITEM_ALIGN_CENTER = 1, // aligns center of text to center of containing rectangle
ITEM_ALIGN_RIGHT = 2, // aligns right of text to right of containing rectangle
ITEM_ALIGN_X_MASK = 3,
};
enum MENU_ITEM_V_ALIGN {
ITEM_ALIGN_LEGACY = 0, // aligns bottom of text to top of containing rectangle
ITEM_ALIGN_TOP = 4, // aligns top of text to top of containing rectangle
ITEM_ALIGN_MIDDLE = 8, // aligns middle of text to middle of containing rectangle
ITEM_ALIGN_BOTTOM = 12, // aligns bottom of text to bottom of containing rectangle
ITEM_ALIGN_Y_MASK = 12,
};
enum MENU_ITEM_ALIGN {
ITEM_ALIGN_LEGACY_LEFT = 0,
ITEM_ALIGN_LEGACY_CENTER = 1,
ITEM_ALIGN_LEGACY_RIGHT = 2,
ITEM_ALIGN_TOP_LEFT = 4,
ITEM_ALIGN_TOP_CENTER = 5,
ITEM_ALIGN_TOP_RIGHT = 6,
ITEM_ALIGN_MIDDLE_LEFT = 8,
ITEM_ALIGN_MIDDLE_CENTER = 9,
ITEM_ALIGN_MIDDLE_RIGHT = 10,
ITEM_ALIGN_BOTTOM_LEFT = 12,
ITEM_ALIGN_BOTTOM_CENTER = 13,
ITEM_ALIGN_BOTTOM_RIGHT = 14
};
enum MENU_ITEM_TEXTSTYLE {
ITEM_TEXTSTYLE_NORMAL = 0, // normal text
ITEM_TEXTSTYLE_BLINK = 1, // fast blinking
ITEM_TEXTSTYLE_SHADOWED = 3, // drop shadow ( need a color for this )
ITEM_TEXTSTYLE_SHADOWEDMORE = 6, // drop shadow ( need a color for this )
ITEM_TEXTSTYLE_MONOSPACE = 128
};
enum MENU_WINDOW_BORDER {
WINDOW_BORDER_NONE = 0, // no border
WINDOW_BORDER_FULL = 1, // full border based on border color ( single pixel )
WINDOW_BORDER_HORZ = 2, // horizontal borders only
WINDOW_BORDER_VERT = 3, // vertical borders only
WINDOW_BORDER_KCGRADIENT = 4, // horizontal border using the gradient bars
WINDOW_BORDER_RAISED = 5, // darken the bottom and right sides of the border
WINDOW_BORDER_SUNKEN = 6 // darken the top and left sides of the border
};
enum MENU_WINDOW_STYLE {
WINDOW_STYLE_EMPTY = 0, // no background
WINDOW_STYLE_FILLED = 1, // filled with background color
WINDOW_STYLE_GRADIENT = 2, // gradient bar based on background color
WINDOW_STYLE_SHADER = 3, // shader based on background color
WINDOW_STYLE_TEAMCOLOR = 4, // team color
WINDOW_STYLE_DVAR_SHADER = 5, // draws the shader specified by the dvar
WINDOW_STYLE_LOADBAR = 6, // shader based on background color
};
enum MENU_MODE {
MODE_BOTTOMUP_ALIGN_TOP = 0, // text appears on bottom of list and moves up to specified Y coordinate as old text fades out
MODE_BOTTOMUP_ALIGN_BOTTOM = 1, // text appears on bottom of list and moves away from specified Y coordinate as new text pushes it up
MODE_TOPDOWN_ALIGN_TOP = 2, // text appears on top of list and moves away from specified Y coordinate as new text pushes it down
MODE_TOPDOWN_ALIGN_BOTTOM = 3 // text appears on top of list and moves down to specified Y coordinate as old text fades out
};
enum MENU_BOOL {
MENU_TRUE = 1,
MENU_FALSE = 0
};
enum MENU_ORIENTATION {
HUD_VERTICAL = 0x00,
HUD_HORIZONTAL = 0x01
};
enum MENU_RANGETYPE {
RANGETYPE_ABSOLUTE = 0,
RANGETYPE_RELATIVE = 1
};
// list box element types
enum MENU_LIST_BOX {
LISTBOX_TEXT = 0x00,
LISTBOX_IMAGE = 0x01
};
// list feeders
enum MENU_FEEDERS {
FEEDER_HEADS = 0x00, // model heads
FEEDER_MAPS = 0x01, // text maps based on game type
FEEDER_SERVERS = 0x02, // servers
FEEDER_CLAN_MEMBERS = 0x03, // clan names
FEEDER_ALLMAPS = 0x04, // all maps available, in graphic format
FEEDER_REDTEAM_LIST = 0x05, // red team members
FEEDER_BLUETEAM_LIST = 0x06, // blue team members
FEEDER_PLAYER_LIST = 0x07, // players
FEEDER_TEAM_LIST = 0x08, // team members for team voting
FEEDER_MODS = 0x09, // team members for team voting
FEEDER_DEMOS = 0x0a, // team members for team voting
FEEDER_SCOREBOARD = 0x0b, // team members for team voting
FEEDER_Q3HEADS = 0x0c, // model heads
FEEDER_SERVERSTATUS = 0x0d, // server status
FEEDER_FINDPLAYER = 0x0e, // find player
FEEDER_CINEMATICS = 0x0f, // cinematics
FEEDER_SAVEGAMES = 0x10, // savegames
FEEDER_PICKSPAWN = 0x11, // pickspawn
FEEDER_LOBBY_MEMBERS = 0x12, // list of players in your party
FEEDER_LOBBY_MEMBERS_TALK = 0x13, // icon for whether they are speaking or not
FEEDER_MUTELIST = 0x14, // list of musted players
FEEDER_PLAYERSTALKING = 0x15, // list of players who are currently talking
FEEDER_SPLITSCREENPLAYERS = 0x16, // list of all players who are playing splitscreen
FEEDER_LOBBY_MEMBERS_READY = 0x17, // icon for whether they are ready or not
FEEDER_PLAYER_PROFILES = 0x18, // player profiles
FEEDER_PARTY_MEMBERS = 0x19, // list of players in your party
FEEDER_PARTY_MEMBERS_TALK = 0x1a, // icon for whether they are speaking or not
FEEDER_PARTY_MEMBERS_READY = 0x1b, // icon for whether they are ready or not
FEEDER_PLAYLISTS = 0x1c, // list of all playlists
FEEDER_GAMEMODES = 0x1d, // list of all game type modes, including any player custom modes
FEEDER_CATEGORIES = 0x1e, // list of all categories
FEEDER_LEADERBOARD = 0x1f, // list of rows for a leaderboard
FEEDER_MYTEAM_MEMBERS = 0x20, // list of marine team members
FEEDER_MYTEAM_MEMBERS_TALK = 0x21, // icon for whether they are speaking
FEEDER_ENEMY_MEMBERS = 0x22, // list of opfor team members
FEEDER_ENEMY_MEMBERS_TALK = 0x23, // icon for whether they are speaking
FEEDER_LOBBY_MEMBERS_STAT = 0x24, // last round stats for lobby members
FEEDER_MYTEAM_MEMBERS_STAT = 0x25, // last round stats for marine team members
FEEDER_ENEMY_MEMBERS_STAT = 0x26, // last round stats for opfor team members
FEEDER_ONLINEFRIENDS = 0x27, // list of your online friends
FEEDER_LOBBY_MEMBERS_RANK = 0x28, // rank icon
FEEDER_PARTY_MEMBERS_RANK = 0x29, // rank icon
FEEDER_ENEMY_MEMBERS_RANK = 0x2a, // rank icon
FEEDER_MYTEAM_MEMBERS_RANK = 0x2b, // rank icon
FEEDER_TESTMAPS = 0x2c, // department test maps
FEEDER_SYSTEMLINK_LOBBY_MEMBERS = 0x2d, // list of players in a system link lobby
FEEDER_LOBBY_MEMBERS_CONTROLLER = 0x2e, // icon for controller quadrant for splitscreen
FEEDER_PARTY_MEMBERS_CONTROLLER = 0x2f, // icon for controller quadrant for splitscreen
FEEDER_MYTEAM_MEMBERS_SQUAD = 0x30, // squad icon
FEEDER_ENEMY_MEMBERS_SQUAD = 0x31, // squad icon
FEEDER_INGAME_SQUAD_MEMBERS = 0x32, // Squad members displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_MEMBERS_FULL = 0x33, // Squad members' name, rank, talk, leader displayed in PC MP 'Pause' menu
FEEDER_INGAME_SQUAD_NAMES = 0x34, // Squad names displayed in MP 'Join Squad' menu
FEEDER_INGAME_SQUAD_NAMES2 = 0x35, // Squad names displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_NAMES_FULL = 0x36, // Squad names, lock, invite displayed in PC MP 'Pause' menu
FEEDER_CUSTOM_GAMETYPES = 0x37, // list of all the gametypes for custom matches
FEEDER_INGAME_SQUAD_MEMBER_RANK = 0x38, // Squad members' rank displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_MEMBER_TALK = 0x39, // Squad members' talk icon displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_LOCKED = 0x3a, // Squad lock icon displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_MEMBER_INVITED = 0x3b, // Squad invite icon displayed in MP 'Pause' menu
FEEDER_INGAME_SQUAD_INVITE = 0x3c, // Squad invite icon displayed in MP 'Join Squad' menu
FEEDER_INGAME_SQUAD_LEADER = 0x3d, // Squad leader icon displayled in MP 'Pause' menu
FEEDER_FRIENDS = 0x3e, // list of your friends
FEEDER_PENDINGFRIENDS = 0x3f, // list of your pending friends
FEEDER_INVITES = 0x40, // list of the game invites from your friends
};
// display flags
enum MENU_DISPLAY_FLAG {
CG_SHOW_BLUE_TEAM_HAS_REDFLAG = 0x00000001,
CG_SHOW_RED_TEAM_HAS_BLUEFLAG = 0x00000002,
CG_SHOW_ANYTEAMGAME = 0x00000004,
CG_SHOW_CTF = 0x00000020,
CG_SHOW_OBELISK = 0x00000040,
CG_SHOW_HEALTHCRITICAL = 0x00000080,
CG_SHOW_SINGLEPLAYER = 0x00000100,
CG_SHOW_TOURNAMENT = 0x00000200,
CG_SHOW_DURINGINCOMINGVOICE = 0x00000400,
CG_SHOW_IF_PLAYER_HAS_FLAG = 0x00000800,
CG_SHOW_LANPLAYONLY = 0x00001000,
CG_SHOW_MINED = 0x00002000,
CG_SHOW_HEALTHOK = 0x00004000,
CG_SHOW_TEAMINFO = 0x00008000,
CG_SHOW_NOTEAMINFO = 0x00010000,
CG_SHOW_OTHERTEAMHASFLAG = 0x00020000,
CG_SHOW_YOURTEAMHASENEMYFLAG = 0x00040000,
CG_SHOW_ANYNONTEAMGAME = 0x00080000,
CG_SHOW_TEXTASINT = 0x00200000,
CG_SHOW_HIGHLIGHTED = 0x00100000,
CG_SHOW_NOT_V_CLEAR = 0x02000000,
CG_SHOW_2DONLY = 0x10000000
};
enum MENU_UI_FLAG{
UI_SHOW_LEADER = 0x00000001,
UI_SHOW_NOTLEADER = 0x00000002,
UI_SHOW_FAVORITESERVERS = 0x00000004,
UI_SHOW_ANYNONTEAMGAME = 0x00000008,
UI_SHOW_ANYTEAMGAME = 0x00000010,
UI_SHOW_NEWHIGHSCORE = 0x00000020,
UI_SHOW_DEMOAVAILABLE = 0x00000040,
UI_SHOW_NEWBESTTIME = 0x00000080,
UI_SHOW_FFA = 0x00000100,
UI_SHOW_NOTFFA = 0x00000200,
UI_SHOW_NETANYNONTEAMGAME = 0x00000400,
UI_SHOW_NETANYTEAMGAME = 0x00000800,
UI_SHOW_NOTFAVORITESERVERS = 0x00001000
};
// font types
enum MENU_FONT_TYPE{
UI_FONT_DEFAULT = 0, // auto-chose betwen big/reg/small
UI_FONT_NORMAL = 1,
UI_FONT_BIG = 2,
UI_FONT_SMALL = 3,
UI_FONT_BOLD = 4,
UI_FONT_CONSOLE = 5,
UI_FONT_OBJECTIVE = 6,
UI_FONT_MAX = 6,
};
// owner draw types
// ideally these should be done outside of this file but
// this makes it much easier for the macro expansion to
// convert them for the designers ( from the .menu files )
enum MENU_OWNER_DRAW_TYPE {
CG_OWNERDRAW_BASE = 1,
CG_PLAYER_AMMO_VALUE = 5,
CG_PLAYER_AMMO_BACKDROP = 6,
CG_PLAYER_HEAT_VALUE = 7,
CG_PLAYER_STANCE = 20,
CG_SPECTATORS = 60,
CG_HOLD_BREATH_HINT = 71,
CG_CURSORHINT = 72,
CG_PLAYER_POWERUP = 73,
CG_PLAYER_HOLDABLE = 74,
CG_PLAYER_INVENTORY = 75,
CG_CURSORHINT_STATUS = 78, // like 'health' bar when pointing at a func_explosive
CG_PLAYER_BAR_HEALTH = 79,
CG_MANTLE_HINT = 80,
CG_PLAYER_WEAPON_NAME = 81,
CG_PLAYER_WEAPON_NAME_BACK = 82,
CG_CENTER_MESSAGE = 90, // for things like "You were killed by ..."
CG_TANK_BODY_DIR = 95,
CG_TANK_BARREL_DIR = 96,
CG_DEADQUOTE = 97,
CG_PLAYER_BAR_HEALTH_BACK = 98,
CG_MISSION_OBJECTIVE_HEADER = 99,
CG_MISSION_OBJECTIVE_LIST = 100,
CG_MISSION_OBJECTIVE_BACKDROP = 101,
CG_PAUSED_MENU_LINE = 102,
CG_OFFHAND_WEAPON_ICON_FRAG = 103,
CG_OFFHAND_WEAPON_ICON_SMOKEFLASH = 104,
CG_OFFHAND_WEAPON_AMMO_FRAG = 105,
CG_OFFHAND_WEAPON_AMMO_SMOKEFLASH = 106,
CG_OFFHAND_WEAPON_NAME_FRAG = 107,
CG_OFFHAND_WEAPON_NAME_SMOKEFLASH = 108,
CG_OFFHAND_WEAPON_SELECT_FRAG = 109,
CG_OFFHAND_WEAPON_SELECT_SMOKEFLASH = 110,
CG_SAVING = 111,
CG_PLAYER_LOW_HEALTH_OVERLAY = 112,
CG_INVALID_CMD_HINT = 113,
CG_PLAYER_SPRINT_METER = 114,
CG_PLAYER_SPRINT_BACK = 115,
CG_PLAYER_WEAPON_BACKGROUND = 116,
CG_PLAYER_WEAPON_AMMO_CLIP_GRAPHIC = 117,
CG_PLAYER_WEAPON_PRIMARY_ICON = 118,
CG_PLAYER_WEAPON_AMMO_STOCK = 119,
CG_PLAYER_WEAPON_LOW_AMMO_WARNING = 120,
CG_BATTLE_COMPASS_MARKERS = 122,
CG_BATTLE_FULLMAP_MARKERS = 123,
CG_SUCCESSFUL_CMD_HINT = 130,
CG_WAR_TEXT = 135,
CG_PLAYER_COMPASS_TICKERTAPE = 145,
CG_PLAYER_COMPASS_TICKERTAPE_NO_OBJ = 146,
CG_PLAYER_COMPASS_DOGS = 147,
CG_PLAYER_COMPASS_ARTILLERY_ICON = 148,
CG_PLAYER_COMPASS_SQUAD_OBJECTIVE = 149,
CG_PLAYER_COMPASS_PLAYER = 150,
CG_PLAYER_COMPASS_BACK = 151,
CG_PLAYER_COMPASS_POINTERS = 152,
CG_PLAYER_COMPASS_ACTORS = 153,
CG_PLAYER_COMPASS_TANKS = 154,
CG_PLAYER_COMPASS_HELICOPTERS = 155,
CG_PLAYER_COMPASS_PLANES = 156,
CG_PLAYER_COMPASS_AUTOMOBILES = 157,
CG_PLAYER_COMPASS_FRIENDS = 158,
CG_PLAYER_COMPASS_MAP = 159,
CG_PLAYER_COMPASS_NORTHCOORD = 160,
CG_PLAYER_COMPASS_EASTCOORD = 161,
CG_PLAYER_COMPASS_NCOORD_SCROLL = 162,
CG_PLAYER_COMPASS_ECOORD_SCROLL = 163,
CG_PLAYER_COMPASS_GOALDISTANCE = 164,
CG_PLAYER_ACTIONSLOT_DPAD = 165,
CG_PLAYER_ACTIONSLOT_1 = 166,
CG_PLAYER_ACTIONSLOT_2 = 167,
CG_PLAYER_ACTIONSLOT_3 = 168,
CG_PLAYER_ACTIONSLOT_4 = 169,
CG_PLAYER_COMPASS_ENEMIES = 170,
CG_PLAYER_FULLMAP_DOGS = 176,
CG_PLAYER_FULLMAP_VEHICLES = 177,
CG_PLAYER_FULLMAP_ARTILLERY_ICON = 178,
CG_PLAYER_FULLMAP_SQUAD_OBJECTIVE = 179,
CG_PLAYER_FULLMAP_BACK = 180,
CG_PLAYER_FULLMAP_MAP = 181,
CG_PLAYER_FULLMAP_POINTERS = 182,
CG_PLAYER_FULLMAP_PLAYER = 183,
CG_PLAYER_FULLMAP_ACTORS = 184,
CG_PLAYER_FULLMAP_FRIENDS = 185,
CG_PLAYER_FULLMAP_LOCATION_SELECTOR = 186,
CG_PLAYER_FULLMAP_BORDER = 187,
CG_PLAYER_FULLMAP_ENEMIES = 188,
CG_PLAYER_COMPASS = 189,
CG_VEHICLE_RETICLE = 190,
CG_HUD_TARGETS_VEHICLE = 191,
CG_HUD_TARGETS_JAVELIN = 192,
CG_TALKER1 = 193,
CG_TALKER2 = 194,
CG_TALKER3 = 195,
CG_TALKER4 = 196,
CG_FRIENDLYARROWS = 197,
CG_FRIENDLYNAMES = 198,
UI_OWNERDRAW_BASE = 200,
UI_HANDICAP = 200,
UI_EFFECTS = 201,
UI_PLAYERMODEL = 202,
UI_GAMETYPE = 205,
UI_SKILL = 207,
UI_NETSOURCE = 220,
UI_NETFILTER = 222,
UI_VOTE_KICK = 238,
UI_NETGAMETYPE = 245,
UI_SERVERREFRESHDATE = 247,
UI_SERVERMOTD = 248,
UI_GLINFO = 249,
UI_KEYBINDSTATUS = 250,
UI_JOINGAMETYPE = 253,
UI_MAPPREVIEW = 254,
UI_MENUMODEL = 257,
UI_SAVEGAME_SHOT = 258,
UI_SAVEGAMENAME = 262,
UI_SAVEGAMEINFO = 263,
UI_LOADPROFILING = 264,
UI_RECORDLEVEL = 265,
UI_AMITALKING = 266,
UI_TALKER1 = 267,
UI_TALKER2 = 268,
UI_TALKER3 = 269,
UI_TALKER4 = 270,
UI_PARTYSTATUS = 271,
UI_LOGGEDINUSER = 272,
UI_RESERVEDSLOTS = 273,
UI_PLAYLISTNAME = 274,
UI_PLAYLISTDESCRIPTION = 275,
UI_USERNAME = 276,
UI_CINEMATIC = 277,
UI_TOTALONLINE = 278,
UI_CATEGORYNAME = 279,
UI_CATEGORYDESCRIPTION = 280,
UI_PLAYLISTICON = 281,
UI_CATEGORYICON = 282,
UI_GAMETYPE_MAPNAME = 283,
CG_HUD_WAR_MOMENTUM_PROGRESS = 284,
CG_HUD_WAR_MOMENTUM_MULTIPLIER = 285,
CG_HUD_WAR_MOMENTUM_MULTIPLIER_DETAIL = 286,
CG_HUD_WAR_MOMENTUM_MULTIPLIER_BLITZKRIEG = 287,
CG_COMPETITIVE_MODE_SCORES = 288,
UI_LOAD_STATUS_SCREEN = 289,
UI_LEADERBOARD_GAMEMODE = 290,
CG_PLAYER_ACTIONSLOT_BACK_1 = 290,
CG_PLAYER_ACTIONSLOT_BACK_2 = 291,
CG_PLAYER_ACTIONSLOT_BACK_3 = 292,
CG_PLAYER_ACTIONSLOT_BACK_4 = 293,
CG_PLAYER_ACTIONSLOT_ARROW_1 = 294,
CG_PLAYER_ACTIONSLOT_ARROW_2 = 295,
CG_PLAYER_ACTIONSLOT_ARROW_3 = 296,
CG_PLAYER_ACTIONSLOT_ARROW_4 = 297,
UI_DIFFICULTY_INFO = 298,
UI_DIFFICULTY_ICON = 299,
UI_LOBBY_CHAT = 300
};
// Edge relative placement values for rect->h_align and rect->v_align
enum MENU_H_ALIGNMENT {
HORIZONTAL_ALIGN_SUBLEFT = 0, // left edge of a 4:3 screen (safe area not included)
HORIZONTAL_ALIGN_LEFT = 1, // left viewable (safe area) edge
HORIZONTAL_ALIGN_CENTER = 2, // center of the screen (reticle)
HORIZONTAL_ALIGN_RIGHT = 3, // right viewable (safe area) edge
HORIZONTAL_ALIGN_FULLSCREEN = 4, // disregards safe area
HORIZONTAL_ALIGN_NOSCALE = 5, // uses exact parameters - neither adjusts for safe area nor scales for screen size
HORIZONTAL_ALIGN_TO640 = 6, // scales a real-screen resolution x down into the 0 - 640 range
HORIZONTAL_ALIGN_CENTER_SAFEAREA = 7, // center of the safearea
HORIZONTAL_ALIGN_MAX = HORIZONTAL_ALIGN_CENTER_SAFEAREA,
HORIZONTAL_ALIGN_DEFAULT = HORIZONTAL_ALIGN_SUBLEFT
};
enum MENU_V_ALIGNMENT {
VERTICAL_ALIGN_SUBTOP = 0, // top edge of the 4:3 screen (safe area not included)
VERTICAL_ALIGN_TOP = 1, // top viewable (safe area) edge
VERTICAL_ALIGN_CENTER = 2, // center of the screen (reticle)
VERTICAL_ALIGN_BOTTOM = 3, // bottom viewable (safe area) edge
VERTICAL_ALIGN_FULLSCREEN = 4, // disregards safe area
VERTICAL_ALIGN_NOSCALE = 5, // uses exact parameters - neither adjusts for safe area nor scales for screen size
VERTICAL_ALIGN_TO480 = 6, // scales a real-screen resolution y down into the 0 - 480 range
VERTICAL_ALIGN_CENTER_SAFEAREA = 7, // center of the save area
VERTICAL_ALIGN_MAX = VERTICAL_ALIGN_CENTER_SAFEAREA,
VERTICAL_ALIGN_DEFAULT = VERTICAL_ALIGN_SUBTOP
};
enum MENU_BUTTON {
BUTTON_A = 1,
BUTTON_B = 2,
BUTTON_X = 3,
BUTTON_Y = 4,
BUTTON_LSHLDR = 5,
BUTTON_RSHLDR = 6,
BUTTON_START = 14,
BUTTON_BACK = 15,
BUTTON_LSTICK = 16,
BUTTON_RSTICK = 17,
BUTTON_LTRIG = 18,
BUTTON_RTRIG = 19,
DPAD_UP = 20,
DPAD_DOWN = 21,
DPAD_LEFT = 22,
DPAD_RIGHT = 23,
APAD_UP = 28,
APAD_DOWN = 29,
APAD_LEFT = 30,
APAD_RIGHT = 31
};
enum ASSET_TYPE {
ASSET_UNKNOWN = 0,
ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED
ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED
ASSET_MATERIAL = 6, // material VERIFIED
ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED
ASSET_SOUND = 9, // loaded_sound VERIFIED
ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED
ASSET_SHADER = 13, // shader PARTIALLY VERIFIED
ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED
ASSET_FONT = 20, // font PARTIALLY VERIFIED
ASSET_MENU = 21, // menu_file VERIFIED
ASSET_LOCAL_STRING = 23, // localized string VERIFIED
ASSET_WEAPON = 24, // weapon VERIFIED
ASSET_EFFECT = 26, // fx VERIFIED
ASSET_RAW_FILE = 32, // raw_file VERIFIED
ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED
};
// Change this depending on the platform
// PC
#define DEVMAP_LEVEL_FIRST "devmap intro_pac"
#define DEVMAP "devmap"
// Not PC
// #define DEVMAP_LEVEL_FIRST "map intro_pac"
// #define DEVMAP "map"
// Remove this to restore full frontend instead of limited EPD frontend
#define COOP_EPD 0
// LDS - This enables a German SKU with Nazi Zombies enabled *SHOULD BE SET TO 0 IF NOT APPROVED*
#define GERMAN_ZOMBIE_BUILD 0
#define DEVMAP_LEVEL_TRAINING "devmap training"
#define LEVEL_FIRST "intro_pac"
#define LEVEL_TRAINING "training"
#define FIRST_PLAYABLE_CAMPAIGN_LEVEL "mak"
#define FIRST_PLAYABLE_ZOMBIE_LEVEL "nazi_zombie_prototype"
// Size define for the hud compass
// These are used for both the dynamic & non-dynamic compass drawing
// If these are changed, the cgame should be recompiled
#define COMPASS_SIZE 160
#define MINIMAP_X 11.5
#define MINIMAP_Y 5
#define MINIMAP_W 89.5
#define MINIMAP_H 89.5
#define COMPASS_SIZE_MP 125
#define MINIMAP_X_MP 0
#define MINIMAP_Y_MP 12
#define MINIMAP_W_MP 102
#define MINIMAP_H_MP 102
#define FULLSCREEN 0 0 640 480
#define FULLSCREEN_WIDE -107 0 854 480
// PC
#define ORIGIN_TITLE 30 34
// Not PC
// #define ORIGIN_TITLE 0 0
#define ORIGIN_TITLE_SS 104 120
#define FONTSCALE_SMALL 0.3095 //0.3750 // <-- COD4 // COD5 --> 0.30952//0.35897//0.24138 //14 pt //0.2900 //0.2750 // 18
#define FONTSCALE_LOBBY 0.26 // <--Slate // 0.3010 <-- Slate Compressed // 0.3750 // <-- COD4 CONDUIT ITC small
#define FONTSCALE_NORMAL 0.3810 //0.35897//0.4583
#define FONTSCALE_BOLD 0.5476 //0.4583
#define FONTSCALE_BIG 0.5476 //0.5833
#define FONTSCALE_EXTRABIG 1 //1.0000
// new settings
#define TEXTSIZE_SMALL FONTSCALE_SMALL
#define TEXTSIZE_SMALL_SS (FONTSCALE_SMALL*2)
#define TEXTSIZE_DEFAULT FONTSCALE_NORMAL
#define TEXTSIZE_DEFAULT_SS (FONTSCALE_NORMAL*2)
#define TEXTSIZE_TITLE FONTSCALE_BIG
#define TEXTSIZE_TITLE_SS 1
#define TEXTSIZE_BOLD TEXTSIZE_DEFAULT
#define TEXTSIZE_BIG TEXTSIZE_TITLE
//#define COLOR_TITLE 1 0.8 0.4 1
#define COLOR_TITLE 1 1 1 1
#define COLOR_HEADER 0.69 0.69 0.69 1
#define COLOR_FOCUSED 0.95294 0.72156 0.21176 1 //1 0.788 0.129 1
//#define COLOR_FOCUS_YELLOW 0.95294 0.72156 0.21176 1
#define COLOR_UNFOCUSED 0.4823 0.4823 0.4823 1
//#define COLOR_DISABLED 0.35 0.35 0.35 1
#define COLOR_SAFEAREA 0 0 1 1
#define COLOR_INFO_YELLOW COLOR_FOCUSED//1 0.84706 0 1
#define COLOR_TEXT 0.84313 0.84313 0.84313 1
#define COLOR_DISABLED 0.34118 0.36863 0.37647 1
#define COLOR_TITLEBAR 0.14510 0.16078 0.16862 0.3//1
#define COLOR_RED_TEXT 0.69020 0.00784 0.00784 1
#define COLOR_FADEOUT 0.09412 0.09412 0.04912 0.65
#define COLOR_BODY_TEXT 0.62745 0.66667 0.67451 1
#define COLOR_USMC 0 0.0196 0.41
#define COLOR_JPN 0.53 0.027 0.027
#define COLOR_USSR 0.368 0.035 0.035
#define COLOR_GER 0.937 0.9 0.607
#define DEFAULT_MP_CFG "default_mp.cfg"
#define SPLITSCREEN_MP_CFG "default_splitscreen.cfg"
#define SYSTEMLINK_MP_CFG "default_systemlink.cfg"
#define XBOXLIVE_MP_CFG "default_xboxlive.cfg"
#define MAX_RANK int(tableLookup( "mp/rankTable.csv", 0, "maxrank", 1))
#define MAX_PRESTIGE int(tableLookup( "mp/rankIconTable.csv", 0, "maxprestige", 1))
#define PRESTIGE_AVAIL (stat(2326) < MAX_PRESTIGE && stat(2301) == int(tableLookup("mp/rankTable.csv",0,MAX_RANK,7)))
#define PRESTIGE_NEXT (stat(2326) < MAX_PRESTIGE && stat(252) == MAX_RANK)
#define PRESTIGE_FINISH (stat(2326) == MAX_PRESTIGE)
#define CAN_RANK_UP (stat(252) < MAX_RANK || stat(2326) < MAX_PRESTIGE)
// Bink constants
const quint32 BINK_SURFACE32RGBA = 6;
#endif // ENUMS_H

View File

@ -1,5 +1,5 @@
#include "compression.h" #include "compression.h"
//#include "lzokay.h" #include "minilzo.h"
#define XBOXAPI __declspec(dllimport) #define XBOXAPI __declspec(dllimport)
#include "xcompress.h" #include "xcompress.h"
@ -13,8 +13,8 @@ QByteArray Compression::CompressXMem(const QByteArray &data)
{ {
XMEMCODEC_PARAMETERS_LZX lzxParams = {}; XMEMCODEC_PARAMETERS_LZX lzxParams = {};
lzxParams.Flags = 0; lzxParams.Flags = 0;
lzxParams.WindowSize = XCOMPRESS_LZX_BLOCK_SIZE; lzxParams.WindowSize = 0x20000;
lzxParams.CompressionPartitionSize = XCOMPRESS_LZX_BLOCK_SIZE; lzxParams.CompressionPartitionSize = 0x80000;
XMEMCOMPRESSION_CONTEXT ctx = nullptr; XMEMCOMPRESSION_CONTEXT ctx = nullptr;
if (FAILED(XMemCreateCompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx) if (FAILED(XMemCreateCompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx)
@ -34,25 +34,35 @@ QByteArray Compression::CompressXMem(const QByteArray &data)
return output; return output;
} }
QByteArray Compression::DecompressXMem(const QByteArray &data) QByteArray Compression::DecompressXMem(const QByteArray &data, int flags, int windowSize, int partSize)
{ {
if (data.isEmpty())
return {};
XMEMCODEC_PARAMETERS_LZX lzxParams = {}; XMEMCODEC_PARAMETERS_LZX lzxParams = {};
lzxParams.Flags = 0; lzxParams.Flags = flags;
lzxParams.WindowSize = XCOMPRESS_LZX_BLOCK_SIZE; lzxParams.WindowSize = windowSize;
lzxParams.CompressionPartitionSize = XCOMPRESS_LZX_BLOCK_SIZE; lzxParams.CompressionPartitionSize = partSize;
XMEMDECOMPRESSION_CONTEXT ctx = nullptr; XMEMDECOMPRESSION_CONTEXT ctx = nullptr;
if (FAILED(XMemCreateDecompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx) if (FAILED(XMemCreateDecompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx)
return QByteArray(); return {};
QByteArray output(data.size(), 0); // Allocate large enough buffer for decompression (16 MB is a safe upper bound)
SIZE_T actualSize = data.size(); const SIZE_T kMaxOutSize = 16 * 1024 * 1024;
QByteArray output(static_cast<int>(kMaxOutSize), Qt::Uninitialized);
SIZE_T actualSize = kMaxOutSize;
HRESULT hr = XMemDecompress(ctx,
output.data(), &actualSize,
data.constData(), data.size() + 16);
HRESULT hr = XMemDecompress(ctx, output.data(), &actualSize, data.constData(), data.size());
XMemDestroyDecompressionContext(ctx); XMemDestroyDecompressionContext(ctx);
if (FAILED(hr)) if (FAILED(hr)) {
return QByteArray(); qWarning() << "XMemDecompress failed with HRESULT:" << hr;
return {};
}
output.resize(static_cast<int>(actualSize)); output.resize(static_cast<int>(actualSize));
return output; return output;
@ -68,6 +78,46 @@ quint32 Compression::CalculateAdler32Checksum(const QByteArray &data) {
return adler; return adler;
} }
qint64 Compression::FindZlibOffset(const QByteArray &bytes)
{
static const QByteArray iwffs("IWffs");
auto idx = bytes.indexOf(iwffs);
if (idx != -1)
return idx + 0x4000;
const char header = 0x78; // z-lib: 0x78 [FLG]
int pos = -1;
while ((pos = bytes.indexOf(header, pos + 1)) != -1)
{
QByteArray window = bytes.mid(pos, 0x20);
if (!window.contains(QByteArray::fromHex("000000")) &&
!window.contains(QByteArray::fromHex("FFFFFF")))
return pos;
}
return -1;
}
QByteArray Compression::StripHashBlocks(const QByteArray &raw,
int dataChunkSize,
int hashChunkSize)
{
QByteArray cleaned;
cleaned.reserve(raw.size()); // upper bound
int p = 0;
while (p < raw.size())
{
const int chunk = qMin(dataChunkSize, raw.size() - p);
cleaned.append(raw.constData() + p, chunk);
p += chunk;
// skip hash bytes if they are still inside the buffer
if (p < raw.size())
p += qMin(hashChunkSize, raw.size() - p);
}
return cleaned;
}
QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) { QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) {
if (aCompressedData.isEmpty()) { if (aCompressedData.isEmpty()) {
return {}; return {};
@ -95,22 +145,23 @@ QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) {
ret = inflate(&strm, Z_NO_FLUSH); ret = inflate(&strm, Z_NO_FLUSH);
if (strm.avail_out < buffer.size()) { // Data has been written to the buffer if (strm.avail_out < buffer.size()) {
decompressed.append(buffer.constData(), buffer.size() - strm.avail_out); decompressed.append(buffer.constData(), buffer.size() - strm.avail_out);
} }
if (ret == Z_STREAM_END) { if (ret == Z_STREAM_END) {
break; // Proper end of the data stream break;
} }
if (ret == Z_BUF_ERROR && strm.avail_out == 0) { if (ret == Z_BUF_ERROR && strm.avail_out == 0) {
// Buffer was completely used, resize it buffer.resize(buffer.size() * 2);
int newSize = buffer.size() * 2; // Double the buffer size
buffer.resize(newSize);
} else if (ret != Z_OK) { } else if (ret != Z_OK) {
qWarning() << "Zlib error:" << zError(ret); size_t errorOffset = strm.total_in;
qWarning() << "Zlib error:" << zError(ret)
<< "at offset" << errorOffset
<< "of" << aCompressedData.size() << "bytes";
inflateEnd(&strm); inflateEnd(&strm);
return {}; // Return on other errors return decompressed;
} }
} while (ret != Z_STREAM_END); } while (ret != Z_STREAM_END);
@ -118,6 +169,7 @@ QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) {
return decompressed; return decompressed;
} }
QByteArray Compression::CompressZLIB(const QByteArray &aData) { QByteArray Compression::CompressZLIB(const QByteArray &aData) {
return CompressZLIBWithSettings(aData); return CompressZLIBWithSettings(aData);
} }
@ -242,6 +294,27 @@ QByteArray Compression::CompressDeflateWithSettings(const QByteArray &aData, int
return compressed; return compressed;
} }
QByteArray Compression::DecompressLZO(const QByteArray &aCompressedData, quint32 aDestSize) {
static bool ok = (lzo_init() == LZO_E_OK);
if (!ok)
throw std::runtime_error("lzo_init failed");
QByteArray dst(aDestSize, Qt::Uninitialized);
lzo_uint out = aDestSize;
int rc = lzo1x_decompress_safe(
reinterpret_cast<const lzo_bytep>(aCompressedData.constData()),
static_cast<lzo_uint>(aCompressedData.size()),
reinterpret_cast<lzo_bytep>(dst.data()),
&out,
nullptr);
if (rc != LZO_E_OK || out != aDestSize)
throw std::runtime_error("LZO decompression error");
return dst;
}
QByteArray Compression::DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize) { QByteArray Compression::DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize) {
return pDecompressOodle(aCompressedData, aCompressedData.length(), aDecompressedSize); return pDecompressOodle(aCompressedData, aCompressedData.length(), aDecompressedSize);
} }

View File

@ -47,6 +47,10 @@ class Compression {
public: public:
static quint32 CalculateAdler32Checksum(const QByteArray &data); static quint32 CalculateAdler32Checksum(const QByteArray &data);
static QByteArray DecompressZLIB(const QByteArray &aCompressedData); static QByteArray DecompressZLIB(const QByteArray &aCompressedData);
static qint64 FindZlibOffset(const QByteArray &bytes);
static QByteArray StripHashBlocks(const QByteArray &raw,
int dataChunkSize = 0x200000,
int hashChunkSize = 0x2000);
static QByteArray CompressZLIB(const QByteArray &aData); static QByteArray CompressZLIB(const QByteArray &aData);
static QByteArray CompressZLIBWithSettings(const QByteArray &aData, static QByteArray CompressZLIBWithSettings(const QByteArray &aData,
int aCompressionLevel = Z_BEST_COMPRESSION, int aCompressionLevel = Z_BEST_COMPRESSION,
@ -64,13 +68,14 @@ public:
int aStrategy = Z_DEFAULT_STRATEGY, int aStrategy = Z_DEFAULT_STRATEGY,
const QByteArray &aDictionary = {}); const QByteArray &aDictionary = {});
static QByteArray DecompressLZO(const QByteArray &aCompressedData, quint32 aDestSize);
static QByteArray DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize); static QByteArray DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize);
static QByteArray CompressOodle(const QByteArray &aData); static QByteArray CompressOodle(const QByteArray &aData);
static QByteArray CompressXMem(const QByteArray &data); static QByteArray CompressXMem(const QByteArray &data);
static QByteArray DecompressXMem(const QByteArray &data); static QByteArray DecompressXMem(const QByteArray &data, int flags = 0, int windowSize = 0x20000, int partSize = 0x80000);
private: private:
static quint32 pGetOodleCompressedBounds(quint32 aBufferSize); static quint32 pGetOodleCompressedBounds(quint32 aBufferSize);
static QByteArray pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize, static QByteArray pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize,

View File

@ -1,14 +1,17 @@
QT += core QT += core
TEMPLATE = lib TEMPLATE = lib
CONFIG += staticlib c++17 CONFIG += staticlib c++17
DEFINES += MINILZO_USE_STATIC
SOURCES += \ SOURCES += \
compression.cpp \ compression.cpp \
lzokay.cpp \ minilzo.c \
lzoconf.h \
lzodefs.h
HEADERS += \ HEADERS += \
compression.h \ compression.h \
lzokay.h minilzo.h
LIBS += \ LIBS += \
-L$$PWD/../../third_party/xbox_sdk/lib -lxcompress64 \ -L$$PWD/../../third_party/xbox_sdk/lib -lxcompress64 \

453
libs/compression/lzoconf.h Normal file
View File

@ -0,0 +1,453 @@
/* lzoconf.h -- configuration of the LZO data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __LZOCONF_H_INCLUDED
#define __LZOCONF_H_INCLUDED 1
#define LZO_VERSION 0x20a0 /* 2.10 */
#define LZO_VERSION_STRING "2.10"
#define LZO_VERSION_DATE "Mar 01 2017"
/* internal Autoconf configuration file - only used when building LZO */
#if defined(LZO_HAVE_CONFIG_H)
# include <config.h>
#endif
#include <limits.h>
#include <stddef.h>
/***********************************************************************
// LZO requires a conforming <limits.h>
************************************************************************/
#if !defined(CHAR_BIT) || (CHAR_BIT != 8)
# error "invalid CHAR_BIT"
#endif
#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX)
# error "check your compiler installation"
#endif
#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1)
# error "your limits.h macros are broken"
#endif
/* get OS and architecture defines */
#ifndef __LZODEFS_H_INCLUDED
#include <lzo/lzodefs.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
// some core defines
************************************************************************/
/* memory checkers */
#if !defined(__LZO_CHECKER)
# if defined(__BOUNDS_CHECKING_ON)
# define __LZO_CHECKER 1
# elif defined(__CHECKER__)
# define __LZO_CHECKER 1
# elif defined(__INSURE__)
# define __LZO_CHECKER 1
# elif defined(__PURIFY__)
# define __LZO_CHECKER 1
# endif
#endif
/***********************************************************************
// integral and pointer types
************************************************************************/
/* lzo_uint must match size_t */
#if !defined(LZO_UINT_MAX)
# if (LZO_ABI_LLP64)
# if (LZO_OS_WIN64)
typedef unsigned __int64 lzo_uint;
typedef __int64 lzo_int;
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64
# else
typedef lzo_ullong_t lzo_uint;
typedef lzo_llong_t lzo_int;
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG
# endif
# define LZO_SIZEOF_LZO_INT 8
# define LZO_UINT_MAX 0xffffffffffffffffull
# define LZO_INT_MAX 9223372036854775807LL
# define LZO_INT_MIN (-1LL - LZO_INT_MAX)
# elif (LZO_ABI_IP32L64) /* MIPS R5900 */
typedef unsigned int lzo_uint;
typedef int lzo_int;
# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT
# define LZO_UINT_MAX UINT_MAX
# define LZO_INT_MAX INT_MAX
# define LZO_INT_MIN INT_MIN
# elif (ULONG_MAX >= LZO_0xffffffffL)
typedef unsigned long lzo_uint;
typedef long lzo_int;
# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG
# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG
# define LZO_UINT_MAX ULONG_MAX
# define LZO_INT_MAX LONG_MAX
# define LZO_INT_MIN LONG_MIN
# else
# error "lzo_uint"
# endif
#endif
/* The larger type of lzo_uint and lzo_uint32_t. */
#if (LZO_SIZEOF_LZO_INT >= 4)
# define lzo_xint lzo_uint
#else
# define lzo_xint lzo_uint32_t
#endif
typedef int lzo_bool;
/* sanity checks */
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t))
#ifndef __LZO_MMODEL
#define __LZO_MMODEL /*empty*/
#endif
/* no typedef here because of const-pointer issues */
#define lzo_bytep unsigned char __LZO_MMODEL *
#define lzo_charp char __LZO_MMODEL *
#define lzo_voidp void __LZO_MMODEL *
#define lzo_shortp short __LZO_MMODEL *
#define lzo_ushortp unsigned short __LZO_MMODEL *
#define lzo_intp lzo_int __LZO_MMODEL *
#define lzo_uintp lzo_uint __LZO_MMODEL *
#define lzo_xintp lzo_xint __LZO_MMODEL *
#define lzo_voidpp lzo_voidp __LZO_MMODEL *
#define lzo_bytepp lzo_bytep __LZO_MMODEL *
#define lzo_int8_tp lzo_int8_t __LZO_MMODEL *
#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL *
#define lzo_int16_tp lzo_int16_t __LZO_MMODEL *
#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL *
#define lzo_int32_tp lzo_int32_t __LZO_MMODEL *
#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL *
#if defined(lzo_int64_t)
#define lzo_int64_tp lzo_int64_t __LZO_MMODEL *
#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL *
#endif
/* Older LZO versions used to support ancient systems and memory models
* such as 16-bit MSDOS with __huge pointers or Cray PVP, but these
* obsolete configurations are not supported any longer.
*/
#if defined(__LZO_MMODEL_HUGE)
#error "__LZO_MMODEL_HUGE memory model is unsupported"
#endif
#if (LZO_MM_PVP)
#error "LZO_MM_PVP memory model is unsupported"
#endif
#if (LZO_SIZEOF_INT < 4)
#error "LZO_SIZEOF_INT < 4 is unsupported"
#endif
#if (__LZO_UINTPTR_T_IS_POINTER)
#error "__LZO_UINTPTR_T_IS_POINTER is unsupported"
#endif
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4)
/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should
* work but have not received much testing lately, so be strict here.
*/
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp))
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep))
/***********************************************************************
// function types
************************************************************************/
/* name mangling */
#if !defined(__LZO_EXTERN_C)
# ifdef __cplusplus
# define __LZO_EXTERN_C extern "C"
# else
# define __LZO_EXTERN_C extern
# endif
#endif
/* calling convention */
#if !defined(__LZO_CDECL)
# define __LZO_CDECL __lzo_cdecl
#endif
/* DLL export information */
#if !defined(__LZO_EXPORT1)
# define __LZO_EXPORT1 /*empty*/
#endif
#if !defined(__LZO_EXPORT2)
# define __LZO_EXPORT2 /*empty*/
#endif
/* __cdecl calling convention for public C and assembly functions */
#if !defined(LZO_PUBLIC)
# define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL
#endif
#if !defined(LZO_EXTERN)
# define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r)
#endif
#if !defined(LZO_PRIVATE)
# define LZO_PRIVATE(r) static r __LZO_CDECL
#endif
/* function types */
typedef int
(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
typedef int
(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem,
const lzo_bytep dict, lzo_uint dict_len );
typedef int
(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem,
const lzo_bytep dict, lzo_uint dict_len );
/* Callback interface. Currently only the progress indicator ("nprogress")
* is used, but this may change in a future release. */
struct lzo_callback_t;
typedef struct lzo_callback_t lzo_callback_t;
#define lzo_callback_p lzo_callback_t __LZO_MMODEL *
/* malloc & free function types */
typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t)
(lzo_callback_p self, lzo_uint items, lzo_uint size);
typedef void (__LZO_CDECL *lzo_free_func_t)
(lzo_callback_p self, lzo_voidp ptr);
/* a progress indicator callback function */
typedef void (__LZO_CDECL *lzo_progress_func_t)
(lzo_callback_p, lzo_uint, lzo_uint, int);
struct lzo_callback_t
{
/* custom allocators (set to 0 to disable) */
lzo_alloc_func_t nalloc; /* [not used right now] */
lzo_free_func_t nfree; /* [not used right now] */
/* a progress indicator callback function (set to 0 to disable) */
lzo_progress_func_t nprogress;
/* INFO: the first parameter "self" of the nalloc/nfree/nprogress
* callbacks points back to this struct, so you are free to store
* some extra info in the following variables. */
lzo_voidp user1;
lzo_xint user2;
lzo_xint user3;
};
/***********************************************************************
// error codes and prototypes
************************************************************************/
/* Error codes for the compression/decompression functions. Negative
* values are errors, positive values will be used for special but
* normal events.
*/
#define LZO_E_OK 0
#define LZO_E_ERROR (-1)
#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */
#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */
#define LZO_E_INPUT_OVERRUN (-4)
#define LZO_E_OUTPUT_OVERRUN (-5)
#define LZO_E_LOOKBEHIND_OVERRUN (-6)
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */
#define LZO_E_INVALID_ARGUMENT (-10)
#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */
#define LZO_E_OUTPUT_NOT_CONSUMED (-12)
#define LZO_E_INTERNAL_ERROR (-99)
#ifndef lzo_sizeof_dict_t
# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep))
#endif
/* lzo_init() should be the first function you call.
* Check the return code !
*
* lzo_init() is a macro to allow checking that the library and the
* compiler's view of various types are consistent.
*/
#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\
(int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\
(int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\
(int)sizeof(lzo_callback_t))
LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
/* version functions (useful for shared libraries) */
LZO_EXTERN(unsigned) lzo_version(void);
LZO_EXTERN(const char *) lzo_version_string(void);
LZO_EXTERN(const char *) lzo_version_date(void);
LZO_EXTERN(const lzo_charp) _lzo_version_string(void);
LZO_EXTERN(const lzo_charp) _lzo_version_date(void);
/* string functions */
LZO_EXTERN(int)
lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len);
LZO_EXTERN(lzo_voidp)
lzo_memset(lzo_voidp buf, int c, lzo_uint len);
/* checksum functions */
LZO_EXTERN(lzo_uint32_t)
lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
LZO_EXTERN(lzo_uint32_t)
lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len);
LZO_EXTERN(const lzo_uint32_tp)
lzo_get_crc32_table(void);
/* misc. */
LZO_EXTERN(int) _lzo_config_check(void);
typedef union {
lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04;
void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09;
#if defined(lzo_int64_t)
lzo_uint64_t a10;
#endif
} lzo_align_t;
/* align a char pointer on a boundary that is a multiple of 'size' */
LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size);
#define LZO_PTR_ALIGN_UP(p,size) \
((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size)))
/***********************************************************************
// deprecated macros - only for backward compatibility
************************************************************************/
/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */
#define lzo_byte unsigned char
/* deprecated type names */
#define lzo_int32 lzo_int32_t
#define lzo_uint32 lzo_uint32_t
#define lzo_int32p lzo_int32_t __LZO_MMODEL *
#define lzo_uint32p lzo_uint32_t __LZO_MMODEL *
#define LZO_INT32_MAX LZO_INT32_C(2147483647)
#define LZO_UINT32_MAX LZO_UINT32_C(4294967295)
#if defined(lzo_int64_t)
#define lzo_int64 lzo_int64_t
#define lzo_uint64 lzo_uint64_t
#define lzo_int64p lzo_int64_t __LZO_MMODEL *
#define lzo_uint64p lzo_uint64_t __LZO_MMODEL *
#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807)
#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615)
#endif
/* deprecated types */
typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u;
typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u;
/* deprecated defines */
#if !defined(LZO_SIZEOF_LZO_UINT)
# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT
#endif
#if defined(LZO_CFG_COMPAT)
#define __LZOCONF_H 1
#if defined(LZO_ARCH_I086)
# define __LZO_i386 1
#elif defined(LZO_ARCH_I386)
# define __LZO_i386 1
#endif
#if defined(LZO_OS_DOS16)
# define __LZO_DOS 1
# define __LZO_DOS16 1
#elif defined(LZO_OS_DOS32)
# define __LZO_DOS 1
#elif defined(LZO_OS_WIN16)
# define __LZO_WIN 1
# define __LZO_WIN16 1
#elif defined(LZO_OS_WIN32)
# define __LZO_WIN 1
#endif
#define __LZO_CMODEL /*empty*/
#define __LZO_DMODEL /*empty*/
#define __LZO_ENTRY __LZO_CDECL
#define LZO_EXTERN_CDECL LZO_EXTERN
#define LZO_ALIGN LZO_PTR_ALIGN_UP
#define lzo_compress_asm_t lzo_compress_t
#define lzo_decompress_asm_t lzo_decompress_t
#endif /* LZO_CFG_COMPAT */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

3268
libs/compression/lzodefs.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,647 +0,0 @@
#include "lzokay.h"
#include <cstring>
#include <algorithm>
#include <iterator>
/*
* Based on documentation from the Linux sources: Documentation/lzo.txt
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/lzo.txt
*/
namespace lzokay {
#if _WIN32
#define HOST_BIG_ENDIAN 0
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define HOST_BIG_ENDIAN 1
#else
#define HOST_BIG_ENDIAN 0
#endif
#if HOST_BIG_ENDIAN
static uint16_t get_le16(const uint8_t* p) {
uint16_t val = *reinterpret_cast<const uint16_t*>(p);
#if __GNUC__
return __builtin_bswap16(val);
#elif _WIN32
return _byteswap_ushort(val);
#else
return (val = (val << 8) | ((val >> 8) & 0xFF));
#endif
}
#else
static uint16_t get_le16(const uint8_t* p) {
return *reinterpret_cast<const uint16_t*>(p);
}
#endif
constexpr std::size_t Max255Count = std::size_t(~0) / 255 - 2;
#define NEEDS_IN(count) \
if (inp + (count) > inp_end) { \
dst_size = outp - dst; \
return EResult::InputOverrun; \
}
#define NEEDS_OUT(count) \
if (outp + (count) > outp_end) { \
dst_size = outp - dst; \
return EResult::OutputOverrun; \
}
#define CONSUME_ZERO_BYTE_LENGTH \
std::size_t offset; \
{ \
const uint8_t *old_inp = inp; \
while (*inp == 0) ++inp; \
offset = inp - old_inp; \
if (offset > Max255Count) { \
dst_size = outp - dst; \
return EResult::Error; \
} \
}
#define WRITE_ZERO_BYTE_LENGTH(length) \
{ \
std::size_t l; \
for (l = length; l > 255; l -= 255) { *outp++ = 0; } \
*outp++ = static_cast<uint8_t>(l); \
}
constexpr uint32_t M1MaxOffset = 0x0400;
constexpr uint32_t M2MaxOffset = 0x0800;
constexpr uint32_t M3MaxOffset = 0x4000;
// constexpr uint32_t M4MaxOffset = 0xbfff;
// constexpr uint32_t M1MinLen = 2;
// constexpr uint32_t M1MaxLen = 2;
constexpr uint32_t M2MinLen = 3;
constexpr uint32_t M2MaxLen = 8;
// constexpr uint32_t M3MinLen = 3;
constexpr uint32_t M3MaxLen = 33;
// constexpr uint32_t M4MinLen = 3;
constexpr uint32_t M4MaxLen = 9;
constexpr uint32_t M1Marker = 0x0;
// constexpr uint32_t M2Marker = 0x40;
constexpr uint32_t M3Marker = 0x20;
constexpr uint32_t M4Marker = 0x10;
constexpr uint32_t MaxMatchByLengthLen = 34; /* Max M3 len + 1 */
EResult decompress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t init_dst_size,
std::size_t& dst_size) {
dst_size = init_dst_size;
if (src_size < 3) {
dst_size = 0;
return EResult::InputOverrun;
}
const uint8_t* inp = src;
const uint8_t* inp_end = src + src_size;
uint8_t* outp = dst;
uint8_t* outp_end = dst + dst_size;
uint8_t* lbcur;
std::size_t lblen;
std::size_t state = 0;
std::size_t nstate = 0;
/* First byte encoding */
if (*inp >= 22) {
/* 22..255 : copy literal string
* length = (byte - 17) = 4..238
* state = 4 [ don't copy extra literals ]
* skip byte
*/
std::size_t len = *inp++ - uint8_t(17);
NEEDS_IN(len)
NEEDS_OUT(len)
for (std::size_t i = 0; i < len; ++i)
*outp++ = *inp++;
state = 4;
} else if (*inp >= 18) {
/* 18..21 : copy 0..3 literals
* state = (byte - 17) = 0..3 [ copy <state> literals ]
* skip byte
*/
nstate = *inp++ - uint8_t(17);
state = nstate;
NEEDS_IN(nstate)
NEEDS_OUT(nstate)
for (std::size_t i = 0; i < nstate; ++i)
*outp++ = *inp++;
}
/* 0..17 : follow regular instruction encoding, see below. It is worth
* noting that codes 16 and 17 will represent a block copy from
* the dictionary which is empty, and that they will always be
* invalid at this place.
*/
while (true) {
NEEDS_IN(1)
uint8_t inst = *inp++;
if (inst & 0xC0) {
/* [M2]
* 1 L L D D D S S (128..255)
* Copy 5-8 bytes from block within 2kB distance
* state = S (copy S literals after this block)
* length = 5 + L
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 3) + D + 1
*
* 0 1 L D D D S S (64..127)
* Copy 3-4 bytes from block within 2kB distance
* state = S (copy S literals after this block)
* length = 3 + L
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 3) + D + 1
*/
NEEDS_IN(1)
lbcur = outp - ((*inp++ << 3) + ((inst >> 2) & 0x7) + 1);
lblen = std::size_t(inst >> 5) + 1;
nstate = inst & uint8_t(0x3);
} else if (inst & M3Marker) {
/* [M3]
* 0 0 1 L L L L L (32..63)
* Copy of small block within 16kB distance (preferably less than 34B)
* length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte)
* Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S
* distance = D + 1
* state = S (copy S literals after this block)
*/
lblen = std::size_t(inst & uint8_t(0x1f)) + 2;
if (lblen == 2) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
lblen += offset * 255 + 31 + *inp++;
}
NEEDS_IN(2)
nstate = get_le16(inp);
inp += 2;
lbcur = outp - ((nstate >> 2) + 1);
nstate &= 0x3;
} else if (inst & M4Marker) {
/* [M4]
* 0 0 0 1 H L L L (16..31)
* Copy of a block within 16..48kB distance (preferably less than 10B)
* length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte)
* Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S
* distance = 16384 + (H << 14) + D
* state = S (copy S literals after this block)
* End of stream is reached if distance == 16384
*/
lblen = std::size_t(inst & uint8_t(0x7)) + 2;
if (lblen == 2) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
lblen += offset * 255 + 7 + *inp++;
}
NEEDS_IN(2)
nstate = get_le16(inp);
inp += 2;
lbcur = outp - (((inst & 0x8) << 11) + (nstate >> 2));
nstate &= 0x3;
if (lbcur == outp)
break; /* Stream finished */
lbcur -= 16384;
} else {
/* [M1] Depends on the number of literals copied by the last instruction. */
if (state == 0) {
/* If last instruction did not copy any literal (state == 0), this
* encoding will be a copy of 4 or more literal, and must be interpreted
* like this :
*
* 0 0 0 0 L L L L (0..15) : copy long literal string
* length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte)
* state = 4 (no extra literals are copied)
*/
std::size_t len = inst + 3;
if (len == 3) {
CONSUME_ZERO_BYTE_LENGTH
NEEDS_IN(1)
len += offset * 255 + 15 + *inp++;
}
/* copy_literal_run */
NEEDS_IN(len)
NEEDS_OUT(len)
for (std::size_t i = 0; i < len; ++i)
*outp++ = *inp++;
state = 4;
continue;
} else if (state != 4) {
/* If last instruction used to copy between 1 to 3 literals (encoded in
* the instruction's opcode or distance), the instruction is a copy of a
* 2-byte block from the dictionary within a 1kB distance. It is worth
* noting that this instruction provides little savings since it uses 2
* bytes to encode a copy of 2 other bytes but it encodes the number of
* following literals for free. It must be interpreted like this :
*
* 0 0 0 0 D D S S (0..15) : copy 2 bytes from <= 1kB distance
* length = 2
* state = S (copy S literals after this block)
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 2) + D + 1
*/
NEEDS_IN(1)
nstate = inst & uint8_t(0x3);
lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 1);
lblen = 2;
} else {
/* If last instruction used to copy 4 or more literals (as detected by
* state == 4), the instruction becomes a copy of a 3-byte block from the
* dictionary from a 2..3kB distance, and must be interpreted like this :
*
* 0 0 0 0 D D S S (0..15) : copy 3 bytes from 2..3 kB distance
* length = 3
* state = S (copy S literals after this block)
* Always followed by exactly one byte : H H H H H H H H
* distance = (H << 2) + D + 2049
*/
NEEDS_IN(1)
nstate = inst & uint8_t(0x3);
lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 2049);
lblen = 3;
}
}
if (lbcur < dst) {
dst_size = outp - dst;
return EResult::LookbehindOverrun;
}
NEEDS_IN(nstate)
NEEDS_OUT(lblen + nstate)
/* Copy lookbehind */
for (std::size_t i = 0; i < lblen; ++i)
*outp++ = *lbcur++;
state = nstate;
/* Copy literal */
for (std::size_t i = 0; i < nstate; ++i)
*outp++ = *inp++;
}
dst_size = outp - dst;
if (lblen != 3) /* Ensure terminating M4 was encountered */
return EResult::Error;
if (inp == inp_end)
return EResult::Success;
else if (inp < inp_end)
return EResult::InputNotConsumed;
else
return EResult::InputOverrun;
}
struct State {
const uint8_t* src;
const uint8_t* src_end;
const uint8_t* inp;
uint32_t wind_sz;
uint32_t wind_b;
uint32_t wind_e;
uint32_t cycle1_countdown;
const uint8_t* bufp;
uint32_t buf_sz;
/* Access next input byte and advance both ends of circular buffer */
void get_byte(uint8_t* buf) {
if (inp >= src_end) {
if (wind_sz > 0)
--wind_sz;
buf[wind_e] = 0;
if (wind_e < DictBase::MaxMatchLen)
buf[DictBase::BufSize + wind_e] = 0;
} else {
buf[wind_e] = *inp;
if (wind_e < DictBase::MaxMatchLen)
buf[DictBase::BufSize + wind_e] = *inp;
++inp;
}
if (++wind_e == DictBase::BufSize)
wind_e = 0;
if (++wind_b == DictBase::BufSize)
wind_b = 0;
}
uint32_t pos2off(uint32_t pos) const {
return wind_b > pos ? wind_b - pos : DictBase::BufSize - (pos - wind_b);
}
};
class DictImpl : public DictBase {
public:
struct Match3Impl : DictBase::Match3 {
static uint32_t make_key(const uint8_t* data) {
return ((0x9f5f * (((uint32_t(data[0]) << 5 ^ uint32_t(data[1])) << 5) ^ data[2])) >> 5) & 0x3fff;
}
uint16_t get_head(uint32_t key) const {
return (chain_sz[key] == 0) ? uint16_t(UINT16_MAX) : head[key];
}
void init() {
std::fill(std::begin(chain_sz), std::end(chain_sz), 0);
}
void remove(uint32_t pos, const uint8_t* b) {
--chain_sz[make_key(b + pos)];
}
void advance(State& s, uint32_t& match_pos, uint32_t& match_count, const uint8_t* b) {
uint32_t key = make_key(b + s.wind_b);
match_pos = chain[s.wind_b] = get_head(key);
match_count = chain_sz[key]++;
if (match_count > DictBase::MaxMatchLen)
match_count = DictBase::MaxMatchLen;
head[key] = uint16_t(s.wind_b);
}
void skip_advance(State& s, const uint8_t* b) {
uint32_t key = make_key(b + s.wind_b);
chain[s.wind_b] = get_head(key);
head[key] = uint16_t(s.wind_b);
best_len[s.wind_b] = uint16_t(DictBase::MaxMatchLen + 1);
chain_sz[key]++;
}
};
struct Match2Impl : DictBase::Match2 {
static uint32_t make_key(const uint8_t* data) {
return uint32_t(data[0]) ^ (uint32_t(data[1]) << 8);
}
void init() {
std::fill(std::begin(head), std::end(head), UINT16_MAX);
}
void add(uint16_t pos, const uint8_t* b) {
head[make_key(b + pos)] = pos;
}
void remove(uint32_t pos, const uint8_t* b) {
uint16_t& p = head[make_key(b + pos)];
if (p == pos)
p = UINT16_MAX;
}
bool search(State& s, uint32_t& lb_pos, uint32_t& lb_len,
uint32_t best_pos[MaxMatchByLengthLen], const uint8_t* b) const {
uint16_t pos = head[make_key(b + s.wind_b)];
if (pos == UINT16_MAX)
return false;
if (best_pos[2] == 0)
best_pos[2] = pos + 1;
if (lb_len < 2) {
lb_len = 2;
lb_pos = pos;
}
return true;
}
};
void init(State& s, const uint8_t* src, std::size_t src_size) {
auto& match3 = static_cast<Match3Impl&>(_storage->match3);
auto& match2 = static_cast<Match2Impl&>(_storage->match2);
s.cycle1_countdown = DictBase::MaxDist;
match3.init();
match2.init();
s.src = src;
s.src_end = src + src_size;
s.inp = src;
s.wind_sz = uint32_t(std::min(src_size, std::size_t(MaxMatchLen)));
s.wind_b = 0;
s.wind_e = s.wind_sz;
std::copy_n(s.inp, s.wind_sz, _storage->buffer);
s.inp += s.wind_sz;
if (s.wind_e == DictBase::BufSize)
s.wind_e = 0;
if (s.wind_sz < 3)
std::fill_n(_storage->buffer + s.wind_b + s.wind_sz, 3, 0);
}
void reset_next_input_entry(State& s, Match3Impl& match3, Match2Impl& match2) {
/* Remove match from about-to-be-clobbered buffer entry */
if (s.cycle1_countdown == 0) {
match3.remove(s.wind_e, _storage->buffer);
match2.remove(s.wind_e, _storage->buffer);
} else {
--s.cycle1_countdown;
}
}
void advance(State& s, uint32_t& lb_off, uint32_t& lb_len,
uint32_t best_off[MaxMatchByLengthLen], bool skip) {
auto& match3 = static_cast<Match3Impl&>(_storage->match3);
auto& match2 = static_cast<Match2Impl&>(_storage->match2);
if (skip) {
for (uint32_t i = 0; i < lb_len - 1; ++i) {
reset_next_input_entry(s, match3, match2);
match3.skip_advance(s, _storage->buffer);
match2.add(uint16_t(s.wind_b), _storage->buffer);
s.get_byte(_storage->buffer);
}
}
lb_len = 1;
lb_off = 0;
uint32_t lb_pos;
uint32_t best_pos[MaxMatchByLengthLen] = {};
uint32_t match_pos, match_count;
match3.advance(s, match_pos, match_count, _storage->buffer);
int best_char = _storage->buffer[s.wind_b];
uint32_t best_len = lb_len;
if (lb_len >= s.wind_sz) {
if (s.wind_sz == 0)
best_char = -1;
lb_off = 0;
match3.best_len[s.wind_b] = DictBase::MaxMatchLen + 1;
} else {
if (match2.search(s, lb_pos, lb_len, best_pos, _storage->buffer) && s.wind_sz >= 3) {
for (uint32_t i = 0; i < match_count; ++i, match_pos = match3.chain[match_pos]) {
auto ref_ptr = _storage->buffer + s.wind_b;
auto match_ptr = _storage->buffer + match_pos;
auto mismatch = std::mismatch(ref_ptr, ref_ptr + s.wind_sz, match_ptr);
auto match_len = uint32_t(mismatch.first - ref_ptr);
if (match_len < 2)
continue;
if (match_len < MaxMatchByLengthLen && best_pos[match_len] == 0)
best_pos[match_len] = match_pos + 1;
if (match_len > lb_len) {
lb_len = match_len;
lb_pos = match_pos;
if (match_len == s.wind_sz || match_len > match3.best_len[match_pos])
break;
}
}
}
if (lb_len > best_len)
lb_off = s.pos2off(lb_pos);
match3.best_len[s.wind_b] = uint16_t(lb_len);
for (auto posit = std::begin(best_pos) + 2, offit = best_off + 2;
posit != std::end(best_pos); ++posit, ++offit) {
*offit = (*posit > 0) ? s.pos2off(*posit - 1) : 0;
}
}
reset_next_input_entry(s, match3, match2);
match2.add(uint16_t(s.wind_b), _storage->buffer);
s.get_byte(_storage->buffer);
if (best_char < 0) {
s.buf_sz = 0;
lb_len = 0;
/* Signal exit */
} else {
s.buf_sz = s.wind_sz + 1;
}
s.bufp = s.inp - s.buf_sz;
}
};
static void find_better_match(const uint32_t best_off[MaxMatchByLengthLen], uint32_t& lb_len, uint32_t& lb_off) {
if (lb_len <= M2MinLen || lb_off <= M2MaxOffset)
return;
if (lb_off > M2MaxOffset && lb_len >= M2MinLen + 1 && lb_len <= M2MaxLen + 1 &&
best_off[lb_len - 1] != 0 && best_off[lb_len - 1] <= M2MaxOffset) {
lb_len -= 1;
lb_off = best_off[lb_len];
} else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M2MaxLen + 2 &&
best_off[lb_len - 2] && best_off[lb_len] <= M2MaxOffset) {
lb_len -= 2;
lb_off = best_off[lb_len];
} else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M3MaxLen + 1 &&
best_off[lb_len - 1] != 0 && best_off[lb_len - 2] <= M3MaxOffset) {
lb_len -= 1;
lb_off = best_off[lb_len];
}
}
static EResult encode_literal_run(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size,
const uint8_t* lit_ptr, uint32_t lit_len) {
if (outp == dst && lit_len <= 238) {
NEEDS_OUT(1);
*outp++ = uint8_t(17 + lit_len);
} else if (lit_len <= 3) {
outp[-2] = uint8_t(outp[-2] | lit_len);
} else if (lit_len <= 18) {
NEEDS_OUT(1);
*outp++ = uint8_t(lit_len - 3);
} else {
NEEDS_OUT((lit_len - 18) / 255 + 2);
*outp++ = 0;
WRITE_ZERO_BYTE_LENGTH(lit_len - 18);
}
NEEDS_OUT(lit_len);
outp = std::copy_n(lit_ptr, lit_len, outp);
return EResult::Success;
}
static EResult encode_lookback_match(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size,
uint32_t lb_len, uint32_t lb_off, uint32_t last_lit_len) {
if (lb_len == 2) {
lb_off -= 1;
NEEDS_OUT(2);
*outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2));
*outp++ = uint8_t(lb_off >> 2);
} else if (lb_len <= M2MaxLen && lb_off <= M2MaxOffset) {
lb_off -= 1;
NEEDS_OUT(2);
*outp++ = uint8_t((lb_len - 1) << 5 | ((lb_off & 0x7) << 2));
*outp++ = uint8_t(lb_off >> 3);
} else if (lb_len == M2MinLen && lb_off <= M1MaxOffset + M2MaxOffset && last_lit_len >= 4) {
lb_off -= 1 + M2MaxOffset;
NEEDS_OUT(2);
*outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2));
*outp++ = uint8_t(lb_off >> 2);
} else if (lb_off <= M3MaxOffset) {
lb_off -= 1;
if (lb_len <= M3MaxLen) {
NEEDS_OUT(1);
*outp++ = uint8_t(M3Marker | (lb_len - 2));
} else {
lb_len -= M3MaxLen;
NEEDS_OUT(lb_len / 255 + 2);
*outp++ = uint8_t(M3Marker);
WRITE_ZERO_BYTE_LENGTH(lb_len);
}
NEEDS_OUT(2);
*outp++ = uint8_t(lb_off << 2);
*outp++ = uint8_t(lb_off >> 6);
} else {
lb_off -= 0x4000;
if (lb_len <= M4MaxLen) {
NEEDS_OUT(1);
*outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11) | (lb_len - 2));
} else {
lb_len -= M4MaxLen;
NEEDS_OUT(lb_len / 255 + 2);
*outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11));
WRITE_ZERO_BYTE_LENGTH(lb_len);
}
NEEDS_OUT(2);
*outp++ = uint8_t(lb_off << 2);
*outp++ = uint8_t(lb_off >> 6);
}
return EResult::Success;
}
EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t init_dst_size,
std::size_t& dst_size, DictBase& dict) {
EResult err;
State s;
auto& d = static_cast<DictImpl&>(dict);
dst_size = init_dst_size;
uint8_t* outp = dst;
uint8_t* outp_end = dst + dst_size;
uint32_t lit_len = 0;
uint32_t lb_off, lb_len;
uint32_t best_off[MaxMatchByLengthLen];
d.init(s, src, src_size);
const uint8_t* lit_ptr = s.inp;
d.advance(s, lb_off, lb_len, best_off, false);
while (s.buf_sz > 0) {
if (lit_len == 0)
lit_ptr = s.bufp;
if (lb_len < 2 || (lb_len == 2 && (lb_off > M1MaxOffset || lit_len == 0 || lit_len >= 4)) ||
(lb_len == 2 && outp == dst) || (outp == dst && lit_len == 0)) {
lb_len = 0;
} else if (lb_len == M2MinLen && lb_off > M1MaxOffset + M2MaxOffset && lit_len >= 4) {
lb_len = 0;
}
if (lb_len == 0) {
++lit_len;
d.advance(s, lb_off, lb_len, best_off, false);
continue;
}
find_better_match(best_off, lb_len, lb_off);
if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success)
return err;
if ((err = encode_lookback_match(outp, outp_end, dst, dst_size, lb_len, lb_off, lit_len)) < EResult::Success)
return err;
lit_len = 0;
d.advance(s, lb_off, lb_len, best_off, true);
}
if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success)
return err;
/* Terminating M4 */
NEEDS_OUT(3);
*outp++ = M4Marker | 1;
*outp++ = 0;
*outp++ = 0;
dst_size = outp - dst;
return EResult::Success;
}
}

View File

@ -1,79 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <memory>
namespace lzokay {
enum class EResult {
LookbehindOverrun = -4,
OutputOverrun = -3,
InputOverrun = -2,
Error = -1,
Success = 0,
InputNotConsumed = 1,
};
class DictBase {
protected:
static constexpr uint32_t HashSize = 0x4000;
static constexpr uint32_t MaxDist = 0xbfff;
static constexpr uint32_t MaxMatchLen = 0x800;
static constexpr uint32_t BufSize = MaxDist + MaxMatchLen;
/* List encoding of previous 3-byte data matches */
struct Match3 {
uint16_t head[HashSize]; /* key -> chain-head-pos */
uint16_t chain_sz[HashSize]; /* key -> chain-size */
uint16_t chain[BufSize]; /* chain-pos -> next-chain-pos */
uint16_t best_len[BufSize]; /* chain-pos -> best-match-length */
};
/* Encoding of 2-byte data matches */
struct Match2 {
uint16_t head[1 << 16]; /* 2-byte-data -> head-pos */
};
struct Data {
Match3 match3;
Match2 match2;
/* Circular buffer caching enough data to access the maximum lookback
* distance of 48K + maximum match length of 2K. An additional 2K is
* allocated so the start of the buffer may be replicated at the end,
* therefore providing efficient circular access.
*/
uint8_t buffer[BufSize + MaxMatchLen];
};
using storage_type = Data;
storage_type* _storage;
DictBase() = default;
friend struct State;
friend EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t& dst_size, DictBase& dict);
};
template <template<typename> class _Alloc = std::allocator>
class Dict : public DictBase {
_Alloc<DictBase::storage_type> _allocator;
public:
Dict() { _storage = _allocator.allocate(1); }
~Dict() { _allocator.deallocate(_storage, 1); }
};
EResult decompress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size);
EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size, DictBase& dict);
inline EResult compress(const uint8_t* src, std::size_t src_size,
uint8_t* dst, std::size_t dst_size,
std::size_t& out_size) {
Dict<> dict;
return compress(src, src_size, dst, dst_size, out_size, dict);
}
constexpr std::size_t compress_worst_size(std::size_t s) {
return s + s / 16 + 64 + 3;
}
}

6365
libs/compression/minilzo.c Normal file

File diff suppressed because it is too large Load Diff

106
libs/compression/minilzo.h Normal file
View File

@ -0,0 +1,106 @@
/* minilzo.h -- mini subset of the LZO real-time data compression library
This file is part of the LZO real-time data compression library.
Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer
All Rights Reserved.
The LZO library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
The LZO library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the LZO library; see the file COPYING.
If not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Markus F.X.J. Oberhumer
<markus@oberhumer.com>
http://www.oberhumer.com/opensource/lzo/
*/
/*
* NOTE:
* the full LZO package can be found at
* http://www.oberhumer.com/opensource/lzo/
*/
#ifndef __MINILZO_H_INCLUDED
#define __MINILZO_H_INCLUDED 1
#define MINILZO_VERSION 0x20a0 /* 2.10 */
#if defined(__LZOCONF_H_INCLUDED)
# error "you cannot use both LZO and miniLZO"
#endif
/* internal Autoconf configuration file - only used when building miniLZO */
#ifdef MINILZO_HAVE_CONFIG_H
# include <config.h>
#endif
#include <limits.h>
#include <stddef.h>
#ifndef __LZODEFS_H_INCLUDED
#include "lzodefs.h"
#endif
#undef LZO_HAVE_CONFIG_H
#include "lzoconf.h"
#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION)
# error "version mismatch in header files"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/***********************************************************************
//
************************************************************************/
/* Memory required for the wrkmem parameter.
* When the required size is 0, you can also pass a NULL pointer.
*/
#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t))
#define LZO1X_MEM_DECOMPRESS (0)
/* compression */
LZO_EXTERN(int)
lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem );
/* decompression */
LZO_EXTERN(int)
lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
/* safe decompression with overrun testing */
LZO_EXTERN(int)
lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len,
lzo_bytep dst, lzo_uintp dst_len,
lzo_voidp wrkmem /* NOT USED */ );
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* already included */
/* vim:set ts=4 sw=4 et: */

View File

@ -3,11 +3,19 @@ TEMPLATE = lib
CONFIG += staticlib c++17 CONFIG += staticlib c++17
SOURCES += \ SOURCES += \
highlighter_cfg.cpp \
highlighter_shock.cpp \
highlighter_rumble.cpp \
highlighter_gsc.cpp \
logmanager.cpp \ logmanager.cpp \
statusbarmanager.cpp statusbarmanager.cpp
HEADERS += \ HEADERS += \
enums.h \ enums.h \
highlighter_cfg.h \
highlighter_shock.h \
highlighter_rumble.h \
highlighter_gsc.h \
logmanager.h \ logmanager.h \
stringutils.h \ stringutils.h \
utils.h \ utils.h \

View File

@ -650,25 +650,6 @@ enum MENU_BUTTON {
APAD_RIGHT = 31 APAD_RIGHT = 31
}; };
enum ASSET_TYPE {
ASSET_UNKNOWN = 0,
ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED
ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED
ASSET_MATERIAL = 6, // material VERIFIED
ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED
ASSET_SOUND = 9, // loaded_sound VERIFIED
ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED
ASSET_SHADER = 13, // shader PARTIALLY VERIFIED
ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED
ASSET_FONT = 20, // font PARTIALLY VERIFIED
ASSET_MENU = 21, // menu_file VERIFIED
ASSET_LOCAL_STRING = 23, // localized string VERIFIED
ASSET_WEAPON = 24, // weapon VERIFIED
ASSET_EFFECT = 26, // fx VERIFIED
ASSET_RAW_FILE = 32, // raw_file VERIFIED
ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED
};
enum SHADER_TYPE { enum SHADER_TYPE {
SHADER_NONE = 0x00, SHADER_NONE = 0x00,
SHADER_PIXEL = 0x01, SHADER_PIXEL = 0x01,

View File

@ -0,0 +1,111 @@
#include "highlighter_cfg.h"
Highlighter_CFG::Highlighter_CFG(QTextDocument *parent)
: QSyntaxHighlighter(parent) {
HighlightingRule rule;
// Command keywords: set, seta, bind, etc.
keywordFormat.setForeground(QColor("#569CD6"));
keywordFormat.setFontWeight(QFont::Bold);
const QString keywordPatterns[] = {
QStringLiteral("\\bset\\b"),
QStringLiteral("\\bseta\\b"),
QStringLiteral("\\bbind\\b"),
QStringLiteral("\\bvstr\\b"),
QStringLiteral("\\bsay\\b"),
QStringLiteral("\\bwait\\b"),
QStringLiteral("\\bexec\\b"),
QStringLiteral("\\bunbind\\b"),
QStringLiteral("\\bcreatefx\\b"),
QStringLiteral("\\bcreatefx_drawdist\\b"),
QStringLiteral("\\bcreatefx_scaleid\\b"),
QStringLiteral("\\bbindaxis\\b")
};
for (const QString &pattern : keywordPatterns) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
}
// Button constants: BUTTON_*, DPAD_*
buttonFormat.setForeground(QColor("#4EC9B0"));
rule.pattern = QRegularExpression(QStringLiteral("\\b(BUTTON|DPAD)_[A-Z]+\\b"));
rule.format = buttonFormat;
highlightingRules.append(rule);
// Highlight *entire* 'bind var' or 'seta var' as one match, so we can highlight the variable part manually in highlightBlock()
// Regex captures the command and the following variable as two groups
bindSetVariablePattern = QRegularExpression(QStringLiteral("\\b(bind|bindaxis|set|seta)\\s+(\\w+)"));
// Quoted strings (highlight first so numbers inside are overridden)
quotationFormat.setForeground(QColor("#CE9178"));
rule.pattern = QRegularExpression(QStringLiteral("\".*?\""));
rule.format = quotationFormat;
highlightingRules.append(rule);
// Numbers (normal numbers, no filtering for inside strings, since strings override them)
numberFormat.setForeground(QColor("#B5CEA8"));
rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b"));
rule.format = numberFormat;
highlightingRules.append(rule);
// Comments: single-line comments with //
singleLineCommentFormat.setForeground(QColor("#6A9955"));
rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
// Command chaining symbol: ;
operatorFormat.setForeground(QColor("#D4D4D4"));
rule.pattern = QRegularExpression(QStringLiteral(";"));
rule.format = operatorFormat;
highlightingRules.append(rule);
}
void Highlighter_CFG::highlightBlock(const QString &text) {
// Apply all standard highlighting rules
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
// Highlight the immediate variable after 'bind', 'bindaxis', 'set', or 'seta'
QRegularExpressionMatchIterator iter = bindSetVariablePattern.globalMatch(text);
while (iter.hasNext()) {
QRegularExpressionMatch match = iter.next();
int varStart = match.capturedStart(2); // Group 2 is the variable
int varLength = match.capturedLength(2);
setFormat(varStart, varLength, variableFormat);
}
setCurrentBlockState(0);
// Handle multiline comments safely
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);
while (startIndex >= 0) {
QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
int endIndex = match.hasMatch() ? match.capturedStart() : -1;
int commentLength;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex + match.capturedLength();
}
// Safety check to avoid infinite loops
if (commentLength <= 0) {
break;
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}
}

View File

@ -0,0 +1,45 @@
#ifndef HIGHLIGHTER_CFG_H
#define HIGHLIGHTER_CFG_H
#include <QSyntaxHighlighter>
#include <QRegularExpression>
class Highlighter_CFG : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter_CFG(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};
QList<HighlightingRule> highlightingRules;
QRegularExpression commentStartExpression;
QRegularExpression commentEndExpression;
QRegularExpression bindSetVariablePattern;
QTextCharFormat buttonFormat;
QTextCharFormat operatorFormat;
QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat quotationFormat;
QTextCharFormat functionFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat preprocessorFormat;
QTextCharFormat variableFormat;
QTextCharFormat numberFormat;
QTextCharFormat devBlockCommentFormat;
QRegularExpression devCommentStart;
QRegularExpression devCommentEnd;
};
#endif // HIGHLIGHTER_CFG_H

View File

@ -0,0 +1,138 @@
#include "highlighter_gsc.h"
Highlighter_GSC::Highlighter_GSC(QTextDocument *parent)
: QSyntaxHighlighter(parent) {
HighlightingRule rule;
// C++ Keywords
keywordFormat.setForeground(QColor("#569CD6"));
keywordFormat.setFontWeight(QFont::Bold);
const QString keywordPatterns[] = {
QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"),
QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"),
QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"),
QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"),
QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"),
QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"),
QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"),
QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"),
QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"),
QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b")
};
for (const QString &pattern : keywordPatterns) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
}
// GSC Control Keywords
const QString gscKeywords[] = {
QStringLiteral("\\bif\\b"), QStringLiteral("\\belse\\b"), QStringLiteral("\\bswitch\\b"),
QStringLiteral("\\bcase\\b"), QStringLiteral("\\bbreak\\b"), QStringLiteral("\\bbreakpoint\\b"),
QStringLiteral("\\bcontinue\\b"), QStringLiteral("\\bfor\\b"), QStringLiteral("\\bwhile\\b"),
QStringLiteral("\\breturn\\b"), QStringLiteral("\\bdefault\\b"), QStringLiteral("\\bwait\\b"),
QStringLiteral("\\bwaittill\\b"), QStringLiteral("\\bwaittillframeend\\b"),
QStringLiteral("\\bendon\\b"), QStringLiteral("\\bnotify\\b"), QStringLiteral("\\bthread\\b")
};
for (const QString &pattern : gscKeywords) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
}
// Class format
classFormat.setForeground(QColor("#C586C0"));
classFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
rule.format = classFormat;
highlightingRules.append(rule);
// Preprocessor: #include and #using_animtree
preprocessorFormat.setForeground(QColor("#D7BA7D"));
preprocessorFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression(QStringLiteral("^\\s*#(?:include|using_animtree)\\b.*"));
rule.format = preprocessorFormat;
highlightingRules.append(rule);
// Hardcoded Variables: self, level, game
variableFormat.setForeground(QColor("#4EC9B0"));
rule.pattern = QRegularExpression(QStringLiteral("\\b(self|level|game)\\b"));
rule.format = variableFormat;
highlightingRules.append(rule);
// Quoted Strings
quotationFormat.setForeground(QColor("#CE9178"));
rule.pattern = QRegularExpression(QStringLiteral("\".*?\""));
rule.format = quotationFormat;
highlightingRules.append(rule);
// Numeric literals (including optional .f)
numberFormat.setForeground(QColor("#B5CEA8"));
rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b"));
rule.format = numberFormat;
highlightingRules.append(rule);
// Boolean literals
rule.pattern = QRegularExpression(QStringLiteral("\\b(true|false|undefined)\\b"));
rule.format = numberFormat;
highlightingRules.append(rule);
// Function calls
functionFormat.setForeground(QColor("#9CDCFE"));
functionFormat.setFontItalic(true);
rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()"));
rule.format = functionFormat;
highlightingRules.append(rule);
// Function pointers ::func
rule.pattern = QRegularExpression(QStringLiteral("::\\b(\\w+)\\b"));
rule.format = functionFormat;
highlightingRules.append(rule);
// Single-line comments
singleLineCommentFormat.setForeground(QColor("#6A9955"));
rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
// Developer block comments /# ... #/
devBlockCommentFormat.setForeground(QColor("#6A9955"));
devCommentStart = QRegularExpression(QStringLiteral("/#"));
devCommentEnd = QRegularExpression(QStringLiteral("#/"));
// Multi-line comment /* ... */
multiLineCommentFormat.setForeground(QColor("#6A9955"));
commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
}
void Highlighter_GSC::highlightBlock(const QString &text) {
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);
while (startIndex >= 0) {
QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
int endIndex = match.capturedStart();
int commentLength = 0;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ match.capturedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}
}

View File

@ -0,0 +1,42 @@
#ifndef HIGHLIGHTER_GSC_H
#define HIGHLIGHTER_GSC_H
#include <QSyntaxHighlighter>
#include <QRegularExpression>
class Highlighter_GSC : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter_GSC(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};
QList<HighlightingRule> highlightingRules;
QRegularExpression commentStartExpression;
QRegularExpression commentEndExpression;
QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat quotationFormat;
QTextCharFormat functionFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat preprocessorFormat;
QTextCharFormat variableFormat;
QTextCharFormat numberFormat;
QTextCharFormat devBlockCommentFormat;
QRegularExpression devCommentStart;
QRegularExpression devCommentEnd;
};
#endif // HIGHLIGHTER_GSC_H

View File

@ -0,0 +1,37 @@
#include "highlighter_rumble.h"
Highlighter_Rumble::Highlighter_Rumble(QTextDocument *parent)
: QSyntaxHighlighter(parent) {
HighlightingRule rule;
// Format for the "RUMBLEGRAPHFILE" header
headerFormat.setForeground(QColor("#569CD6"));
headerFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression(QStringLiteral("^RUMBLEGRAPHFILE\\b"));
rule.format = headerFormat;
highlightingRules.append(rule);
// Format for line count (second line, typically a single integer)
countFormat.setForeground(QColor("#C586C0"));
rule.pattern = QRegularExpression(QStringLiteral("^\\d+$"));
rule.format = countFormat;
highlightingRules.append(rule);
// Format for floating-point number pairs (e.g. 0.0000 0.4701)
floatPairFormat.setForeground(QColor("#B5CEA8"));
rule.pattern = QRegularExpression(QStringLiteral("^\\s*-?\\d+\\.\\d+\\s+-?\\d+\\.\\d+\\s*$"));
rule.format = floatPairFormat;
highlightingRules.append(rule);
}
void Highlighter_Rumble::highlightBlock(const QString &text) {
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
}

View File

@ -0,0 +1,29 @@
#ifndef HIGHLIGHTER_RUMBLE_H
#define HIGHLIGHTER_RUMBLE_H
#include <QSyntaxHighlighter>
#include <QRegularExpression>
class Highlighter_Rumble : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter_Rumble(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule {
QRegularExpression pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QTextCharFormat headerFormat;
QTextCharFormat countFormat;
QTextCharFormat floatPairFormat;
};
#endif // HIGHLIGHTER_RUMBLE_H

View File

@ -0,0 +1,43 @@
#include "highlighter_shock.h"
Highlighter_Shock::Highlighter_Shock(QTextDocument *parent)
: QSyntaxHighlighter(parent) {
HighlightingRule rule;
// Format for bg_shock_* keys
keyFormat.setForeground(QColor("#569CD6"));
keyFormat.setFontWeight(QFont::Bold);
rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_[\\w]+\\b"));
rule.format = keyFormat;
highlightingRules.append(rule);
// Format for quoted string values
stringFormat.setForeground(QColor("#CE9178"));
rule.pattern = QRegularExpression(QStringLiteral("\"[^\"]*\""));
rule.format = stringFormat;
highlightingRules.append(rule);
// Format for numeric values inside quotes (overridden by stringFormat but still useful for raw values)
numberFormat.setForeground(QColor("#B5CEA8"));
rule.pattern = QRegularExpression(QStringLiteral("-?\\d+(\\.\\d+)?"));
rule.format = numberFormat;
highlightingRules.append(rule);
// Optional: Format for control groups (e.g., bg_shock_volume_*)
subgroupFormat.setForeground(QColor("#4EC9B0"));
rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_volume_\\w+\\b"));
rule.format = subgroupFormat;
highlightingRules.append(rule);
}
void Highlighter_Shock::highlightBlock(const QString &text) {
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}
setCurrentBlockState(0);
}

View File

@ -0,0 +1,30 @@
#ifndef HIGHLIGHTER_SHOCK_H
#define HIGHLIGHTER_SHOCK_H
#include <QSyntaxHighlighter>
#include <QRegularExpression>
class Highlighter_Shock : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter_Shock(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule {
QRegularExpression pattern;
QTextCharFormat format;
};
QVector<HighlightingRule> highlightingRules;
QTextCharFormat keyFormat;
QTextCharFormat stringFormat;
QTextCharFormat numberFormat;
QTextCharFormat subgroupFormat;
};
#endif // HIGHLIGHTER_SHOCK_H

View File

@ -7,6 +7,8 @@
#include <QtZlib/zlib.h> #include <QtZlib/zlib.h>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QPainter>
#include <QCryptographicHash>
class Utils { class Utils {
public: public:
@ -22,6 +24,178 @@ public:
testFile.close(); testFile.close();
return true; return true;
} }
static quint8 ReverseBits(quint8 b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
static QIcon CreateAssetIcon(const QString& name, QColor color = QColor()) {
constexpr int iconSize = 32;
constexpr int padding = 4;
QImage result(iconSize, iconSize, QImage::Format_ARGB32);
result.fill(Qt::transparent);
if (!color.isValid()) {
color = Utils::StringToColor(name);
}
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHint(QPainter::TextAntialiasing, true);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
// Draw background
QBrush brush(color);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(color);
painter.setPen(Qt::NoPen);
painter.drawRoundedRect(0, 0, iconSize, iconSize, 4, 4);
// Set base font
QFont font("Heavitas");
font.setPixelSize(iconSize); // Start large
painter.setFont(font);
// Adjust font size to fit text width (only reduce, not increase)
QFontMetrics fm(font);
int textWidth = fm.horizontalAdvance(name);
while (textWidth > iconSize - 2 * padding && font.pixelSize() > 1) {
font.setPixelSize(font.pixelSize() - 1);
painter.setFont(font);
fm = QFontMetrics(font);
textWidth = fm.horizontalAdvance(name);
}
// Calculate vertical scaling factor
qreal scaleY = 1.2 * iconSize / fm.height();
// Apply transform: scale vertically, center align
painter.save();
painter.translate(iconSize / 2.0, iconSize / 2.0);
painter.scale(1.0, scaleY);
painter.translate(-iconSize / 2.0, -iconSize / 2.0);
QRect textRect(0, 0, iconSize, iconSize);
// Draw stroke
painter.setPen(Qt::black);
for (int dx = 0; dx <= 1; ++dx) {
for (int dy = 0; dy <= 1; ++dy) {
if (dx || dy)
painter.drawText(textRect.translated(dx, dy), Qt::AlignCenter, name);
}
}
// Draw main text
painter.setPen(Qt::white);
painter.drawText(textRect, Qt::AlignCenter, name);
painter.restore();
// Debug output
QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/");
result.save(QDir().absoluteFilePath(".") + "/icons/" + name + ".png");
return QIcon(QPixmap::fromImage(result));
}
static QIcon CreateGameIcon(const int gameNum, QColor color = QColor()) {
constexpr int size = 32;
constexpr int padding = 4; // pixels of padding on all sides
const int contentSize = size - 2 * padding;
QImage result(size, size, QImage::Format_ARGB32);
result.fill(Qt::transparent);
if (!color.isValid()) {
color = Utils::StringToColor(QString("COD%1").arg(gameNum));
}
QPainter painter(&result);
painter.setRenderHint(QPainter::Antialiasing, false);
painter.setRenderHint(QPainter::TextAntialiasing, false);
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
// Draw background
painter.setBrush(color);
painter.setPen(Qt::NoPen);
painter.drawRoundedRect(0, 0, size, size, 4, 4);
// === Font Setup ===
QFont codFont("Heavitas");
codFont.setPixelSize(contentSize * 0.40);
QFont numFont("Heavitas");
numFont.setPixelSize(contentSize);
// === Layout Areas (inside padding) ===
const QRect contentRect(padding, padding, contentSize, contentSize);
const int col1 = contentRect.left();
const int col2 = contentRect.left() + contentRect.width() / 3;
const int thirdH = contentRect.height() / 3;
const QRect codRects[] = {
QRect(col1, 2 + contentRect.top(), contentRect.width() / 3, thirdH),
QRect(col1, contentRect.top() + thirdH, contentRect.width() / 3, thirdH),
QRect(col1, -2 + contentRect.top() + 2 * thirdH, contentRect.width() / 3, thirdH),
};
const QRect numRect(col2, contentRect.top(), contentRect.width() * 2 / 3, contentRect.height());
const QString codLetters[] = { "C", "O", "D" };
const QString numText = QString::number(gameNum);
// === Stroke pass ===
for (int dx = -1; dx <= 2; ++dx) {
for (int dy = -1; dy <= 2; ++dy) {
if (dx == 0 && dy == 0) continue;
painter.setPen(Qt::black);
painter.setFont(codFont);
for (int i = 0; i < 3; ++i)
painter.drawText(codRects[i].translated(dx, dy), Qt::AlignCenter, codLetters[i]);
painter.setFont(numFont);
painter.drawText(numRect.translated(dx, dy), Qt::AlignCenter, numText);
}
}
// === Fill pass ===
painter.setPen(Qt::white);
painter.setFont(codFont);
for (int i = 0; i < 3; ++i)
painter.drawText(codRects[i], Qt::AlignCenter, codLetters[i]);
painter.setFont(numFont);
painter.drawText(numRect, Qt::AlignCenter, numText);
// Save & return icon
QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/");
result.save(QDir().absoluteFilePath(".") + QString("/icons/COD%1.png").arg(gameNum));
return QIcon(QPixmap::fromImage(result));
}
static QColor StringToColor(const QString& str) {
// 1. Hash the string using Qt's built-in hash (MD5, SHA1, or any)
QByteArray hash = QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5);
// 2. Use first 3 bytes of hash for RGB
// This guarantees same string = same color every time
int r = static_cast<unsigned char>(hash[0]);
int g = static_cast<unsigned char>(hash[1]);
int b = static_cast<unsigned char>(hash[2]);
// 3. Optionally adjust brightness or saturation to avoid too dark/light colors
QColor color(r, g, b);
if (color.value() < 128) { // brighten if too dark
color = color.lighter(150);
}
return color;
}
static bool ReadUntilString(QDataStream* stream, const QString& targetString) { static bool ReadUntilString(QDataStream* stream, const QString& targetString) {
if (!stream || targetString.isEmpty()) { if (!stream || targetString.isEmpty()) {
return false; // Invalid input return false; // Invalid input
@ -90,53 +264,6 @@ public:
return false; return false;
} }
/*
AssetTypeToString()
Convert asset type string to asset desc string
*/
static QString AssetTypeToString(const QString aAssetType) {
const QString cleanedType = aAssetType.toUpper();
if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED
return "LOCAL STRING";
} else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED
return "RAW FILE";
} else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED
return "EFFECT";
} else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED
return "SOUND";
} else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED
return "ANIMATION";
} else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED
return "COLLISION MAP";
} else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED
return "STRING TABLE";
} else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED
return "MENU";
} else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED
return "TECH SET";
} else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED
return "WEAPON";
} else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED
return "GFX MAP";
} else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED
return "LIGHT DEF";
} else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED
return "FONT";
} else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED
return "MODEL";
} else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED
return "D3DBSP";
} else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED
return "IMAGE";
} else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED
return "GAME MAP SP";
} else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED
return "COL MAP SP";
}
return aAssetType;
}
/* /*
LumpTypeToString() LumpTypeToString()

View File

@ -648,25 +648,6 @@ enum MENU_BUTTON {
APAD_RIGHT = 31 APAD_RIGHT = 31
}; };
enum ASSET_TYPE {
ASSET_UNKNOWN = 0,
ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED
ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED
ASSET_MATERIAL = 6, // material VERIFIED
ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED
ASSET_SOUND = 9, // loaded_sound VERIFIED
ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED
ASSET_SHADER = 13, // shader PARTIALLY VERIFIED
ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED
ASSET_FONT = 20, // font PARTIALLY VERIFIED
ASSET_MENU = 21, // menu_file VERIFIED
ASSET_LOCAL_STRING = 23, // localized string VERIFIED
ASSET_WEAPON = 24, // weapon VERIFIED
ASSET_EFFECT = 26, // fx VERIFIED
ASSET_RAW_FILE = 32, // raw_file VERIFIED
ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED
};
enum SHADER_TYPE { enum SHADER_TYPE {
SHADER_NONE = 0x00, SHADER_NONE = 0x00,
SHADER_PIXEL = 0x01, SHADER_PIXEL = 0x01,

View File

@ -1,6 +1,7 @@
#include "encryption.h" #include "encryption.h"
#include "QtZlib/zlib.h" #include "QtZlib/zlib.h"
#include "ecrypt-sync.h" #include "ecrypt-sync.h"
#include "compression.h"
void Encryption::Convert32BitTo8Bit(quint32 value, quint8 *array) { void Encryption::Convert32BitTo8Bit(quint32 value, quint8 *array) {
array[0] = static_cast<quint8>(value >> 0); array[0] = static_cast<quint8>(value >> 0);
@ -350,7 +351,7 @@ void Encryption::generateNewIV(int index, const QByteArray &hash, QByteArray &iv
ivCounter[index]++; ivCounter[index]++;
} }
QByteArray Encryption::decryptFastFile(const QByteArray &fastFileData) QByteArray Encryption::decryptFastFile_BO2(const QByteArray &fastFileData)
{ {
const QByteArray bo2_salsa20_key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); const QByteArray bo2_salsa20_key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
@ -438,3 +439,68 @@ QByteArray Encryption::decryptFastFile(const QByteArray &fastFileData)
return finalFastFile; return finalFastFile;
} }
QByteArray Encryption::decryptFastFile_BO3(const QByteArray &fastFileData) {
const QByteArray salsaKey = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
QByteArray ivTable(0xFB0, 0);
fillIVTable(fastFileData, ivTable, 0xFB0 - 1);
QVector<quint32> ivCounter(4, 1);
QDataStream stream(fastFileData);
stream.setByteOrder(QDataStream::LittleEndian);
QByteArray finalFastFile;
QByteArray sha1Hash(20, 0);
QByteArray ivPtr(8, 0);
int chunkIndex = 0;
while (!stream.atEnd()) {
if (stream.device()->bytesAvailable() < 4) {
qWarning() << "No sufficient data for chunk size at offset:" << stream.device()->pos();
break;
}
quint32 dataLength;
stream >> dataLength;
if (dataLength == 0 || dataLength > fastFileData.size() - stream.device()->pos()) {
qWarning() << "Invalid data length at offset:" << stream.device()->pos();
break;
}
fillIV(chunkIndex % 4, ivPtr, ivTable, ivCounter);
ECRYPT_ctx x;
ECRYPT_keysetup(&x, reinterpret_cast<const u8*>(salsaKey.constData()), 256, 0);
ECRYPT_ivsetup(&x, reinterpret_cast<const u8*>(ivPtr.constData()));
QByteArray encryptedBlock = fastFileData.mid(stream.device()->pos(), dataLength);
QByteArray decryptedBlock(dataLength, Qt::Uninitialized);
ECRYPT_decrypt_bytes(&x,
reinterpret_cast<const u8*>(encryptedBlock.constData()),
reinterpret_cast<u8*>(decryptedBlock.data()),
dataLength);
// SHA1 hash update
sha1Hash = QCryptographicHash::hash(decryptedBlock, QCryptographicHash::Sha1);
// Decompress (ZLIB raw DEFLATE)
QByteArray decompressedData = Compression::DecompressDeflate(decryptedBlock);
if (decompressedData.isEmpty()) {
qWarning() << "Failed decompression at chunk index:" << chunkIndex;
return QByteArray();
}
finalFastFile.append(decompressedData);
// Update IV table using SHA1
generateNewIV(chunkIndex % 4, sha1Hash, ivTable, ivCounter);
stream.skipRawData(dataLength);
chunkIndex++;
}
return finalFastFile;
}

View File

@ -46,7 +46,8 @@ public:
static void generateNewIV(int index, const QByteArray& hash, QByteArray& ivTable, QVector<quint32>& ivCounter); static void generateNewIV(int index, const QByteArray& hash, QByteArray& ivTable, QVector<quint32>& ivCounter);
static QByteArray decryptFastFile(const QByteArray& fastFileData); static QByteArray decryptFastFile_BO2(const QByteArray& fastFileData);
static QByteArray decryptFastFile_BO3(const QByteArray& fastFileData);
}; };
#endif // ENCRYPTION_H #endif // ENCRYPTION_H

View File

@ -17,4 +17,16 @@ HEADERS += \
config_win32.h \ config_win32.h \
sha1.h sha1.h
app.depends += \
compression
LIBS += \
-L$$OUT_PWD/../ -lcompression
INCLUDEPATH += \
$$PWD/../compression
DEPENDPATH += \
$$PWD/../compression
DESTDIR = $$OUT_PWD/../ DESTDIR = $$OUT_PWD/../

View File

@ -0,0 +1,115 @@
#include "fastfile_cod10_360.h"
#include "zonefile_cod10_360.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD10_360::FastFile_COD10_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetPlatform("360");
SetGame("COD10");
}
FastFile_COD10_360::FastFile_COD10_360(const QByteArray& aData)
: FastFile_COD10_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD10_360::FastFile_COD10_360(const QString aFilePath)
: FastFile_COD10_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD10_360::~FastFile_COD10_360() {
}
QByteArray FastFile_COD10_360::GetBinaryData() {
return QByteArray();
}
bool FastFile_COD10_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD10_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a QDataStream on the input data.
QDataStream fastFileStream(aData);
fastFileStream.setByteOrder(QDataStream::LittleEndian);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(QDataStream::BigEndian);
// Select key based on game.
QByteArray key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
decompressedData = Encryption::decryptFastFile_BO2(aData);
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD10_360 zoneFile;
zoneFile.SetStem(GetBaseStem() + ".zone");
zoneFile.Load(decompressedData);
SetZoneFile(std::make_shared<ZoneFile_COD10_360>(zoneFile));
return true;
}

View File

@ -0,0 +1,20 @@
#ifndef FASTFILE_COD10_360_H
#define FASTFILE_COD10_360_H
#include "fastfile.h"
class FastFile_COD10_360 : public FastFile
{
public:
FastFile_COD10_360();
FastFile_COD10_360(const QByteArray& aData);
FastFile_COD10_360(const QString aFilePath);
~FastFile_COD10_360();
QByteArray GetBinaryData() override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD10_360_H

View File

@ -0,0 +1,107 @@
#include "fastfile_cod11_360.h"
#include "zonefile_cod11_360.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD11_360::FastFile_COD11_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetGame("COD11");
SetPlatform("PC");
}
FastFile_COD11_360::FastFile_COD11_360(const QByteArray& aData)
: FastFile_COD11_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD11_360::FastFile_COD11_360(const QString aFilePath)
: FastFile_COD11_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD11_360::~FastFile_COD11_360() {
}
QByteArray FastFile_COD11_360::GetBinaryData() {
return QByteArray();
}
bool FastFile_COD11_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD11_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Prepare data stream for parsing
QDataStream fastFileStream(aData);
fastFileStream.setByteOrder(QDataStream::LittleEndian);
// Verify magic header
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "TAff0000") {
qWarning() << "Invalid fast file magic for COD12!";
return false;
}
// Skip: File size (4 bytes), flags/version (4 bytes), unknown (8 bytes), build tag (32 bytes), RSA signature (256 bytes)
fastFileStream.skipRawData(4 + 4 + 8 + 32 + 256); // total 304 bytes skipped so far + 8 bytes magic = 312 bytes at correct position.
// Correctly positioned at 0x138
QByteArray encryptedData = aData.mid(0x138);
decompressedData = Encryption::decryptFastFile_BO3(encryptedData);
// Output for verification/testing
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with decompressed data
ZoneFile_COD11_360 zoneFile;
zoneFile.SetStem(GetBaseStem() + ".zone");
if (!zoneFile.Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(std::make_shared<ZoneFile_COD11_360>(zoneFile));
return true;
}

View File

@ -0,0 +1,20 @@
#ifndef FASTFILE_COD11_360_H
#define FASTFILE_COD11_360_H
#include "fastfile.h"
class FastFile_COD11_360 : public FastFile
{
public:
FastFile_COD11_360();
FastFile_COD11_360(const QByteArray &aData);
FastFile_COD11_360(const QString aFilePath);
~FastFile_COD11_360();
QByteArray GetBinaryData() override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD11_360_H

View File

@ -0,0 +1,107 @@
#include "fastfile_cod12_360.h"
#include "zonefile_cod12_360.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD12_360::FastFile_COD12_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetGame("COD12");
SetPlatform("PC");
}
FastFile_COD12_360::FastFile_COD12_360(const QByteArray& aData)
: FastFile_COD12_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD12_360::FastFile_COD12_360(const QString aFilePath)
: FastFile_COD12_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD12_360::~FastFile_COD12_360() {
}
QByteArray FastFile_COD12_360::GetBinaryData() {
return QByteArray();
}
bool FastFile_COD12_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD12_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Prepare data stream for parsing
QDataStream fastFileStream(aData);
fastFileStream.setByteOrder(QDataStream::LittleEndian);
// Verify magic header
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "TAff0000") {
qWarning() << "Invalid fast file magic for COD12!";
return false;
}
// Skip: File size (4 bytes), flags/version (4 bytes), unknown (8 bytes), build tag (32 bytes), RSA signature (256 bytes)
fastFileStream.skipRawData(4 + 4 + 8 + 32 + 256); // total 304 bytes skipped so far + 8 bytes magic = 312 bytes at correct position.
// Correctly positioned at 0x138
QByteArray encryptedData = aData.mid(0x138);
decompressedData = Encryption::decryptFastFile_BO3(encryptedData);
// Output for verification/testing
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with decompressed data
ZoneFile_COD12_360 zoneFile;
zoneFile.SetStem(GetBaseStem() + ".zone");
if (!zoneFile.Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(std::make_shared<ZoneFile_COD12_360>(zoneFile));
return true;
}

View File

@ -0,0 +1,20 @@
#ifndef FASTFILE_COD12_360_H
#define FASTFILE_COD12_360_H
#include "fastfile.h"
class FastFile_COD12_360 : public FastFile
{
public:
FastFile_COD12_360();
FastFile_COD12_360(const QByteArray &aData);
FastFile_COD12_360(const QString aFilePath);
~FastFile_COD12_360();
QByteArray GetBinaryData() override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD12_360_H

View File

@ -1,25 +1,48 @@
#include "fastfile_cod2.h" #include "fastfile_cod2_360.h"
#include "utils.h" #include "utils.h"
#include "compression.h" #include "compression.h"
#include "zonefile_cod2.h" #include "zonefile_cod2_360.h"
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
FastFile_COD2::FastFile_COD2() { FastFile_COD2_360::FastFile_COD2_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetPlatform("360");
SetGame("COD2");
}
FastFile_COD2_360::FastFile_COD2_360(const QByteArray& aData)
: FastFile_COD2_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD2_360::FastFile_COD2_360(const QString aFilePath)
: FastFile_COD2_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD2_360::~FastFile_COD2_360() {
} }
FastFile_COD2::~FastFile_COD2() { QByteArray FastFile_COD2_360::GetBinaryData() {
}
QByteArray FastFile_COD2::GetBinaryData() {
return QByteArray(); return QByteArray();
} }
bool FastFile_COD2::Load(const QString aFilePath) { bool FastFile_COD2_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) { if (aFilePath.isEmpty()) {
return false; return false;
} }
@ -32,11 +55,9 @@ bool FastFile_COD2::Load(const QString aFilePath) {
} }
// Decompress fastfile and close // Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0); SetStem(aFilePath.section("/", -1, -1));
qDebug() << "fastFileStem: " << fastFileStem;
SetStem(fastFileStem);
if (!Load(file->readAll())) { if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem; qDebug() << "Error: Failed to load fastfile: " << GetStem();
return false; return false;
} }
@ -46,38 +67,22 @@ bool FastFile_COD2::Load(const QString aFilePath) {
return true; return true;
} }
bool FastFile_COD2::Load(const QByteArray aData) { bool FastFile_COD2_360::Load(const QByteArray aData) {
// Create a QDataStream on the input data. // Create a QDataStream on the input data.
QDataStream fastFileStream(aData); QDataStream fastFileStream(aData);
fastFileStream.setByteOrder(QDataStream::LittleEndian); fastFileStream.setByteOrder(QDataStream::LittleEndian);
// Parse header values.
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetPlatform("360");
SetGame("COD2");
Utils::ReadUntilHex(&fastFileStream, "78"); Utils::ReadUntilHex(&fastFileStream, "78");
QByteArray compressedData = aData.mid(fastFileStream.device()->pos()); QByteArray compressedData = aData.mid(fastFileStream.device()->pos());
QByteArray decompressedData = Compression::DecompressZLIB(compressedData); QByteArray decompressedData = Compression::DecompressZLIB(compressedData);
QDir exportsDir(QDir::currentPath()); Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
exportsDir.mkdir("exports");
QFile testFile("exports/" + GetStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag). // Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD2 zoneFile; ZoneFile_COD2_360 zoneFile;
zoneFile.SetStem(GetStem()); zoneFile.SetStem(GetBaseStem() + ".zone");
zoneFile.Load(decompressedData, FF_PLATFORM_XBOX); zoneFile.Load(decompressedData);
SetZoneFile(std::make_shared<ZoneFile_COD2>(zoneFile)); SetZoneFile(std::make_shared<ZoneFile_COD2_360>(zoneFile));
return true; return true;
} }

View File

@ -0,0 +1,20 @@
#ifndef FASTFILE_COD2_360_H
#define FASTFILE_COD2_360_H
#include "fastfile.h"
class FastFile_COD2_360 : public FastFile
{
public:
FastFile_COD2_360();
FastFile_COD2_360(const QByteArray& aData);
FastFile_COD2_360(const QString aFilePath);
~FastFile_COD2_360();
QByteArray GetBinaryData() override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD2_360_H

View File

@ -0,0 +1,139 @@
#include "fastfile_cod4_360.h"
#include "zonefile_cod4_360.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD4_360::FastFile_COD4_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
SetPlatform("360");
SetGame("COD4");
}
FastFile_COD4_360::FastFile_COD4_360(const QByteArray& aData)
: FastFile_COD4_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD4_360::FastFile_COD4_360(const QString aFilePath)
: FastFile_COD4_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD4_360::~FastFile_COD4_360() {
}
QByteArray FastFile_COD4_360::GetBinaryData() {
return QByteArray();
}
bool FastFile_COD4_360::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
QString fastFileStem = aFilePath.split('/').last().replace(".ff", "");
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD4_360::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
const QString header = aData.left(8);
if (header == "IWffu100") {
// For COD5, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
} else if (header == "IWff0100") {
// Create a QDataStream on the input data.
QDataStream fastFileStream(aData.mid(12));
fastFileStream.setByteOrder(QDataStream::LittleEndian);
QByteArray magic(8, Qt::Uninitialized);
fastFileStream.readRawData(magic.data(), 8);
if (magic != "IWffs100") {
qDebug() << "Found invalid signed header: " << magic;
return false;
}
fastFileStream.skipRawData(4);
QByteArray rsaSigChecksum(32, Qt::Uninitialized);
fastFileStream.readRawData(rsaSigChecksum.data(), 32);
QByteArray rsaSig(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSig.data(), 256);
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
fastFileStream.skipRawData(4);
QByteArray bigSigBlock(7856, Qt::Uninitialized);
fastFileStream.readRawData(bigSigBlock.data(), 7856);
QVector<QByteArray> sigBlocks = QVector<QByteArray>();
QByteArray compressedData;
for (int i = 0; i < (aData.size() / 202000) + 1; i++)
{
QByteArray newSigBlocks;
for (int j = 0; j < 256; j++) {
QByteArray newSigBlock(32, Qt::Uninitialized);
fastFileStream.readRawData(newSigBlock.data(), 32);
sigBlocks.append(newSigBlock);
}
newSigBlocks.append(newSigBlocks);
for (int j = 0; j < 256; j++) {
QByteArray compressedChunk(8192, Qt::Uninitialized);
fastFileStream.readRawData(compressedChunk.data(), 8192);
compressedData.append(compressedChunk);
}
}
decompressedData = Compression::DecompressZLIB(compressedData);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD4_360 zoneFile;
zoneFile.SetStem(GetBaseStem() + ".zone");
zoneFile.Load(decompressedData);
SetZoneFile(std::make_shared<ZoneFile_COD4_360>(zoneFile));
return true;
}

View File

@ -0,0 +1,20 @@
#ifndef FASTFILE_COD4_360_H
#define FASTFILE_COD4_360_H
#include "fastfile.h"
class FastFile_COD4_360 : public FastFile
{
public:
FastFile_COD4_360();
FastFile_COD4_360(const QByteArray &aData);
FastFile_COD4_360(const QString aFilePath);
~FastFile_COD4_360();
QByteArray GetBinaryData() override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD4_360_H

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