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);
|
||||
fs::path stringsPath(context.m_base_path);
|
||||
stringsPath.append(language);
|
||||
stringsPath.append("/localizedstrings");
|
||||
stringsPath.append("localizedstrings");
|
||||
|
||||
create_directories(stringsPath);
|
||||
|
||||
auto stringFilePath(stringsPath);
|
||||
stringFilePath.append(context.m_zone->m_name);
|
||||
stringFilePath.append(".str");
|
||||
stringFilePath.append(context.m_zone->m_name + ".str");
|
||||
|
||||
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_OAT = "ABff0100";
|
||||
static constexpr const char* MAGIC_UNSIGNED = "IWffu100";
|
||||
static constexpr const char* MAGIC_IW4X = "IW4x";
|
||||
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";
|
||||
inline static const uint8_t RSA_PUBLIC_KEY_INFINITY_WARD[]
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "Loading/Processor/ProcessorAuthedBlocks.h"
|
||||
#include "Loading/Processor/ProcessorCaptureData.h"
|
||||
#include "Loading/Processor/ProcessorInflate.h"
|
||||
#include "Loading/Processor/ProcessorIW4xDecryption.h"
|
||||
#include "Loading/Steps/StepVerifyMagic.h"
|
||||
#include "Loading/Steps/StepSkipBytes.h"
|
||||
#include "Loading/Steps/StepVerifyFileName.h"
|
||||
@ -36,27 +37,43 @@ class ZoneLoaderFactory::Impl
|
||||
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(isOfficial != nullptr);
|
||||
assert(isIw4x != nullptr);
|
||||
|
||||
if (header.m_version != ZoneConstants::ZONE_VERSION)
|
||||
{
|
||||
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)))
|
||||
{
|
||||
*isSecure = true;
|
||||
*isOfficial = true;
|
||||
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;
|
||||
}
|
||||
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_SIGNED_INFINITY_WARD, std::char_traits<char>::length(ZoneConstants::MAGIC_SIGNED_INFINITY_WARD)))
|
||||
{
|
||||
*isSecure = true;
|
||||
*isOfficial = true;
|
||||
*isIw4x = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!memcmp(header.m_magic, ZoneConstants::MAGIC_UNSIGNED, std::char_traits<char>::length(ZoneConstants::MAGIC_UNSIGNED)))
|
||||
{
|
||||
*isSecure = false;
|
||||
*isOfficial = true;
|
||||
*isIw4x = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -153,9 +170,10 @@ public:
|
||||
{
|
||||
bool isSecure;
|
||||
bool isOfficial;
|
||||
bool isIw4x;
|
||||
|
||||
// Check if this file is a supported IW4 zone.
|
||||
if (!CanLoad(header, &isSecure, &isOfficial))
|
||||
if (!CanLoad(header, &isSecure, &isOfficial, &isIw4x))
|
||||
return nullptr;
|
||||
|
||||
// Create new zone
|
||||
@ -180,6 +198,12 @@ public:
|
||||
|
||||
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
|
||||
zoneLoader->AddLoadingStep(std::make_unique<StepSkipBytes>(8));
|
||||
// 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();
|
||||
}
|
||||
|
||||
return m_stream.avail_out;
|
||||
return length - m_stream.avail_out;
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user