mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Merge branch 'master' into indev
This commit is contained in:
commit
f1f0ca35f8
@ -6,6 +6,8 @@ using std::pair;
|
|||||||
using std::regex;
|
using std::regex;
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
using std::u16string;
|
||||||
|
using std::u32string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using std::fstream;
|
using std::fstream;
|
||||||
using std::ifstream;
|
using std::ifstream;
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
#include "public/include/binstream.h"
|
#include "public/include/binstream.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: CIOStream constructor
|
// Purpose: CIOStream constructors
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CIOStream::CIOStream()
|
CIOStream::CIOStream()
|
||||||
{
|
{
|
||||||
eCurrentMode = eStreamFileMode::NONE;
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
|
}
|
||||||
|
CIOStream::CIOStream(const string& svFileFullPath, Mode_t eMode)
|
||||||
|
{
|
||||||
|
Open(svFileFullPath, eMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -14,15 +18,10 @@ CIOStream::CIOStream()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
CIOStream::~CIOStream()
|
CIOStream::~CIOStream()
|
||||||
{
|
{
|
||||||
if (writer.is_open())
|
if (m_oStream.is_open())
|
||||||
{
|
m_oStream.close();
|
||||||
writer.close();
|
if (m_iStream.is_open())
|
||||||
}
|
m_iStream.close();
|
||||||
|
|
||||||
if (reader.is_open())
|
|
||||||
{
|
|
||||||
reader.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -30,82 +29,155 @@ CIOStream::~CIOStream()
|
|||||||
// Input : fileFullPath - mode
|
// Input : fileFullPath - mode
|
||||||
// Output : true if operation is successfull
|
// Output : true if operation is successfull
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CIOStream::open(std::string svFileFullPath, eStreamFileMode eMode)
|
bool CIOStream::Open(const string& svFilePath, Mode_t eMode)
|
||||||
{
|
{
|
||||||
svFilePath = svFileFullPath;
|
m_svFilePath = svFilePath;
|
||||||
|
m_eCurrentMode = eMode;
|
||||||
|
|
||||||
if (eMode == eStreamFileMode::WRITE)
|
switch (m_eCurrentMode)
|
||||||
{
|
{
|
||||||
eCurrentMode = eMode;
|
case Mode_t::READ:
|
||||||
|
if (m_iStream.is_open())
|
||||||
// check if we had a previously opened file to close it
|
|
||||||
if (writer.is_open())
|
|
||||||
{
|
{
|
||||||
writer.close();
|
m_iStream.close();
|
||||||
}
|
}
|
||||||
|
m_iStream.open(m_svFilePath.c_str(), std::ios::binary);
|
||||||
writer.open(svFilePath.c_str(), std::ios::binary);
|
if (!m_iStream.is_open())
|
||||||
if (!writer.is_open())
|
|
||||||
{
|
{
|
||||||
DevMsg(eDLL_T::FS, "Error opening file '%s' for write operation!\n", svFilePath.c_str());
|
Error(eDLL_T::FS, "Error opening file '%s' for read operation.\n", m_svFilePath.c_str());
|
||||||
eCurrentMode = eStreamFileMode::NONE;
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
}
|
}
|
||||||
|
if (!m_iStream.good())
|
||||||
|
{
|
||||||
|
Error(eDLL_T::FS, "Error opening file '%s' for read operation.\n", m_svFilePath.c_str());
|
||||||
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_iStream.seekg(0, fstream::end);
|
||||||
|
m_vData.resize(m_iStream.tellg());
|
||||||
|
m_iStream.seekg(0, fstream::beg);
|
||||||
|
m_iStream.read(reinterpret_cast<char*>(m_vData.data()), m_vData.size());
|
||||||
|
m_iStream.seekg(0);
|
||||||
|
m_iStream.clear();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case Mode_t::WRITE:
|
||||||
|
if (m_oStream.is_open())
|
||||||
|
{
|
||||||
|
m_oStream.close();
|
||||||
|
}
|
||||||
|
m_oStream.open(m_svFilePath.c_str(), std::ios::binary);
|
||||||
|
if (!m_oStream.is_open())
|
||||||
|
{
|
||||||
|
Error(eDLL_T::FS, "Error opening file '%s' for write operation.\n", m_svFilePath.c_str());
|
||||||
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_oStream.good())
|
||||||
|
{
|
||||||
|
Error(eDLL_T::FS, "Error opening file '%s' for write operation.\n", m_svFilePath.c_str());
|
||||||
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
// Read mode
|
|
||||||
else if (eMode == eStreamFileMode::READ)
|
|
||||||
{
|
|
||||||
eCurrentMode = eMode;
|
|
||||||
|
|
||||||
// check if we had a previously opened file to close it
|
|
||||||
if (reader.is_open())
|
|
||||||
{
|
|
||||||
reader.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.open(svFilePath.c_str(), std::ios::binary);
|
|
||||||
if (!reader.is_open())
|
|
||||||
{
|
|
||||||
DevMsg(eDLL_T::FS, "Error opening file '%s' for read operation!\n", svFilePath.c_str());
|
|
||||||
eCurrentMode = eStreamFileMode::NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the mode is still the NONE -> we failed
|
|
||||||
return eCurrentMode == eStreamFileMode::NONE ? false : true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: closes the file
|
// Purpose: closes the stream
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CIOStream::close()
|
void CIOStream::Close()
|
||||||
{
|
{
|
||||||
if (eCurrentMode == eStreamFileMode::WRITE)
|
switch (m_eCurrentMode)
|
||||||
{
|
{
|
||||||
writer.close();
|
case Mode_t::READ:
|
||||||
|
m_iStream.close();
|
||||||
|
return;
|
||||||
|
case Mode_t::WRITE:
|
||||||
|
m_oStream.close();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (eCurrentMode == eStreamFileMode::READ)
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: gets the possition of the current character in the stream
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
size_t CIOStream::GetPosition()
|
||||||
|
{
|
||||||
|
switch (m_eCurrentMode)
|
||||||
{
|
{
|
||||||
reader.close();
|
case Mode_t::READ:
|
||||||
|
return m_iStream.tellg();
|
||||||
|
break;
|
||||||
|
case Mode_t::WRITE:
|
||||||
|
return m_oStream.tellp();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return static_cast<size_t>(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: sets the possition of the current character in the stream
|
||||||
|
// Input : nOffset -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void CIOStream::SetPosition(int64_t nOffset)
|
||||||
|
{
|
||||||
|
switch (m_eCurrentMode)
|
||||||
|
{
|
||||||
|
case Mode_t::READ:
|
||||||
|
m_iStream.seekg(nOffset);
|
||||||
|
break;
|
||||||
|
case Mode_t::WRITE:
|
||||||
|
m_oStream.seekp(nOffset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: returns the vector (ifstream only)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
const vector<uint8_t>& CIOStream::GetVector() const
|
||||||
|
{
|
||||||
|
return m_vData;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: returns the data (ifstream only)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
const uint8_t* CIOStream::GetData() const
|
||||||
|
{
|
||||||
|
return m_vData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: returns the data size (ifstream only)
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
const size_t CIOStream::GetSize() const
|
||||||
|
{
|
||||||
|
return m_vData.size();
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if we are able to read the file
|
// Purpose: checks if we are able to read the file
|
||||||
|
// Output : true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CIOStream::checkReadabilityStatus()
|
bool CIOStream::IsReadable()
|
||||||
{
|
{
|
||||||
if (eCurrentMode != eStreamFileMode::READ)
|
if (m_eCurrentMode != Mode_t::READ)
|
||||||
{
|
|
||||||
Error(eDLL_T::FS, "Error: StreamFileMode doesn't match required mode for read operation.\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// check if we hit the end of the file.
|
// check if we hit the end of the file.
|
||||||
if (reader.eof())
|
if (m_iStream.eof())
|
||||||
{
|
{
|
||||||
Error(eDLL_T::FS, "Error: trying to read past EOF.\n");
|
m_iStream.close();
|
||||||
reader.close();
|
m_eCurrentMode = Mode_t::NONE;
|
||||||
eCurrentMode = eStreamFileMode::NONE;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -113,38 +185,37 @@ bool CIOStream::checkReadabilityStatus()
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if we are able to write to file
|
// Purpose: checks if we are able to write to file
|
||||||
|
// Output : true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CIOStream::checkWritabilityStatus()
|
bool CIOStream::IsWritable() const
|
||||||
{
|
{
|
||||||
if (eCurrentMode != eStreamFileMode::WRITE)
|
if (m_eCurrentMode != Mode_t::WRITE)
|
||||||
{
|
|
||||||
Error(eDLL_T::FS, "Error: StreamFileMode doesn't match required mode for write operation.\n");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: checks if we hit the end of file
|
// Purpose: checks if we hit the end of file
|
||||||
|
// Output : true on success, false otherwise
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool CIOStream::eof()
|
bool CIOStream::IsEof() const
|
||||||
{
|
{
|
||||||
return reader.eof();
|
return m_iStream.eof();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: reads a string from the file and returns it
|
// Purpose: reads a string from the file and returns it
|
||||||
|
// Output : string
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
std::string CIOStream::readString()
|
string CIOStream::ReadString()
|
||||||
{
|
{
|
||||||
if (checkReadabilityStatus())
|
if (IsReadable())
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
std::string result = "";
|
string result = "";
|
||||||
while (!reader.eof() && (c = readR<char>()) != '\0')
|
while (!m_iStream.eof() && (c = Read<char>()) != '\0')
|
||||||
{
|
|
||||||
result += c;
|
result += c;
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -154,17 +225,15 @@ std::string CIOStream::readString()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: writes a string to the file
|
// Purpose: writes a string to the file
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CIOStream::writeString(std::string str)
|
void CIOStream::WriteString(string svInput)
|
||||||
{
|
{
|
||||||
if (!checkWritabilityStatus())
|
if (!IsWritable())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
str += '\0'; // null-terminate the string.
|
svInput += '\0'; // null-terminate the string.
|
||||||
|
|
||||||
char* text = (char*)(str.c_str());
|
char* szText = const_cast<char*>(svInput.c_str());
|
||||||
size_t size = str.size();
|
size_t nSize = svInput.size();
|
||||||
|
|
||||||
writer.write((const char*)text, size);
|
m_oStream.write(reinterpret_cast<const char*>(szText), nSize);
|
||||||
}
|
}
|
||||||
|
@ -1,68 +1,104 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
enum class eStreamFileMode
|
|
||||||
{
|
|
||||||
NONE = 0,
|
|
||||||
READ,
|
|
||||||
WRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
class CIOStream
|
class CIOStream
|
||||||
{
|
{
|
||||||
std::ofstream writer; // Output file stream.
|
|
||||||
std::ifstream reader; // Input file stream.
|
|
||||||
std::string svFilePath = ""; // Filepath.
|
|
||||||
eStreamFileMode eCurrentMode = eStreamFileMode::NONE; // Current active mode.
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum class Mode_t
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
READ,
|
||||||
|
WRITE
|
||||||
|
};
|
||||||
|
|
||||||
CIOStream();
|
CIOStream();
|
||||||
|
CIOStream(const string& svFileFullPath, Mode_t eMode);
|
||||||
~CIOStream();
|
~CIOStream();
|
||||||
|
|
||||||
bool open(std::string fileFullPath, eStreamFileMode mode);
|
bool Open(const string& svFileFullPath, Mode_t eMode);
|
||||||
void close();
|
void Close();
|
||||||
|
|
||||||
bool checkWritabilityStatus();
|
size_t GetPosition();
|
||||||
bool checkReadabilityStatus();
|
void SetPosition(int64_t nOffset);
|
||||||
|
|
||||||
bool eof();
|
const vector<uint8_t>& GetVector() const;
|
||||||
|
const uint8_t* GetData() const;
|
||||||
|
const size_t GetSize() const;
|
||||||
|
|
||||||
|
bool IsReadable();
|
||||||
|
bool IsWritable() const;
|
||||||
|
|
||||||
|
bool IsEof() const;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: reads any value from the file (for strings use 'readString(...)' instead)
|
// Purpose: reads any value from the file
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void read(T& value) // Template functions have to be in the header!
|
void Read(T& tValue) // Template functions have to be in the header!
|
||||||
{
|
{
|
||||||
if (checkReadabilityStatus())
|
if (IsReadable())
|
||||||
{
|
m_iStream.read(reinterpret_cast<char*>(&tValue), sizeof(tValue));
|
||||||
reader.read((char*)&value, sizeof(value));
|
else
|
||||||
}
|
printf("TEST\n");
|
||||||
|
|
||||||
|
printf("%d\n", tValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: reads any value from the file and returns it (for strings use 'readString(...)' instead)
|
// Purpose: reads any value from the file with specified size
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T readR() // Template functions have to be in the header!
|
void Read(T& tValue, size_t nSize) // Template functions have to be in the header!
|
||||||
{
|
{
|
||||||
checkReadabilityStatus();
|
if (IsReadable())
|
||||||
|
m_iStream.read(reinterpret_cast<char*>(&tValue), nSize);
|
||||||
|
}
|
||||||
|
|
||||||
T value;
|
//-----------------------------------------------------------------------------
|
||||||
reader.read((char*)&value, sizeof(value));
|
// Purpose: reads any value from the file and returns it
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template<typename T>
|
||||||
|
T Read() // Template functions have to be in the header!
|
||||||
|
{
|
||||||
|
T value{};
|
||||||
|
if (!IsReadable())
|
||||||
|
return value;
|
||||||
|
|
||||||
|
m_iStream.read(reinterpret_cast<char*>(&value), sizeof(value));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
std::string readString();
|
string ReadString();
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: writes any value to the file (for strings use 'writeString(...)' instead)
|
// Purpose: writes any value to the file
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void write(T& value) // Template functions have to be in the header!
|
void Write(T tValue) // Template functions have to be in the header!
|
||||||
{
|
{
|
||||||
if (!checkWritabilityStatus())
|
if (!IsWritable())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
writer.write((const char*)&value, sizeof(value));
|
m_oStream.write(reinterpret_cast<const char*>(&tValue), sizeof(tValue));
|
||||||
}
|
}
|
||||||
void writeString(std::string str);
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: writes any value to the file with specified size
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template<typename T>
|
||||||
|
void Write(T tValue, size_t nSize) // Template functions have to be in the header!
|
||||||
|
{
|
||||||
|
if (!IsWritable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_oStream.write(reinterpret_cast<const char*>(tValue), nSize);
|
||||||
|
m_oStream.flush();
|
||||||
|
}
|
||||||
|
void WriteString(string svInput);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ofstream m_oStream; // Output file stream.
|
||||||
|
ifstream m_iStream; // Input file stream.
|
||||||
|
string m_svFilePath; // Filepath.
|
||||||
|
vector<uint8_t> m_vData; // Data vector
|
||||||
|
Mode_t m_eCurrentMode; // Current active mode.
|
||||||
};
|
};
|
||||||
|
@ -14,24 +14,34 @@ void DbgPrint(LPCSTR sFormat, ...);
|
|||||||
void PrintLastError(void);
|
void PrintLastError(void);
|
||||||
void HexDump(const char* szHeader, const char* szLogger, const void* pData, int nSize);
|
void HexDump(const char* szHeader, const char* szLogger, const void* pData, int nSize);
|
||||||
|
|
||||||
string CreateDirectories(string svFilePath);
|
string GetExtension(const string& svInput);
|
||||||
|
string RemoveExtension(const string& svInput);
|
||||||
|
|
||||||
|
string GetFileName(const string& svInput, bool bRemoveExtension, bool bWindows = false);
|
||||||
|
string RemoveFileName(const string& svInput, bool bWindows = false);
|
||||||
|
|
||||||
|
string CreateDirectories(string svInput);
|
||||||
string ConvertToWinPath(const string& svInput);
|
string ConvertToWinPath(const string& svInput);
|
||||||
string ConvertToUnixPath(const string& svInput);
|
string ConvertToUnixPath(const string& svInput);
|
||||||
|
|
||||||
string Base64Encode(const string& svInput);
|
string Base64Encode(const string& svInput);
|
||||||
string Base64Decode(const string& svInput);
|
string Base64Decode(const string& svInput);
|
||||||
|
|
||||||
|
string UTF8Encode(const wstring& wsvInput);
|
||||||
|
u32string UTF8Decode(const string& svInput);
|
||||||
|
|
||||||
bool StringIsDigit(const string& svInput);
|
bool StringIsDigit(const string& svInput);
|
||||||
bool CompareStringAlphabetically(const string& svA, const string& svB);
|
bool CompareStringAlphabetically(const string& svA, const string& svB);
|
||||||
bool CompareStringLexicographically(const string& svA, const string& svB);
|
bool CompareStringLexicographically(const string& svA, const string& svB);
|
||||||
|
|
||||||
bool StringReplace(string& svInput, const string& svFrom, const string& svTo);
|
bool StringReplace(string& svInput, const string& svFrom, const string& svTo);
|
||||||
|
string StringReplaceC(const string& svInput, const string& svFrom, const string& svTo);
|
||||||
string StringEscape(const string& svInput);
|
string StringEscape(const string& svInput);
|
||||||
string StringUnescape(const string& svInput);
|
string StringUnescape(const string& svInput);
|
||||||
|
|
||||||
vector<int> StringToBytes(const string& svInput, bool bNullTerminator);
|
vector<int> StringToBytes(const string& svInput, bool bNullTerminator);
|
||||||
vector<int> PatternToBytes(const string& svInput);
|
vector<int> PatternToBytes(const string& svInput);
|
||||||
vector<int> IntToDigits(int value);
|
vector<int> IntToDigits(int iValue);
|
||||||
|
|
||||||
void PrintM128i8(__m128i in);
|
void PrintM128i8(__m128i in);
|
||||||
void PrintM128i16(__m128i in);
|
void PrintM128i16(__m128i in);
|
||||||
|
@ -232,6 +232,81 @@ void HexDump(const char* szHeader, const char* szLogger, const void* pData, int
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For removing file names from the extension.
|
||||||
|
string GetExtension(const string& svInput)
|
||||||
|
{
|
||||||
|
string::size_type nPos = svInput.rfind('.');
|
||||||
|
if (nPos != std::string::npos)
|
||||||
|
{
|
||||||
|
return svInput.substr(nPos + 1);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For removing extensions from file names.
|
||||||
|
string RemoveExtension(const string& svInput)
|
||||||
|
{
|
||||||
|
string::size_type nPos = svInput.find_last_of(".");
|
||||||
|
if (nPos == string::npos)
|
||||||
|
{
|
||||||
|
return svInput;
|
||||||
|
}
|
||||||
|
return svInput.substr(0, nPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For removing the path from file names.
|
||||||
|
string GetFileName(const string& svInput, bool bRemoveExtension, bool bWindows)
|
||||||
|
{
|
||||||
|
string::size_type nPos;
|
||||||
|
if (bWindows)
|
||||||
|
{
|
||||||
|
nPos = svInput.rfind('\\');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nPos = svInput.rfind('/');
|
||||||
|
}
|
||||||
|
if (nPos != std::string::npos)
|
||||||
|
{
|
||||||
|
if (bRemoveExtension)
|
||||||
|
{
|
||||||
|
return RemoveExtension(svInput.substr(nPos + 1));
|
||||||
|
}
|
||||||
|
return svInput.substr(nPos + 1);
|
||||||
|
}
|
||||||
|
else // File name is not within path.
|
||||||
|
{
|
||||||
|
if (bRemoveExtension)
|
||||||
|
{
|
||||||
|
return RemoveExtension(svInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return svInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For removing file names from the path.
|
||||||
|
string RemoveFileName(const string& svInput, bool bWindows)
|
||||||
|
{
|
||||||
|
string::size_type nPos;
|
||||||
|
if (bWindows)
|
||||||
|
{
|
||||||
|
nPos = svInput.find_last_of("\\");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nPos = svInput.find_last_of("/");
|
||||||
|
}
|
||||||
|
if (nPos == string::npos)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return svInput.substr(0, nPos);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For creating directories for output streams.
|
// For creating directories for output streams.
|
||||||
string CreateDirectories(string svInput)
|
string CreateDirectories(string svInput)
|
||||||
@ -286,7 +361,7 @@ string ConvertToUnixPath(const string& svInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For encoding data in base64.
|
// For encoding data in Base64.
|
||||||
string Base64Encode(const string& svInput)
|
string Base64Encode(const string& svInput)
|
||||||
{
|
{
|
||||||
string results;
|
string results;
|
||||||
@ -314,7 +389,7 @@ string Base64Encode(const string& svInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For decoding data in base64.
|
// For decoding data in Base64.
|
||||||
string Base64Decode(const string& svInput)
|
string Base64Decode(const string& svInput)
|
||||||
{
|
{
|
||||||
string results;
|
string results;
|
||||||
@ -343,6 +418,33 @@ string Base64Decode(const string& svInput)
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For encoding data in UTF8.
|
||||||
|
string UTF8Encode(const wstring& wsvInput)
|
||||||
|
{
|
||||||
|
string results;
|
||||||
|
int nLen = WideCharToMultiByte(CP_UTF8, 0, wsvInput.c_str(), wsvInput.length(), NULL, 0, NULL, NULL);
|
||||||
|
if (nLen > 0)
|
||||||
|
{
|
||||||
|
results.resize(nLen);
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, wsvInput.c_str(), wsvInput.length(), &results[0], nLen, NULL, NULL);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For decoding data in UTF8.
|
||||||
|
u32string UTF8Decode(const string& svInput)
|
||||||
|
{
|
||||||
|
//struct destructible_codecvt : public std::codecvt<char32_t, char, std::mbstate_t>
|
||||||
|
//{
|
||||||
|
// using std::codecvt<char32_t, char, std::mbstate_t>::codecvt;
|
||||||
|
// ~destructible_codecvt() = default;
|
||||||
|
//};
|
||||||
|
//std::wstring_convert<destructible_codecvt, char32_t> utf32_converter;
|
||||||
|
//return utf32_converter.from_bytes(svInput);
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For checking if a string is a number.
|
// For checking if a string is a number.
|
||||||
bool StringIsDigit(const string& svInput)
|
bool StringIsDigit(const string& svInput)
|
||||||
@ -378,19 +480,35 @@ bool CompareStringLexicographically(const string& svA, const string& svB)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For replacing parts of a given string.
|
// For replacing parts of a given string by reference.
|
||||||
bool StringReplace(string& svInput, const string& svFrom, const string& svTo)
|
bool StringReplace(string& svInput, const string& svFrom, const string& svTo)
|
||||||
{
|
{
|
||||||
size_t start_pos = svInput.find(svFrom);
|
string::size_type nPos = svInput.find(svFrom);
|
||||||
if (start_pos == string::npos)
|
if (nPos == string::npos)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
svInput.replace(start_pos, svFrom.length(), svTo);
|
svInput.replace(nPos, svFrom.length(), svTo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// For replacing parts of a given string by value.
|
||||||
|
string StringReplaceC(const string& svInput, const string& svFrom, const string& svTo)
|
||||||
|
{
|
||||||
|
string results = svInput;
|
||||||
|
string::size_type nPos = results.find(svFrom);
|
||||||
|
|
||||||
|
if (nPos == string::npos)
|
||||||
|
{
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
results.replace(nPos, svFrom.length(), svTo);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For escaping special characters in a string.
|
// For escaping special characters in a string.
|
||||||
string StringEscape(const string& svInput)
|
string StringEscape(const string& svInput)
|
||||||
@ -491,12 +609,12 @@ vector<int> PatternToBytes(const string& svInput)
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// For converting a integer into digits.
|
// For converting a integer into digits.
|
||||||
vector<int> IntToDigits(int value)
|
vector<int> IntToDigits(int iValue)
|
||||||
{
|
{
|
||||||
vector<int> vDigits;
|
vector<int> vDigits;
|
||||||
for (; value > 0; value /= 10)
|
for (; iValue > 0; iValue /= 10)
|
||||||
{
|
{
|
||||||
vDigits.push_back(value % 10);
|
vDigits.push_back(iValue % 10);
|
||||||
}
|
}
|
||||||
std::reverse(vDigits.begin(), vDigits.end());
|
std::reverse(vDigits.begin(), vDigits.end());
|
||||||
return vDigits;
|
return vDigits;
|
||||||
|
@ -725,7 +725,10 @@ eLaunchMode CUIBaseSurface::BuildParameter(string& svParameters)
|
|||||||
results = eLaunchMode::LM_HOST;
|
results = eLaunchMode::LM_HOST;
|
||||||
|
|
||||||
if (this->m_CheatsToggle->Checked())
|
if (this->m_CheatsToggle->Checked())
|
||||||
|
{
|
||||||
svParameters.append("+sv_cheats \"1\" ");
|
svParameters.append("+sv_cheats \"1\" ");
|
||||||
|
svParameters.append("-showdevmenu ");
|
||||||
|
}
|
||||||
|
|
||||||
if (this->m_ConsoleToggle->Checked())
|
if (this->m_ConsoleToggle->Checked())
|
||||||
svParameters.append("-wconsole ");
|
svParameters.append("-wconsole ");
|
||||||
@ -929,7 +932,10 @@ eLaunchMode CUIBaseSurface::BuildParameter(string& svParameters)
|
|||||||
results = eLaunchMode::LM_CLIENT;
|
results = eLaunchMode::LM_CLIENT;
|
||||||
|
|
||||||
if (this->m_CheatsToggle->Checked())
|
if (this->m_CheatsToggle->Checked())
|
||||||
|
{
|
||||||
svParameters.append("+sv_cheats \"1\" ");
|
svParameters.append("+sv_cheats \"1\" ");
|
||||||
|
svParameters.append("-showdevmenu ");
|
||||||
|
}
|
||||||
|
|
||||||
if (this->m_ConsoleToggle->Checked())
|
if (this->m_ConsoleToggle->Checked())
|
||||||
svParameters.append("-wconsole ");
|
svParameters.append("-wconsole ");
|
||||||
|
@ -148,7 +148,7 @@ SQBool Script_CreateServerVM()
|
|||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// Purpose: Creates the CLIENT Squirrel VM
|
// Purpose: Creates the CLIENT Squirrel VM
|
||||||
// Input : *chlclient -
|
// Input : *hlclient -
|
||||||
// Output : True on success, false on failure
|
// Output : True on success, false on failure
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
SQBool Script_CreateClientVM(CHLClient* hlclient)
|
SQBool Script_CreateClientVM(CHLClient* hlclient)
|
||||||
|
@ -131,9 +131,10 @@ void ConVar::Init(void) const
|
|||||||
#endif // !DEDICATED
|
#endif // !DEDICATED
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// FILESYSTEM |
|
// FILESYSTEM |
|
||||||
fs_warning_level_sdk = new ConVar("fs_warning_level_sdk" , "0", FCVAR_DEVELOPMENTONLY, "Set the SDK filesystem warning level.", false, 0.f, false, 0.f, nullptr, nullptr);
|
fs_warning_level_sdk = new ConVar("fs_warning_level_sdk" , "0", FCVAR_DEVELOPMENTONLY, "Set the SDK filesystem warning level.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
fs_show_warning_output = new ConVar("fs_show_warning_output" , "0", FCVAR_DEVELOPMENTONLY, "Logs the filesystem warnings to the console, filtered by 'fs_warning_level_native' ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
|
fs_show_warning_output = new ConVar("fs_show_warning_output" , "0", FCVAR_DEVELOPMENTONLY, "Logs the filesystem warnings to the console, filtered by 'fs_warning_level_native' ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
fs_packedstore_entryblock_stats = new ConVar("fs_packedstore_entryblock_stats", "0", FCVAR_DEVELOPMENTONLY, "If set to 1, prints the stats of each file entry in the VPK during decompression ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
|
fs_packedstore_entryblock_stats = new ConVar("fs_packedstore_entryblock_stats" , "0", FCVAR_DEVELOPMENTONLY, "If set to 1, prints the stats of each file entry in the VPK during decompression ( !slower! ).", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
|
fs_packedstore_workspace = new ConVar("fs_packedstore_workspace", "platform/vpk/", FCVAR_DEVELOPMENTONLY, "Determines the current VPK workspace.", false, 0.f, false, 0.f, nullptr, nullptr);
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// MATERIALSYSTEM |
|
// MATERIALSYSTEM |
|
||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
|
@ -147,8 +147,9 @@ void ConCommand::Init(void)
|
|||||||
#endif // !DEDICATED
|
#endif // !DEDICATED
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// FILESYSTEM API |
|
// FILESYSTEM API |
|
||||||
new ConCommand("fs_unpack_vpk", "Unpacks all files from user specified VPK file.", FCVAR_DEVELOPMENTONLY, VPK_Unpack_f, nullptr);
|
|
||||||
new ConCommand("fs_mount_vpk", "Mounts user specified VPK file for FileSystem usage.", FCVAR_DEVELOPMENTONLY, VPK_Mount_f, nullptr);
|
new ConCommand("fs_mount_vpk", "Mounts user specified VPK file for FileSystem usage.", FCVAR_DEVELOPMENTONLY, VPK_Mount_f, nullptr);
|
||||||
|
new ConCommand("fs_pack_vpk", "Packs all specified files into a VPK file.", FCVAR_DEVELOPMENTONLY, VPK_Pack_f, nullptr);
|
||||||
|
new ConCommand("fs_unpack_vpk", "Unpacks all files from user specified VPK file.", FCVAR_DEVELOPMENTONLY, VPK_Unpack_f, nullptr);
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// RTECH API |
|
// RTECH API |
|
||||||
new ConCommand("rtech_strtoguid", "Calculates the GUID from input data.", FCVAR_DEVELOPMENTONLY, RTech_StringToGUID_f, nullptr);
|
new ConCommand("rtech_strtoguid", "Calculates the GUID from input data.", FCVAR_DEVELOPMENTONLY, RTech_StringToGUID_f, nullptr);
|
||||||
|
@ -105,6 +105,7 @@ ConVar* con_suggestion_flags_realtime = nullptr;
|
|||||||
ConVar* fs_warning_level_sdk = nullptr;
|
ConVar* fs_warning_level_sdk = nullptr;
|
||||||
ConVar* fs_show_warning_output = nullptr;
|
ConVar* fs_show_warning_output = nullptr;
|
||||||
ConVar* fs_packedstore_entryblock_stats = nullptr;
|
ConVar* fs_packedstore_entryblock_stats = nullptr;
|
||||||
|
ConVar* fs_packedstore_workspace = nullptr;
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// MATERIALSYSTEM |
|
// MATERIALSYSTEM |
|
||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
|
@ -102,6 +102,7 @@ extern ConVar* con_suggestion_flags_realtime;
|
|||||||
extern ConVar* fs_warning_level_sdk;
|
extern ConVar* fs_warning_level_sdk;
|
||||||
extern ConVar* fs_show_warning_output;
|
extern ConVar* fs_show_warning_output;
|
||||||
extern ConVar* fs_packedstore_entryblock_stats;
|
extern ConVar* fs_packedstore_entryblock_stats;
|
||||||
|
extern ConVar* fs_packedstore_workspace;
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// MATERIALSYSTEM |
|
// MATERIALSYSTEM |
|
||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
|
@ -19,7 +19,10 @@
|
|||||||
void CPackedStore::InitLzCompParams(void)
|
void CPackedStore::InitLzCompParams(void)
|
||||||
{
|
{
|
||||||
/*| PARAMETERS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
/*| PARAMETERS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
||||||
m_lzCompParams.m_dict_size_log2 = RVPK_DICT_SIZE;
|
m_lzCompParams.m_dict_size_log2 = RVPK_DICT_SIZE;
|
||||||
|
m_lzCompParams.m_level = lzham_compress_level::LZHAM_COMP_LEVEL_FASTER;
|
||||||
|
//m_lzCompParams.m_compress_flags = lzham_compress_flags::LZHAM_COMP_FLAG_DETERMINISTIC_PARSING | lzham_compress_flags::LZHAM_COMP_FLAG_TRADEOFF_DECOMPRESSION_RATE_FOR_COMP_RATIO;
|
||||||
|
m_lzCompParams.m_max_helper_threads = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -29,7 +32,7 @@ void CPackedStore::InitLzDecompParams(void)
|
|||||||
{
|
{
|
||||||
/*| PARAMETERS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
/*| PARAMETERS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
||||||
m_lzDecompParams.m_dict_size_log2 = RVPK_DICT_SIZE;
|
m_lzDecompParams.m_dict_size_log2 = RVPK_DICT_SIZE;
|
||||||
m_lzDecompParams.m_decompress_flags = LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED | LZHAM_DECOMP_FLAG_COMPUTE_CRC32;
|
m_lzDecompParams.m_decompress_flags = lzham_decompress_flags::LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED | lzham_decompress_flags::LZHAM_DECOMP_FLAG_COMPUTE_CRC32;
|
||||||
m_lzDecompParams.m_struct_size = sizeof(lzham_decompress_params);
|
m_lzDecompParams.m_struct_size = sizeof(lzham_decompress_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,25 +91,41 @@ VPKDir_t CPackedStore::GetPackDirFile(string svPackDirFile)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: obtains and returns the entry block to the vector
|
// Purpose: obtains and returns the entry block to the vector
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
vector<VPKEntryBlock_t> CPackedStore::GetEntryBlocks(CIOStream* reader)
|
vector<VPKEntryBlock_t> CPackedStore::GetEntryBlocks(CIOStream* pReader)
|
||||||
{
|
{
|
||||||
/*| ENTRYBLOCKS |||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
/*| ENTRYBLOCKS |||||||||||||||||||||||||||||||||||||||||||||||||||||||||*/
|
||||||
string svName, svPath, svExtension;
|
string svName, svPath, svExtension;
|
||||||
vector<VPKEntryBlock_t> vBlocks;
|
vector<VPKEntryBlock_t> vBlocks;
|
||||||
while (!(svExtension = reader->readString()).empty())
|
while (!(svExtension = pReader->ReadString()).empty())
|
||||||
{
|
{
|
||||||
while (!(svPath = reader->readString()).empty())
|
while (!(svPath = pReader->ReadString()).empty())
|
||||||
{
|
{
|
||||||
while (!(svName = reader->readString()).empty())
|
while (!(svName = pReader->ReadString()).empty())
|
||||||
{
|
{
|
||||||
string svFilePath = FormatBlockPath(svName, svPath, svExtension);
|
string svFilePath = FormatBlockPath(svName, svPath, svExtension);
|
||||||
vBlocks.push_back(VPKEntryBlock_t(reader, svFilePath));
|
vBlocks.push_back(VPKEntryBlock_t(pReader, svFilePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vBlocks;
|
return vBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: scans the input directory and returns the paths to the vector
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
vector<string> CPackedStore::GetEntryPaths(const string& svPathIn) const
|
||||||
|
{
|
||||||
|
vector<string> vPaths;
|
||||||
|
for (const fs::directory_entry& dirEntry : fs::recursive_directory_iterator(fs_packedstore_workspace->GetString()))
|
||||||
|
{
|
||||||
|
if (!GetExtension(dirEntry.path().u8string()).empty())
|
||||||
|
{
|
||||||
|
vPaths.push_back(ConvertToUnixPath(dirEntry.path().u8string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vPaths;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: formats the entry block path
|
// Purpose: formats the entry block path
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -141,17 +160,10 @@ string CPackedStore::StripLocalePrefix(string svPackDirFile)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: validates extraction result with precomputed ADLER32 hash
|
// Purpose: validates extraction result with precomputed ADLER32 hash
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CPackedStore::ValidateAdler32PostDecomp(string svAssetFile)
|
void CPackedStore::ValidateAdler32PostDecomp(const string& svAssetFile)
|
||||||
{
|
{
|
||||||
uint32_t adler_init = {};
|
CIOStream reader(svAssetFile, CIOStream::Mode_t::READ);
|
||||||
ifstream istream(svAssetFile, fstream::binary);
|
m_nAdler32 = adler32::update(m_nAdler32, reader.GetData(), reader.GetSize());
|
||||||
|
|
||||||
istream.seekg(0, fstream::end);
|
|
||||||
m_vHashBuffer.resize(istream.tellg());
|
|
||||||
istream.seekg(0, fstream::beg);
|
|
||||||
istream.read((char*)m_vHashBuffer.data(), m_vHashBuffer.size());
|
|
||||||
|
|
||||||
m_nAdler32 = adler32::update(adler_init, m_vHashBuffer.data(), m_vHashBuffer.size());
|
|
||||||
|
|
||||||
if (m_nAdler32 != m_nAdler32_Internal)
|
if (m_nAdler32 != m_nAdler32_Internal)
|
||||||
{
|
{
|
||||||
@ -159,49 +171,81 @@ void CPackedStore::ValidateAdler32PostDecomp(string svAssetFile)
|
|||||||
m_nAdler32 = 0;
|
m_nAdler32 = 0;
|
||||||
m_nAdler32_Internal = 0;
|
m_nAdler32_Internal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
istream.close();
|
|
||||||
m_vHashBuffer.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: validates extraction result with precomputed CRC32 hash
|
// Purpose: validates extraction result with precomputed CRC32 hash
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CPackedStore::ValidateCRC32PostDecomp(string svDirAsset)
|
void CPackedStore::ValidateCRC32PostDecomp(const string& svAssetFile)
|
||||||
{
|
{
|
||||||
uint32_t crc32_init = {};
|
CIOStream reader(svAssetFile, CIOStream::Mode_t::READ);
|
||||||
ifstream istream(svDirAsset, fstream::binary);
|
m_nCrc32 = crc32::update(m_nCrc32, reader.GetData(), reader.GetSize());
|
||||||
|
|
||||||
istream.seekg(0, fstream::end);
|
|
||||||
m_vHashBuffer.resize(istream.tellg());
|
|
||||||
istream.seekg(0, fstream::beg);
|
|
||||||
istream.read((char*)m_vHashBuffer.data(), m_vHashBuffer.size());
|
|
||||||
|
|
||||||
m_nCrc32 = crc32::update(crc32_init, m_vHashBuffer.data(), m_vHashBuffer.size());
|
|
||||||
|
|
||||||
if (m_nCrc32 != m_nCrc32_Internal)
|
if (m_nCrc32 != m_nCrc32_Internal)
|
||||||
{
|
{
|
||||||
Warning(eDLL_T::FS, "Warning: CRC32 checksum mismatch for entry '%s' computed value '0x%lX' doesn't match expected value '0x%lX'. File may be corrupt!\n", svDirAsset.c_str(), m_nCrc32, m_nCrc32_Internal);
|
Warning(eDLL_T::FS, "Warning: CRC32 checksum mismatch for entry '%s' computed value '0x%lX' doesn't match expected value '0x%lX'. File may be corrupt!\n", svAssetFile.c_str(), m_nCrc32, m_nCrc32_Internal);
|
||||||
m_nCrc32 = 0;
|
m_nCrc32 = 0;
|
||||||
m_nCrc32_Internal = 0;
|
m_nCrc32_Internal = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
istream.close();
|
void CPackedStore::PackAll(string svDirIn, string svPathOut)
|
||||||
m_vHashBuffer.clear();
|
{
|
||||||
|
CIOStream writer("client_mp_rr_canyonlands_staging.bsp.pak000_000.vpk", CIOStream::Mode_t::WRITE);
|
||||||
|
|
||||||
|
vector<VPKEntryBlock_t> vEntryBlocks;
|
||||||
|
vector<string> vPaths = GetEntryPaths(svDirIn);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vPaths.size(); i++)
|
||||||
|
{
|
||||||
|
CIOStream reader(vPaths[i], CIOStream::Mode_t::READ);
|
||||||
|
if (reader.IsReadable())
|
||||||
|
{
|
||||||
|
vEntryBlocks.push_back(VPKEntryBlock_t(reader.GetVector(), writer.GetPosition(), 0, 0x101, 0, StringReplaceC(vPaths[i], fs_packedstore_workspace->GetString(), "")));
|
||||||
|
for (size_t j = 0; j < vEntryBlocks[i].m_vvEntries.size(); j++)
|
||||||
|
{
|
||||||
|
uint8_t* pSrc = new uint8_t[vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize];
|
||||||
|
uint8_t* pDest = new uint8_t[DECOMP_MAX_BUF];
|
||||||
|
|
||||||
|
reader.Read(*pSrc, vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize);
|
||||||
|
vEntryBlocks[i].m_vvEntries[j].m_nArchiveOffset = writer.GetPosition();
|
||||||
|
|
||||||
|
m_lzCompStatus = lzham_compress_memory(&m_lzCompParams, pDest, &vEntryBlocks[i].m_vvEntries[j].m_nCompressedSize, pSrc, vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize, &m_nAdler32_Internal, &m_nCrc32_Internal);
|
||||||
|
if (m_lzCompStatus != lzham_compress_status_t::LZHAM_COMP_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
Error(eDLL_T::FS, "Error: failed compression for an entry within block '%s' for archive '%d'\n", vEntryBlocks.at(i).m_svBlockPath.c_str(), vEntryBlocks.at(i).m_iArchiveIndex);
|
||||||
|
Error(eDLL_T::FS, "'lzham::lzham_lib_compress_memory' returned with status '%d' (file will be packed without compression.)\n", m_lzCompStatus);
|
||||||
|
|
||||||
|
vEntryBlocks[i].m_vvEntries[j].m_nCompressedSize = vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize;
|
||||||
|
writer.Write(pSrc, vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
writer.Write(pDest, vEntryBlocks[i].m_vvEntries[j].m_nCompressedSize);
|
||||||
|
|
||||||
|
vEntryBlocks[i].m_vvEntries[j].m_bIsCompressed = vEntryBlocks[i].m_vvEntries[j].m_nCompressedSize != vEntryBlocks[i].m_vvEntries[j].m_nUncompressedSize;
|
||||||
|
|
||||||
|
delete[] pSrc;
|
||||||
|
delete[] pDest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VPKDir_t vDir = VPKDir_t();
|
||||||
|
vDir.Build("englishclient_mp_rr_canyonlands_staging.bsp.pak000_dir.vpk", vEntryBlocks); // [!!! <<DEVELOPMENT>> !!!]
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: extracts all files from specified vpk file
|
// Purpose: extracts all files from specified vpk file
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void CPackedStore::UnpackAll(VPKDir_t vpk_dir, string svPathOut)
|
void CPackedStore::UnpackAll(VPKDir_t vpkDir, string svPathOut)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < vpk_dir.m_vsvArchives.size(); i++)
|
for (int i = 0; i < vpkDir.m_vsvArchives.size(); i++)
|
||||||
{
|
{
|
||||||
fs::path fspVpkPath(vpk_dir.m_svDirPath);
|
fs::path fspVpkPath(vpkDir.m_svDirPath);
|
||||||
string svPath = fspVpkPath.parent_path().u8string() + "\\" + vpk_dir.m_vsvArchives[i];
|
string svPath = fspVpkPath.parent_path().u8string() + "\\" + vpkDir.m_vsvArchives[i];
|
||||||
ifstream packChunkStream(svPath, std::ios_base::binary); // Create stream to read from each archive.
|
ifstream packChunkStream(svPath, std::ios_base::binary); // Create stream to read from each archive.
|
||||||
|
|
||||||
for ( VPKEntryBlock_t block : vpk_dir.m_vvEntryBlocks)
|
for ( VPKEntryBlock_t block : vpkDir.m_vvEntryBlocks)
|
||||||
{
|
{
|
||||||
// Escape if block archive index is not part of the extracting archive chunk index.
|
// Escape if block archive index is not part of the extracting archive chunk index.
|
||||||
if (block.m_iArchiveIndex != i) { goto escape; }
|
if (block.m_iArchiveIndex != i) { goto escape; }
|
||||||
@ -215,7 +259,7 @@ void CPackedStore::UnpackAll(VPKDir_t vpk_dir, string svPathOut)
|
|||||||
Error(eDLL_T::FS, "Error: unable to access file '%s'!\n", svFilePath.c_str());
|
Error(eDLL_T::FS, "Error: unable to access file '%s'!\n", svFilePath.c_str());
|
||||||
}
|
}
|
||||||
outFileStream.clear(); // Make sure file is empty before writing.
|
outFileStream.clear(); // Make sure file is empty before writing.
|
||||||
for (VPKEntryDescr_t entry : block.m_vvEntries)
|
for (VPKEntryDescriptor_t entry : block.m_vvEntries)
|
||||||
{
|
{
|
||||||
char* pCompressedData = new char[entry.m_nCompressedSize];
|
char* pCompressedData = new char[entry.m_nCompressedSize];
|
||||||
memset(pCompressedData, 0, entry.m_nCompressedSize); // Compressed region.
|
memset(pCompressedData, 0, entry.m_nCompressedSize); // Compressed region.
|
||||||
@ -226,7 +270,9 @@ void CPackedStore::UnpackAll(VPKDir_t vpk_dir, string svPathOut)
|
|||||||
if (entry.m_bIsCompressed)
|
if (entry.m_bIsCompressed)
|
||||||
{
|
{
|
||||||
lzham_uint8* pLzOutputBuf = new lzham_uint8[entry.m_nUncompressedSize];
|
lzham_uint8* pLzOutputBuf = new lzham_uint8[entry.m_nUncompressedSize];
|
||||||
m_lzDecompStatus = lzham_decompress_memory(&m_lzDecompParams, pLzOutputBuf, (size_t*)&entry.m_nUncompressedSize, (lzham_uint8*)pCompressedData, entry.m_nCompressedSize, &m_nAdler32_Internal, &m_nCrc32_Internal);
|
m_lzDecompStatus = lzham_decompress_memory(&m_lzDecompParams, pLzOutputBuf,
|
||||||
|
(size_t*)&entry.m_nUncompressedSize, (lzham_uint8*)pCompressedData,
|
||||||
|
entry.m_nCompressedSize, &m_nAdler32_Internal, &m_nCrc32_Internal);
|
||||||
|
|
||||||
if (fs_packedstore_entryblock_stats->GetBool())
|
if (fs_packedstore_entryblock_stats->GetBool())
|
||||||
{
|
{
|
||||||
@ -253,20 +299,21 @@ void CPackedStore::UnpackAll(VPKDir_t vpk_dir, string svPathOut)
|
|||||||
if (m_lzDecompStatus != lzham_decompress_status_t::LZHAM_DECOMP_STATUS_SUCCESS)
|
if (m_lzDecompStatus != lzham_decompress_status_t::LZHAM_DECOMP_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
Error(eDLL_T::FS, "Error: failed decompression for an entry within block '%s' in archive '%d'!\n", block.m_svBlockPath.c_str(), i);
|
Error(eDLL_T::FS, "Error: failed decompression for an entry within block '%s' in archive '%d'!\n", block.m_svBlockPath.c_str(), i);
|
||||||
Error(eDLL_T::FS, "'lzham_decompress_memory_func' returned with status '%d'.\n", m_lzDecompStatus);
|
Error(eDLL_T::FS, "'lzham::lzham_lib_decompress_memory' returned with status '%d'.\n", m_lzDecompStatus);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If successfully decompressed, write to file.
|
// If successfully decompressed, write to file.
|
||||||
outFileStream.write((char*)pLzOutputBuf, entry.m_nUncompressedSize);
|
outFileStream.write((char*)pLzOutputBuf, entry.m_nUncompressedSize);
|
||||||
delete[] pLzOutputBuf, pCompressedData;
|
|
||||||
}
|
}
|
||||||
|
delete[] pLzOutputBuf;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If not compressed, write raw data into output file.
|
// If not compressed, write raw data into output file.
|
||||||
outFileStream.write(pCompressedData, entry.m_nUncompressedSize);
|
outFileStream.write(pCompressedData, entry.m_nUncompressedSize);
|
||||||
}
|
}
|
||||||
|
delete[] pCompressedData;
|
||||||
}
|
}
|
||||||
outFileStream.close();
|
outFileStream.close();
|
||||||
if (m_nEntryCount == block.m_vvEntries.size()) // Only validate after last entry in block had been written.
|
if (m_nEntryCount == block.m_vvEntries.size()) // Only validate after last entry in block had been written.
|
||||||
@ -292,57 +339,85 @@ VPKEntryBlock_t::VPKEntryBlock_t(CIOStream* reader, string svPath)
|
|||||||
std::replace(svPath.begin(), svPath.end(), '/', '\\'); // Flip forward slashes in filepath to windows-style backslash.
|
std::replace(svPath.begin(), svPath.end(), '/', '\\'); // Flip forward slashes in filepath to windows-style backslash.
|
||||||
|
|
||||||
this->m_svBlockPath = svPath; // Set path of block.
|
this->m_svBlockPath = svPath; // Set path of block.
|
||||||
reader->read<uint32_t>(this->m_nCrc32); //
|
reader->Read<uint32_t>(this->m_nCrc32); //
|
||||||
reader->read<uint16_t>(this->m_nPreloadBytes); //
|
reader->Read<uint16_t>(this->m_nPreloadBytes); //
|
||||||
reader->read<uint16_t>(this->m_iArchiveIndex); //
|
reader->Read<uint16_t>(this->m_iArchiveIndex); //
|
||||||
|
|
||||||
do // Loop through all entries in the block and push them to the vector.
|
do // Loop through all entries in the block and push them to the vector.
|
||||||
{
|
{
|
||||||
VPKEntryDescr_t entry(reader);
|
VPKEntryDescriptor_t entry(reader);
|
||||||
this->m_vvEntries.push_back(entry);
|
this->m_vvEntries.push_back(entry);
|
||||||
} while (reader->readR<uint16_t>() != 65535);
|
} while (reader->Read<uint16_t>() != 0xFFFF);
|
||||||
|
}
|
||||||
|
#undef min
|
||||||
|
VPKEntryBlock_t::VPKEntryBlock_t(const vector<uint8_t> &vData, int64_t nOffset, uint16_t nArchiveIndex, uint32_t nEntryFlags, uint16_t nTextureFlags, string svBlockPath)
|
||||||
|
{
|
||||||
|
m_nCrc32 = crc32::update(m_nCrc32, vData.data(), vData.size());
|
||||||
|
m_nPreloadBytes = 0;
|
||||||
|
m_iArchiveIndex = nArchiveIndex;
|
||||||
|
m_svBlockPath = svBlockPath;
|
||||||
|
|
||||||
|
int nEntryCount = (vData.size() + RVPK_MAX_BLOCK - 1) / RVPK_MAX_BLOCK;
|
||||||
|
uint64_t nDataSize = vData.size();
|
||||||
|
int64_t nCurrentOffset = nOffset;
|
||||||
|
for (int i = 0; i < nEntryCount; i++)
|
||||||
|
{
|
||||||
|
uint64_t nSize = std::min<uint64_t>(RVPK_MAX_BLOCK, nDataSize);
|
||||||
|
nDataSize -= nSize;
|
||||||
|
m_vvEntries.push_back(VPKEntryDescriptor_t(nEntryFlags, nTextureFlags, nCurrentOffset, nSize, nSize));
|
||||||
|
nCurrentOffset += nSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VPKEntryDescriptor_t::VPKEntryDescriptor_t(uint32_t nEntryFlags, uint16_t nTextureFlags, uint64_t nArchiveOffset, uint64_t nCompressedSize, uint64_t nUncompressedSize)
|
||||||
|
{
|
||||||
|
m_nEntryFlags = nEntryFlags;
|
||||||
|
m_nTextureFlags = nTextureFlags;
|
||||||
|
m_nArchiveOffset = nArchiveOffset;
|
||||||
|
|
||||||
|
m_nCompressedSize = nCompressedSize;
|
||||||
|
m_nUncompressedSize = nUncompressedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: 'vpk_entry_h' constructor
|
// Purpose: 'VPKDir_t' constructor
|
||||||
|
// Input : *pReader -
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
VPKEntryDescr_t::VPKEntryDescr_t(CIOStream* reader)
|
VPKEntryDescriptor_t::VPKEntryDescriptor_t(CIOStream* pReader)
|
||||||
{
|
{
|
||||||
reader->read<uint32_t>(this->m_nEntryFlags); //
|
pReader->Read<uint32_t>(this->m_nEntryFlags); //
|
||||||
reader->read<uint16_t>(this->m_nTextureFlags); //
|
pReader->Read<uint16_t>(this->m_nTextureFlags); //
|
||||||
reader->read<uint64_t>(this->m_nArchiveOffset); //
|
pReader->Read<uint64_t>(this->m_nArchiveOffset); //
|
||||||
reader->read<uint64_t>(this->m_nCompressedSize); //
|
pReader->Read<uint64_t>(this->m_nCompressedSize); //
|
||||||
reader->read<uint64_t>(this->m_nUncompressedSize); //
|
pReader->Read<uint64_t>(this->m_nUncompressedSize); //
|
||||||
this->m_bIsCompressed = (this->m_nCompressedSize != this->m_nUncompressedSize);
|
this->m_bIsCompressed = (this->m_nCompressedSize != this->m_nUncompressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: 'vpk_dir_h' constructor
|
// Purpose: 'VPKDir_t' file constructor
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
VPKDir_t::VPKDir_t(string svPath)
|
VPKDir_t::VPKDir_t(const string& svPath)
|
||||||
{
|
{
|
||||||
CIOStream reader;
|
CIOStream reader(svPath, CIOStream::Mode_t::READ);
|
||||||
|
reader.Read<uint32_t>(this->m_vHeader.m_nFileMagic);
|
||||||
|
|
||||||
reader.open(svPath, eStreamFileMode::READ);
|
if (this->m_vHeader.m_nFileMagic != RVPK_DIR_MAGIC)
|
||||||
reader.read<uint32_t>(this->m_nFileMagic);
|
|
||||||
|
|
||||||
if (this->m_nFileMagic != RVPK_DIR_MAGIC)
|
|
||||||
{
|
{
|
||||||
Error(eDLL_T::FS, "Error: vpk_dir file '%s' has invalid magic!\n", svPath.c_str());
|
Error(eDLL_T::FS, "Error: vpk_dir file '%s' has invalid magic!\n", svPath.c_str());
|
||||||
return;
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.read<uint16_t>(this->m_nMajorVersion); //
|
reader.Read<uint16_t>(this->m_vHeader.m_nMajorVersion); //
|
||||||
reader.read<uint16_t>(this->m_nMinorVersion); //
|
reader.Read<uint16_t>(this->m_vHeader.m_nMinorVersion); //
|
||||||
reader.read<uint32_t>(this->m_nTreeSize); //
|
reader.Read<uint32_t>(this->m_vHeader.m_nTreeSize); //
|
||||||
reader.read<uint32_t>(this->m_nFileDataSize); //
|
reader.Read<uint32_t>(this->m_nFileDataSize); //
|
||||||
|
|
||||||
DevMsg(eDLL_T::FS, "______________________________________________________________\n");
|
DevMsg(eDLL_T::FS, "______________________________________________________________\n");
|
||||||
DevMsg(eDLL_T::FS, "] HEADER_DETAILS ---------------------------------------------\n");
|
DevMsg(eDLL_T::FS, "] HEADER_DETAILS ---------------------------------------------\n");
|
||||||
DevMsg(eDLL_T::FS, "] File Magic : '%lu'\n", this->m_nFileMagic);
|
DevMsg(eDLL_T::FS, "] File Magic : '%lu'\n", this->m_vHeader.m_nFileMagic);
|
||||||
DevMsg(eDLL_T::FS, "] Major Version : '%hu'\n", this->m_nMajorVersion);
|
DevMsg(eDLL_T::FS, "] Major Version : '%hu'\n", this->m_vHeader.m_nMajorVersion);
|
||||||
DevMsg(eDLL_T::FS, "] Minor Version : '%hu'\n", this->m_nMinorVersion);
|
DevMsg(eDLL_T::FS, "] Minor Version : '%hu'\n", this->m_vHeader.m_nMinorVersion);
|
||||||
DevMsg(eDLL_T::FS, "] Tree Size : '%lu'\n", this->m_nTreeSize);
|
DevMsg(eDLL_T::FS, "] Tree Size : '%lu'\n", this->m_vHeader.m_nTreeSize);
|
||||||
DevMsg(eDLL_T::FS, "] File Data Size : '%lu'\n", this->m_nFileDataSize);
|
DevMsg(eDLL_T::FS, "] File Data Size : '%lu'\n", this->m_nFileDataSize);
|
||||||
|
|
||||||
this->m_vvEntryBlocks = g_pPackedStore->GetEntryBlocks(&reader);
|
this->m_vvEntryBlocks = g_pPackedStore->GetEntryBlocks(&reader);
|
||||||
@ -366,5 +441,91 @@ VPKDir_t::VPKDir_t(string svPath)
|
|||||||
this->m_vsvArchives.push_back(svArchivePath);
|
this->m_vsvArchives.push_back(svArchivePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: builds the VPKDir file
|
||||||
|
// Input : &svFileName -
|
||||||
|
// &vEntryBlocks -
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void VPKDir_t::Build(const string& svFileName, const vector<VPKEntryBlock_t>& vEntryBlocks)
|
||||||
|
{
|
||||||
|
CIOStream writer(svFileName, CIOStream::Mode_t::WRITE);
|
||||||
|
auto vMap = std::map<string, std::map<string, std::list<VPKEntryBlock_t>>>();
|
||||||
|
|
||||||
|
writer.Write<uint32_t>(this->m_vHeader.m_nFileMagic);
|
||||||
|
writer.Write<uint16_t>(this->m_vHeader.m_nMajorVersion);
|
||||||
|
writer.Write<uint16_t>(this->m_vHeader.m_nMinorVersion);
|
||||||
|
writer.Write<uint32_t>(this->m_vHeader.m_nTreeSize);
|
||||||
|
writer.Write<uint32_t>(this->m_vHeader.m_nTreeSize);
|
||||||
|
|
||||||
|
for (VPKEntryBlock_t vBlock : vEntryBlocks)
|
||||||
|
{
|
||||||
|
string svExtension = GetExtension(vBlock.m_svBlockPath);
|
||||||
|
string svFileName = GetFileName(vBlock.m_svBlockPath, true);
|
||||||
|
string svFilePath = RemoveFileName(vBlock.m_svBlockPath);
|
||||||
|
|
||||||
|
if (svFilePath.empty())
|
||||||
|
{
|
||||||
|
svFilePath = " "; // Has to be padded with a space character if empty.
|
||||||
|
}
|
||||||
|
if (!vMap.count(svExtension))
|
||||||
|
{
|
||||||
|
vMap.insert({ svExtension, std::map<string, std::list<VPKEntryBlock_t>>() });
|
||||||
|
}
|
||||||
|
if (!vMap[svExtension].count(svFilePath))
|
||||||
|
{
|
||||||
|
vMap[svExtension].insert({ svFilePath, std::list<VPKEntryBlock_t>() });
|
||||||
|
}
|
||||||
|
vMap[svExtension][svFilePath].push_back(vBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& iKeyValue : vMap)
|
||||||
|
{
|
||||||
|
writer.WriteString(iKeyValue.first);
|
||||||
|
for (auto& jKeyValue : iKeyValue.second)
|
||||||
|
{
|
||||||
|
writer.WriteString(jKeyValue.first);
|
||||||
|
for (auto& eKeyValue : jKeyValue.second)
|
||||||
|
{
|
||||||
|
writer.WriteString(GetFileName(eKeyValue.m_svBlockPath, true));
|
||||||
|
{/*Write entry block*/
|
||||||
|
writer.Write(eKeyValue.m_nCrc32);
|
||||||
|
writer.Write(eKeyValue.m_nPreloadBytes);
|
||||||
|
writer.Write(eKeyValue.m_iArchiveIndex);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < eKeyValue.m_vvEntries.size(); i++)
|
||||||
|
{
|
||||||
|
{/*Write entry descriptor*/
|
||||||
|
writer.Write(eKeyValue.m_vvEntries[i].m_nEntryFlags);
|
||||||
|
writer.Write(eKeyValue.m_vvEntries[i].m_nTextureFlags);
|
||||||
|
writer.Write(eKeyValue.m_vvEntries[i].m_nArchiveOffset);
|
||||||
|
writer.Write(eKeyValue.m_vvEntries[i].m_nCompressedSize);
|
||||||
|
writer.Write(eKeyValue.m_vvEntries[i].m_nUncompressedSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != (eKeyValue.m_vvEntries.size() - 1))
|
||||||
|
{
|
||||||
|
const ushort s = 0;
|
||||||
|
writer.Write(s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ushort s = UINT16_MAX;
|
||||||
|
writer.Write(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.Write<uint8_t>('\0');
|
||||||
|
}
|
||||||
|
writer.Write<uint8_t>('\0');
|
||||||
|
}
|
||||||
|
writer.Write<uint8_t>('\0');
|
||||||
|
m_vHeader.m_nTreeSize = static_cast<uint32_t>(writer.GetPosition() - sizeof(VPKHeader_t));
|
||||||
|
|
||||||
|
writer.SetPosition(offsetof(VPKDir_t, m_vHeader.m_nTreeSize));
|
||||||
|
writer.Write(this->m_vHeader.m_nTreeSize);
|
||||||
|
writer.Write(0);
|
||||||
|
}
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
CPackedStore* g_pPackedStore = new CPackedStore();
|
CPackedStore* g_pPackedStore = new CPackedStore();
|
||||||
|
@ -2,10 +2,15 @@
|
|||||||
#include "public/include/binstream.h"
|
#include "public/include/binstream.h"
|
||||||
#include "thirdparty/lzham/include/lzham.h"
|
#include "thirdparty/lzham/include/lzham.h"
|
||||||
|
|
||||||
|
constexpr unsigned int RVPK_DIR_MAGIC = 'Uª4';
|
||||||
|
constexpr unsigned int RVPK_MAJOR_VER = 2;
|
||||||
|
constexpr unsigned int RVPK_MINOR_VER = 3;
|
||||||
|
|
||||||
constexpr unsigned int LIBRARY_PACKS = 2;
|
constexpr unsigned int LIBRARY_PACKS = 2;
|
||||||
constexpr unsigned int LANGUAGE_PACKS = 11;
|
constexpr unsigned int LANGUAGE_PACKS = 11;
|
||||||
constexpr unsigned int RVPK_DICT_SIZE = 20;
|
constexpr unsigned int RVPK_DICT_SIZE = 20;
|
||||||
constexpr unsigned int RVPK_DIR_MAGIC = 'Uª4';
|
constexpr int RVPK_MAX_BLOCK = 1024 * 1024;
|
||||||
|
constexpr int DECOMP_MAX_BUF = 2024 * 2024;
|
||||||
|
|
||||||
const std::string DIR_LIBRARY_PREFIX[LIBRARY_PACKS] = { "server", "client" };
|
const std::string DIR_LIBRARY_PREFIX[LIBRARY_PACKS] = { "server", "client" };
|
||||||
const std::string DIR_LOCALE_PREFIX[LANGUAGE_PACKS] = { "english", "french", "german", "italian", "japanese", "korean", "polish", "portuguese", "russian", "spanish", "tchinese" };
|
const std::string DIR_LOCALE_PREFIX[LANGUAGE_PACKS] = { "english", "french", "german", "italian", "japanese", "korean", "polish", "portuguese", "russian", "spanish", "tchinese" };
|
||||||
@ -31,7 +36,7 @@ struct VPKData_t
|
|||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct VPKEntryDescr_t
|
struct VPKEntryDescriptor_t
|
||||||
{
|
{
|
||||||
uint32_t m_nEntryFlags {}; // Entry flags.
|
uint32_t m_nEntryFlags {}; // Entry flags.
|
||||||
uint16_t m_nTextureFlags {}; // Texture flags (only used if the entry is a vtf).
|
uint16_t m_nTextureFlags {}; // Texture flags (only used if the entry is a vtf).
|
||||||
@ -40,38 +45,49 @@ struct VPKEntryDescr_t
|
|||||||
uint64_t m_nUncompressedSize{}; // Uncompressed size of entry.
|
uint64_t m_nUncompressedSize{}; // Uncompressed size of entry.
|
||||||
bool m_bIsCompressed = false;
|
bool m_bIsCompressed = false;
|
||||||
|
|
||||||
VPKEntryDescr_t(CIOStream* reader);
|
VPKEntryDescriptor_t(){};
|
||||||
|
VPKEntryDescriptor_t(CIOStream* reader);
|
||||||
|
VPKEntryDescriptor_t(uint32_t nEntryFlags, uint16_t nTextureFlags, uint64_t nArchiveOffset, uint64_t nCompressedSize, uint64_t nUncompressedSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VPKEntryBlock_t
|
struct VPKEntryBlock_t
|
||||||
{
|
{
|
||||||
uint32_t m_nCrc32 {}; // Crc32 for the uncompressed block.
|
uint32_t m_nCrc32 {}; // Crc32 for the uncompressed block.
|
||||||
uint16_t m_nPreloadBytes{}; // Preload bytes.
|
uint16_t m_nPreloadBytes{}; // Preload bytes.
|
||||||
uint16_t m_iArchiveIndex{}; // Index of the archive that contains this block.
|
uint16_t m_iArchiveIndex{}; // Index of the archive that contains this block.
|
||||||
vector<VPKEntryDescr_t> m_vvEntries {}; // Vector of all the entries of a given block (entries have a size limit of 1 MiB, so anything over is split into separate entries within the same block).
|
vector<VPKEntryDescriptor_t> m_vvEntries {}; // Vector of all the entries of a given block (entries have a size limit of 1 MiB, so anything over is split into separate entries within the same block).
|
||||||
string m_svBlockPath {}; // Path to block within vpk.
|
string m_svBlockPath {}; // Path to block within vpk.
|
||||||
|
|
||||||
VPKEntryBlock_t(CIOStream* reader, string path);
|
VPKEntryBlock_t(CIOStream* reader, string path);
|
||||||
|
VPKEntryBlock_t(const vector<uint8_t>& vData, int64_t nOffset, uint16_t nArchiveIndex, uint32_t nEntryFlags, uint16_t nTextureFlags, string svBlockPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VPKDir_t
|
struct VPKHeader_t
|
||||||
{
|
{
|
||||||
uint32_t m_nFileMagic {}; // File magic.
|
uint32_t m_nFileMagic {}; // File magic.
|
||||||
uint16_t m_nMajorVersion{}; // Vpk major version.
|
uint16_t m_nMajorVersion{}; // Vpk major version.
|
||||||
uint16_t m_nMinorVersion{}; // Vpk minor version.
|
uint16_t m_nMinorVersion{}; // Vpk minor version.
|
||||||
uint32_t m_nTreeSize {}; // Directory tree size.
|
uint32_t m_nTreeSize {}; // Directory tree size.
|
||||||
|
uint32_t m_nPadding {}; // Padding to align the header.
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VPKDir_t
|
||||||
|
{
|
||||||
|
VPKHeader_t m_vHeader {}; // Dir header.
|
||||||
uint32_t m_nFileDataSize{}; // File data section size.
|
uint32_t m_nFileDataSize{}; // File data section size.
|
||||||
vector<VPKEntryBlock_t> m_vvEntryBlocks{}; // Vector of entry blocks.
|
vector<VPKEntryBlock_t> m_vvEntryBlocks{}; // Vector of entry blocks.
|
||||||
uint16_t m_iArchiveCount{}; // Highest archive index (archive count-1).
|
uint16_t m_iArchiveCount{}; // Highest archive index (archive count-1).
|
||||||
vector<string> m_vsvArchives {}; // Vector of archive file names.
|
vector<string> m_vsvArchives {}; // Vector of archive file names.
|
||||||
string m_svDirPath {}; // Path to vpk_dir file.
|
string m_svDirPath {}; // Path to vpk_dir file.
|
||||||
|
|
||||||
VPKDir_t(string path);
|
VPKDir_t() { m_vHeader.m_nFileMagic = RVPK_DIR_MAGIC; m_vHeader.m_nMajorVersion = RVPK_MAJOR_VER; m_vHeader.m_nMinorVersion = RVPK_MINOR_VER; };
|
||||||
|
VPKDir_t(const string& svPath);
|
||||||
|
|
||||||
|
void Build(const string& svFileName, const vector<VPKEntryBlock_t>& vEntryBlocks);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPackedStore
|
class CPackedStore
|
||||||
{
|
{
|
||||||
vector<uint8_t> m_vHashBuffer {}; // Buffer for post decomp file validation.
|
|
||||||
size_t m_nEntryCount {}; // Entry per-block incrementor.
|
size_t m_nEntryCount {}; // Entry per-block incrementor.
|
||||||
lzham_uint32 m_nAdler32_Internal{}; // Internal operation Adler32 file checksum.
|
lzham_uint32 m_nAdler32_Internal{}; // Internal operation Adler32 file checksum.
|
||||||
lzham_uint32 m_nAdler32 {}; // Pre/post operation Adler32 file checksum.
|
lzham_uint32 m_nAdler32 {}; // Pre/post operation Adler32 file checksum.
|
||||||
@ -88,11 +104,13 @@ public:
|
|||||||
VPKDir_t GetPackDirFile(string svPackDirFile);
|
VPKDir_t GetPackDirFile(string svPackDirFile);
|
||||||
string GetPackChunkFile(string svPackDirFile, int iArchiveIndex);
|
string GetPackChunkFile(string svPackDirFile, int iArchiveIndex);
|
||||||
vector<VPKEntryBlock_t> GetEntryBlocks(CIOStream* reader);
|
vector<VPKEntryBlock_t> GetEntryBlocks(CIOStream* reader);
|
||||||
|
vector<string> GetEntryPaths(const string& svPathIn) const;
|
||||||
string FormatBlockPath(string svName, string svPath, string svExtension);
|
string FormatBlockPath(string svName, string svPath, string svExtension);
|
||||||
string StripLocalePrefix(string svPackDirFile);
|
string StripLocalePrefix(string svPackDirFile);
|
||||||
|
void PackAll(string svDirIn, string svPathOut = "");
|
||||||
void UnpackAll(VPKDir_t vpk, string svPathOut = "");
|
void UnpackAll(VPKDir_t vpk, string svPathOut = "");
|
||||||
void ValidateAdler32PostDecomp(string svDirAsset);
|
void ValidateAdler32PostDecomp(const string& svDirAsset);
|
||||||
void ValidateCRC32PostDecomp(string svDirAsset);
|
void ValidateCRC32PostDecomp(const string& svDirAsset);
|
||||||
};
|
};
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
extern CPackedStore* g_pPackedStore;
|
extern CPackedStore* g_pPackedStore;
|
||||||
|
@ -611,7 +611,34 @@ void RTech_Decompress_f(const CCommand& args)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
=====================
|
=====================
|
||||||
VPK_Decompress_f
|
VPK_Pack_f
|
||||||
|
|
||||||
|
Compresses new VPK files and
|
||||||
|
dumps the output to '\vpk'.
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void VPK_Pack_f(const CCommand& args)
|
||||||
|
{
|
||||||
|
if (args.ArgC() < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string szPathOut = "platform\\vpk";
|
||||||
|
std::chrono::milliseconds msStart = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||||
|
|
||||||
|
//VPKDir_t vpk = g_pPackedStore->GetPackDirFile(args.Arg(1));
|
||||||
|
g_pPackedStore->InitLzCompParams();
|
||||||
|
|
||||||
|
std::thread th([&] { g_pPackedStore->PackAll(args.Arg(1), szPathOut); });
|
||||||
|
th.join();
|
||||||
|
|
||||||
|
std::chrono::milliseconds msEnd = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||||
|
float duration = msEnd.count() - msStart.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
VPK_Unpack_f
|
||||||
|
|
||||||
Decompresses input VPK files and
|
Decompresses input VPK files and
|
||||||
dumps the output to '<mod>\vpk'.
|
dumps the output to '<mod>\vpk'.
|
||||||
|
@ -29,6 +29,7 @@ void Pak_RequestLoad_f(const CCommand& args);
|
|||||||
void Pak_Swap_f(const CCommand& args);
|
void Pak_Swap_f(const CCommand& args);
|
||||||
void RTech_StringToGUID_f(const CCommand& args);
|
void RTech_StringToGUID_f(const CCommand& args);
|
||||||
void RTech_Decompress_f(const CCommand& args);
|
void RTech_Decompress_f(const CCommand& args);
|
||||||
|
void VPK_Pack_f(const CCommand& args);
|
||||||
void VPK_Unpack_f(const CCommand& args);
|
void VPK_Unpack_f(const CCommand& args);
|
||||||
void VPK_Mount_f(const CCommand& args);
|
void VPK_Mount_f(const CCommand& args);
|
||||||
void NET_SetKey_f(const CCommand& args);
|
void NET_SetKey_f(const CCommand& args);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user