Skip to content

Commit

Permalink
Simplify pointer assignment and registration API
Browse files Browse the repository at this point in the history
Make an API that registers and sets the pointer to the struct in a single call. The function only expects the objects now and deals with the calls internally. This significantly improves the readability of the code, and also significantly reduces the chances for human error where the previous GetPointer call for example as called on a different struct member than AddPointer. Now it is only defined once on call site.
  • Loading branch information
Mauler125 committed Dec 23, 2024
1 parent 1195bd7 commit 27862c9
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 213 deletions.
10 changes: 3 additions & 7 deletions src/assets/animrig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@ void Assets::AddAnimRigAsset_v4(CPakFileBuilder* const pak, const PakGuid_t asse
char* const nameBuf = rigChunk.data;

memcpy(nameBuf, assetPath, assetNameBufLen);
pHdr->name = rigChunk.GetPointer();
pak->AddPointer(hdrChunk.GetPointer(offsetof(AnimRigAssetHeader_t, name)));
pak->AddPointer(hdrChunk, offsetof(AnimRigAssetHeader_t, name), rigChunk, 0);

studiohdr_t* const studioBuf = reinterpret_cast<studiohdr_t*>(&rigChunk.data[assetNameBufLen]);

memcpy(studioBuf, animRigFileBuffer, studiohdr->length);
pHdr->data = rigChunk.GetPointer(assetNameBufLen);
pak->AddPointer(hdrChunk.GetPointer(offsetof(AnimRigAssetHeader_t, data)));
pak->AddPointer(hdrChunk, offsetof(AnimRigAssetHeader_t, data), rigChunk, assetNameBufLen);

delete[] animRigFileBuffer;

Expand All @@ -59,9 +57,7 @@ void Assets::AddAnimRigAsset_v4(CPakFileBuilder* const pak, const PakGuid_t asse
delete[] sequenceRefs;

pHdr->sequenceCount = sequenceCount;
pHdr->pSequences = rigChunk.GetPointer(base);

pak->AddPointer(hdrChunk.GetPointer(offsetof(AnimRigAssetHeader_t, pSequences)));
pak->AddPointer(hdrChunk, offsetof(AnimRigAssetHeader_t, pSequences), rigChunk, base);

for (uint32_t i = 0; i < sequenceCount; ++i)
{
Expand Down
26 changes: 11 additions & 15 deletions src/assets/animseq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,29 @@ static void AnimSeq_InternalAddAnimSeq(CPakFileBuilder* const pak, const PakGuid
return;
}

PakPageLump_s hdrChunk = pak->CreatePageLump(sizeof(AnimSeqAssetHeader_t), SF_HEAD, 8);
PakPageLump_s hdrLump = pak->CreatePageLump(sizeof(AnimSeqAssetHeader_t), SF_HEAD, 8);

const size_t rseqNameBufLen = strlen(assetPath) + 1;
const size_t rseqFileSize = rseqInput.GetSize();

PakPageLump_s dataChunk = pak->CreatePageLump(rseqNameBufLen + rseqFileSize, SF_CPU, 1);
PakPageLump_s dataLump = pak->CreatePageLump(rseqNameBufLen + rseqFileSize, SF_CPU, 1);

// write the rseq file path into the data buffer
memcpy(dataChunk.data, assetPath, rseqNameBufLen);
memcpy(dataLump.data, assetPath, rseqNameBufLen);

// write the rseq data into the data buffer
rseqInput.Read(dataChunk.data + rseqNameBufLen, rseqFileSize);
rseqInput.Read(dataLump.data + rseqNameBufLen, rseqFileSize);
rseqInput.Close();

const mstudioseqdesc_t& seqdesc = *reinterpret_cast<mstudioseqdesc_t*>(dataChunk.data + rseqNameBufLen);
AnimSeqAssetHeader_t* const aseqHeader = reinterpret_cast<AnimSeqAssetHeader_t*>(hdrChunk.data);
const mstudioseqdesc_t& seqdesc = *reinterpret_cast<mstudioseqdesc_t*>(dataLump.data + rseqNameBufLen);

aseqHeader->szname = dataChunk.GetPointer();
pak->AddPointer(hdrChunk.GetPointer(offsetof(AnimSeqAssetHeader_t, szname)));

aseqHeader->data = dataChunk.GetPointer(rseqNameBufLen);
pak->AddPointer(hdrChunk.GetPointer(offsetof(AnimSeqAssetHeader_t, data)));
pak->AddPointer(hdrLump, offsetof(AnimSeqAssetHeader_t, szname), dataLump, 0);
pak->AddPointer(hdrLump, offsetof(AnimSeqAssetHeader_t, data), dataLump, rseqNameBufLen);

if (seqdesc.numautolayers > 0)
asset.ExpandGuidBuf(seqdesc.numautolayers);

rmem dataBuf(dataChunk.data);
rmem dataBuf(dataLump.data);
dataBuf.seek(rseqNameBufLen + seqdesc.autolayerindex, rseekdir::beg);

// Iterate over each of the sequence's autolayers to register each of the autolayer GUIDs
Expand All @@ -56,11 +52,11 @@ static void AnimSeq_InternalAddAnimSeq(CPakFileBuilder* const pak, const PakGuid
const mstudioautolayer_t* const autolayer = dataBuf.get<const mstudioautolayer_t>();

const size_t offset = dataBuf.getPosition() + offsetof(mstudioautolayer_t, guid);
Pak_RegisterGuidRefAtOffset(autolayer->guid, offset, dataChunk, asset);
Pak_RegisterGuidRefAtOffset(autolayer->guid, offset, dataLump, asset);
}

asset.InitAsset(assetPath, assetGuid, hdrChunk.GetPointer(), hdrChunk.size, PagePtr_t::NullPtr(), UINT64_MAX, UINT64_MAX, AssetType::ASEQ);
asset.SetHeaderPointer(hdrChunk.data);
asset.InitAsset(assetPath, assetGuid, hdrLump.GetPointer(), hdrLump.size, PagePtr_t::NullPtr(), UINT64_MAX, UINT64_MAX, AssetType::ASEQ);
asset.SetHeaderPointer(hdrLump.data);

asset.version = 7;
asset.pageEnd = pak->GetNumPages();
Expand Down
100 changes: 55 additions & 45 deletions src/assets/datatable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,70 +20,71 @@ static void DataTable_ReportInvalidDataTypeError(const char* const type, const u
Error("Invalid data type \"%s\" at cell (%u, %u).\n", type, colIdx, rowIdx);
}

static void DataTable_SetupRows(const rapidcsv::Document& doc, datatable_asset_t* const pHdrTemp, std::vector<std::string>& outTypeRow)
template <typename datatable_t>
static void DataTable_SetupRows(const rapidcsv::Document& doc, datatable_t* const dtblHdr, datatable_asset_t& tmp, std::vector<std::string>& outTypeRow)
{
// cache it so we don't have to make another deep copy.
outTypeRow = doc.GetRow<std::string>(pHdrTemp->numRows);
outTypeRow = doc.GetRow<std::string>(dtblHdr->numRows);
const uint32_t numTypeNames = static_cast<uint32_t>(outTypeRow.size());

// typically happens when there's an empty line in the csv file.
if (numTypeNames != pHdrTemp->numColumns)
Error("Expected %u columns for type name row, found %u.\n", pHdrTemp->numRows, numTypeNames);
if (numTypeNames != dtblHdr->numColumns)
Error("Expected %u columns for type name row, found %u.\n", dtblHdr->numRows, numTypeNames);

for (uint32_t i = 0; i < pHdrTemp->numColumns; ++i)
for (uint32_t i = 0; i < dtblHdr->numColumns; ++i)
{
const std::string& typeString = outTypeRow[i];
const dtblcoltype_t type = DataTable_GetTypeFromString(typeString);

if (type == dtblcoltype_t::INVALID)
DataTable_ReportInvalidDataTypeError(typeString.c_str(), i, pHdrTemp->numRows);
DataTable_ReportInvalidDataTypeError(typeString.c_str(), i, dtblHdr->numRows);

if (DataTable_IsStringType(type))
{
for (uint32_t j = 0; j < pHdrTemp->numRows; ++j)
for (uint32_t j = 0; j < dtblHdr->numRows; ++j)
{
// this can be std::string since we only deal with the string types here
std::vector<std::string> row = doc.GetRow<std::string>(j);
pHdrTemp->rowStringValueBufSize += row[i].length() + 1;
tmp.rowStringValueBufSize += row[i].length() + 1;
}
}

pHdrTemp->rowPodValueBufSize += static_cast<size_t>(DataTable_GetValueSize(type)) * pHdrTemp->numRows; // size of type * row count (excluding the type row)
tmp.rowPodValueBufSize += static_cast<size_t>(DataTable_GetValueSize(type)) * dtblHdr->numRows; // size of type * row count (excluding the type row)
}
}

// fills a PakPageDataChunk_s with column data from a provided csv
static void DataTable_SetupColumns(CPakFileBuilder* const pak, PakPageLump_s& dataChunk, const size_t columnNameBase, datatable_asset_t* const pHdrTemp,
const rapidcsv::Document& doc, const std::vector<std::string>& typeRow)
template <typename datatable_t>
static void DataTable_SetupColumns(CPakFileBuilder* const pak, PakPageLump_s& dataChunk, const size_t columnNameBase, datatable_t* const dtblHdr,
datatable_asset_t& tmp, const rapidcsv::Document& doc, const std::vector<std::string>& typeRow)
{
char* const colNameBufBase = &dataChunk.data[columnNameBase];
char* colNameBuf = colNameBufBase;

for (uint32_t i = 0; i < pHdrTemp->numColumns; ++i)
for (uint32_t i = 0; i < dtblHdr->numColumns; ++i)
{
const std::string name = doc.GetColumnName(i);
const size_t nameBufLen = name.length() + 1;

// copy the column name into the namebuf
memcpy(colNameBuf, name.c_str(), nameBufLen);

datacolumn_t& col = pHdrTemp->pDataColums[i];
col.pName = dataChunk.GetPointer(columnNameBase + (colNameBuf - colNameBufBase));
datacolumn_t& col = tmp.pDataColums[i];

// register name pointer
pak->AddPointer(dataChunk.GetPointer(((sizeof(datacolumn_t) * i) + offsetof(datacolumn_t, pName))));
pak->AddPointer(dataChunk, ((sizeof(datacolumn_t) * i) + offsetof(datacolumn_t, pName)), dataChunk, columnNameBase + (colNameBuf - colNameBufBase));
colNameBuf += nameBufLen;

const std::string& typeString = typeRow[i];
const dtblcoltype_t type = DataTable_GetTypeFromString(typeString);

if (type == dtblcoltype_t::INVALID)
DataTable_ReportInvalidDataTypeError(typeString.c_str(), i, pHdrTemp->numRows);
DataTable_ReportInvalidDataTypeError(typeString.c_str(), i, dtblHdr->numRows);

col.rowOffset = pHdrTemp->rowStride;
col.rowOffset = dtblHdr->rowStride;
col.type = type;

pHdrTemp->rowStride += DataTable_GetValueSize(type);
dtblHdr->rowStride += DataTable_GetValueSize(type);
}
}

Expand All @@ -93,17 +94,19 @@ static void DataTable_ReportInvalidValueError(const dtblcoltype_t type, const ui
}

// fills a PakPageDataChunk_s with row data from a provided csv
static void DataTable_SetupValues(CPakFileBuilder* const pak, PakPageLump_s& dataChunk, const size_t podValueBase, const size_t stringValueBase, datatable_asset_t* const pHdrTemp, rapidcsv::Document& doc)
template <typename datatable_t>
static void DataTable_SetupValues(CPakFileBuilder* const pak, PakPageLump_s& dataChunk, const size_t podValueBase, const size_t stringValueBase,
datatable_t* const dtblHdr, datatable_asset_t& tmp, rapidcsv::Document& doc)
{
char* const pStringBufBase = &dataChunk.data[stringValueBase];
char* pStringBuf = pStringBufBase;

for (uint32_t rowIdx = 0; rowIdx < pHdrTemp->numRows; ++rowIdx)
for (uint32_t rowIdx = 0; rowIdx < dtblHdr->numRows; ++rowIdx)
{
for (uint32_t colIdx = 0; colIdx < pHdrTemp->numColumns; ++colIdx)
for (uint32_t colIdx = 0; colIdx < dtblHdr->numColumns; ++colIdx)
{
const datacolumn_t& col = pHdrTemp->pDataColums[colIdx];
const size_t valueOffset = (pHdrTemp->rowStride * rowIdx) + col.rowOffset;
const datacolumn_t& col = tmp.pDataColums[colIdx];
const size_t valueOffset = (dtblHdr->rowStride * rowIdx) + col.rowOffset;

void* const valueBufBase = &dataChunk.data[podValueBase + valueOffset];

Expand Down Expand Up @@ -172,7 +175,8 @@ static void DataTable_SetupValues(CPakFileBuilder* const pak, PakPageLump_s& dat
memcpy(pStringBuf, val.c_str(), valBufLen);

valbuf.write(dataChunk.GetPointer(stringValueBase + (pStringBuf - pStringBufBase)));
pak->AddPointer(dataChunk.GetPointer(podValueBase + valueOffset));

pak->AddPointer(dataChunk, podValueBase + valueOffset);

pStringBuf += valBufLen;
break;
Expand All @@ -185,7 +189,8 @@ static void DataTable_SetupValues(CPakFileBuilder* const pak, PakPageLump_s& dat
// page chunk structure and order:
// - header HEAD (align=8)
// - data CPU (align=8) data columns, column names, pod row values then string row values. only data columns is aligned to 8, the rest is 1.
void Assets::AddDataTableAsset(CPakFileBuilder* const pak, const PakGuid_t assetGuid, const char* const assetPath, const rapidjson::Value& mapEntry)
template <typename datatable_t>
static void DataTable_AddDataTable(CPakFileBuilder* const pak, const PakGuid_t assetGuid, const char* const assetPath, const rapidjson::Value& mapEntry)
{
UNUSED(mapEntry);
PakAsset_t asset;
Expand Down Expand Up @@ -219,50 +224,47 @@ void Assets::AddDataTableAsset(CPakFileBuilder* const pak, const PakGuid_t asset
else
hdrChunk = pak->CreatePageLump(sizeof(datatable_v1_t), SF_HEAD, 8);

datatable_asset_t dtblHdr{}; // temp header that we store values in, this is for sharing funcs across versions
datatable_t* const dtblHdr = reinterpret_cast<datatable_t*>(hdrChunk.data);
datatable_asset_t dtblAsset{}; // temp header that we store values in.

dtblHdr.numColumns = static_cast<uint32_t>(doc.GetColumnCount());
dtblHdr.numRows = static_cast<uint32_t>(doc.GetRowCount()-1); // -1 because last row isn't added (used for type info)
dtblHdr.assetPath = assetPath;
dtblHdr->numColumns = static_cast<uint32_t>(doc.GetColumnCount());
dtblHdr->numRows = static_cast<uint32_t>(doc.GetRowCount() - 1); // -1 because last row isn't added (used for type info)

std::vector<std::string> typeRow;
DataTable_SetupRows(doc, &dtblHdr, typeRow);
DataTable_SetupRows(doc, dtblHdr, dtblAsset, typeRow);

const size_t dataColumnsBufSize = dtblHdr.numColumns * sizeof(datacolumn_t);
const size_t dataColumnsBufSize = dtblHdr->numColumns * sizeof(datacolumn_t);
const size_t columnNamesBufSize = DataTable_CalcColumnNameBufSize(doc);

const size_t totalChunkSize = dataColumnsBufSize + columnNamesBufSize + dtblHdr.rowPodValueBufSize + dtblHdr.rowStringValueBufSize;
const size_t totalChunkSize = dataColumnsBufSize + columnNamesBufSize + dtblAsset.rowPodValueBufSize + dtblAsset.rowStringValueBufSize;

// create whole datatable chunk
PakPageLump_s dataChunk = pak->CreatePageLump(totalChunkSize, SF_CPU, 8);

// colums from data chunk
dtblHdr.pColumns = dataChunk.GetPointer();
dtblHdr.pDataColums = reinterpret_cast<datacolumn_t*>(dataChunk.data);
dtblAsset.pDataColums = reinterpret_cast<datacolumn_t*>(dataChunk.data);

pak->AddPointer(hdrChunk.GetPointer(offsetof(datatable_asset_t, pColumns)));
// datatable v0 and v1 use the same struct offset for pColumns.
pak->AddPointer(hdrChunk, offsetof(datatable_v1_t, pColumns), dataChunk, 0);

// setup data in column data chunk
DataTable_SetupColumns(pak, dataChunk, dataColumnsBufSize, &dtblHdr, doc, typeRow);
DataTable_SetupColumns(pak, dataChunk, dataColumnsBufSize, dtblHdr, dtblAsset, doc, typeRow);

// Plain-old-data and string values use different buffers!
const size_t rowPodValuesBase = dataColumnsBufSize + columnNamesBufSize;
const size_t rowStringValuesBase = rowPodValuesBase + dtblHdr.rowPodValueBufSize;
const size_t rowStringValuesBase = rowPodValuesBase + dtblAsset.rowPodValueBufSize;

// setup row data chunks
DataTable_SetupValues(pak, dataChunk, rowPodValuesBase, rowStringValuesBase, &dtblHdr, doc);
DataTable_SetupValues(pak, dataChunk, rowPodValuesBase, rowStringValuesBase, dtblHdr, dtblAsset, doc);

// setup row page ptr
dtblHdr.pRows = dataChunk.GetPointer(rowPodValuesBase);
pak->AddPointer(hdrChunk.GetPointer(offsetof(datatable_asset_t, pRows)));

dtblHdr.WriteToBuffer(hdrChunk.data, pak->GetVersion());
// datatable v0 and v1 use the same struct offset for pRows.
pak->AddPointer(hdrChunk, offsetof(datatable_v0_t, pRows), dataChunk, rowPodValuesBase);

asset.InitAsset(
assetPath,
assetGuid,
hdrChunk.GetPointer(), hdrChunk.size,
dtblHdr.pRows,
dataChunk.GetPointer(rowPodValuesBase), // points to datatable_asset_t::pRow
UINT64_MAX, UINT64_MAX, AssetType::DTBL);

asset.SetHeaderPointer(hdrChunk.data);
Expand All @@ -273,4 +275,12 @@ void Assets::AddDataTableAsset(CPakFileBuilder* const pak, const PakGuid_t asset
asset.pageEnd = pak->GetNumPages();

pak->PushAsset(asset);
}

void Assets::AddDataTableAsset(CPakFileBuilder* const pak, const PakGuid_t assetGuid, const char* const assetPath, const rapidjson::Value& mapEntry)
{
if (pak->GetVersion() <= 7)
DataTable_AddDataTable<datatable_v0_t>(pak, assetGuid, assetPath, mapEntry);
else
DataTable_AddDataTable<datatable_v1_t>(pak, assetGuid, assetPath, mapEntry);
}
Loading

0 comments on commit 27862c9

Please sign in to comment.