[ZoneBuilder] Enumerate XAssetEntries instead of logging them

This commit is contained in:
momo5502 2017-05-01 13:08:34 +02:00
parent 70d7312472
commit 2c9a051aad
9 changed files with 134 additions and 45 deletions

View File

@ -142,29 +142,30 @@ namespace Assets
replacementFound = false;
// Find correct sortkey by comparing techsets
Game::DB_EnumXAssets_Internal(Game::XAssetType::ASSET_TYPE_MATERIAL, [](Game::XAssetHeader header, void* data)
Game::DB_EnumXAssetEntries(Game::XAssetType::ASSET_TYPE_MATERIAL, [asset](Game::XAssetEntry* entry)
{
if (!replacementFound)
{
Game::Material* material = reinterpret_cast<Game::Material*>(data);
const char* name = material->techniqueSet->name;
Game::XAssetHeader header = entry->asset.header;
const char* name = asset->techniqueSet->name;
if (name[0] == ',') ++name;
if (std::string(name) == header.material->techniqueSet->name)
{
material->sortKey = header.material->sortKey;
asset->sortKey = header.material->sortKey;
// This is temp, as nobody has time to fix materials
material->stateBitsCount = header.material->stateBitsCount;
material->stateBitTable = header.material->stateBitTable;
std::memcpy(material->stateBitsEntry, header.material->stateBitsEntry, 48);
material->constantCount = header.material->constantCount;
material->constantTable = header.material->constantTable;
asset->stateBitsCount = header.material->stateBitsCount;
asset->stateBitTable = header.material->stateBitTable;
std::memcpy(asset->stateBitsEntry, header.material->stateBitsEntry, 48);
asset->constantCount = header.material->constantCount;
asset->constantTable = header.material->constantTable;
replacementFound = true;
}
}
}, asset, false);
}, false, false);
if (!replacementFound && asset->techniqueSet)
{

View File

@ -696,6 +696,16 @@ namespace Components
Dvar::Var("isDlcInstalled_All").setRaw(hasAllDlcs ? 1 : 0);
}
Game::XAssetEntry* Maps::GetAssetEntryPool()
{
if(Maps::EntryPool.empty())
{
return reinterpret_cast<Game::XAssetEntry*>(0x134CAD8);
}
return Maps::EntryPool.data();
}
void Maps::reallocateEntryPool()
{
AssertSize(Game::XAssetEntry, 16);

View File

@ -67,6 +67,8 @@ namespace Components
static UserMapContainer* GetUserMap();
static unsigned int GetUsermapHash(std::string map);
static Game::XAssetEntry* GetAssetEntryPool();
private:
class DLC
{

View File

@ -555,13 +555,13 @@ namespace Components
if (type == Game::ASSET_TYPE_TECHNIQUE_SET)
{
Utils::IO::CreateDir("userraw/techsets");
Utils::Stream* buffer = new Utils::Stream(0x1000);
Game::MaterialTechniqueSet* dest = buffer->dest<Game::MaterialTechniqueSet>();
buffer->save(asset.techniqueSet);
Utils::Stream buffer(0x1000);
Game::MaterialTechniqueSet* dest = buffer.dest<Game::MaterialTechniqueSet>();
buffer.save(asset.techniqueSet);
if (asset.techniqueSet->name)
{
buffer->saveString(asset.techniqueSet->name);
buffer.saveString(asset.techniqueSet->name);
Utils::Stream::ClearPointer(&dest->name);
}
@ -575,15 +575,15 @@ namespace Components
if (!dest->techniques)
{
// Size-check is obsolete, as the structure is dynamic
buffer->align(Utils::Stream::ALIGN_4);
buffer.align(Utils::Stream::ALIGN_4);
//storePointer(technique, buffer->);
Game::MaterialTechnique* destTechnique = buffer->dest<Game::MaterialTechnique>();
buffer->save(technique, 8);
Game::MaterialTechnique* destTechnique = buffer.dest<Game::MaterialTechnique>();
buffer.save(technique, 8);
// Save_MaterialPassArray
Game::MaterialPass* destPasses = buffer->dest<Game::MaterialPass>();
buffer->saveArray(technique->passArray, technique->passCount);
Game::MaterialPass* destPasses = buffer.dest<Game::MaterialPass>();
buffer.saveArray(technique->passArray, technique->passCount);
for (short j = 0; j < technique->passCount; ++j)
{
@ -599,15 +599,15 @@ namespace Components
if (pass->args)
{
buffer->align(Utils::Stream::ALIGN_4);
buffer->saveArray(pass->args, pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount);
buffer.align(Utils::Stream::ALIGN_4);
buffer.saveArray(pass->args, pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount);
Utils::Stream::ClearPointer(&destPass->args);
}
}
if (technique->name)
{
buffer->saveString(technique->name);
buffer.saveString(technique->name);
Utils::Stream::ClearPointer(&destTechnique->name);
}

View File

@ -7,8 +7,6 @@ namespace Components
std::string ZoneBuilder::TraceZone;
std::vector<std::pair<Game::XAssetType, std::string>> ZoneBuilder::TraceAssets;
std::vector<std::pair<Game::XAssetType, std::string>> ZoneBuilder::CommonAssets;
ZoneBuilder::Zone::Zone(std::string name) : indexStart(0), externalSize(0),
// Reserve 100MB by default.
@ -749,21 +747,25 @@ namespace Components
if (type >= 0 && type < Game::XAssetType::ASSET_TYPE_COUNT)
{
for (auto& asset : ZoneBuilder::CommonAssets)
int zoneIndex = Game::DB_GetZoneIndex("common_mp");
if (zoneIndex > 0)
{
if (asset.first == type && asset.second == name)
Game::DB_EnumXAssetEntries(type, [&](Game::XAssetEntry* entry)
{
// Allocate an empty asset (filled with zeros)
header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]());
if (!header.data && entry->zoneIndex == zoneIndex && Game::DB_GetXAssetName(&entry->asset) == name)
{
// Allocate an empty asset (filled with zeros)
header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]());
// Set the name to the original name, so it can be stored
Game::DB_SetXAssetNameHandlers[type](&header, name.data());
AssetHandler::StoreTemporaryAsset(type, header);
// Set the name to the original name, so it can be stored
Game::DB_SetXAssetNameHandlers[type](&header, name.data());
AssetHandler::StoreTemporaryAsset(type, header);
// Set the name to the empty name
Game::DB_SetXAssetNameHandlers[type](&header, builder->getAllocator()->duplicateString("," + name));
break;
}
// Set the name to the empty name
Game::DB_SetXAssetNameHandlers[type](&header, builder->getAllocator()->duplicateString("," + name));
}
}, true, true);
}
}
@ -853,12 +855,6 @@ namespace Components
AssetHandler::OnLoad([](Game::XAssetType type, Game::XAssetHeader /*asset*/, std::string name, bool* /*restrict*/)
{
// This is used to track which assets can be stored as empty assets
if (FastFiles::Current() == "common_mp")
{
ZoneBuilder::CommonAssets.push_back({ type, name });
}
if (!ZoneBuilder::TraceZone.empty() && ZoneBuilder::TraceZone == FastFiles::Current())
{
ZoneBuilder::TraceAssets.push_back({ type, name });
@ -998,7 +994,6 @@ namespace Components
ZoneBuilder::~ZoneBuilder()
{
assert(ZoneBuilder::MemAllocator.empty());
ZoneBuilder::CommonAssets.clear();
}
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)

View File

@ -105,8 +105,6 @@ namespace Components
static std::string TraceZone;
static std::vector<std::pair<Game::XAssetType, std::string>> TraceAssets;
static std::vector<std::pair<Game::XAssetType, std::string>> CommonAssets;
static void BeginAssetTrace(std::string zone);
static std::vector<std::pair<Game::XAssetType, std::string>> EndAssetTrace();

View File

@ -363,6 +363,9 @@ namespace Game
infoParm_t* infoParams = reinterpret_cast<infoParm_t*>(0x79D260); // Count 0x1E
XZone* g_zones = reinterpret_cast<XZone*>(0x14C0F80);
unsigned short* db_hashTable = reinterpret_cast<unsigned short*>(0x12412B0);
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize)
{
int elSize = DB_GetXAssetSizeHandlers[type]();
@ -476,6 +479,19 @@ namespace Game
return ASSET_TYPE_INVALID;
}
int DB_GetZoneIndex(std::string name)
{
for (int i = 0; i < 32; ++i)
{
if (Game::g_zones[i].name == name)
{
return i;
}
}
return -1;
}
bool DB_IsZoneLoaded(const char* zone)
{
int zoneCount = Utils::Hook::Get<int>(0x1261BCC);
@ -495,6 +511,48 @@ namespace Game
return false;
}
void DB_EnumXAssetEntries(XAssetType type, std::function<void(XAssetEntry*)> callback, bool overrides, bool lock)
{
volatile long* lockVar = reinterpret_cast<volatile long*>(0x16B8A54);
if (lock) InterlockedIncrement(lockVar);
while (lock && *reinterpret_cast<volatile long*>(0x16B8A58)) std::this_thread::sleep_for(1ms);
unsigned int index = 0;
do
{
unsigned short hashIndex = db_hashTable[index];
if (hashIndex)
{
do
{
XAssetEntry* asset = &Components::Maps::GetAssetEntryPool()[hashIndex];
hashIndex = asset->nextHash;
if (asset->asset.type == type)
{
callback(asset);
if (overrides)
{
unsigned short overrideIndex = asset->nextOverride;
if (asset->nextOverride)
{
do
{
asset = &Components::Maps::GetAssetEntryPool()[overrideIndex];
callback(asset);
overrideIndex = asset->nextOverride;
} while (overrideIndex);
}
}
}
} while (hashIndex);
}
++index;
} while (index < 74000);
if(lock) InterlockedDecrement(lockVar);
}
__declspec(naked) XAssetHeader DB_FindXAssetDefaultHeaderInternal(XAssetType /*type*/)
{
__asm

View File

@ -758,6 +758,9 @@ namespace Game
extern infoParm_t* infoParams;
extern XZone* g_zones;
extern unsigned short* db_hashTable;
XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize);
void Menu_FreeItemMemory(Game::itemDef_t* item);
const char* TableLookup(StringTable* stringtable, int row, int column);
@ -767,7 +770,9 @@ namespace Game
const char *DB_GetXAssetName(XAsset *asset);
XAssetType DB_GetXAssetNameType(const char* name);
int DB_GetZoneIndex(std::string name);
bool DB_IsZoneLoaded(const char* zone);
void DB_EnumXAssetEntries(XAssetType type, std::function<void(XAssetEntry*)> callback, bool overrides, bool lock);
XAssetHeader DB_FindXAssetDefaultHeaderInternal(XAssetType type);
XAssetEntry* DB_FindXAssetEntry(XAssetType type, const char* name);

View File

@ -3674,7 +3674,7 @@ namespace Game
{
XAsset asset;
char zoneIndex;
bool inuse;
volatile char inuse;
unsigned __int16 nextHash;
unsigned __int16 nextOverride;
unsigned __int16 usageFrame;
@ -3755,6 +3755,26 @@ namespace Game
XAssetList assetList;
};
struct XZoneMemory
{
XBlock blocks[MAX_XFILE_COUNT];
char *lockedVertexData;
char *lockedIndexData;
void *vertexBuffer;
void *indexBuffer;
};
struct XZone
{
int unk;
char name[64];
int flags;
int allocType;
XZoneMemory mem;
int fileSize;
char modZone;
};
struct XNKID
{
char ab[8];