mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-01 08:05:07 -04:00
303 lines
7.3 KiB
C++
303 lines
7.3 KiB
C++
#include "Globals.h"
|
|
|
|
#include <algorithm>
|
|
#include <string_view>
|
|
|
|
#include "Utils/File.h"
|
|
#include "Utils/Path.h"
|
|
#include "WarningHandler.h"
|
|
#include "tinyxml2.h"
|
|
|
|
Globals* Globals::Instance;
|
|
|
|
Globals::Globals()
|
|
{
|
|
Instance = this;
|
|
|
|
game = ZGame::OOT_RETAIL;
|
|
genSourceFile = true;
|
|
testMode = false;
|
|
profile = false;
|
|
useLegacyZDList = false;
|
|
useExternalResources = true;
|
|
singleThreaded = true;
|
|
verbosity = VerbosityLevel::VERBOSITY_SILENT;
|
|
outputPath = Directory::GetCurrentDirectory();
|
|
}
|
|
|
|
Globals::~Globals()
|
|
{
|
|
auto& exporters = GetExporterMap();
|
|
|
|
for (auto& it : exporters)
|
|
{
|
|
delete it.second;
|
|
}
|
|
}
|
|
|
|
void Globals::AddSegment(int32_t segment, ZFile* file, int workerID)
|
|
{
|
|
if (!Globals::Instance->singleThreaded)
|
|
{
|
|
auto worker = workerData[workerID];
|
|
|
|
if (std::find(worker->segments.begin(), worker->segments.end(), segment) ==
|
|
worker->segments.end())
|
|
worker->segments.push_back(segment);
|
|
if (worker->segmentRefFiles.find(segment) == worker->segmentRefFiles.end())
|
|
worker->segmentRefFiles[segment] = std::vector<ZFile*>();
|
|
|
|
worker->segmentRefFiles[segment].push_back(file);
|
|
}
|
|
else
|
|
{
|
|
if (std::find(segments.begin(), segments.end(), segment) == segments.end())
|
|
segments.push_back(segment);
|
|
if (cfg.segmentRefFiles.find(segment) == cfg.segmentRefFiles.end())
|
|
cfg.segmentRefFiles[segment] = std::vector<ZFile*>();
|
|
|
|
cfg.segmentRefFiles[segment].push_back(file);
|
|
}
|
|
}
|
|
|
|
bool Globals::HasSegment(int32_t segment, int workerID)
|
|
{
|
|
if (!Globals::Instance->singleThreaded)
|
|
return std::find(workerData[workerID]->segments.begin(),
|
|
workerData[workerID]->segments.end(), segment) != workerData[workerID]->segments.end();
|
|
else
|
|
return std::find(segments.begin(), segments.end(), segment) != segments.end();
|
|
}
|
|
|
|
ZFile* Globals::GetSegment(int32_t segment, int workerID)
|
|
{
|
|
if (!Globals::Instance->singleThreaded)
|
|
{
|
|
if (HasSegment(segment, workerID))
|
|
{
|
|
int idx = std::find(workerData[workerID]->segments.begin(),
|
|
workerData[workerID]->segments.end(), segment) -
|
|
workerData[workerID]->segments.begin();
|
|
return workerData[workerID]->files[idx];
|
|
}
|
|
else
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
if (HasSegment(segment, workerID))
|
|
{
|
|
int idx = std::find(segments.begin(), segments.end(), segment) - segments.begin();
|
|
return files[idx];
|
|
}
|
|
else
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
std::map<int32_t, std::vector<ZFile*>> Globals::GetSegmentRefFiles(int workerID)
|
|
{
|
|
if (!Globals::Instance->singleThreaded)
|
|
return workerData[workerID]->segmentRefFiles;
|
|
else
|
|
return cfg.segmentRefFiles;
|
|
}
|
|
|
|
void Globals::AddFile(ZFile* file, int workerID)
|
|
{
|
|
if (singleThreaded)
|
|
files.push_back(file);
|
|
else
|
|
workerData[workerID]->files.push_back(file);
|
|
}
|
|
|
|
void Globals::AddExternalFile(ZFile* file, int workerID)
|
|
{
|
|
if (singleThreaded)
|
|
externalFiles.push_back(file);
|
|
else
|
|
workerData[workerID]->externalFiles.push_back(file);
|
|
}
|
|
|
|
std::map<std::string, ExporterSet*>& Globals::GetExporterMap()
|
|
{
|
|
static std::map<std::string, ExporterSet*> exporters;
|
|
return exporters;
|
|
}
|
|
|
|
void Globals::AddExporter(std::string exporterName, ExporterSet* exporterSet)
|
|
{
|
|
auto& exporters = GetExporterMap();
|
|
exporters[exporterName] = exporterSet;
|
|
}
|
|
|
|
ZResourceExporter* Globals::GetExporter(ZResourceType resType)
|
|
{
|
|
auto& exporters = GetExporterMap();
|
|
|
|
if (currentExporter != "" && exporters[currentExporter]->exporters.find(resType) !=
|
|
exporters[currentExporter]->exporters.end())
|
|
return exporters[currentExporter]->exporters[resType];
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
ExporterSet* Globals::GetExporterSet()
|
|
{
|
|
auto& exporters = GetExporterMap();
|
|
|
|
if (currentExporter != "")
|
|
return exporters[currentExporter];
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<uint8_t> Globals::GetBaseromFile(std::string fileName)
|
|
{
|
|
if (fileMode == ZFileMode::ExtractDirectory)
|
|
{
|
|
if (StringHelper::Contains(fileName, "baserom/"))
|
|
fileName = StringHelper::Split(fileName, "baserom/")[1];
|
|
|
|
return rom->GetFile(fileName);
|
|
|
|
}
|
|
else
|
|
return File::ReadAllBytes(fileName);
|
|
}
|
|
|
|
bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
|
|
const std::string& expectedType, std::string& declName, int workerID)
|
|
{
|
|
if (segAddress == 0)
|
|
{
|
|
declName = "NULL";
|
|
return true;
|
|
}
|
|
|
|
uint8_t segment = GETSEGNUM(segAddress);
|
|
uint32_t offset = Seg2Filespace(segAddress, currentFile->baseAddress);
|
|
ZSymbol* sym;
|
|
|
|
sym = currentFile->GetSymbolResource(offset);
|
|
if (sym != nullptr)
|
|
{
|
|
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
|
|
{
|
|
declName = sym->GetName();
|
|
return true;
|
|
}
|
|
}
|
|
sym = currentFile->GetSymbolResource(segAddress);
|
|
if (sym != nullptr)
|
|
{
|
|
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
|
|
{
|
|
declName = sym->GetName();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (currentFile->IsSegmentedInFilespaceRange(segAddress))
|
|
{
|
|
if (currentFile->GetDeclarationPtrName(segAddress, expectedType, declName))
|
|
return true;
|
|
}
|
|
else if (HasSegment(segment, workerID))
|
|
{
|
|
// OTRTODO: Multithreading
|
|
auto segs = GetSegmentRefFiles(workerID);
|
|
for (auto file : segs[segment])
|
|
{
|
|
offset = Seg2Filespace(segAddress, file->baseAddress);
|
|
|
|
sym = file->GetSymbolResource(offset);
|
|
if (sym != nullptr)
|
|
{
|
|
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
|
|
{
|
|
declName = sym->GetName();
|
|
return true;
|
|
}
|
|
}
|
|
sym = file->GetSymbolResource(segAddress);
|
|
if (sym != nullptr)
|
|
{
|
|
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
|
|
{
|
|
declName = sym->GetName();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (file->IsSegmentedInFilespaceRange(segAddress))
|
|
{
|
|
if (file->GetDeclarationPtrName(segAddress, expectedType, declName))
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
const auto& symbolFromMap = Globals::Instance->cfg.symbolMap.find(segAddress);
|
|
if (symbolFromMap != Globals::Instance->cfg.symbolMap.end())
|
|
{
|
|
declName = "&" + symbolFromMap->second;
|
|
return true;
|
|
}
|
|
|
|
declName = StringHelper::Sprintf("0x%08X", segAddress);
|
|
return false;
|
|
}
|
|
|
|
bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize,
|
|
ZFile* currentFile, const std::string& expectedType,
|
|
std::string& declName, int workerID)
|
|
{
|
|
if (segAddress == 0)
|
|
{
|
|
declName = "NULL";
|
|
return true;
|
|
}
|
|
|
|
uint8_t segment = GETSEGNUM(segAddress);
|
|
|
|
if (currentFile->IsSegmentedInFilespaceRange(segAddress))
|
|
{
|
|
bool addressFound = currentFile->GetDeclarationArrayIndexedName(segAddress, elementSize,
|
|
expectedType, declName);
|
|
if (addressFound)
|
|
return true;
|
|
}
|
|
else if (HasSegment(segment, workerID))
|
|
{
|
|
// OTRTODO: Multithreading
|
|
auto segs = GetSegmentRefFiles(workerID);
|
|
for (auto file : segs[segment])
|
|
{
|
|
if (file->IsSegmentedInFilespaceRange(segAddress))
|
|
{
|
|
bool addressFound = file->GetDeclarationArrayIndexedName(segAddress, elementSize,
|
|
expectedType, declName);
|
|
if (addressFound)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
declName = StringHelper::Sprintf("0x%08X", segAddress);
|
|
return false;
|
|
}
|
|
|
|
ExternalFile::ExternalFile(fs::path nXmlPath, fs::path nOutPath)
|
|
: xmlPath{nXmlPath}, outPath{nOutPath}
|
|
{
|
|
}
|
|
|
|
ExporterSet::~ExporterSet()
|
|
{
|
|
for (auto& it : exporters)
|
|
{
|
|
delete it.second;
|
|
}
|
|
}
|