Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FileFormats/2da/2da_Raw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ bool TwoDA::ConstructInternal(std::byte const* bytes, std::size_t bytesCount)
{
while (*head++ != '\n' && head < end) {}
lines.emplace_back(std::string(tail, head - tail));
tail = head++;
tail = head;
}

flattenedLines.clear();
Expand Down
93 changes: 93 additions & 0 deletions FileFormats/Erf/Erf_Friendly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

namespace FileFormats::Erf::Friendly {

Erf::Erf()
{ }

Erf::Erf(Raw::Erf const& rawErf)
{
ConstructInternal(rawErf);
Expand All @@ -16,16 +19,106 @@ Erf::Erf(Raw::Erf&& rawErf) : m_RawErf(std::forward<Raw::Erf>(rawErf))
ConstructInternal(m_RawErf.value());
}

std::vector<Raw::ErfLocalisedString>& Erf::GetDescriptions()
{
return m_Descriptions;
}

std::vector<Raw::ErfLocalisedString> const& Erf::GetDescriptions() const
{
return m_Descriptions;
}

std::vector<ErfResource>& Erf::GetResources()
{
return m_Resources;
}

std::vector<ErfResource> const& Erf::GetResources() const
{
return m_Resources;
}

char* Erf::GetFileType()
{
return m_FileType;
}

const char* Erf::GetFileType() const
{
return m_FileType;
}

bool Erf::WriteToFile(char const* path) const
{
Raw::Erf raw_erf;

std::memcpy(raw_erf.m_Header.m_FileType, m_FileType, 4);
std::memcpy(raw_erf.m_Header.m_Version, "V1.0", 4);

raw_erf.m_Header.m_LanguageCount = (std::uint32_t)m_Descriptions.size();
raw_erf.m_Header.m_EntryCount = (std::uint32_t)m_Resources.size();

raw_erf.m_Header.m_LocalizedStringSize = 0;
for (const Raw::ErfLocalisedString& str : m_Descriptions)
{
raw_erf.m_Header.m_LocalizedStringSize += sizeof(str.m_LanguageId)
+ sizeof(std::uint32_t) // string size
+ (std::uint32_t)str.m_String.size(); // string
}

std::uint32_t offset_str_table = sizeof(raw_erf.m_Header);
std::uint32_t offset_keys = offset_str_table + raw_erf.m_Header.m_LocalizedStringSize;
std::uint32_t offset_resources = offset_keys + (raw_erf.m_Header.m_EntryCount * sizeof(Raw::ErfKey));
std::uint32_t offset_to_res_data = offset_resources + (raw_erf.m_Header.m_EntryCount * sizeof(Raw::ErfResource));

raw_erf.m_Header.m_OffsetToLocalizedString = offset_str_table;
raw_erf.m_Header.m_OffsetToKeyList = offset_keys;
raw_erf.m_Header.m_OffsetToResourceList = offset_resources;
raw_erf.m_Header.m_BuildYear = 666;
raw_erf.m_Header.m_BuildDay = 333;
raw_erf.m_Header.m_DescriptionStrRef = ~0u;
std::memset(raw_erf.m_Header.m_Reserved, 0, sizeof(raw_erf.m_Header.m_Reserved));

raw_erf.m_LocalisedStrings = m_Descriptions;

{
uint32_t total_data_size = 0;

for (const ErfResource& friendly_res : m_Resources)
{
total_data_size += (std::uint32_t)friendly_res.m_DataBlock->GetDataLength();
}

std::unique_ptr<OwningDataBlock> data = std::make_unique<OwningDataBlock>();
data->m_Data.resize(total_data_size);
raw_erf.m_ResourceData = std::move(data);
}

for (std::uint32_t i = 0, offset_in_res_data = 0; i < raw_erf.m_Header.m_EntryCount; ++i)
{
const ErfResource& friendly_res = m_Resources[i];

Raw::ErfKey key;
std::memset(key.m_ResRef, 0, sizeof(key.m_ResRef));
std::memcpy(key.m_ResRef, friendly_res.m_ResRef.c_str(), friendly_res.m_ResRef.size());
key.m_ResId = i;
key.m_ResType = friendly_res.m_ResType;
std::memset(key.m_Reserved, 0, sizeof(key.m_Reserved));
raw_erf.m_Keys.emplace_back(std::move(key));

Raw::ErfResource res;
res.m_OffsetToResource = offset_to_res_data + offset_in_res_data;
res.m_ResourceSize = (std::uint32_t)friendly_res.m_DataBlock->GetDataLength();
raw_erf.m_Resources.emplace_back(std::move(res));

std::memcpy((void*)(raw_erf.m_ResourceData->GetData() + offset_in_res_data), friendly_res.m_DataBlock->GetData(), res.m_ResourceSize);
offset_in_res_data += res.m_ResourceSize;
}

return raw_erf.WriteToFile(path);
}

void Erf::ConstructInternal(Raw::Erf const& rawErf)
{
// First - copy in the descriptions. This one is simple.
Expand Down
12 changes: 12 additions & 0 deletions FileFormats/Erf/Erf_Friendly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ struct ErfResource
class Erf
{
public:
Erf();

// This constructs a friendly Erf from a raw Erf.
Erf(Raw::Erf const& rawBif);

Expand All @@ -33,9 +35,17 @@ class Erf
// the memory usage significantly.
Erf(Raw::Erf&& rawBif);

std::vector<Raw::ErfLocalisedString>& GetDescriptions();
std::vector<Raw::ErfLocalisedString> const& GetDescriptions() const;

std::vector<ErfResource>& GetResources();
std::vector<ErfResource> const& GetResources() const;

char* GetFileType();
const char* GetFileType() const;

bool WriteToFile(char const* path) const;

private:
std::optional<Raw::Erf> m_RawErf;

Expand All @@ -46,6 +56,8 @@ class Erf

// A vector of resources contained within this ERF.
std::vector<ErfResource> m_Resources;

char m_FileType[4];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change this (and the other one) to std:array<char, 4>?

};

}
28 changes: 28 additions & 0 deletions FileFormats/Erf/Erf_Raw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,34 @@ bool Erf::ReadFromFile(char const* path, Erf* out)
return true;
}

bool Erf::WriteToFile(char const* path) const
{
ASSERT(path);

FILE* outFile = std::fopen(path, "wb");

if (outFile)
{
std::fwrite(&m_Header, sizeof(m_Header), 1, outFile);

for (const ErfLocalisedString& str : m_LocalisedStrings)
{
std::fwrite(&str.m_LanguageId, sizeof(str.m_LanguageId), 1, outFile);
uint32_t len = (std::uint32_t)str.m_String.size();
std::fwrite(&len, sizeof(len), 1, outFile);
std::fwrite(str.m_String.c_str(), len, 1, outFile);
}

std::fwrite(m_Keys.data(), m_Keys.size() * sizeof(ErfKey), 1, outFile);
std::fwrite(m_Resources.data(), m_Resources.size() * sizeof(ErfResource), 1, outFile);
std::fwrite(m_ResourceData->GetData(), m_ResourceData->GetDataLength(), 1, outFile);

std::fclose(outFile);
return true;
}

return false;
}

bool Erf::ConstructInternal(std::byte const* bytes)
{
Expand Down
4 changes: 3 additions & 1 deletion FileFormats/Erf/Erf_Raw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ struct Erf
// Constructs an Erf from a file. The file with be memory mapped so memory usage will be ideal.
static bool ReadFromFile(char const* path, Erf* out);

// Writes the raw ERF to disk.
bool WriteToFile(char const* path) const;

private:

// This is an RAII wrapper around the various methods of loading a BIF that we have.
Expand All @@ -133,7 +136,6 @@ struct Erf
void ReadLocalisedStrings(std::byte const* data);
void ReadKeys(std::byte const* data);
void ReadResources(std::byte const* data);
void ReadResourceData(std::byte const* data, std::size_t bytesCount);
};

}
27 changes: 22 additions & 5 deletions FileFormats/Gff/Gff_Friendly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ Gff::Gff() : m_TopLevelStruct()
{ }

Gff::Gff(Raw::Gff const& rawGff) : m_TopLevelStruct(rawGff.m_Structs[0], rawGff)
{ }
{
memcpy(m_FileType, rawGff.m_Header.m_FileType, sizeof(m_FileType));
}

GffStruct& Gff::GetTopLevelStruct()
{
Expand All @@ -225,10 +227,20 @@ GffStruct const& Gff::GetTopLevelStruct() const
return m_TopLevelStruct;
}

char* Gff::GetFileType()
{
return m_FileType;
}

const char* Gff::GetFileType() const
{
return m_FileType;
}

struct GffCreator
{
public:
std::unique_ptr<Raw::Gff> Create(const GffStruct& topLevelStruct);
std::unique_ptr<Raw::Gff> Create(const GffStruct& topLevelStruct, const char* fleType);

private:
template <typename T>
Expand Down Expand Up @@ -262,16 +274,21 @@ struct GffCreator

bool Gff::WriteToFile(char const* path) const
{
return GffCreator().Create(m_TopLevelStruct)->WriteToFile(path);
return GffCreator().Create(m_TopLevelStruct, m_FileType)->WriteToFile(path);
}

size_t Gff::WriteToBytes(std::byte* bytes, size_t max_len) const
{
return GffCreator().Create(m_TopLevelStruct, m_FileType)->WriteToBytes(bytes, max_len);
}

std::unique_ptr<Raw::Gff> GffCreator::Create(const GffStruct& topLevelStruct)
std::unique_ptr<Raw::Gff> GffCreator::Create(const GffStruct& topLevelStruct, const char* fileType)
{
m_RawGff = std::make_unique<Raw::Gff>();
InsertIntoRawGff(topLevelStruct);

Raw::GffHeader* header = &m_RawGff->m_Header;
std::memcpy(header->m_FileType, "UTC ", 4);
std::memcpy(header->m_FileType, fileType, 4);
std::memcpy(header->m_FileVersion, "V3.2", 4);

header->m_StructOffset = sizeof(Raw::GffHeader);
Expand Down
7 changes: 7 additions & 0 deletions FileFormats/Gff/Gff_Friendly.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <any>
#include <cstddef>
#include <map>
#include <memory>
#include <vector>

#include "FileFormats/Gff/Gff_Raw.hpp"
Expand Down Expand Up @@ -174,10 +176,15 @@ class Gff
GffStruct& GetTopLevelStruct();
GffStruct const& GetTopLevelStruct() const;

char* GetFileType();
const char* GetFileType() const;

bool WriteToFile(char const* path) const;
size_t WriteToBytes(std::byte* bytes, size_t max_len) const;

private:
GffStruct m_TopLevelStruct;
char m_FileType[4];
};

}
43 changes: 35 additions & 8 deletions FileFormats/Gff/Gff_Raw.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "FileFormats/Gff/Gff_Raw.hpp"
#include "Utility/Assert.hpp"
#include "Utility/MemoryMappedFile.hpp"
#include "Utility/StreamWriter.hpp"

#include <cstring>

Expand Down Expand Up @@ -41,23 +42,38 @@ bool Gff::WriteToFile(char const* path) const
ASSERT(path);

FILE* outFile = std::fopen(path, "wb");

if (outFile)
{
std::fwrite(&m_Header, sizeof(m_Header), 1, outFile);
std::fwrite(m_Structs.data(), sizeof(m_Structs[0]), m_Structs.size(), outFile);
std::fwrite(m_Fields.data(), sizeof(m_Fields[0]), m_Fields.size(), outFile);
std::fwrite(m_Labels.data(), sizeof(m_Labels[0]), m_Labels.size(), outFile);
std::fwrite(m_FieldData.data(), sizeof(m_FieldData[0]), m_FieldData.size(), outFile);
std::fwrite(m_FieldIndices.data(), sizeof(m_FieldIndices[0]), m_FieldIndices.size(), outFile);
std::fwrite(m_ListIndices.data(), sizeof(m_ListIndices[0]), m_ListIndices.size(), outFile);
FileStreamWriter writer(outFile);
WriteInternal(&writer);
std::fclose(outFile);
return true;
}

return false;
}

size_t Gff::WriteToBytes(std::byte* bytes, size_t max_len) const
{
SizeStreamWriter size_writer;
WriteInternal(&size_writer);
size_t len_required = size_writer.GetSize();

if (max_len == 0)
{
return len_required;
}

if (max_len < len_required)
{
return 0;
}

MemoryStreamWriter memory_writer(bytes);
WriteInternal(&memory_writer);
return len_required;
}

namespace {

template <typename T>
Expand Down Expand Up @@ -276,6 +292,17 @@ bool Gff::ConstructInternal(std::byte const* bytes)
return true;
}

void Gff::WriteInternal(IStreamWriter* writer) const
{
writer->Write(&m_Header, sizeof(m_Header));
writer->Write(m_Structs.data(), sizeof(m_Structs[0]) * m_Structs.size());
writer->Write(m_Fields.data(), sizeof(m_Fields[0]) * m_Fields.size());
writer->Write(m_Labels.data(), sizeof(m_Labels[0]) * m_Labels.size());
writer->Write(m_FieldData.data(), sizeof(m_FieldData[0]) * m_FieldData.size());
writer->Write(m_FieldIndices.data(), sizeof(m_FieldIndices[0]) * m_FieldIndices.size());
writer->Write(m_ListIndices.data(), sizeof(m_ListIndices[0]) * m_ListIndices.size());
}

namespace {

template <typename T>
Expand Down
Loading