-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* use image.OverrideFormat() * 1.6.4 * import std * uninitialised member variable * debug statement for 64 bit hash testing * nopetynope * uint32_t * support for 64 bit hashes, but rip compute time :/ * refactor weird comments and constructors * 1.7.0.0 because of 64 bit hashes * only check crc64 if at least one mod with crc64 is loaded * do some dumb shit to deal with incorrect bmps somehow (needs work) * remove image interpretation for bmps * create TpfConvert.exe to convert tpf files easily * attempt * set up vcpkg and install d3dx though that * missing env variable? * Win32 architecture * update ci to tag TpfConvert.exe and d3dx9.dll as well (required to run TpfConvert) * documentation
- Loading branch information
1 parent
8664555
commit fd9d1af
Showing
24 changed files
with
726 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,8 +29,20 @@ jobs: | |
- name: Setup MSBuild.exe | ||
uses: microsoft/[email protected] | ||
|
||
- name: Build CMake Files | ||
run: cmake -S . -B build -A Win32 | ||
- name: Install vcpkg | ||
run: | | ||
git clone https://github.com/microsoft/vcpkg.git | ||
.\vcpkg\bootstrap-vcpkg.bat | ||
- name: Set VCPKG_ROOT | ||
run: | | ||
echo "VCPKG_ROOT=$(Get-Location)\vcpkg" >> $env:GITHUB_ENV | ||
shell: powershell | ||
|
||
- name: Build CMake Files with vcpkg toolchain | ||
run: cmake --preset=vcpkg | ||
env: | ||
VCPKG_ROOT: ${{ env.VCPKG_ROOT }} | ||
|
||
- name: Build binaries | ||
run: cmake --build build --config Release | ||
|
@@ -54,7 +66,7 @@ jobs: | |
mode: update | ||
tag_name: v${{ steps.set_version.outputs.version }} | ||
release_name: gMod v${{ steps.set_version.outputs.version }} | ||
assets: .\bin\Release\gMod.dll | ||
assets: .\bin\Release\gMod.dll,.\bin\Release\TpfConvert.exe,.\bin\Release\d3dx9_43.dll | ||
github_token: ${{ env.GITHUB_TOKEN }} | ||
replace_assets: true | ||
body_mrkdwn: ${{ env.Changelog }} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
name: gMod CI Pipeline | ||
name: gMod CI Pipeline | ||
|
||
on: | ||
pull_request: | ||
|
@@ -8,9 +8,8 @@ on: | |
branches: | ||
- dev | ||
workflow_dispatch: | ||
|
||
jobs: | ||
|
||
jobs: | ||
build: | ||
|
||
strategy: | ||
|
@@ -32,8 +31,20 @@ jobs: | |
- name: Setup MSBuild.exe | ||
uses: microsoft/[email protected] | ||
|
||
- name: Build CMake Files | ||
run: cmake -S . -B build -A Win32 | ||
- name: Install vcpkg | ||
run: | | ||
git clone https://github.com/microsoft/vcpkg.git | ||
.\vcpkg\bootstrap-vcpkg.bat | ||
- name: Set VCPKG_ROOT | ||
run: | | ||
echo "VCPKG_ROOT=$(Get-Location)\vcpkg" >> $env:GITHUB_ENV | ||
shell: powershell | ||
|
||
- name: Build CMake Files with vcpkg toolchain | ||
run: cmake --preset=vcpkg | ||
env: | ||
VCPKG_ROOT: ${{ env.VCPKG_ROOT }} | ||
|
||
- name: Build binaries | ||
run: cmake --build build --config Release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,8 @@ bin/ | |
*/Release | ||
*/bin | ||
*/obj | ||
vcpkg | ||
vcpkg_installed | ||
|
||
# Bloated Windows Databases | ||
*.sdf | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"version": 2, | ||
"configurePresets": [ | ||
{ | ||
"name": "vcpkg", | ||
"generator": "Visual Studio 17 2022", | ||
"architecture": "Win32", | ||
"binaryDir": "${sourceDir}/build", | ||
"cacheVariables": { | ||
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
add_executable(TpfConvert) | ||
|
||
# Find all .ixx files in the TpfConvert folder | ||
file(GLOB TPF_SOURCES "src/*.ixx") | ||
|
||
# Add the .ixx files to the TpfConvert target | ||
target_sources(TpfConvert PRIVATE ${TPF_SOURCES}) | ||
|
||
set_target_properties(TpfConvert PROPERTIES | ||
CXX_STANDARD 23 | ||
CXX_STANDARD_REQUIRED ON | ||
) | ||
|
||
target_compile_definitions(TpfConvert PRIVATE | ||
"NOMINMAX" | ||
"_WIN32_WINNT=_WIN32_WINNT_WIN7" | ||
"WIN32_LEAN_AND_MEAN" | ||
"VC_EXTRALEAN" | ||
) | ||
|
||
if(DEFINED ENV{VCPKG_ROOT}) | ||
message(STATUS "VCPKG_ROOT: $ENV{VCPKG_ROOT}") | ||
else() | ||
message(STATUS "VCPKG_ROOT is not set") | ||
endif() | ||
|
||
if(DEFINED CMAKE_TOOLCHAIN_FILE) | ||
message(STATUS "CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") | ||
else() | ||
message(STATUS "CMAKE_TOOLCHAIN_FILE is not set") | ||
endif() | ||
|
||
find_package(dxsdk-d3dx CONFIG REQUIRED) | ||
|
||
target_link_libraries(TpfConvert PRIVATE | ||
libzippp | ||
Microsoft::D3DX9 | ||
d3d9 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
export module ModfileLoader; | ||
|
||
import std; | ||
import <libzippp.h>; | ||
import ModfileLoader.TpfReader; | ||
|
||
export using HashType = uint64_t; | ||
|
||
export struct TexEntry { | ||
std::vector<uint8_t> data{}; | ||
HashType crc_hash = 0; // hash value | ||
std::string ext{}; | ||
}; | ||
|
||
namespace { | ||
HashType GetCrcFromFilename(const std::string& filename) { | ||
const static std::regex re(R"(0x[0-9a-f]{4,16})", std::regex::optimize | std::regex::icase); | ||
std::smatch match; | ||
if (!std::regex_search(filename, match, re)) { | ||
return 0; | ||
} | ||
|
||
uint64_t crc64_hash = 0; | ||
const auto number_str = match.str(); | ||
try { | ||
crc64_hash = std::stoull(number_str, nullptr, 16); | ||
} | ||
catch (const std::invalid_argument&) { | ||
std::print(stderr, "Failed to parse {} as a hash\n", filename); | ||
return 0; | ||
} | ||
catch (const std::out_of_range&) { | ||
std::print(stderr, "Out of range while parsing {} as a hash\n", filename); | ||
return 0; | ||
} | ||
return crc64_hash; | ||
} | ||
} | ||
|
||
export class ModfileLoader { | ||
std::filesystem::path file_name; | ||
const std::string TPF_PASSWORD{ | ||
0x73, 0x2A, 0x63, 0x7D, 0x5F, 0x0A, static_cast<char>(0xA6), static_cast<char>(0xBD), | ||
0x7D, 0x65, 0x7E, 0x67, 0x61, 0x2A, 0x7F, 0x7F, | ||
0x74, 0x61, 0x67, 0x5B, 0x60, 0x70, 0x45, 0x74, | ||
0x5C, 0x22, 0x74, 0x5D, 0x6E, 0x6A, 0x73, 0x41, | ||
0x77, 0x6E, 0x46, 0x47, 0x77, 0x49, 0x0C, 0x4B, | ||
0x46, 0x6F | ||
}; | ||
|
||
public: | ||
ModfileLoader(const std::filesystem::path& fileName); | ||
|
||
std::vector<TexEntry> GetContents() const; | ||
|
||
private: | ||
|
||
std::vector<TexEntry> GetTpfContents() const; | ||
|
||
std::vector<TexEntry> GetFileContents() const; | ||
|
||
static void LoadEntries(libzippp::ZipArchive& archive, std::vector<TexEntry>& entries); | ||
}; | ||
|
||
ModfileLoader::ModfileLoader(const std::filesystem::path& fileName) | ||
{ | ||
file_name = std::filesystem::absolute(fileName); | ||
} | ||
|
||
std::vector<TexEntry> ModfileLoader::GetContents() const | ||
{ | ||
try { | ||
return file_name.wstring().ends_with(L".tpf") ? GetTpfContents() : GetFileContents(); | ||
} | ||
catch (const std::exception&) { | ||
std::print(stderr, "Failed to open mod file: {}\n", file_name.string().c_str()); | ||
} | ||
return {}; | ||
} | ||
|
||
std::vector<TexEntry> ModfileLoader::GetTpfContents() const | ||
{ | ||
std::vector<TexEntry> entries; | ||
auto tpf_reader = TpfReader(file_name); | ||
const auto buffer = tpf_reader.ReadToEnd(); | ||
const auto zip_archive = libzippp::ZipArchive::fromBuffer(buffer.data(), buffer.size(), false, TPF_PASSWORD); | ||
if (!zip_archive) { | ||
std::print(stderr, "Failed to open tpf file: {} - {} uint8_ts!\n", file_name.string(), buffer.size()); | ||
return {}; | ||
} | ||
zip_archive->setErrorHandlerCallback( | ||
[](const std::string& message, const std::string& strerror, int zip_error_code, int system_error_code) -> void { | ||
std::print(stderr, "GetTpfContents: {} {} {} {}\n", message, strerror, zip_error_code, system_error_code); | ||
}); | ||
zip_archive->open(); | ||
LoadEntries(*zip_archive, entries); | ||
zip_archive->close(); | ||
libzippp::ZipArchive::free(zip_archive); | ||
|
||
return entries; | ||
} | ||
|
||
std::vector<TexEntry> ModfileLoader::GetFileContents() const | ||
{ | ||
std::vector<TexEntry> entries; | ||
|
||
libzippp::ZipArchive zip_archive(file_name.string()); | ||
zip_archive.open(); | ||
LoadEntries(zip_archive, entries); | ||
zip_archive.close(); | ||
|
||
return entries; | ||
} | ||
|
||
void ParseSimpleArchive(const libzippp::ZipArchive& archive, std::vector<TexEntry>& entries) | ||
{ | ||
for (const auto& entry : archive.getEntries()) { | ||
if (!entry.isFile()) | ||
continue; | ||
const auto crc_hash = GetCrcFromFilename(entry.getName()); | ||
if (!crc_hash) | ||
continue; | ||
const auto data_ptr = static_cast<uint8_t*>(entry.readAsBinary()); | ||
const auto size = entry.getSize(); | ||
std::vector vec(data_ptr, data_ptr + size); | ||
std::filesystem::path tex_name(entry.getName()); | ||
entries.emplace_back(std::move(vec), crc_hash, tex_name.extension().string()); | ||
delete[] data_ptr; | ||
} | ||
} | ||
|
||
void ParseTexmodArchive(std::vector<std::string>& lines, libzippp::ZipArchive& archive, std::vector<TexEntry>& entries) | ||
{ | ||
for (const auto& line : lines) { | ||
// 0xC57D73F7|GW.EXE_0xC57D73F7.tga\r\n | ||
// match[1] | match[2] | ||
const static auto address_file_regex = std::regex(R"(^[\\/.]*([^|]+)\|([^\r\n]+))", std::regex::optimize); | ||
std::smatch match; | ||
if (!std::regex_search(line, match, address_file_regex)) | ||
continue; | ||
const auto address_string = match[1].str(); | ||
const auto file_path = match[2].str(); | ||
|
||
const auto crc_hash = GetCrcFromFilename(address_string); | ||
if (!crc_hash) | ||
continue; | ||
|
||
const auto entry = archive.getEntry(file_path); | ||
if (entry.isNull() || !entry.isFile()) | ||
continue; | ||
|
||
const auto data_ptr = static_cast<uint8_t*>(entry.readAsBinary()); | ||
const auto size = static_cast<size_t>(entry.getSize()); | ||
std::vector vec(data_ptr, data_ptr + size); | ||
const auto tex_name = std::filesystem::path(entry.getName()); | ||
entries.emplace_back(std::move(vec), crc_hash, tex_name.extension().string()); | ||
delete[] data_ptr; | ||
} | ||
} | ||
|
||
void ModfileLoader::LoadEntries(libzippp::ZipArchive& archive, std::vector<TexEntry>& entries) | ||
{ | ||
const auto def_file = archive.getEntry("texmod.def"); | ||
if (def_file.isNull() || !def_file.isFile()) { | ||
ParseSimpleArchive(archive, entries); | ||
} | ||
else { | ||
const auto def = def_file.readAsText(); | ||
std::istringstream iss(def); | ||
std::vector<std::string> lines; | ||
std::string line; | ||
|
||
while (std::getline(iss, line)) { | ||
lines.push_back(line); | ||
} | ||
|
||
ParseTexmodArchive(lines, archive, entries); | ||
} | ||
} |
Oops, something went wrong.