git subrepo clone https://github.com/HarbourMasters/libultraship.git
subrepo: subdir: "libultraship" merged: "a484cda98" upstream: origin: "https://github.com/HarbourMasters/libultraship.git" branch: "main" commit: "a484cda98" git-subrepo: version: "0.4.1" origin: "???" commit: "???"pull/1/head
parent
39cc86c260
commit
d24c8453db
|
@ -0,0 +1,356 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
!otrlib/Lib/SDL/lib/x64
|
||||
!otrlib/Lib/SDL/lib/x86
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
!libultraship/Lib/**
|
||||
libultraship/DebugObj/*
|
|
@ -0,0 +1,12 @@
|
|||
; DO NOT EDIT (unless you know what you are doing)
|
||||
;
|
||||
; This subdirectory is a git "subrepo", and this file is maintained by the
|
||||
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
|
||||
;
|
||||
[subrepo]
|
||||
remote = https://github.com/HarbourMasters/libultraship.git
|
||||
branch = main
|
||||
commit = a484cda9802ed9c39b29e11a703fd0997f42a6af
|
||||
parent = 39cc86c2608e2f75ace33fc7f43bc4f2ad743f1a
|
||||
method = rebase
|
||||
cmdver = 0.4.1
|
|
@ -0,0 +1,9 @@
|
|||
Copyright (c) 2022 Harbour Masters
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,28 @@
|
|||
# Only used for standalone compilation, usually inherits these from the main makefile
|
||||
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
||||
|
||||
SRC_DIRS := $(shell find -type d -not -path "*build*")
|
||||
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
||||
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
||||
|
||||
O_FILES := $(foreach f,$(CPP_FILES:.cpp=.o),build/$f)
|
||||
LIB := otrlib.a
|
||||
|
||||
# create build directories
|
||||
$(shell mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir)))
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
clean:
|
||||
rm -rf build $(LIB)
|
||||
|
||||
format:
|
||||
clang-format-11 -i $(CPP_FILES) $(H_FILES)
|
||||
|
||||
.PHONY: all clean format
|
||||
|
||||
build/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) $(OPTFLAGS) -I ./ -I ../ZAPD/ZAPD -I ../ZAPD/ZAPDUtils -I ../../ZAPD/lib/tinyxml2 -I otrlib/Lib/spdlog/include -c $(OUTPUT_OPTION) $<
|
||||
|
||||
$(LIB): $(O_FILES)
|
||||
$(AR) rcs $@ $^
|
|
@ -0,0 +1,29 @@
|
|||
#include "OTRArchive.h"
|
||||
|
||||
void SaveTest()
|
||||
{
|
||||
auto archPtr = OtrLib::OTRArchive::CreateArchive("myarch.mpq");
|
||||
auto arch = archPtr.get();
|
||||
|
||||
char data[] = "ABCDEFG!";
|
||||
|
||||
arch->AddFile("test.txt", (uintptr_t)data, sizeof(data));
|
||||
}
|
||||
|
||||
void LoadTest()
|
||||
{
|
||||
std::shared_ptr<OtrLib::OTRArchive> archPtr(new OtrLib::OTRArchive("myarch.mpq"));
|
||||
|
||||
archPtr->LoadFile("(crcfile)");
|
||||
|
||||
int bp = 0;
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
LoadTest();
|
||||
//SaveTest();
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,152 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{3c4a8151-48d1-4518-be1a-24016a5b800f}</ProjectGuid>
|
||||
<RootNamespace>TestApp</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(ProjectDir)..\otrlib;$(ProjectDir)..\..\ZAPD\ZAPDUtils;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)x64\Debug;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>otrlib.lib;ZAPDUtils.lib;StormLibDUS.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.30320.27
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libultraship", "libultraship\libultraship.vcxproj", "{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestApp", "TestApp\TestApp.vcxproj", "{3C4A8151-48D1-4518-BE1A-24016A5B800F}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8} = {6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZAPD", "..\ZAPDTR\ZAPD\ZAPD.vcxproj", "{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZAPDUtils", "..\ZAPDTR\ZAPDUtils\ZAPDUtils.vcxproj", "{A2E01C3E-D647-45D1-9788-043DEBC1A908}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Debug|x64.Build.0 = Debug|x64
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Debug|x86.Build.0 = Debug|Win32
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Release|x64.ActiveCfg = Release|x64
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Release|x64.Build.0 = Release|x64
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Release|x86.ActiveCfg = Release|Win32
|
||||
{6DA9B521-65B7-41E2-8F8A-F0451CC18ED8}.Release|x86.Build.0 = Release|Win32
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Debug|x64.Build.0 = Debug|x64
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Release|x64.ActiveCfg = Release|x64
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Release|x64.Build.0 = Release|x64
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3C4A8151-48D1-4518-BE1A-24016A5B800F}.Release|x86.Build.0 = Release|Win32
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Debug|x64.Build.0 = Debug|x64
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Debug|x86.Build.0 = Debug|Win32
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Release|x64.ActiveCfg = Release|x64
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Release|x64.Build.0 = Release|x64
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Release|x86.ActiveCfg = Release|Win32
|
||||
{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}.Release|x86.Build.0 = Release|Win32
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Debug|x64.Build.0 = Debug|x64
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Debug|x86.Build.0 = Debug|Win32
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x64.ActiveCfg = Release|x64
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x64.Build.0 = Release|x64
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x86.ActiveCfg = Release|Win32
|
||||
{A2E01C3E-D647-45D1-9788-043DEBC1A908}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DCE19FF1-37C0-49CD-915A-DD695E15F00B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,72 @@
|
|||
#include "Animation.h"
|
||||
|
||||
void Ship::AnimationV0::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
Animation* anim = (Animation*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
AnimationType animType = (AnimationType)reader->ReadUInt32();
|
||||
anim->type = animType;
|
||||
|
||||
if (animType == AnimationType::Normal)
|
||||
{
|
||||
anim->frameCount = reader->ReadInt16();
|
||||
|
||||
uint32_t rotValuesCnt = reader->ReadUInt32();
|
||||
anim->rotationValues.reserve(rotValuesCnt);
|
||||
for (uint32_t i = 0; i < rotValuesCnt; i++)
|
||||
anim->rotationValues.push_back(reader->ReadUInt16());
|
||||
|
||||
|
||||
uint32_t rotIndCnt = reader->ReadUInt32();
|
||||
anim->rotationIndices.reserve(rotIndCnt);
|
||||
for (int i = 0; i < rotIndCnt; i++)
|
||||
{
|
||||
uint16_t x = reader->ReadUInt16();
|
||||
uint16_t y = reader->ReadUInt16();
|
||||
uint16_t z = reader->ReadUInt16();
|
||||
anim->rotationIndices.push_back(RotationIndex(x, y, z));
|
||||
}
|
||||
anim->limit = reader->ReadInt16();
|
||||
}
|
||||
else if (animType == AnimationType::Curve)
|
||||
{
|
||||
anim->frameCount = reader->ReadInt16();
|
||||
|
||||
uint32_t refArrCnt = reader->ReadUInt32();
|
||||
anim->refIndexArr.reserve(refArrCnt);
|
||||
for (uint32_t i = 0; i < refArrCnt; i++)
|
||||
anim->refIndexArr.push_back(reader->ReadUByte());
|
||||
|
||||
uint32_t transformDataCnt = reader->ReadUInt32();
|
||||
anim->transformDataArr.reserve(transformDataCnt);
|
||||
for (uint32_t i = 0; i < transformDataCnt; i++)
|
||||
{
|
||||
TransformData data;
|
||||
data.unk_00 = reader->ReadUInt16();
|
||||
data.unk_02 = reader->ReadInt16();
|
||||
data.unk_04 = reader->ReadInt16();
|
||||
data.unk_06 = reader->ReadInt16();
|
||||
data.unk_08 = reader->ReadSingle();
|
||||
|
||||
anim->transformDataArr.push_back(data);
|
||||
}
|
||||
|
||||
uint32_t copyValuesCnt = reader->ReadUInt32();
|
||||
anim->copyValuesArr.reserve(copyValuesCnt);
|
||||
for (uint32_t i = 0; i < copyValuesCnt; i++)
|
||||
{
|
||||
anim->copyValuesArr.push_back(reader->ReadInt16());
|
||||
}
|
||||
}
|
||||
else if (animType == AnimationType::Link)
|
||||
{
|
||||
anim->frameCount = reader->ReadInt16();
|
||||
anim->segPtr = reader->ReadUInt32();
|
||||
}
|
||||
else if (animType == AnimationType::Legacy)
|
||||
{
|
||||
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
enum class AnimationType
|
||||
{
|
||||
Normal = 0,
|
||||
Link = 1,
|
||||
Curve = 2,
|
||||
Legacy = 3,
|
||||
};
|
||||
|
||||
struct RotationIndex
|
||||
{
|
||||
uint16_t x, y, z;
|
||||
|
||||
RotationIndex(uint16_t nX, uint16_t nY, uint16_t nZ) : x(nX), y(nY), z(nZ) {}
|
||||
};
|
||||
|
||||
class TransformData
|
||||
{
|
||||
public:
|
||||
///* 0x0000 */ u16 unk_00; // appears to be flags
|
||||
uint16_t unk_00;
|
||||
///* 0x0002 */ s16 unk_02;
|
||||
int16_t unk_02;
|
||||
///* 0x0004 */ s16 unk_04;
|
||||
int16_t unk_04;
|
||||
///* 0x0006 */ s16 unk_06;
|
||||
int16_t unk_06;
|
||||
///* 0x0008 */ f32 unk_08;
|
||||
float unk_08;
|
||||
};
|
||||
|
||||
class AnimationV0 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
};
|
||||
|
||||
class Animation : public Resource
|
||||
{
|
||||
public:
|
||||
AnimationType type;
|
||||
int16_t frameCount;
|
||||
|
||||
// NORMAL
|
||||
std::vector<uint16_t> rotationValues;
|
||||
std::vector<RotationIndex> rotationIndices;
|
||||
int16_t limit = 0;
|
||||
|
||||
// CURVE
|
||||
std::vector<uint8_t> refIndexArr;
|
||||
std::vector<TransformData> transformDataArr;
|
||||
std::vector<int16_t> copyValuesArr;
|
||||
|
||||
// LINK
|
||||
uint32_t segPtr; // This is temp
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
#include "Archive.h"
|
||||
#include "Resource.h"
|
||||
#include "File.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "Utils/StringHelper.h"
|
||||
#include "Lib/StrHash64.h"
|
||||
#include <filesystem>
|
||||
|
||||
namespace Ship {
|
||||
Archive::Archive(const std::string& MainPath, bool enableWriting) : Archive(MainPath, "", enableWriting)
|
||||
{
|
||||
mainMPQ = nullptr;
|
||||
}
|
||||
|
||||
Archive::Archive(const std::string& MainPath, const std::string& PatchesPath, bool enableWriting, bool genCRCMap) : MainPath(MainPath), PatchesPath(PatchesPath) {
|
||||
mainMPQ = nullptr;
|
||||
Load(enableWriting, genCRCMap);
|
||||
}
|
||||
|
||||
Archive::~Archive() {
|
||||
Unload();
|
||||
}
|
||||
|
||||
bool Archive::IsMainMPQValid()
|
||||
{
|
||||
return mainMPQ != nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Archive> Archive::CreateArchive(const std::string& archivePath, int fileCapacity)
|
||||
{
|
||||
Archive* archive = new Archive(archivePath, true);
|
||||
|
||||
TCHAR* t_filename = new TCHAR[archivePath.size() + 1];
|
||||
t_filename[archivePath.size()] = 0;
|
||||
std::copy(archivePath.begin(), archivePath.end(), t_filename);
|
||||
|
||||
bool success = SFileCreateArchive(t_filename, MPQ_CREATE_LISTFILE | MPQ_CREATE_ATTRIBUTES | MPQ_CREATE_ARCHIVE_V2, fileCapacity, &archive->mainMPQ);
|
||||
int error = GetLastError();
|
||||
|
||||
if (success) {
|
||||
archive->mpqHandles[archivePath] = archive->mainMPQ;
|
||||
return std::make_shared<Archive>(*archive);
|
||||
} else {
|
||||
SPDLOG_ERROR("({}) We tried to create an archive, but it has fallen and cannot get up.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<File> Archive::LoadFile(const std::string& filePath, bool includeParent, std::shared_ptr<File> FileToLoad) {
|
||||
HANDLE fileHandle = NULL;
|
||||
|
||||
if (!SFileOpenFileEx(mainMPQ, filePath.c_str(), 0, &fileHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to open file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
std::unique_lock<std::mutex> Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->bHasLoadError = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DWORD dwFileSize = SFileGetFileSize(fileHandle, 0);
|
||||
std::shared_ptr<char[]> fileData(new char[dwFileSize]);
|
||||
DWORD dwBytes;
|
||||
|
||||
if (!SFileReadFile(fileHandle, fileData.get(), dwFileSize, &dwBytes, NULL)) {
|
||||
SPDLOG_ERROR("({}) Failed to read file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
if (!SFileCloseFile(fileHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} from mpq after read failure in archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
}
|
||||
std::unique_lock<std::mutex> Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->bHasLoadError = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!SFileCloseFile(fileHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
}
|
||||
|
||||
if (FileToLoad == nullptr) {
|
||||
FileToLoad = std::make_shared<File>();
|
||||
FileToLoad->path = filePath;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->parent = includeParent ? shared_from_this() : nullptr;
|
||||
FileToLoad->buffer = fileData;
|
||||
FileToLoad->dwBufferSize = dwFileSize;
|
||||
FileToLoad->bIsLoaded = true;
|
||||
|
||||
return FileToLoad;
|
||||
}
|
||||
|
||||
std::shared_ptr<File> Archive::LoadPatchFile(const std::string& filePath, bool includeParent, std::shared_ptr<File> FileToLoad) {
|
||||
HANDLE fileHandle = NULL;
|
||||
HANDLE mpqHandle = NULL;
|
||||
|
||||
for(auto [path, handle] : mpqHandles) {
|
||||
if (SFileOpenFileEx(mpqHandle, filePath.c_str(), 0, &fileHandle)) {
|
||||
std::unique_lock Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->bHasLoadError = false;
|
||||
mpqHandle = handle;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mpqHandle) {
|
||||
FileToLoad->bHasLoadError = true;
|
||||
return FileToLoad;
|
||||
}
|
||||
|
||||
DWORD dwFileSize = SFileGetFileSize(fileHandle, 0);
|
||||
std::shared_ptr<char[]> fileData(new char[dwFileSize]);
|
||||
DWORD dwBytes;
|
||||
|
||||
if (!SFileReadFile(fileHandle, fileData.get(), dwFileSize, &dwBytes, NULL)) {
|
||||
SPDLOG_ERROR("({}) Failed to read file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
if (!SFileCloseFile(fileHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} from mpq after read failure in archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
}
|
||||
std::unique_lock<std::mutex> Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->bHasLoadError = true;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!SFileCloseFile(fileHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} from mpq archive {}", GetLastError(), filePath.c_str(), MainPath.c_str());
|
||||
}
|
||||
|
||||
if (FileToLoad == nullptr) {
|
||||
FileToLoad = std::make_shared<File>();
|
||||
FileToLoad->path = filePath;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> Lock(FileToLoad->FileLoadMutex);
|
||||
FileToLoad->parent = includeParent ? shared_from_this() : nullptr;
|
||||
FileToLoad->buffer = fileData;
|
||||
FileToLoad->dwBufferSize = dwFileSize;
|
||||
FileToLoad->bIsLoaded = true;
|
||||
|
||||
return FileToLoad;
|
||||
}
|
||||
|
||||
bool Archive::AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize) {
|
||||
HANDLE hFile;
|
||||
|
||||
SYSTEMTIME sysTime;
|
||||
GetSystemTime(&sysTime);
|
||||
FILETIME t;
|
||||
SystemTimeToFileTime(&sysTime, &t);
|
||||
ULONGLONG stupidHack = static_cast<uint64_t>(t.dwHighDateTime) << (sizeof(t.dwHighDateTime) * 8) | t.dwLowDateTime;
|
||||
|
||||
if (!SFileCreateFile(mainMPQ, path.c_str(), stupidHack, dwFileSize, 0, MPQ_FILE_COMPRESS, &hFile)) {
|
||||
SPDLOG_ERROR("({}) Failed to create file of {} bytes {} in archive {}", GetLastError(), dwFileSize, path.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SFileWriteFile(hFile, (void*)fileData, dwFileSize, MPQ_COMPRESSION_ZLIB)) {
|
||||
SPDLOG_ERROR("({}) Failed to write {} bytes to {} in archive {}", GetLastError(), dwFileSize, path.c_str(), MainPath.c_str());
|
||||
if (!SFileCloseFile(hFile)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} after write failure in archive {}", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SFileFinishFile(hFile)) {
|
||||
SPDLOG_ERROR("({}) Failed to finish file {} in archive {}", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
if (!SFileCloseFile(hFile)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file {} after finish failure in archive {}", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// SFileFinishFile already frees the handle, so no need to close it again.
|
||||
|
||||
addedFiles.push_back(path);
|
||||
hashes[CRC64(path.c_str())] = path;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Archive::RemoveFile(const std::string& path) {
|
||||
// TODO: Notify the resource manager and child Files
|
||||
|
||||
if (!SFileRemoveFile(mainMPQ, path.c_str(), 0)) {
|
||||
SPDLOG_ERROR("({}) Failed to remove file {} in archive {}", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Archive::RenameFile(const std::string& oldPath, const std::string& newPath) {
|
||||
// TODO: Notify the resource manager and child Files
|
||||
|
||||
if (!SFileRenameFile(mainMPQ, oldPath.c_str(), newPath.c_str())) {
|
||||
SPDLOG_ERROR("({}) Failed to rename file {} to {} in archive {}", GetLastError(), oldPath.c_str(), newPath.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<SFILE_FIND_DATA> Archive::ListFiles(const std::string& searchMask) {
|
||||
auto fileList = std::vector<SFILE_FIND_DATA>();
|
||||
SFILE_FIND_DATA findContext;
|
||||
HANDLE hFind;
|
||||
|
||||
|
||||
hFind = SFileFindFirstFile(mainMPQ, searchMask.c_str(), &findContext, nullptr);
|
||||
//if (hFind && GetLastError() != ERROR_NO_MORE_FILES) {
|
||||
if (hFind != nullptr) {
|
||||
fileList.push_back(findContext);
|
||||
|
||||
bool fileFound;
|
||||
do {
|
||||
fileFound = SFileFindNextFile(hFind, &findContext);
|
||||
|
||||
if (fileFound) {
|
||||
fileList.push_back(findContext);
|
||||
}
|
||||
else if (!fileFound && GetLastError() != ERROR_NO_MORE_FILES)
|
||||
//else if (!fileFound)
|
||||
{
|
||||
SPDLOG_ERROR("({}), Failed to search with mask {} in archive {}", GetLastError(), searchMask.c_str(), MainPath.c_str());
|
||||
if (!SListFileFindClose(hFind)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file search {} after failure in archive {}", GetLastError(), searchMask.c_str(), MainPath.c_str());
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
} while (fileFound);
|
||||
}
|
||||
else if (GetLastError() != ERROR_NO_MORE_FILES) {
|
||||
SPDLOG_ERROR("({}), Failed to search with mask {} in archive {}", GetLastError(), searchMask.c_str(), MainPath.c_str());
|
||||
return fileList;
|
||||
}
|
||||
|
||||
if (hFind != nullptr)
|
||||
{
|
||||
if (!SFileFindClose(hFind)) {
|
||||
SPDLOG_ERROR("({}) Failed to close file search {} in archive {}", GetLastError(), searchMask.c_str(), MainPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return fileList;
|
||||
}
|
||||
|
||||
bool Archive::HasFile(const std::string& filename) {
|
||||
bool result = false;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
auto lst = ListFiles(filename);
|
||||
|
||||
for (const auto& item : lst) {
|
||||
if (item.cFileName == filename) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto end = std::chrono::steady_clock::now();
|
||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Archive::HashToString(uint64_t hash) {
|
||||
return hashes[hash];
|
||||
}
|
||||
|
||||
bool Archive::Load(bool enableWriting, bool genCRCMap) {
|
||||
return LoadMainMPQ(enableWriting, genCRCMap) && LoadPatchMPQs();
|
||||
}
|
||||
|
||||
bool Archive::Unload()
|
||||
{
|
||||
bool success = true;
|
||||
for (const auto& mpqHandle : mpqHandles) {
|
||||
if (!SFileCloseArchive(mpqHandle.second)) {
|
||||
SPDLOG_ERROR("({}) Failed to close mpq {}", GetLastError(), mpqHandle.first.c_str());
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
mainMPQ = nullptr;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Archive::LoadPatchMPQs() {
|
||||
// OTRTODO: We also want to periodically scan the patch directories for new MPQs. When new MPQs are found we will load the contents to fileCache and then copy over to gameResourceAddresses
|
||||
if (PatchesPath.length() > 0) {
|
||||
if (std::filesystem::is_directory(PatchesPath)) {
|
||||
for (const auto& p : std::filesystem::recursive_directory_iterator(PatchesPath)) {
|
||||
if (StringHelper::IEquals(p.path().extension().string(), ".otr") || StringHelper::IEquals(p.path().extension().string(), ".mpq")) {
|
||||
SPDLOG_ERROR("Reading {} mpq patch", p.path().string().c_str());
|
||||
if (!LoadPatchMPQ(p.path().string())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Archive::LoadMainMPQ(bool enableWriting, bool genCRCMap) {
|
||||
HANDLE mpqHandle = NULL;
|
||||
std::string fullPath = std::filesystem::absolute(MainPath).string();
|
||||
|
||||
std::wstring wFileName = std::filesystem::absolute(MainPath).wstring();
|
||||
|
||||
if (!SFileOpenArchive(wFileName.c_str(), 0, enableWriting ? 0 : MPQ_OPEN_READ_ONLY, &mpqHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to open main mpq file {}.", GetLastError(), fullPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
mpqHandles[fullPath] = mpqHandle;
|
||||
mainMPQ = mpqHandle;
|
||||
|
||||
if (genCRCMap) {
|
||||
auto listFile = LoadFile("(listfile)", false);
|
||||
|
||||
std::vector<std::string> lines = StringHelper::Split(std::string(listFile->buffer.get(), listFile->dwBufferSize), "\n");
|
||||
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
std::string line = StringHelper::Strip(lines[i], "\r");
|
||||
//uint64_t hash = StringHelper::StrToL(lines[i], 16);
|
||||
|
||||
uint64_t hash = CRC64(line.c_str());
|
||||
hashes[hash] = line;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Archive::LoadPatchMPQ(const std::string& path) {
|
||||
HANDLE patchHandle = NULL;
|
||||
std::string fullPath = std::filesystem::absolute(path).string();
|
||||
if (mpqHandles.contains(fullPath)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring wPath = std::filesystem::absolute(path).wstring();
|
||||
|
||||
if (!SFileOpenArchive(wPath.c_str(), 0, MPQ_OPEN_READ_ONLY, &patchHandle)) {
|
||||
SPDLOG_ERROR("({}) Failed to open patch mpq file {} while applying to {}.", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SFileOpenPatchArchive(mainMPQ, wPath.c_str(), "", 0)) {
|
||||
SPDLOG_ERROR("({}) Failed to apply patch mpq file {} to main mpq {}.", GetLastError(), path.c_str(), MainPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
mpqHandles[fullPath] = patchHandle;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#pragma once
|
||||
|
||||
#undef _DLL
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Resource.h"
|
||||
//#include "Lib/StrHash64.h"
|
||||
#include "Lib/StormLib/StormLib.h"
|
||||
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
class File;
|
||||
|
||||
class Archive : public std::enable_shared_from_this<Archive>
|
||||
{
|
||||
public:
|
||||
Archive(const std::string& MainPath, bool enableWriting);
|
||||
Archive(const std::string& MainPath, const std::string& PatchesPath, bool enableWriting, bool genCRCMap = true);
|
||||
~Archive();
|
||||
|
||||
bool IsMainMPQValid();
|
||||
|
||||
static std::shared_ptr<Archive> CreateArchive(const std::string& archivePath, int fileCapacity);
|
||||
|
||||
std::shared_ptr<File> LoadFile(const std::string& filePath, bool includeParent = true, std::shared_ptr<File> FileToLoad = nullptr);
|
||||
std::shared_ptr<File> LoadPatchFile(const std::string& filePath, bool includeParent = true, std::shared_ptr<File> FileToLoad = nullptr);
|
||||
|
||||
bool AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize);
|
||||
bool RemoveFile(const std::string& path);
|
||||
bool RenameFile(const std::string& oldPath, const std::string& newPath);
|
||||
std::vector<SFILE_FIND_DATA> ListFiles(const std::string& searchMask);
|
||||
bool HasFile(const std::string& searchMask);
|
||||
std::string HashToString(uint64_t hash);
|
||||
protected:
|
||||
bool Load(bool enableWriting, bool genCRCMap);
|
||||
bool Unload();
|
||||
private:
|
||||
std::string MainPath;
|
||||
std::string PatchesPath;
|
||||
std::map<std::string, HANDLE> mpqHandles;
|
||||
std::vector<std::string> addedFiles;
|
||||
std::map<uint64_t, std::string> hashes;
|
||||
HANDLE mainMPQ;
|
||||
|
||||
bool LoadMainMPQ(bool enableWriting, bool genCRCMap);
|
||||
bool LoadPatchMPQs();
|
||||
bool LoadPatchMPQ(const std::string& path);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#include "Array.h"
|
||||
#include "Vertex.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
void ArrayV0::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
Array* arr = (Array*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
ZResourceType resType = (ZResourceType)reader->ReadUInt32();
|
||||
uint32_t arrayCnt = reader->ReadUInt32();
|
||||
|
||||
for (uint32_t i = 0; i < arrayCnt; i++)
|
||||
{
|
||||
if (resType == ZResourceType::Vertex)
|
||||
{
|
||||
Vtx data;
|
||||
data.x = reader->ReadInt16();
|
||||
data.y = reader->ReadInt16();
|
||||
data.z = reader->ReadInt16();
|
||||
data.flag = reader->ReadUInt16();
|
||||
data.s = reader->ReadInt16();
|
||||
data.t = reader->ReadInt16();
|
||||
data.r = reader->ReadUByte();
|
||||
data.g = reader->ReadUByte();
|
||||
data.b = reader->ReadUByte();
|
||||
data.a = reader->ReadUByte();
|
||||
arr->vertices.push_back(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScalarType scalType = (ScalarType)reader->ReadUInt32();
|
||||
|
||||
int iter = 1;
|
||||
|
||||
if (resType == ZResourceType::Vector)
|
||||
iter = reader->ReadUInt32();
|
||||
|
||||
for (int k = 0; k < iter; k++)
|
||||
{
|
||||
ScalarData data;
|
||||
|
||||
switch (scalType)
|
||||
{
|
||||
case ScalarType::ZSCALAR_S16:
|
||||
data.s16 = reader->ReadInt16();
|
||||
break;
|
||||
case ScalarType::ZSCALAR_U16:
|
||||
data.u16 = reader->ReadUInt16();
|
||||
break;
|
||||
// OTRTODO: IMPLEMENT OTHER TYPES!
|
||||
}
|
||||
|
||||
arr->scalars.push_back(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
#include "Vertex.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
typedef union ScalarData
|
||||
{
|
||||
uint8_t u8;
|
||||
int8_t s8;
|
||||
uint16_t u16;
|
||||
int16_t s16;
|
||||
uint32_t u32;
|
||||
int32_t s32;
|
||||
uint64_t u64;
|
||||
int64_t s64;
|
||||
float f32;
|
||||
double f64;
|
||||
} ScalarData;
|
||||
|
||||
enum class ScalarType
|
||||
{
|
||||
ZSCALAR_NONE,
|
||||
ZSCALAR_S8,
|
||||
ZSCALAR_U8,
|
||||
ZSCALAR_X8,
|
||||
ZSCALAR_S16,
|
||||
ZSCALAR_U16,
|
||||
ZSCALAR_X16,
|
||||
ZSCALAR_S32,
|
||||
ZSCALAR_U32,
|
||||
ZSCALAR_X32,
|
||||
ZSCALAR_S64,
|
||||
ZSCALAR_U64,
|
||||
ZSCALAR_X64,
|
||||
ZSCALAR_F32,
|
||||
ZSCALAR_F64
|
||||
};
|
||||
|
||||
// OTRTODO: Replace this with something that can be shared between the exporter and importer...
|
||||
enum class ZResourceType
|
||||
{
|
||||
Error,
|
||||
Animation,
|
||||
Array,
|
||||
AltHeader,
|
||||
Background,
|
||||
Blob,
|
||||
CollisionHeader,
|
||||
Cutscene,
|
||||
DisplayList,
|
||||
Limb,
|
||||
LimbTable,
|
||||
Mtx,
|
||||
Path,
|
||||
PlayerAnimationData,
|
||||
Room,
|
||||
RoomCommand,
|
||||
Scalar,
|
||||
Scene,
|
||||
Skeleton,
|
||||
String,
|
||||
Symbol,
|
||||
Texture,
|
||||
TextureAnimation,
|
||||
TextureAnimationParams,
|
||||
Vector,
|
||||
Vertex,
|
||||
};
|
||||
|
||||
class ArrayV0 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
};
|
||||
|
||||
class Array : public Resource
|
||||
{
|
||||
public:
|
||||
std::vector<ScalarData> scalars;
|
||||
std::vector<Vtx> vertices;
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "stdint.h"
|
||||
|
||||
namespace Ship {
|
||||
class AudioPlayer {
|
||||
|
||||
public:
|
||||
AudioPlayer() { };
|
||||
|
||||
virtual bool Init(void) = 0;
|
||||
virtual int Buffered(void) = 0;
|
||||
virtual int GetDesiredBuffered(void) = 0;
|
||||
virtual void Play(const uint8_t* buf, uint32_t len) = 0;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#include "Blob.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
void BlobV0::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
Blob* blob = (Blob*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, blob);
|
||||
|
||||
uint32_t dataSize = reader->ReadUInt32();
|
||||
|
||||
blob->data.reserve(dataSize);
|
||||
|
||||
for (uint32_t i = 0; i < dataSize; i++)
|
||||
blob->data.push_back(reader->ReadUByte());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource.h"
|
||||
|
||||
namespace Ship
|
||||
{
|
||||
class BlobV0 : public ResourceFile
|
||||
{
|
||||
public:
|
||||
|
||||
void ParseFileBinary(BinaryReader* reader, Resource* res) override;
|
||||
};
|
||||
|
||||
class Blob : public Resource
|
||||
{
|
||||
public:
|
||||
std::vector<uint8_t> data;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,99 @@
|
|||
#include "CollisionHeader.h"
|
||||
|
||||
void Ship::CollisionHeaderV0::ParseFileBinary(BinaryReader* reader, Resource* res)
|
||||
{
|
||||
CollisionHeader* col = (CollisionHeader*)res;
|
||||
|
||||
ResourceFile::ParseFileBinary(reader, res);
|
||||
|
||||
col->absMinX = reader->ReadInt16();
|
||||
col->absMinY = reader->ReadInt16();
|
||||
col->absMinZ = reader->ReadInt16();
|
||||
|
||||
col->absMaxX = reader->ReadInt16();
|
||||
col->absMaxY = reader->ReadInt16();
|
||||
col->absMaxZ = reader->ReadInt16();
|
||||
|
||||
uint32_t vtxCnt = reader->ReadInt32();
|
||||
col->vertices.reserve(vtxCnt);
|
||||
|
||||
for (uint32_t i = 0; i < vtxCnt; i++)
|
||||
{
|
||||
float x = reader->ReadInt16();
|
||||
float y = reader->ReadInt16();
|
||||
float z = reader->ReadInt16();
|
||||
col->vertices.push_back(Vec3f(x, y, z));
|
||||
}
|
||||
|
||||
uint32_t polyCnt = reader->ReadUInt32();
|
||||
col->polygons.reserve(polyCnt);
|
||||
|
||||
for (uint32_t i = 0; i < polyCnt; i++)
|
||||
col->polygons.push_back(Ship::PolygonEntry(reader));
|
||||
|
||||
uint32_t polyTypesCnt = reader->ReadUInt32();
|
||||
col->polygonTypes.reserve(polyTypesCnt);
|
||||
|
||||
for (uint32_t i = 0; i < polyTypesCnt; i++)
|
||||
col->polygonTypes.push_back(reader->ReadUInt64());
|
||||
|
||||
col->camData = new CameraDataList();
|
||||
|
||||
uint32_t camEntriesCnt = reader->ReadUInt32();
|
||||
col->camData->entries.reserve(camEntriesCnt);
|
||||
|
||||
for (uint32_t i = 0; i < camEntriesCnt; i++)
|
||||
{
|
||||
Ship::CameraDataEntry* entry = new Ship::CameraDataEntry();
|
||||
entry->cameraSType = reader->ReadUInt16();
|
||||
entry->numData = reader->ReadInt16();
|
||||
entry->cameraPosDataIdx = reader->ReadInt32();
|
||||
col->camData->entries.push_back(entry);
|
||||
}
|
||||
|
||||
uint32_t camPosCnt = reader->ReadInt32();
|
||||
col->camData->cameraPositionData.reserve(camPosCnt);
|
||||
|
||||
for (uint32_t i = 0; i < camPosCnt; i++)
|
||||
{
|
||||
Ship::CameraPositionData* entry = new Ship::CameraPositionData();
|
||||
entry->x = reader->ReadInt16();
|
||||
entry->y = reader->ReadInt16();
|
||||
entry->z = reader->ReadInt16();
|
||||
col->camData->cameraPositionData.push_back(entry);
|
||||
}
|
||||
|
||||
uint32_t waterBoxCnt = reader->ReadInt32();
|
||||
col->waterBoxes.reserve(waterBoxCnt);
|
||||
|
||||
for (uint32_t i = 0; i < waterBoxCnt; i++)
|
||||
{
|
||||
Ship::WaterBoxHeader waterBox;
|
||||
waterBox.xMin = reader->ReadInt16();
|
||||
waterBox.ySurface = reader->ReadInt16();
|
||||
waterBox.zMin = reader->ReadInt16();
|
||||
waterBox.xLength = reader->ReadInt16();
|
||||
waterBox.zLength = reader->ReadInt16();
|
||||
waterBox.properties = reader->ReadInt32();
|
||||
|
||||
col->waterBoxes.push_back(waterBox);
|
||||
}
|
||||
}
|
||||
|
||||
Ship::PolygonEntry::PolygonEntry(BinaryReader* reader)
|
||||
{
|
||||
type = reader->ReadUInt16();
|
||||
|
||||
vtxA = reader->ReadUInt16();
|
||||
vtxB = reader->ReadUInt16();
|
||||
vtxC = reader->ReadUInt16();
|
||||
|
||||
a = reader->ReadUInt16();
|
||||
b = reader->ReadUInt16();
|
||||
c = reader->ReadUInt16();
|
||||
d = |