mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Load iw4x zones for iw4
This commit is contained in:
parent
590a108a1b
commit
1cc5be2f64
@ -17,13 +17,12 @@ void AssetDumperLocalizeEntry::DumpPool(AssetDumpingContext& context, AssetPool<
|
|||||||
const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone->m_language);
|
const auto language = LocalizeCommon::GetNameOfLanguage(context.m_zone->m_language);
|
||||||
fs::path stringsPath(context.m_base_path);
|
fs::path stringsPath(context.m_base_path);
|
||||||
stringsPath.append(language);
|
stringsPath.append(language);
|
||||||
stringsPath.append("/localizedstrings");
|
stringsPath.append("localizedstrings");
|
||||||
|
|
||||||
create_directories(stringsPath);
|
create_directories(stringsPath);
|
||||||
|
|
||||||
auto stringFilePath(stringsPath);
|
auto stringFilePath(stringsPath);
|
||||||
stringFilePath.append(context.m_zone->m_name);
|
stringFilePath.append(context.m_zone->m_name + ".str");
|
||||||
stringFilePath.append(".str");
|
|
||||||
|
|
||||||
std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary);
|
std::ofstream stringFile(stringFilePath, std::fstream::out | std::ofstream::binary);
|
||||||
|
|
||||||
|
@ -15,7 +15,14 @@ namespace IW4
|
|||||||
static constexpr const char* MAGIC_SIGNED_INFINITY_WARD = "IWff0100";
|
static constexpr const char* MAGIC_SIGNED_INFINITY_WARD = "IWff0100";
|
||||||
static constexpr const char* MAGIC_SIGNED_OAT = "ABff0100";
|
static constexpr const char* MAGIC_SIGNED_OAT = "ABff0100";
|
||||||
static constexpr const char* MAGIC_UNSIGNED = "IWffu100";
|
static constexpr const char* MAGIC_UNSIGNED = "IWffu100";
|
||||||
|
static constexpr const char* MAGIC_IW4X = "IW4x";
|
||||||
static constexpr int ZONE_VERSION = 276;
|
static constexpr int ZONE_VERSION = 276;
|
||||||
|
static constexpr int IW4X_ZONE_VERSION = 3;
|
||||||
|
|
||||||
|
static_assert(std::char_traits<char>::length(MAGIC_SIGNED_INFINITY_WARD) == sizeof(ZoneHeader::m_magic));
|
||||||
|
static_assert(std::char_traits<char>::length(MAGIC_SIGNED_OAT) == sizeof(ZoneHeader::m_magic));
|
||||||
|
static_assert(std::char_traits<char>::length(MAGIC_UNSIGNED) == sizeof(ZoneHeader::m_magic));
|
||||||
|
static_assert(std::char_traits<char>::length(MAGIC_IW4X) == sizeof(ZoneHeader::m_magic) - sizeof(uint32_t));
|
||||||
|
|
||||||
static constexpr const char* MAGIC_AUTH_HEADER = "IWffs100";
|
static constexpr const char* MAGIC_AUTH_HEADER = "IWffs100";
|
||||||
inline static const uint8_t RSA_PUBLIC_KEY_INFINITY_WARD[]
|
inline static const uint8_t RSA_PUBLIC_KEY_INFINITY_WARD[]
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "Loading/Processor/ProcessorAuthedBlocks.h"
|
#include "Loading/Processor/ProcessorAuthedBlocks.h"
|
||||||
#include "Loading/Processor/ProcessorCaptureData.h"
|
#include "Loading/Processor/ProcessorCaptureData.h"
|
||||||
#include "Loading/Processor/ProcessorInflate.h"
|
#include "Loading/Processor/ProcessorInflate.h"
|
||||||
|
#include "Loading/Processor/ProcessorIW4xDecryption.h"
|
||||||
#include "Loading/Steps/StepVerifyMagic.h"
|
#include "Loading/Steps/StepVerifyMagic.h"
|
||||||
#include "Loading/Steps/StepSkipBytes.h"
|
#include "Loading/Steps/StepSkipBytes.h"
|
||||||
#include "Loading/Steps/StepVerifyFileName.h"
|
#include "Loading/Steps/StepVerifyFileName.h"
|
||||||
@ -36,27 +37,43 @@ class ZoneLoaderFactory::Impl
|
|||||||
return GameLanguage::LANGUAGE_NONE;
|
return GameLanguage::LANGUAGE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CanLoad(ZoneHeader& header, bool* isSecure, bool* isOfficial)
|
static bool CanLoad(ZoneHeader& header, bool* isSecure, bool* isOfficial, bool* isIw4x)
|
||||||
{
|
{
|
||||||
assert(isSecure != nullptr);
|
assert(isSecure != nullptr);
|
||||||
assert(isOfficial != nullptr);
|
assert(isOfficial != nullptr);
|
||||||
|
assert(isIw4x != nullptr);
|
||||||
|
|
||||||
if (header.m_version != ZoneConstants::ZONE_VERSION)
|
if (header.m_version != ZoneConstants::ZONE_VERSION)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, 8))
|
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_IW4X, std::char_traits<char>::length(ZoneConstants::MAGIC_IW4X)))
|
||||||
|
{
|
||||||
|
if(*reinterpret_cast<uint32_t*>(&header.m_magic[std::char_traits<char>::length(ZoneConstants::MAGIC_IW4X)]) == ZoneConstants::IW4X_ZONE_VERSION)
|
||||||
|
{
|
||||||
|
*isSecure = false;
|
||||||
|
*isOfficial = false;
|
||||||
|
*isIw4x = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, std::char_traits<char>::length(ZoneConstants::MAGIC_SIGNED_INFINITY_WARD)))
|
||||||
{
|
{
|
||||||
*isSecure = true;
|
*isSecure = true;
|
||||||
*isOfficial = true;
|
*isOfficial = true;
|
||||||
|
*isIw4x = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, 8))
|
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, std::char_traits<char>::length(ZoneConstants::MAGIC_UNSIGNED)))
|
||||||
{
|
{
|
||||||
*isSecure = false;
|
*isSecure = false;
|
||||||
*isOfficial = true;
|
*isOfficial = true;
|
||||||
|
*isIw4x = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,9 +170,10 @@ public:
|
|||||||
{
|
{
|
||||||
bool isSecure;
|
bool isSecure;
|
||||||
bool isOfficial;
|
bool isOfficial;
|
||||||
|
bool isIw4x;
|
||||||
|
|
||||||
// Check if this file is a supported IW4 zone.
|
// Check if this file is a supported IW4 zone.
|
||||||
if (!CanLoad(header, &isSecure, &isOfficial))
|
if (!CanLoad(header, &isSecure, &isOfficial, &isIw4x))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Create new zone
|
// Create new zone
|
||||||
@ -180,6 +198,12 @@ public:
|
|||||||
|
|
||||||
zoneLoader->AddLoadingStep(std::make_unique<StepAddProcessor>(std::make_unique<ProcessorInflate>(ZoneConstants::AUTHED_CHUNK_SIZE)));
|
zoneLoader->AddLoadingStep(std::make_unique<StepAddProcessor>(std::make_unique<ProcessorInflate>(ZoneConstants::AUTHED_CHUNK_SIZE)));
|
||||||
|
|
||||||
|
if (isIw4x) // IW4x has one extra byte of padding here for protection purposes
|
||||||
|
{
|
||||||
|
zoneLoader->AddLoadingStep(std::make_unique<StepAddProcessor>(std::make_unique<ProcessorIW4xDecryption>()));
|
||||||
|
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(1));
|
||||||
|
}
|
||||||
|
|
||||||
// Start of the XFile struct
|
// Start of the XFile struct
|
||||||
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(8));
|
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(8));
|
||||||
// Skip size and externalSize fields since they are not interesting for us
|
// Skip size and externalSize fields since they are not interesting for us
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
#include "ProcessorIW4xDecryption.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
ProcessorIW4xDecryption::ProcessorIW4xDecryption()
|
||||||
|
: m_last_byte(0u)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ProcessorIW4xDecryption::RotateLeft(const uint8_t value, const unsigned count)
|
||||||
|
{
|
||||||
|
assert(count < sizeof(value) * 8);
|
||||||
|
return static_cast<uint8_t>(value << count | (value >> ((sizeof(value) * 8) - count)));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ProcessorIW4xDecryption::RotateRight(uint8_t value, const unsigned count)
|
||||||
|
{
|
||||||
|
assert(count < sizeof(value) * 8);
|
||||||
|
return static_cast<uint8_t>(value >> count | (value << ((sizeof(value) * 8) - count)));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ProcessorIW4xDecryption::Load(void* buffer, const size_t length)
|
||||||
|
{
|
||||||
|
const auto readLen = m_base_stream->Load(buffer, length);
|
||||||
|
|
||||||
|
auto* charBuffer = static_cast<uint8_t*>(buffer);
|
||||||
|
for(auto i = 0u; i < readLen; i++)
|
||||||
|
{
|
||||||
|
auto value = charBuffer[i];
|
||||||
|
value ^= m_last_byte;
|
||||||
|
value = RotateLeft(value, 4);
|
||||||
|
value ^= -1;
|
||||||
|
value = RotateRight(value, 6);
|
||||||
|
|
||||||
|
charBuffer[i] = value;
|
||||||
|
m_last_byte = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return readLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t ProcessorIW4xDecryption::Pos()
|
||||||
|
{
|
||||||
|
return m_base_stream->Pos();
|
||||||
|
}
|
16
src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h
Normal file
16
src/ZoneLoading/Loading/Processor/ProcessorIW4xDecryption.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Loading/StreamProcessor.h"
|
||||||
|
|
||||||
|
class ProcessorIW4xDecryption final : public StreamProcessor
|
||||||
|
{
|
||||||
|
uint8_t m_last_byte;
|
||||||
|
|
||||||
|
static uint8_t RotateLeft(uint8_t value, unsigned count);
|
||||||
|
static uint8_t RotateRight(uint8_t value, unsigned count);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ProcessorIW4xDecryption();
|
||||||
|
|
||||||
|
size_t Load(void* buffer, size_t length) override;
|
||||||
|
int64_t Pos() override;
|
||||||
|
};
|
@ -69,7 +69,7 @@ public:
|
|||||||
throw InvalidCompressionException();
|
throw InvalidCompressionException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_stream.avail_out;
|
return length - m_stream.avail_out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user