Files
Diddy-Kong-Racing/tools/dkr_assets_tool_src/builder/buildAssetTable.cpp
David Benepe c8a755a5c9 DKR Assets Tool v0.5 (#577)
* Saving files before attempting to integrate custom crash screen

* Put code under DkrAssetsTool namespace

* More progress

* Lots of work done.

* Forgot to revert back to v77 in the makefile

* Included cstdint in bytes_view.hpp

* Hopefully fixed issue with CEnum::tostring(), removed asset_enums from tracking, and modified gitignore to allow obj files from the mods folder

* .mtl file and the textures should now check if the path is absolute or relative.

* Fixed compile_all.sh

* Doing a thing that is technically not valid.

* Removed 'make assets', now assets are built in the normal 'make' setting.
2025-05-16 17:51:40 -04:00

194 lines
7.8 KiB
C++

#include "buildAssetTable.h"
#include "helpers/assetsHelper.h"
#include "helpers/jsonHelper.h"
#include "helpers/dataHelper.h"
#include "helpers/debugHelper.h"
using namespace DkrAssetsTool;
BuildAssetTable::BuildAssetTable(std::string assetType) {
_type = AssetTable::table_type_from_section_type(assetType);
_isDirty = true;
}
BuildAssetTable::BuildAssetTable(DkrAssetTableType tableType) : _type(tableType) {
_isDirty = true;
}
BuildAssetTable::~BuildAssetTable() {
}
void BuildAssetTable::add_entry(int32_t size, bool highestBitSet) {
DebugHelper::assert_(_type != DkrAssetTableType::ObjectAnimationIdsTable,
"(BuildAssetTable::add_entry) Table is the incorrect type! Should NOT be a ObjectAnimationIdsTable.");
if(_type == DkrAssetTableType::MiscTable) {
size /= 4; // Misc table entries have to be divided by 4 (for some reason)
}
// GameText uses the highest bit to determine if the entry is a textbox or dialog.
int32_t offset = _currentOffset | (highestBitSet ? (0x80000000) : 0);
_entries.emplace_back(offset, size);
_currentOffset += size;
_isDirty = true;
}
int BuildAssetTable::_find_index_of_object_model_id(int32_t objectModelId) {
int foundIndex = -1;
for(size_t i = 0; i < _entries.size(); i++) {
if(_entries[i].objectModelId == objectModelId) {
foundIndex = i;
break;
}
}
return foundIndex;
}
void BuildAssetTable::add_object_animation_ids_entry(int32_t objectModelId) {
DebugHelper::assert_(_type == DkrAssetTableType::ObjectAnimationIdsTable,
"(BuildAssetTable::add_object_animation_ids_entry) Table is the incorrect type! Should be a ObjectAnimationIdsTable.");
int foundIndex = _find_index_of_object_model_id(objectModelId);
if(foundIndex < 0) {
foundIndex = _entries.size();
_entries.emplace_back(objectModelId, 0);
}
_entries[foundIndex].count++;
_isDirty = true;
}
BytesView BuildAssetTable::get_view(CContext &cContext) {
if(_isDirty) {
_compile_entries_to_data(cContext);
}
return BytesView(_data);
}
size_t BuildAssetTable::get_size_of_entries() const {
return _currentOffset;
}
BytesView BuildAssetTable::_reset_data(size_t newSize) {
_data.clear();
_data.resize(DataHelper::align16(newSize));
return BytesView(_data);
}
void BuildAssetTable::_compile_entries_to_data(CContext &cContext) {
int32_t totalSizeOfEntries = _currentOffset;
switch(_type) {
case DkrAssetTableType::FixedTable:
{
int32_t numberOfEntries = (int32_t)_entries.size();
BytesView view = _reset_data((numberOfEntries + 2) * 4);
view.set_s32_be(0, numberOfEntries); // First entry is the number of following entries.
for(int32_t i = 0; i < numberOfEntries; i++) {
view.set_s32_be((1 + i) * 4, _entries[i].offset);
}
view.set_s32_be((1 + numberOfEntries) * 4, totalSizeOfEntries); // Last entry is the total size of the assets.
}
break;
case DkrAssetTableType::VariableTable:
case DkrAssetTableType::GameTextTable:
case DkrAssetTableType::MiscTable:
case DkrAssetTableType::AudioTable:
{
int32_t numberOfEntries = (int32_t)_entries.size();
BytesView view = _reset_data((numberOfEntries + 2) * 4);
int startOffset = 0;
// The audio table skips the first entry for whatever reason.
if(_type == DkrAssetTableType::AudioTable) {
numberOfEntries--;
startOffset = 1;
}
for(int i = 0; i < numberOfEntries; i++) {
view.set_s32_be(i * 4, _entries[startOffset + i].offset);
}
view.set_s32_be(numberOfEntries * 4, totalSizeOfEntries); // 2nd to last entry is the total size of the assets.
view.set_s32_be((numberOfEntries + 1) * 4, -1); // Last entry should be -1
}
break;
case DkrAssetTableType::MenuTextTable:
{
int32_t numberOfEntries = (int32_t)_entries.size();
JsonFile &menuTextSectionJson = AssetsHelper::get_asset_section_json("ASSET_MENU_TEXT");
size_t numberOfMenuTextEntries = menuTextSectionJson.length_of_array("/menu-text-build-ids");
BytesView view = _reset_data((numberOfEntries + 3) * 4);
view.set_s32_be(0, numberOfMenuTextEntries); // First entry is the number of menu text entries.
for(int32_t i = 0; i < numberOfEntries; i++) {
view.set_s32_be((1 + i) * 4, _entries[i].offset);
}
view.set_s32_be((1 + numberOfEntries) * 4, totalSizeOfEntries); // 2nd to last entry is the total size of the assets.
view.set_s32_be((1 + numberOfEntries + 1) * 4, -1); // Last entry should be -1
}
break;
case DkrAssetTableType::TTGhostTable:
{
int32_t numberOfEntries = (int32_t)_entries.size();
BytesView view = _reset_data((numberOfEntries + 2) * 8);
for(int32_t i = 0; i < numberOfEntries; i++) {
std::string ttGhostBuildId = AssetsHelper::get_build_id_of_index("ASSET_TTGHOSTS", i);
JsonFile &ttGhostJson = AssetsHelper::get_asset_json("ASSET_TTGHOSTS", ttGhostBuildId);
std::string levelBuildId = ttGhostJson.get_string("/header/level");
std::string vehicleEnumStr = ttGhostJson.get_string("/header/vehicle");
int levelIndex = AssetsHelper::get_asset_index("ASSET_LEVEL_HEADERS", levelBuildId) & 0xFF;
int vehicleEnumValue = cContext.get_int_value_of_symbol(vehicleEnumStr) & 0xFF;
view.set_s32_be((i * 8) + 0, (levelIndex << 24) | (vehicleEnumValue << 16));
view.set_s32_be((i * 8) + 4, _entries[i].offset);
}
view.set_s32_be((numberOfEntries * 8) + 0, 0xFFFF0000);
view.set_s32_be((numberOfEntries * 8) + 4, totalSizeOfEntries); // 2nd to last entry is the total size of the assets.
view.set_s32_be(((numberOfEntries + 1) * 8) + 0, 0xFFFF0000);
view.set_s32_be(((numberOfEntries + 1) * 8) + 4, -1); // Last entry should be -1
}
break;
case DkrAssetTableType::ObjectAnimationIdsTable:
{
int32_t numberOfModels = AssetsHelper::get_asset_section_count("ASSET_OBJECT_MODELS");
BytesView view = _reset_data((numberOfModels + 1) * sizeof(int16_t));
int16_t currAnimOffset = 0;
for(int32_t modelIndex = 0; modelIndex < numberOfModels; modelIndex++) {
view.set_s16_be(modelIndex * sizeof(int16_t), currAnimOffset);
int foundIndex = _find_index_of_object_model_id(modelIndex);
if(foundIndex < 0) {
continue;
}
currAnimOffset += _entries[foundIndex].count;
}
// Last entry should be the total number of animations.
view.set_s16_be(numberOfModels * sizeof(int16_t), currAnimOffset);
}
break;
default:
DebugHelper::error("Unknown table type: ", _type);
break;
}
_isDirty = false;
}