diff options
| author | KiritoDv <kiritodev01@gmail.com> | 2024-01-30 01:25:46 -0600 |
|---|---|---|
| committer | Lywx <kiritodev01@gmail.com> | 2024-01-31 12:05:40 -0600 |
| commit | 242f8acf212d143443dc2ce846507bdb82571902 (patch) | |
| tree | 4b4d30a587431b36975d1a25ff47ddd8d4dd0455 | |
| parent | c54ef39005eabc17921436f3cc2482ef8efb0bcd (diff) | |
Swapped mio with offset and fixed samples and animations
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | src/Companion.cpp | 167 | ||||
| -rw-r--r-- | src/Companion.h | 63 | ||||
| -rw-r--r-- | src/factories/BankFactory.cpp | 4 | ||||
| -rw-r--r-- | src/factories/BaseFactory.h | 5 | ||||
| -rw-r--r-- | src/factories/DisplayListFactory.cpp | 111 | ||||
| -rw-r--r-- | src/factories/LightsFactory.cpp | 4 | ||||
| -rw-r--r-- | src/factories/SampleFactory.cpp | 31 | ||||
| -rw-r--r-- | src/factories/SampleFactory.h | 7 | ||||
| -rw-r--r-- | src/factories/TextureFactory.cpp | 25 | ||||
| -rw-r--r-- | src/factories/VtxFactory.cpp | 4 | ||||
| -rw-r--r-- | src/factories/mk64/WaypointFactory.cpp | 4 | ||||
| -rw-r--r-- | src/factories/sm64/AnimationFactory.cpp | 36 | ||||
| -rw-r--r-- | src/factories/sm64/AnimationFactory.h | 4 | ||||
| -rw-r--r-- | src/factories/sm64/DialogFactory.cpp | 4 | ||||
| -rw-r--r-- | src/factories/sm64/TextFactory.cpp | 6 |
16 files changed, 322 insertions, 156 deletions
@@ -11,4 +11,5 @@ debug/ headers/ build/ code/ -.vscode/
\ No newline at end of file +.vscode/ +tools/
\ No newline at end of file diff --git a/src/Companion.cpp b/src/Companion.cpp index 8c838fa..17f4862 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -34,7 +34,7 @@ void Companion::Init(const ExportType type) { spdlog::set_level(spdlog::level::debug); spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] %v"); - this->gExporterType = type; + this->gConfig.exporterType = type; this->RegisterFactory("BLOB", std::make_shared<BlobFactory>()); this->RegisterFactory("TEXTURE", std::make_shared<TextureFactory>()); this->RegisterFactory("VTX", std::make_shared<VtxFactory>()); @@ -77,37 +77,34 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar return; } - if(node["segments"]) { - for(auto segment = node["segments"].begin(); segment != node["segments"].end(); ++segment) { - auto id = std::stoi(segment->first.as<std::string>().substr(3)); - auto replacement = segment->second.as<uint32_t>(); - this->gTemporalSegments[id] = replacement; - } - } - auto result = factory->get()->parse(this->gRomData, node); if(!result.has_value()){ SPDLOG_ERROR("Failed to process {}", name); return; } - auto exporter = factory->get()->GetExporter(this->gExporterType); + auto exporter = factory->get()->GetExporter(this->gConfig.exporterType); if(!exporter.has_value()){ SPDLOG_ERROR("No exporter found for {}", name); return; } for (auto [fst, snd] : this->gAssetDependencies[this->gCurrentFile]) { - if(snd.second) continue; + if(snd.second) { + continue; + } std::string doutput = (this->gCurrentDirectory / fst).string(); std::replace(doutput.begin(), doutput.end(), '\\', '/'); this->gAssetDependencies[this->gCurrentFile][fst].second = true; this->ExtractNode(snd.first, doutput, binary); } - switch (this->gExporterType) { + switch (this->gConfig.exporterType) { case ExportType::Binary: { - if(binary == nullptr) break; + if(binary == nullptr) { + break; + } + stream.str(""); stream.clear(); exporter->get()->Export(stream, result.value(), name, node, &name); @@ -127,6 +124,17 @@ void Companion::ExtractNode(YAML::Node& node, std::string& name, SWrapper* binar } } +void Companion::ParseCurrentFileConfig(YAML::Node node) { + if(node["segments"]) { + for(auto segment = node["segments"].begin(); segment != node["segments"].end(); ++segment) { + const auto id = std::stoi(segment->first.as<std::string>().substr(3)); + const auto replacement = segment->second.as<uint32_t>(); + this->gConfig.segment.local[id] = replacement; + SPDLOG_DEBUG("Segment {} replaced with 0x{:X}", id, replacement); + } + } +} + void Companion::Process() { if(!fs::exists("config.yml")) { @@ -140,42 +148,45 @@ void Companion::Process() { this->gRomData = std::vector<uint8_t>( std::istreambuf_iterator( input ), {} ); input.close(); - this->gCartridge = new N64::Cartridge(this->gRomData); - gCartridge->Initialize(); + this->gCartridge = std::make_shared<N64::Cartridge>(this->gRomData); + this->gCartridge->Initialize(); YAML::Node config = YAML::LoadFile("config.yml"); - if(!config[gCartridge->GetHash()]){ - SPDLOG_ERROR("No config found for {}", gCartridge->GetHash()); + if(!config[this->gCartridge->GetHash()]){ + SPDLOG_ERROR("No config found for {}", this->gCartridge->GetHash()); return; } - auto rom = config[gCartridge->GetHash()]; + auto rom = config[this->gCartridge->GetHash()]; auto cfg = rom["config"]; if(!cfg) { - SPDLOG_ERROR("No config found for {}", gCartridge->GetHash()); + SPDLOG_ERROR("No config found for {}", this->gCartridge->GetHash()); return; } if(rom["segments"]) { - this->gSegments = rom["segments"].as<std::vector<uint32_t>>(); + auto segments = rom["segments"].as<std::vector<uint32_t>>(); + for (int i = 0; i < segments.size(); i++) { + this->gConfig.segment.global[i + 1] = segments[i]; + } } auto path = rom["path"].as<std::string>(); auto opath = cfg["output"]; auto gbi = cfg["gbi"]; - switch (gExporterType) { + switch (this->gConfig.exporterType) { case ExportType::Binary: { - this->gOutputPath = opath && opath["binary"] ? opath["binary"].as<std::string>() : "generic.otr"; + this->gConfig.outputPath = opath && opath["binary"] ? opath["binary"].as<std::string>() : "generic.otr"; break; } case ExportType::Header: { - this->gOutputPath = opath && opath["headers"] ? opath["headers"].as<std::string>() : "headers"; + this->gConfig.outputPath = opath && opath["headers"] ? opath["headers"].as<std::string>() : "headers"; break; } case ExportType::Code: { - this->gOutputPath = opath && opath["code"] ? opath["code"].as<std::string>() : "code"; + this->gConfig.outputPath = opath && opath["code"] ? opath["code"].as<std::string>() : "code"; break; } } @@ -184,18 +195,18 @@ void Companion::Process() { auto key = gbi.as<std::string>(); if(key == "F3D") { - this->gGBIVersion = GBIVersion::f3d; + this->gConfig.gbi.version = GBIVersion::f3d; } else if(key == "F3DEX") { - this->gGBIVersion = GBIVersion::f3dex; + this->gConfig.gbi.version = GBIVersion::f3dex; } else if(key == "F3DB") { - this->gGBIVersion = GBIVersion::f3db; + this->gConfig.gbi.version = GBIVersion::f3db; } else if(key == "F3DEX2") { - this->gGBIVersion = GBIVersion::f3dex2; + this->gConfig.gbi.version = GBIVersion::f3dex2; } else if(key == "F3DEXB") { - this->gGBIVersion = GBIVersion::f3dexb; + this->gConfig.gbi.version = GBIVersion::f3dexb; } else if (key == "F3DEX_MK64") { - this->gGBIVersion = GBIVersion::f3dex; - this->gGBIMinorVersion = GBIMinorVersion::Mk64; + this->gConfig.gbi.version = GBIVersion::f3dex; + this->gConfig.gbi.subversion = GBIMinorVersion::Mk64; } else { SPDLOG_ERROR("Invalid GBI version"); return; @@ -230,29 +241,41 @@ void Companion::Process() { spdlog::set_pattern(line); SPDLOG_INFO("Starting Torch..."); - SPDLOG_INFO("Game: {}", gCartridge->GetGameTitle()); - SPDLOG_INFO("CRC: {}", gCartridge->GetCRC()); - SPDLOG_INFO("Version: {}", gCartridge->GetVersion()); - SPDLOG_INFO("Country: [{}]", gCartridge->GetCountryCode()); - SPDLOG_INFO("Hash: {}", gCartridge->GetHash()); + SPDLOG_INFO("Game: {}", this->gCartridge->GetGameTitle()); + SPDLOG_INFO("CRC: {}", this->gCartridge->GetCRC()); + SPDLOG_INFO("Version: {}", this->gCartridge->GetVersion()); + SPDLOG_INFO("Country: [{}]", this->gCartridge->GetCountryCode()); + SPDLOG_INFO("Hash: {}", this->gCartridge->GetHash()); SPDLOG_INFO("Assets: {}", path); - auto wrapper = this->gExporterType == ExportType::Binary ? new SWrapper(this->gOutputPath) : nullptr; + auto wrapper = this->gConfig.exporterType == ExportType::Binary ? new SWrapper(this->gConfig.outputPath) : nullptr; auto vWriter = LUS::BinaryWriter(); vWriter.SetEndianness(LUS::Endianness::Big); vWriter.Write(static_cast<uint8_t>(LUS::Endianness::Big)); - vWriter.Write(gCartridge->GetCRC()); + vWriter.Write(this->gCartridge->GetCRC()); for (const auto & entry : fs::recursive_directory_iterator(path)){ - if(entry.is_directory()) continue; - YAML::Node root = YAML::LoadFile(entry.path().string()); + if(entry.is_directory()) { + continue; + } + + const auto yamlPath = entry.path().string(); + + if(yamlPath.find(".yaml") == std::string::npos && yamlPath.find(".yml") == std::string::npos) { + continue; + } + + YAML::Node root = YAML::LoadFile(yamlPath); this->gCurrentDirectory = relative(entry.path(), path).replace_extension(""); - this->gCurrentFile = entry.path().string(); + this->gCurrentFile = yamlPath; for(auto asset = root.begin(); asset != root.end(); ++asset){ auto node = asset->second; - if(!asset->second["offset"]) continue; + + if(!asset->second["offset"]) { + continue; + } auto output = (this->gCurrentDirectory / asset->first.as<std::string>()).string(); std::replace(output.begin(), output.end(), '\\', '/'); @@ -261,26 +284,40 @@ void Companion::Process() { } // Stupid hack because the iteration broke the assets - root = YAML::LoadFile(entry.path().string()); + root = YAML::LoadFile(yamlPath); + this->gConfig.segment.local.clear(); - for(auto asset = root.begin(); asset != root.end(); ++asset){ + if(root[":config"]) { + this->ParseCurrentFileConfig(root[":config"]); + } - spdlog::set_pattern(regular); - SPDLOG_INFO("------------------------------------------------"); - spdlog::set_pattern(line); + spdlog::set_pattern(regular); + SPDLOG_INFO("------------------------------------------------"); + spdlog::set_pattern(line); + + for(auto asset = root.begin(); asset != root.end(); ++asset){ auto entryName = asset->first.as<std::string>(); std::string output = (this->gCurrentDirectory / entryName).string(); std::replace(output.begin(), output.end(), '\\', '/'); - this->gTemporalSegments.clear(); + if(entryName.find(":config") != std::string::npos) { + continue; + } + + this->gConfig.segment.temporal.clear(); + this->ExtractNode(asset->second, output, wrapper); + + spdlog::set_pattern(regular); + SPDLOG_INFO("------------------------------------------------"); + spdlog::set_pattern(line); } - if(gExporterType != ExportType::Binary){ - std::string output = (this->gOutputPath / this->gCurrentDirectory).string(); + if(this->gConfig.exporterType != ExportType::Binary){ + std::string output = (this->gConfig.outputPath / this->gCurrentDirectory).string(); - switch (gExporterType) { + switch (this->gConfig.exporterType) { case ExportType::Header: { output += "/definition.h"; break; @@ -345,7 +382,7 @@ void Companion::Process() { std::ofstream file(output, std::ios::binary); - if(gExporterType == ExportType::Header) { + if(this->gConfig.exporterType == ExportType::Header) { std::string symbol = entry.path().stem().string(); std::transform(symbol.begin(), symbol.end(), symbol.begin(), toupper); file << "#ifndef " << symbol << "_H" << std::endl; @@ -360,9 +397,6 @@ void Companion::Process() { } } - spdlog::set_pattern(regular); - SPDLOG_INFO("------------------------------------------------"); - spdlog::set_pattern(line); if(wrapper != nullptr) { SPDLOG_INFO("Writing version file"); wrapper->CreateFile("version", vWriter.ToVector()); @@ -393,7 +427,10 @@ void Companion::Pack(const std::string& folder, const std::string& output) { std::unordered_map<std::string, std::vector<char>> files; for (const auto & entry : fs::recursive_directory_iterator(folder)){ - if(entry.is_directory()) continue; + if(entry.is_directory()) { + continue; + } + std::ifstream input( entry.path(), std::ios::binary ); auto data = std::vector( std::istreambuf_iterator( input ), {} ); input.close(); @@ -447,17 +484,23 @@ std::optional<std::shared_ptr<BaseFactory>> Companion::GetFactory(const std::str return this->gFactories[type]; } -std::optional<std::uint32_t> Companion::GetSegmentedAddr(const uint8_t segment) { +std::optional<std::uint32_t> Companion::GetSegmentedAddr(const uint8_t segment) const { + + auto segments = this->gConfig.segment; - if(this->gTemporalSegments.contains(segment)) { - return this->gTemporalSegments[segment]; + if(segments.temporal.contains(segment)) { + return segments.temporal[segment]; } - if(segment >= this->gSegments.size()) { - return std::nullopt; + if(segments.local.contains(segment)) { + return segments.local[segment]; + } + + if(segments.global.contains(segment)) { + return segments.global[segment]; } - return this->gSegments[segment]; + return std::nullopt; } std::optional<std::tuple<std::string, YAML::Node>> Companion::GetNodeByAddr(const uint32_t addr){ diff --git a/src/Companion.h b/src/Companion.h index cd0620b..bf61f11 100644 --- a/src/Companion.h +++ b/src/Companion.h @@ -27,47 +27,74 @@ enum class GBIMinorVersion { SM64 }; +struct SegmentConfig { + std::unordered_map<uint32_t, uint32_t> global; + std::unordered_map<uint32_t, uint32_t> local; + std::unordered_map<uint32_t, uint32_t> temporal; +}; + +struct GBIConfig { + GBIVersion version = GBIVersion::f3d; + GBIMinorVersion subversion = GBIMinorVersion::None; +}; + +struct TorchConfig { + GBIConfig gbi; + SegmentConfig segment; + std::string outputPath; + ExportType exporterType; + bool otrMode; + bool debug; +}; + class Companion { public: static Companion* Instance; - explicit Companion(std::filesystem::path rom, bool otr, bool debug) : gRomPath(std::move(rom)), gOTRMode(otr), gIsDebug(debug) {} + + explicit Companion(std::filesystem::path rom, const bool otr, const bool debug) : gRomPath(std::move(rom)), gCartridge(nullptr) { + this->gConfig.otrMode = otr; + this->gConfig.debug = debug; + } + void Init(ExportType type); void Process(); - bool IsOTRMode() { return this->gOTRMode; } - bool IsDebug() { return this->gIsDebug; } - N64::Cartridge* GetCartridge() { return this->gCartridge; } + + bool IsOTRMode() const { return this->gConfig.otrMode; } + bool IsDebug() const { return this->gConfig.debug; } + + N64::Cartridge* GetCartridge() const { return this->gCartridge.get(); } std::vector<uint8_t> GetRomData() { return this->gRomData; } - std::string GetOutputPath() { return this->gOutputPath; } - GBIVersion GetGBIVersion() { return this->gGBIVersion; } - GBIMinorVersion GetGBIMinorVersion() { return this->gGBIMinorVersion; } - std::optional<std::uint32_t> GetSegmentedAddr(uint8_t segment); + std::string GetOutputPath() { return this->gConfig.outputPath; } + + GBIVersion GetGBIVersion() const { return this->gConfig.gbi.version; } + GBIMinorVersion GetGBIMinorVersion() const { return this->gConfig.gbi.subversion; } + + std::optional<std::uint32_t> GetSegmentedAddr(uint8_t segment) const; std::optional<std::tuple<std::string, YAML::Node>> GetNodeByAddr(uint32_t addr); std::optional<std::shared_ptr<BaseFactory>> GetFactory(const std::string& type); static void Pack(const std::string& folder, const std::string& output); std::string NormalizeAsset(const std::string& name) const; + + TorchConfig& GetConfig() { return this->gConfig; } + std::optional<std::tuple<std::string, YAML::Node>> RegisterAsset(const std::string& name, YAML::Node& node); private: - bool gOTRMode = false; - bool gIsDebug = false; - GBIVersion gGBIVersion = GBIVersion::f3d; - GBIMinorVersion gGBIMinorVersion = GBIMinorVersion::None; - std::string gOutputPath; - std::string gCurrentFile; - ExportType gExporterType; + TorchConfig gConfig; fs::path gCurrentDirectory; - N64::Cartridge* gCartridge; std::vector<uint8_t> gRomData; std::filesystem::path gRomPath; - std::vector<uint32_t> gSegments; - std::unordered_map<uint32_t, uint32_t> gTemporalSegments; + std::shared_ptr<N64::Cartridge> gCartridge; + // Temporal Variables + std::string gCurrentFile; std::variant<std::vector<std::string>, std::string> gWriteOrder; std::unordered_map<std::string, std::shared_ptr<BaseFactory>> gFactories; std::map<std::string, std::map<std::string, std::pair<YAML::Node, bool>>> gAssetDependencies; std::map<std::string, std::map<std::string, std::vector<std::pair<uint32_t, std::string>>>> gWriteMap; std::unordered_map<std::string, std::unordered_map<uint32_t, std::tuple<std::string, YAML::Node>>> gAddrMap; + void ParseCurrentFileConfig(YAML::Node node); void RegisterFactory(const std::string& type, const std::shared_ptr<BaseFactory>& factory); void ExtractNode(YAML::Node& node, std::string& name, SWrapper* binary); }; diff --git a/src/factories/BankFactory.cpp b/src/factories/BankFactory.cpp index 6b4dc93..53f4869 100644 --- a/src/factories/BankFactory.cpp +++ b/src/factories/BankFactory.cpp @@ -92,6 +92,10 @@ std::optional<std::shared_ptr<IParsedData>> BankFactory::parse(std::vector<uint8 auto banks = AudioManager::Instance->get_banks(); auto bankId = data["id"].as<uint32_t>(); + if(AudioManager::Instance == nullptr){ + throw std::runtime_error("AudioManager not initialized"); + } + auto gSampleTable = Companion::Instance->GetCartridge()->GetCountry() == N64::CountryCode::Japan ? gJPSampleTable : gUSSampleTable; return std::make_shared<BankData>(banks[bankId], bankId, gSampleTable); }
\ No newline at end of file diff --git a/src/factories/BaseFactory.h b/src/factories/BaseFactory.h index 706116d..902b02e 100644 --- a/src/factories/BaseFactory.h +++ b/src/factories/BaseFactory.h @@ -15,8 +15,9 @@ #define REGISTER(type, c) { ExportType::type, std::make_shared<c>() }, -#define SEGMENT_OFFSET(a) ((uint32_t)(a)&0x00FFFFFF) -#define SEGMENT_NUMBER(x) ((x >> 24) & 0xFF) +#define SEGMENT_OFFSET(a) ((uint32_t)(a) & 0x00FFFFFF) +#define SEGMENT_NUMBER(x) (((uint32_t)(x) >> 24) & 0xFF) +#define IS_SEGMENTED(x) (((x) & 0x01000000 > 0) && (SEGMENT_NUMBER(x) < 0x20)) #define tab "\t" #define fourSpaceTab " " diff --git a/src/factories/DisplayListFactory.cpp b/src/factories/DisplayListFactory.cpp index 4d8d276..2481d46 100644 --- a/src/factories/DisplayListFactory.cpp +++ b/src/factories/DisplayListFactory.cpp @@ -37,7 +37,8 @@ std::unordered_map<std::string, uint8_t> gF3DExTable = { }; std::unordered_map<GBIVersion, std::unordered_map<std::string, uint8_t>> gGBITable = { - { GBIVersion::f3d, gF3DTable } + { GBIVersion::f3d, gF3DTable }, + { GBIVersion::f3dex, gF3DExTable }, }; #define GBI(cmd) gGBITable[Companion::Instance->GetGBIVersion()][#cmd] @@ -257,14 +258,33 @@ void DListBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDat writer.Finish(write); } -std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) { +std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint8_t>& raw_buffer, YAML::Node& node) { const auto gbi = Companion::Instance->GetGBIVersion(); - const auto mio0 = node["mio0"].as<uint32_t>(); - const auto offset = node["offset"].as<int32_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); + auto offset = node["offset"].as<uint32_t>(); + const bool isCompressed = node["mio0"] ? true : false; - LUS::BinaryReader reader(decoded.data(), decoded.size()); + std::vector<uint8_t> buffer; + + if(IS_SEGMENTED(offset)){ + const auto segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(offset)); + + if(!segment.has_value()) { + SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(offset)); + return std::nullopt; + } + + offset = segment.value() + SEGMENT_OFFSET(offset); + } + + if(isCompressed){ + const auto mio0 = node["mio0"].as<uint32_t>(); + buffer = MIO0Decoder::Decode(raw_buffer, mio0); + } else { + buffer = raw_buffer; + } + + LUS::BinaryReader reader(buffer.data(), buffer.size()); reader.SetEndianness(LUS::Endianness::Big); reader.Seek(offset, LUS::SeekOffsetType::Start); @@ -282,25 +302,53 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint } if(opcode == GBI(G_DL)) { - auto ptr = SEGMENT_OFFSET(w1); - auto dec = Companion::Instance->GetNodeByAddr(ptr); - if(!dec.has_value()){ - SPDLOG_INFO("Addr to Display list command at 0x{:X} not in yaml, autogenerating it", w1); - auto addr = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1)); - if(!addr.has_value()) { + std::optional<uint32_t> segment; + uint32_t ptr; + + if(IS_SEGMENTED(w1)){ + segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1)); + + if(!segment.has_value()) { SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1)); continue; } + ptr = SEGMENT_OFFSET(w1); + } else { + ptr = w1; + } + + auto dec = Companion::Instance->GetNodeByAddr(w1); + + if(!dec.has_value()){ + SPDLOG_INFO("Addr to Display list command at 0x{:X} not in yaml, autogenerating it", w1); + auto rom = Companion::Instance->GetRomData(); auto factory = Companion::Instance->GetFactory("GFX")->get(); - std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + Torch::to_hex(addr.value() + w1, false)); + + std::string output; YAML::Node dl; + + if(isCompressed){ + dl["mio0"] = segment.has_value() ? segment.value() : ptr; + if(segment.has_value()) { + SPDLOG_INFO("Found compressed and segmented display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_dl_" + Torch::to_hex(segment.value() + w1, false)); + } else { + SPDLOG_INFO("Found compressed display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false)); + } + } else { + SPDLOG_INFO("Found display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false)); + } + + dl["type"] = "GFX"; - dl["mio0"] = addr.value(); dl["offset"] = ptr; dl["symbol"] = output; + auto result = factory->parse(rom, dl); if(!result.has_value()){ @@ -376,7 +424,21 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint break; } - uint32_t ptr = SEGMENT_OFFSET(w1); + std::optional<uint32_t> segment; + uint32_t ptr; + + if(IS_SEGMENTED(w1)){ + segment = Companion::Instance->GetSegmentedAddr(SEGMENT_NUMBER(w1)); + + if(!segment.has_value()) { + SPDLOG_ERROR("Segment data missing from game config\nPlease add an entry for segment {}", SEGMENT_NUMBER(w1)); + continue; + } + + ptr = SEGMENT_OFFSET(w1); + } else { + ptr = w1; + } if(const auto decl = Companion::Instance->GetNodeByAddr(ptr); !decl.has_value()){ SPDLOG_INFO("Addr to Vtx array at 0x{:X} not in yaml, autogenerating it", w1); @@ -388,10 +450,25 @@ std::optional<std::shared_ptr<IParsedData>> DListFactory::parse(std::vector<uint auto rom = Companion::Instance->GetRomData(); auto factory = Companion::Instance->GetFactory("VTX")->get(); - std::string output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(addr.value() + w1, false)); + + std::string output; YAML::Node vtx; + + if(isCompressed){ + vtx["mio0"] = segment.has_value() ? segment.value() : ptr; + if(segment.has_value()) { + SPDLOG_INFO("Found compressed and segmented display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("seg" + std::to_string(SEGMENT_NUMBER(w1)) +"_vtx_" + Torch::to_hex(segment.value() + w1, false)); + } else { + SPDLOG_INFO("Found compressed display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("vtx_" + Torch::to_hex(w1, false)); + } + } else { + SPDLOG_INFO("Found display list at 0x{:X}", ptr); + output = Companion::Instance->NormalizeAsset("dl_" + Torch::to_hex(w1, false)); + } + vtx["type"] = "VTX"; - vtx["mio0"] = addr.value(); vtx["offset"] = ptr; vtx["count"] = nvtx; vtx["symbol"] = output; diff --git a/src/factories/LightsFactory.cpp b/src/factories/LightsFactory.cpp index 4c64d58..bcabbe8 100644 --- a/src/factories/LightsFactory.cpp +++ b/src/factories/LightsFactory.cpp @@ -71,8 +71,8 @@ std::optional<std::shared_ptr<IParsedData>> LightsFactory::parse(std::vector<uin auto mio0 = node["mio0"].as<size_t>(); auto offset = node["offset"].as<uint32_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); - LUS::BinaryReader reader(decoded.data() + offset, sizeof(Lights1Raw)); + auto decoded = MIO0Decoder::Decode(buffer, offset); + LUS::BinaryReader reader(decoded.data() + mio0, sizeof(Lights1Raw)); reader.SetEndianness(LUS::Endianness::Big); Lights1Raw lights; diff --git a/src/factories/SampleFactory.cpp b/src/factories/SampleFactory.cpp index 9b7c48f..100c7da 100644 --- a/src/factories/SampleFactory.cpp +++ b/src/factories/SampleFactory.cpp @@ -6,31 +6,38 @@ void SampleBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedDa auto sample = std::static_pointer_cast<SampleData>(raw)->mSample; WriteHeader(writer, LUS::ResourceType::Sample, 0); - writer.Write((uint32_t) sample.loop.start); - writer.Write((uint32_t) sample.loop.end); - writer.Write((uint32_t) sample.loop.count); - writer.Write((uint32_t) sample.loop.pad); + writer.Write(sample.loop.start); + writer.Write(sample.loop.end); + writer.Write(sample.loop.count); + writer.Write(sample.loop.pad); if(sample.loop.state.has_value()){ auto state = sample.loop.state.value(); - writer.Write((uint32_t) state.size()); - writer.Write((char*) state.data(), state.size() * sizeof(int16_t)); + writer.Write(static_cast<uint32_t>(state.size())); + writer.Write(reinterpret_cast<char*>(state.data()), state.size() * sizeof(int16_t)); } else { - writer.Write((uint32_t) 0); + writer.Write(static_cast<uint32_t>(0)); } - writer.Write((uint32_t) sample.book.order); - writer.Write((uint32_t) sample.book.npredictors); + writer.Write(sample.book.order); + writer.Write(sample.book.npredictors); + + writer.Write(static_cast<uint32_t>(sample.book.table.size())); + writer.Write(reinterpret_cast<char*>(sample.book.table.data()), sample.book.table.size() * sizeof(int16_t)); + + writer.Write(static_cast<int32_t>(sample.data.size())); + writer.Write(reinterpret_cast<char*>(sample.data.data()), sample.data.size()); - writer.Write((uint32_t) sample.book.table.size()); - writer.Write((char*) sample.book.table.data(), sample.book.table.size() * sizeof(int16_t)); writer.Write(sample.name); writer.Finish(write); } std::optional<std::shared_ptr<IParsedData>> SampleFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& data) { - auto id = data["id"].as<int32_t>(); + const auto id = data["id"].as<int32_t>(); + if(AudioManager::Instance == nullptr){ + throw std::runtime_error("AudioManager not initialized"); + } AudioBankSample entry = AudioManager::Instance->get_aifc(id); return std::make_shared<SampleData>(entry); }
\ No newline at end of file diff --git a/src/factories/SampleFactory.h b/src/factories/SampleFactory.h index 2877a66..0a006ca 100644 --- a/src/factories/SampleFactory.h +++ b/src/factories/SampleFactory.h @@ -1,5 +1,7 @@ #pragma once +#include <utility> + #include "BaseFactory.h" #include "audio/AudioManager.h" @@ -7,7 +9,7 @@ class SampleData : public IParsedData { public: AudioBankSample mSample; - SampleData(AudioBankSample sample) : mSample(sample) {} + explicit SampleData(AudioBankSample sample) : mSample(std::move(sample)) {} }; class SampleBinaryExporter : public BaseExporter { @@ -17,7 +19,8 @@ class SampleBinaryExporter : public BaseExporter { class SampleFactory : public BaseFactory { public: std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override; - inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override { + + std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override { return { REGISTER(Binary, SampleBinaryExporter) }; diff --git a/src/factories/TextureFactory.cpp b/src/factories/TextureFactory.cpp index f49db17..3759737 100644 --- a/src/factories/TextureFactory.cpp +++ b/src/factories/TextureFactory.cpp @@ -17,14 +17,14 @@ static const std::unordered_map <std::string, TextureType> gTextureTypes = { { "IA16", TextureType::GrayscaleAlpha16bpp }, }; -uint8_t* alloc_ia8_text_from_i1(uint16_t *in, int16_t width, int16_t height) { +std::vector<uint8_t> alloc_ia8_text_from_i1(uint16_t *in, int16_t width, int16_t height) { int32_t inPos; uint16_t bitMask; int16_t outPos = 0; - auto out = new uint8_t[width * height]; + const auto out = new uint8_t[width * height]; - for (inPos = 0; inPos < (width * height) / 16; inPos++) { - bitMask = 0x8000; + for (int32_t inPos = 0; inPos < (width * height) / 16; inPos++) { + uint16_t bitMask = 0x8000; while (bitMask != 0) { if (BSWAP16(in[inPos]) & bitMask) { @@ -38,7 +38,10 @@ uint8_t* alloc_ia8_text_from_i1(uint16_t *in, int16_t width, int16_t height) { } } - return out; + auto result = std::vector(out, out + width * height); + delete[] out; + + return result; } void TextureHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) { @@ -126,16 +129,16 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui std::vector<uint8_t> result; if(node["mio0"]){ + auto decoded = MIO0Decoder::Decode(buffer, offset); auto mio0 = node["mio0"].as<size_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); - auto data = decoded.data() + offset; + auto data = decoded.data() + mio0; + if(type == TextureType::GrayscaleAlpha1bpp){ - auto ia8 = alloc_ia8_text_from_i1((uint16_t*) data, 8, 16); - result = std::vector(ia8, ia8 + 8 * 16); - delete[] ia8; + result = alloc_ia8_text_from_i1((uint16_t*) data, 8, 16); + } else { + result = std::vector(data, data + size); } - result = std::vector(data, data + size); } else { result = std::vector(buffer.data() + offset, buffer.data() + offset + size); } diff --git a/src/factories/VtxFactory.cpp b/src/factories/VtxFactory.cpp index 8196571..e5214c5 100644 --- a/src/factories/VtxFactory.cpp +++ b/src/factories/VtxFactory.cpp @@ -87,8 +87,8 @@ std::optional<std::shared_ptr<IParsedData>> VtxFactory::parse(std::vector<uint8_ auto offset = node["offset"].as<uint32_t>(); auto count = node["count"].as<size_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); - LUS::BinaryReader reader(decoded.data() + offset, count * sizeof(VtxRaw) ); + auto decoded = MIO0Decoder::Decode(buffer, offset); + LUS::BinaryReader reader(decoded.data() + mio0, count * sizeof(VtxRaw) ); reader.SetEndianness(LUS::Endianness::Big); std::vector<VtxRaw> vertices; diff --git a/src/factories/mk64/WaypointFactory.cpp b/src/factories/mk64/WaypointFactory.cpp index 9ec96bc..ea84ede 100644 --- a/src/factories/mk64/WaypointFactory.cpp +++ b/src/factories/mk64/WaypointFactory.cpp @@ -62,8 +62,8 @@ std::optional<std::shared_ptr<IParsedData>> MK64::WaypointFactory::parse(std::ve auto offset = node["offset"].as<uint32_t>(); auto count = node["count"].as<size_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); - LUS::BinaryReader reader(decoded.data() + offset, count * sizeof(MK64::TrackWaypoint) ); + auto decoded = MIO0Decoder::Decode(buffer, offset); + LUS::BinaryReader reader(decoded.data() + mio0, count * sizeof(MK64::TrackWaypoint) ); reader.SetEndianness(LUS::Endianness::Big); std::vector<MK64::TrackWaypoint> waypoints; diff --git a/src/factories/sm64/AnimationFactory.cpp b/src/factories/sm64/AnimationFactory.cpp index 6afb405..cdbdedf 100644 --- a/src/factories/sm64/AnimationFactory.cpp +++ b/src/factories/sm64/AnimationFactory.cpp @@ -7,22 +7,22 @@ void SM64::AnimationBinaryExporter::Export(std::ostream &write, std::shared_ptr< auto anim = std::static_pointer_cast<AnimationData>(raw); WriteHeader(writer, LUS::ResourceType::Anim, 0); - writer.Write((int16_t) anim->mFlags); - writer.Write((int16_t) anim->mAnimYTransDivisor); - writer.Write((int16_t) anim->mStartFrame); - writer.Write((int16_t) anim->mLoopStart); - writer.Write((int16_t) anim->mLoopEnd); - writer.Write((int16_t) anim->mUnusedBoneCount); - writer.Write((uint64_t) anim->mLength); + writer.Write(anim->mFlags); + writer.Write(anim->mAnimYTransDivisor); + writer.Write(anim->mStartFrame); + writer.Write(anim->mLoopStart); + writer.Write(anim->mLoopEnd); + writer.Write(anim->mUnusedBoneCount); + writer.Write(static_cast<uint64_t>(anim->mLength)); - writer.Write((uint32_t) anim->mIndices.size()); - for (auto& index : anim->mIndices) { - writer.Write((int16_t) index); + writer.Write(static_cast<uint32_t>(anim->mIndices.size())); + for (const auto& index : anim->mIndices) { + writer.Write(index); } - writer.Write((uint32_t) anim->mEntries.size()); - for (auto& entry : anim->mEntries) { - writer.Write((uint16_t) entry); + writer.Write(static_cast<uint32_t>(anim->mEntries.size())); + for (const auto& entry : anim->mEntries) { + writer.Write(entry); } writer.Finish(write); @@ -33,7 +33,7 @@ std::optional<std::shared_ptr<IParsedData>> SM64::AnimationFactory::parse(std::v auto valuesNode = node["values"]; auto indexNode = node["indices"]; - LUS::BinaryReader header((char*) buffer.data() + headerNode["offset"].as<uint32_t>(), headerNode["size"].as<uint32_t>()); + LUS::BinaryReader header(reinterpret_cast<char *>(buffer.data()) + headerNode["offset"].as<uint32_t>(), headerNode["size"].as<uint32_t>()); header.SetEndianness(LUS::Endianness::Big); auto flags = header.ReadInt16(); @@ -46,10 +46,10 @@ std::optional<std::shared_ptr<IParsedData>> SM64::AnimationFactory::parse(std::v header.ReadUInt32(); auto length = header.ReadUInt32(); - LUS::BinaryReader indices((char*) buffer.data() + indexNode["offset"].as<uint32_t>(), indexNode["size"].as<uint32_t>()); + LUS::BinaryReader indices(reinterpret_cast<char*>(buffer.data()) + indexNode["offset"].as<uint32_t>(), indexNode["size"].as<uint32_t>()); indices.SetEndianness(LUS::Endianness::Big); - size_t indexLength = indexNode["size"].as<uint32_t>() / sizeof(uint16_t); - std::vector<uint16_t> indicesData; + size_t indexLength = indexNode["size"].as<uint32_t>() / sizeof(int16_t); + std::vector<int16_t> indicesData; for (size_t i = 0; i < indexLength; i++) { indicesData.push_back(indices.ReadInt16()); } @@ -70,5 +70,5 @@ std::optional<std::shared_ptr<IParsedData>> SM64::AnimationFactory::parse(std::v SPDLOG_INFO("Unused Bone Count: {}", unusedBoneCount); SPDLOG_INFO("Length: {}", length); - return std::make_shared<AnimationData>(flags, animYTransDivisor, startFrame, loopStart, loopEnd, unusedBoneCount, length, valuesData, indicesData); + return std::make_shared<AnimationData>(flags, animYTransDivisor, startFrame, loopStart, loopEnd, unusedBoneCount, length, indicesData, valuesData); }
\ No newline at end of file diff --git a/src/factories/sm64/AnimationFactory.h b/src/factories/sm64/AnimationFactory.h index 2d0ea45..82b073a 100644 --- a/src/factories/sm64/AnimationFactory.h +++ b/src/factories/sm64/AnimationFactory.h @@ -12,10 +12,10 @@ public: int16_t mLoopEnd; int16_t mUnusedBoneCount; int16_t mLength; - std::vector<uint16_t> mIndices; + std::vector<int16_t> mIndices; std::vector<uint16_t> mEntries; - AnimationData(int16_t flags, int16_t animYTransDivisor, int16_t startFrame, int16_t loopStart, int16_t loopEnd, int16_t unusedBoneCount, int16_t length, std::vector<uint16_t>& indices, std::vector<uint16_t>& entries) : mFlags(flags), mAnimYTransDivisor(animYTransDivisor), mStartFrame(startFrame), mLoopStart(loopStart), mLoopEnd(loopEnd), mUnusedBoneCount(unusedBoneCount), mLength(length), mIndices(indices), mEntries(entries) {} + AnimationData(int16_t flags, int16_t animYTransDivisor, int16_t startFrame, int16_t loopStart, int16_t loopEnd, int16_t unusedBoneCount, int16_t length, std::vector<int16_t> indices, std::vector<uint16_t> entries) : mFlags(flags), mAnimYTransDivisor(animYTransDivisor), mStartFrame(startFrame), mLoopStart(loopStart), mLoopEnd(loopEnd), mUnusedBoneCount(unusedBoneCount), mLength(length), mIndices(std::move(indices)), mEntries(std::move(entries)) {} }; class AnimationBinaryExporter : public BaseExporter { diff --git a/src/factories/sm64/DialogFactory.cpp b/src/factories/sm64/DialogFactory.cpp index 897b956..066b575 100644 --- a/src/factories/sm64/DialogFactory.cpp +++ b/src/factories/sm64/DialogFactory.cpp @@ -21,11 +21,11 @@ std::optional<std::shared_ptr<IParsedData>> SM64::DialogFactory::parse(std::vect auto offset = node["offset"].as<int32_t>(); auto mio0 = node["mio0"].as<size_t>(); - auto decoded = MIO0Decoder::Decode(buffer, mio0); + auto decoded = MIO0Decoder::Decode(buffer, offset); auto bytes = (uint8_t*) decoded.data(); LUS::BinaryReader reader(bytes, decoded.size()); reader.SetEndianness(LUS::Endianness::Big); - reader.Seek(offset, LUS::SeekOffsetType::Start); + reader.Seek(mio0, LUS::SeekOffsetType::Start); auto unused = reader.ReadUInt32(); auto linesPerBox = reader.ReadUByte(); diff --git a/src/factories/sm64/TextFactory.cpp b/src/factories/sm64/TextFactory.cpp index 6fcda1e..e32d3ce 100644 --- a/src/factories/sm64/TextFactory.cpp +++ b/src/factories/sm64/TextFactory.cpp @@ -16,11 +16,11 @@ std::optional<std::shared_ptr<IParsedData>> SM64::TextFactory::parse(std::vector auto mio0 = data["mio0"].as<size_t>(); std::vector<uint8_t> text; - auto decoded = MIO0Decoder::Decode(buffer, mio0); + auto decoded = MIO0Decoder::Decode(buffer, offset); auto bytes = (uint8_t*) decoded.data(); - while(bytes[offset] != 0xFF){ - auto c = bytes[offset++]; + while(bytes[mio0] != 0xFF){ + auto c = bytes[mio0++]; text.push_back(c); } text.push_back(0xFF); |
