From 3ed63415a7c99df6f22e40e741bf2b18635cb373 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 23 Mar 2021 01:30:10 +0100 Subject: [PATCH] Add T6 assetloader for string tables --- src/Common/Game/T6/CommonT6.cpp | 16 ++++ src/Common/Game/T6/CommonT6.h | 1 + .../AssetLoaders/AssetLoaderStringTable.cpp | 92 +++++++++++++++++++ .../T6/AssetLoaders/AssetLoaderStringTable.h | 16 ++++ src/ObjLoading/Game/T6/ObjLoaderT6.cpp | 3 +- 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp create mode 100644 src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h diff --git a/src/Common/Game/T6/CommonT6.cpp b/src/Common/Game/T6/CommonT6.cpp index b6d389b5..87270121 100644 --- a/src/Common/Game/T6/CommonT6.cpp +++ b/src/Common/Game/T6/CommonT6.cpp @@ -19,6 +19,22 @@ int CommonT6::Com_HashKey(const char* str, const int maxLen) return hash ^ ((hash ^ (hash >> 10)) >> 10); } +int CommonT6::Com_HashString(const char* str) +{ + if (!str) + return 0; + + auto result = 0x1505; + auto offset = 0; + while(str[offset]) + { + const auto c = tolower(str[offset++]); + result = c + 33 * result; + } + + return result; +} + int CommonT6::Com_HashString(const char* str, const int len) { if (!str) diff --git a/src/Common/Game/T6/CommonT6.h b/src/Common/Game/T6/CommonT6.h index df8cc385..801726df 100644 --- a/src/Common/Game/T6/CommonT6.h +++ b/src/Common/Game/T6/CommonT6.h @@ -337,5 +337,6 @@ class CommonT6 { public: static int Com_HashKey(const char* str, int maxLen); + static int Com_HashString(const char* str); static int Com_HashString(const char* str, int len); }; \ No newline at end of file diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp new file mode 100644 index 00000000..f5f85b27 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.cpp @@ -0,0 +1,92 @@ +#include "AssetLoaderStringTable.h" + +#include + +#include "Csv/CsvStream.h" +#include "Game/T6/CommonT6.h" +#include "Game/T6/T6.h" +#include "Pool/GlobalAssetPool.h" + +using namespace T6; + +void* AssetLoaderStringTable::CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) +{ + auto* stringTable = memory->Create(); + memset(stringTable, 0, sizeof(StringTable)); + stringTable->name = memory->Dup(assetName.c_str()); + return stringTable; +} + +bool AssetLoaderStringTable::CanLoadFromRaw() const +{ + return true; +} + +bool AssetLoaderStringTable::LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const +{ + const auto file = searchPath->Open(assetName); + if (!file.IsOpen()) + return false; + + auto* stringTable = memory->Create(); + stringTable->name = memory->Dup(assetName.c_str()); + + std::vector> csvLines; + std::vector currentLine; + auto maxCols = 0u; + const CsvInputStream csv(*file.m_stream); + + while (csv.NextRow(currentLine)) + { + if (currentLine.size() > maxCols) + maxCols = currentLine.size(); + csvLines.emplace_back(std::move(currentLine)); + } + + stringTable->columnCount = maxCols; + stringTable->rowCount = csvLines.size(); + const auto cellCount = static_cast(stringTable->rowCount) * static_cast(stringTable->columnCount); + + if (cellCount) + { + stringTable->values = static_cast(memory->Alloc(sizeof(StringTableCell) * cellCount)); + stringTable->cellIndex = static_cast(memory->Alloc(sizeof(int16_t) * cellCount)); + + for (auto c = 0u; c < cellCount; c++) + stringTable->cellIndex[c] = static_cast(c); + + for (auto row = 0u; row < csvLines.size(); row++) + { + const auto& rowValues = csvLines[row]; + for (auto col = 0u; col < maxCols; col++) + { + auto& cell = stringTable->values[row * maxCols + col]; + if (col >= rowValues.size() || rowValues[col].empty()) + cell.string = ""; + else + cell.string = memory->Dup(rowValues[col].c_str()); + + cell.hash = CommonT6::Com_HashString(cell.string); + } + } + + + std::sort(&stringTable->cellIndex[0], &stringTable->cellIndex[cellCount - 1], [stringTable, maxCols](const int16_t a, const int16_t b) + { + auto compareResult = stringTable->values[a].hash - stringTable->values[b].hash; + if (compareResult == 0) + compareResult = a % maxCols - b % maxCols; + return compareResult < 0; + }); + } + + else + { + stringTable->values = nullptr; + stringTable->cellIndex = nullptr; + } + + manager->AddAsset(ASSET_TYPE_STRINGTABLE, assetName, stringTable); + + return true; +} diff --git a/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h new file mode 100644 index 00000000..2da2c444 --- /dev/null +++ b/src/ObjLoading/Game/T6/AssetLoaders/AssetLoaderStringTable.h @@ -0,0 +1,16 @@ +#pragma once +#include "Game/T6/T6.h" +#include "AssetLoading/BasicAssetLoader.h" +#include "AssetLoading/IAssetLoadingManager.h" +#include "SearchPath/ISearchPath.h" + +namespace T6 +{ + class AssetLoaderStringTable final : public BasicAssetLoader + { + public: + _NODISCARD void* CreateEmptyAsset(const std::string& assetName, MemoryManager* memory) override; + _NODISCARD bool CanLoadFromRaw() const override; + bool LoadFromRaw(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager) const override; + }; +} diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 6f0b2461..164c245e 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -8,6 +8,7 @@ #include "AssetLoaders/AssetLoaderRawFile.h" #include "AssetLoaders/AssetLoaderScriptParseTree.h" #include "AssetLoaders/AssetLoaderSlug.h" +#include "AssetLoaders/AssetLoaderStringTable.h" #include "AssetLoading/AssetLoadingManager.h" #include "Image/Texture.h" #include "Image/IwiLoader.h" @@ -54,7 +55,7 @@ namespace T6 REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_FX, FxEffectDef)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_IMPACT_FX, FxImpactTable)) REGISTER_ASSET_LOADER(AssetLoaderRawFile) - REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_STRINGTABLE, StringTable)) + REGISTER_ASSET_LOADER(AssetLoaderStringTable) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_LEADERBOARD, LeaderboardDef)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_XGLOBALS, XGlobals)) REGISTER_ASSET_LOADER(BASIC_LOADER(ASSET_TYPE_DDL, ddlRoot_t))