From 3cda71d1e77bb858ebe7e9746f28b8526ca355f1 Mon Sep 17 00:00:00 2001 From: Jan Date: Mon, 5 Apr 2021 18:50:42 +0200 Subject: [PATCH] Dump SoundBank asset data files --- src/Common/Game/T6/T6_Assets.h | 10 +- src/ObjLoading/Game/T6/ObjLoaderT6.cpp | 121 +++++++ src/ObjLoading/Game/T6/ObjLoaderT6.h | 10 + .../ObjContainer/SoundBank/SoundBank.cpp | 299 ++++++++++++++++++ .../ObjContainer/SoundBank/SoundBank.h | 52 +++ .../ObjContainer/SoundBank/SoundBankTypes.h | 45 +++ src/ObjWriting.lua | 2 + .../T6/AssetDumpers/AssetDumperSndBank.cpp | 111 +++++++ .../Game/T6/AssetDumpers/AssetDumperSndBank.h | 19 ++ src/ObjWriting/Game/T6/ZoneDumperT6.cpp | 3 +- 10 files changed, 670 insertions(+), 2 deletions(-) create mode 100644 src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp create mode 100644 src/ObjLoading/ObjContainer/SoundBank/SoundBank.h create mode 100644 src/ObjLoading/ObjContainer/SoundBank/SoundBankTypes.h create mode 100644 src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp create mode 100644 src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h diff --git a/src/Common/Game/T6/T6_Assets.h b/src/Common/Game/T6/T6_Assets.h index f2912804..44c4a180 100644 --- a/src/Common/Game/T6/T6_Assets.h +++ b/src/Common/Game/T6/T6_Assets.h @@ -5755,6 +5755,14 @@ namespace T6 MaterialArgumentDef u; }; + enum SndAliasType + { + SAT_UNKNOWN = 0x0, + SAT_LOADED = 0x1, + SAT_STREAMED = 0x2, + SAT_PRIMED = 0x3, + SAT_COUNT = 0x4, + }; struct SndAlias { @@ -5764,7 +5772,7 @@ namespace T6 const char* secondaryname; unsigned int assetId; const char* assetFileName; - unsigned int flags0; + unsigned int flags0; // Bits 15/16 are SndAliasType unsigned int flags1; unsigned int duck; unsigned int contextType; diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp index 9ef53c25..9788b380 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.cpp +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.cpp @@ -1,5 +1,7 @@ #include "ObjLoaderT6.h" +#include + #include "Game/T6/GameT6.h" #include "Game/T6/GameAssetPoolT6.h" #include "ObjContainer/IPak/IPak.h" @@ -92,6 +94,115 @@ namespace T6 return zone->m_game == &g_GameT6; } + bool ObjLoader::VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank) + { + SndAssetBankChecksum checksum{}; + static_assert(sizeof(SndAssetBankChecksum::checksumBytes) == sizeof(SndRuntimeAssetBank::linkTimeChecksum)); + for (auto i = 0u; i < sizeof(SndAssetBankChecksum::checksumBytes); i++) + checksum.checksumBytes[i] = sndRuntimeAssetBank.linkTimeChecksum[i]; + + return soundBank->VerifyChecksum(checksum); + } + + SoundBank* ObjLoader::LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone) + { + if (ObjLoading::Configuration.Verbose) + std::cout << "Trying to load sound bank '" << soundBankFileName << "' for zone '" << zone->m_name << "'" << std::endl; + + auto* existingSoundBank = SoundBank::Repository.GetContainerByName(soundBankFileName); + if (existingSoundBank != nullptr) + { + if (ObjLoading::Configuration.Verbose) + std::cout << "Referencing loaded sound bank '" << soundBankFileName << "'." << std::endl; + + SoundBank::Repository.AddContainerReference(existingSoundBank, zone); + return existingSoundBank; + } + + auto file = searchPath->Open(soundBankFileName); + if (file.IsOpen()) + { + auto sndBank = std::make_unique(soundBankFileName, std::move(file.m_stream), file.m_length); + auto* sndBankPtr = sndBank.get(); + + if (!sndBank->Initialize()) + { + std::cout << "Failed to load sound bank '" << soundBankFileName << "'" << std::endl; + return nullptr; + } + + SoundBank::Repository.AddContainer(std::move(sndBank), zone); + + if (ObjLoading::Configuration.Verbose) + std::cout << "Found and loaded sound bank '" << soundBankFileName << "'" << std::endl; + + return sndBankPtr; + } + + std::cout << "Failed to load sound bank '" << soundBankFileName << "'" << std::endl; + return nullptr; + } + + void ObjLoader::LoadSoundBankFromLinkedInfo(ISearchPath* searchPath, const std::string& soundBankFileName, const SndRuntimeAssetBank* sndBankLinkedInfo, Zone* zone, std::set& loadedBanksForZone, std::stack& dependenciesToLoad) + { + if (loadedBanksForZone.find(soundBankFileName) == loadedBanksForZone.end()) + { + auto* soundBank = LoadSoundBankForZone(searchPath, soundBankFileName, zone); + + if (soundBank) + { + if (!VerifySoundBankChecksum(soundBank, *sndBankLinkedInfo)) + { + std::cout << "Checksum of sound bank does not match link time checksum for '" << soundBankFileName << "'" << std::endl; + } + loadedBanksForZone.emplace(soundBankFileName); + + for (const auto& dependency : soundBank->GetDependencies()) + { + dependenciesToLoad.emplace(dependency); + } + } + } + } + + void ObjLoader::LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set& loadedBanksForZone) + { + std::stack dependenciesToLoad; + + if (sndBank->streamAssetBank.zone) + { + const auto soundBankFileName = SoundBank::GetFileNameForDefinition(true, sndBank->streamAssetBank.zone, sndBank->streamAssetBank.language); + LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->streamAssetBank, zone, loadedBanksForZone, dependenciesToLoad); + } + + if (sndBank->runtimeAssetLoad && sndBank->loadAssetBank.zone) + { + const auto soundBankFileName = SoundBank::GetFileNameForDefinition(false, sndBank->loadAssetBank.zone, sndBank->loadAssetBank.language); + LoadSoundBankFromLinkedInfo(searchPath, soundBankFileName, &sndBank->loadAssetBank, zone, loadedBanksForZone, dependenciesToLoad); + } + + while(!dependenciesToLoad.empty()) + { + auto dependencyFileName = dependenciesToLoad.top(); + dependenciesToLoad.pop(); + + if (loadedBanksForZone.find(dependencyFileName) == loadedBanksForZone.end()) + { + auto* soundBank = LoadSoundBankForZone(searchPath, dependencyFileName, zone); + + if (soundBank) + { + loadedBanksForZone.emplace(dependencyFileName); + + for (const auto& dependency : soundBank->GetDependencies()) + { + dependenciesToLoad.emplace(dependency); + } + } + } + } + } + void ObjLoader::LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone) { if (ObjLoading::Configuration.Verbose) @@ -199,6 +310,16 @@ namespace T6 } } } + + if (assetPoolT6->m_sound_bank != nullptr) + { + std::set loadedSoundBanksForZone; + + for (auto* sndBankAssetInfo : *assetPoolT6->m_sound_bank) + { + LoadSoundBanksFromAsset(searchPath, sndBankAssetInfo->Asset(), zone, loadedSoundBanksForZone); + } + } } void ObjLoader::UnloadContainersOfZone(Zone* zone) const diff --git a/src/ObjLoading/Game/T6/ObjLoaderT6.h b/src/ObjLoading/Game/T6/ObjLoaderT6.h index daae32c2..92e21948 100644 --- a/src/ObjLoading/Game/T6/ObjLoaderT6.h +++ b/src/ObjLoading/Game/T6/ObjLoaderT6.h @@ -2,11 +2,15 @@ #include #include +#include +#include +#include #include "IObjLoader.h" #include "AssetLoading/IAssetLoader.h" #include "SearchPath/ISearchPath.h" #include "Game/T6/T6.h" +#include "ObjContainer/SoundBank/SoundBank.h" namespace T6 { @@ -17,6 +21,12 @@ namespace T6 std::unordered_map> m_asset_loaders_by_type; + static bool VerifySoundBankChecksum(const SoundBank* soundBank, const SndRuntimeAssetBank& sndRuntimeAssetBank); + static SoundBank* LoadSoundBankForZone(ISearchPath* searchPath, const std::string& soundBankFileName, Zone* zone); + static void LoadSoundBankFromLinkedInfo(ISearchPath* searchPath, const std::string& soundBankFileName, const SndRuntimeAssetBank* sndBankLinkedInfo, Zone* zone, + std::set& loadedBanksForZone, std::stack& dependenciesToLoad); + static void LoadSoundBanksFromAsset(ISearchPath* searchPath, const SndBank* sndBank, Zone* zone, std::set& loadedBanksForZone); + static void LoadIPakForZone(ISearchPath* searchPath, const std::string& ipakName, Zone* zone); static void LoadImageFromIwi(GfxImage* image, ISearchPath* searchPath, Zone* zone); diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp new file mode 100644 index 00000000..019da1a6 --- /dev/null +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.cpp @@ -0,0 +1,299 @@ +#include "SoundBank.h" + +#include +#include +#include + +#include "zlib.h" + +#include "Utils/FileUtils.h" + +ObjContainerRepository SoundBank::Repository; + +class SoundBankInputBuffer final : public objbuf +{ + std::istream& m_stream; + int64_t m_base_offset; + size_t m_size; + size_t m_offset; + bool m_open; + +protected: + std::streamsize showmanyc() override + { + return m_size - m_offset; + } + + int_type underflow() override + { + if (m_offset >= m_size) + return EOF; + + return m_stream.peek(); + } + + int_type uflow() override + { + if (m_offset >= m_size) + return EOF; + + m_offset++; + return m_stream.get(); + } + + std::streamsize xsgetn(char* ptr, std::streamsize count) override + { + if (m_offset + count > m_size) + count = m_size - m_offset; + + if (count > 0) + { + m_stream.read(ptr, count); + + const auto readSize = m_stream.gcount(); + m_offset += readSize; + return readSize; + } + + return 0; + } + + pos_type seekoff(const off_type off, const std::ios_base::seekdir dir, const std::ios_base::openmode mode) override + { + if(dir == std::ios_base::beg) + { + return seekpos(off, mode); + } + + if(dir == std::ios_base::end) + { + if (off > m_size) + return pos_type(-1); + + return seekpos(m_size - off, mode); + } + + return seekpos(m_offset + off, mode); + } + + pos_type seekpos(const pos_type pos, std::ios_base::openmode mode) override + { + if (pos < 0 || pos >= m_size) + return pos_type(-1); + + m_stream.seekg(m_base_offset + pos); + m_offset = static_cast(pos); + return pos; + } + +public: + SoundBankInputBuffer(std::istream& stream, const int64_t baseOffset, const size_t size) + : m_stream(stream), + m_base_offset(baseOffset), + m_size(size), + m_offset(0), + m_open(true) + { + } + + _NODISCARD bool is_open() const override + { + return m_open; + } + + bool close() override + { + const auto result = m_open; + m_open = false; + return result; + } +}; + +bool SoundBank::ReadHeader() +{ + m_stream->read(reinterpret_cast(&m_header), sizeof(m_header)); + if (m_stream->gcount() != sizeof(m_header)) + { + printf("Unexpected eof when trying to load sndbank header.\n"); + return false; + } + + if (m_header.magic != MAGIC) + { + std::cout << "Invalid sndbank magic 0x" << std::hex << m_header.magic << std::endl; + return false; + } + + if (m_header.version != VERSION) + { + std::cout << "Unsupported sndbank version " << m_header.version << " (should be " << VERSION << ")" << std::endl; + return false; + } + + if (m_header.entrySize != sizeof(SndAssetBankEntry)) + { + std::cout << "Invalid sndbank entry size 0x" << std::hex << m_header.entrySize << " (should be 0x" << std::hex << sizeof(SndAssetBankEntry) << ")" << std::endl; + return false; + } + + if (m_header.fileSize != m_file_size) + { + std::cout << "Invalid sndbank " << m_file_size << " (header expects " << m_header.fileSize << ")" << std::endl; + return false; + } + + if (m_header.entryCount + && (m_header.entryOffset <= 0 || m_header.entryOffset + sizeof(SndAssetBankEntry) * m_header.entryCount > m_file_size)) + { + std::cout << "Invalid sndbank entry offset " << m_header.entryOffset << " (filesize is " << m_file_size << ")" << std::endl; + return false; + } + + if (m_header.checksumOffset <= 0 || m_header.checksumOffset + sizeof(SndAssetBankChecksum) * m_header.entryCount > m_file_size) + { + std::cout << "Invalid sndbank checksum offset " << m_header.checksumOffset << " (filesize is " << m_file_size << ")" << std::endl; + return false; + } + + if (m_header.dependencyCount * m_header.dependencySize > sizeof(SndAssetBankHeader::dependencies)) + { + std::cout << "Invalid sndbank dependency sizes (count is " << m_header.dependencyCount << "; size is " << m_header.dependencySize << ")" << std::endl; + return false; + } + + for (auto i = 0u; i < m_header.dependencyCount; i++) + { + const auto dependencyLen = strnlen(&m_header.dependencies[i * m_header.dependencySize], m_header.dependencySize); + std::string dependencyName(&m_header.dependencies[i * m_header.dependencySize], dependencyLen); + + if (dependencyName.empty()) + continue; + + m_dependencies.emplace_back(std::move(dependencyName)); + } + + return true; +} + +bool SoundBank::ReadEntries() +{ + m_stream->seekg(m_header.entryOffset); + + for (auto i = 0u; i < m_header.entryCount; i++) + { + SndAssetBankEntry entry{}; + m_stream->read(reinterpret_cast(&entry), sizeof(entry)); + + if (m_stream->gcount() != sizeof(entry)) + { + std::cout << "Failed to read sound bank entry at index " << i << std::endl; + return false; + } + + if (entry.offset == 0 || entry.offset + entry.size >= m_file_size) + { + std::cout << "Invalid sound bank entry data offset " << entry.offset << " (filesize is " << m_header.fileSize << ")" << std::endl; + return false; + } + + m_entries.push_back(entry); + m_entries_by_id.emplace(std::make_pair(entry.id, i)); + } + + return true; +} + +bool SoundBank::ReadChecksums() +{ + m_stream->seekg(m_header.entryOffset); + + for (auto i = 0u; i < m_header.entryCount; i++) + { + SndAssetBankChecksum checksum{}; + m_stream->read(reinterpret_cast(&checksum), sizeof(checksum)); + + if (m_stream->gcount() != sizeof(checksum)) + { + std::cout << "Failed to read sound bank checksum at index " << i << std::endl; + return false; + } + + m_checksums.push_back(checksum); + } + + return true; +} + +std::string SoundBank::GetFileNameForDefinition(const bool streamed, const char* zone, const char* language) +{ + std::ostringstream str; + + assert(zone != nullptr); + + if (zone) + str << zone; + + if (language) + str << "." << language; + + if (streamed) + str << ".sabs"; + else + str << ".sabl"; + + return str.str(); +} + +SoundBank::SoundBank(std::string fileName, std::unique_ptr stream, const int64_t fileSize) + : m_file_name(std::move(fileName)), + m_stream(std::move(stream)), + m_file_size(fileSize), + m_initialized(false), + m_header{} +{ +} + +std::string SoundBank::GetName() +{ + return m_file_name; +} + +bool SoundBank::Initialize() +{ + if (m_initialized) + return true; + + if (!ReadHeader() + || !ReadEntries() + || !ReadChecksums()) + return false; + + m_initialized = true; + return true; +} + +const std::vector& SoundBank::GetDependencies() const +{ + return m_dependencies; +} + +bool SoundBank::VerifyChecksum(const SndAssetBankChecksum& checksum) const +{ + return m_initialized && memcmp(checksum.checksumBytes, m_header.checksumChecksum.checksumBytes, sizeof(SndAssetBankChecksum)) == 0; +} + +SearchPathOpenFile SoundBank::GetEntryStream(const unsigned id) const +{ + const auto foundEntry = m_entries_by_id.find(id); + + if (foundEntry != m_entries_by_id.end()) + { + const auto& entry = m_entries[foundEntry->second]; + + m_stream->seekg(entry.offset); + + return SearchPathOpenFile(std::make_unique(std::make_unique(*m_stream, entry.offset, entry.size)), entry.size); + } + + return SearchPathOpenFile(); +} diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h new file mode 100644 index 00000000..f7ab2c4a --- /dev/null +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBank.h @@ -0,0 +1,52 @@ +#pragma once + +#include + +#include "Utils/ClassUtils.h" +#include "ObjContainer/ObjContainerReferenceable.h" +#include "ObjContainer/ObjContainerRepository.h" +#include "ObjContainer/SoundBank/SoundBankTypes.h" +#include "SearchPath/ISearchPath.h" +#include "Utils/FileUtils.h" +#include "Utils/ObjStream.h" +#include "Zone/Zone.h" + +class SoundBank final : public ObjContainerReferenceable +{ + static constexpr uint32_t MAGIC = FileUtils::MakeMagic32('2', 'U', 'X', '#'); + static constexpr uint32_t VERSION = 14u; + + std::string m_file_name; + std::unique_ptr m_stream; + int64_t m_file_size; + + bool m_initialized; + SndAssetBankHeader m_header; + std::vector m_dependencies; + std::vector m_entries; + std::vector m_checksums; + std::unordered_map m_entries_by_id; + + bool ReadHeader(); + bool ReadEntries(); + bool ReadChecksums(); + +public: + static ObjContainerRepository Repository; + + static std::string GetFileNameForDefinition(bool streamed, const char* zone, const char* language); + + SoundBank(std::string fileName, std::unique_ptr stream, int64_t fileSize); + SoundBank(const SoundBank& other) = delete; + SoundBank(SoundBank&& other) noexcept = default; + SoundBank& operator=(const SoundBank& other) = delete; + SoundBank& operator=(SoundBank&& other) noexcept = default; + + std::string GetName() override; + + bool Initialize(); + _NODISCARD const std::vector& GetDependencies() const; + + _NODISCARD bool VerifyChecksum(const SndAssetBankChecksum& checksum) const; + _NODISCARD SearchPathOpenFile GetEntryStream(unsigned int id) const; +}; diff --git a/src/ObjLoading/ObjContainer/SoundBank/SoundBankTypes.h b/src/ObjLoading/ObjContainer/SoundBank/SoundBankTypes.h new file mode 100644 index 00000000..0995b0ef --- /dev/null +++ b/src/ObjLoading/ObjContainer/SoundBank/SoundBankTypes.h @@ -0,0 +1,45 @@ +#pragma once + +#include + +class SoundBankConsts +{ + SoundBankConsts() = default; + +public: + static constexpr unsigned OFFSET_DATA_START = 0x800; +}; + +struct SndAssetBankChecksum +{ + char checksumBytes[16]; +}; + +struct SndAssetBankHeader +{ + unsigned int magic; // + 0x0 + unsigned int version; // + 0x4 + unsigned int entrySize; // + 0x8 + unsigned int checksumSize; // + 0xC + unsigned int dependencySize; // + 0x10 + unsigned int entryCount; // + 0x14 + unsigned int dependencyCount; // + 0x18 + unsigned int pad32; // + 0x1C + int64_t fileSize; // + 0x20 + int64_t entryOffset; // + 0x28 + int64_t checksumOffset; // + 0x30 + SndAssetBankChecksum checksumChecksum; // + 0x38 + char dependencies[512]; // + 0x48 +}; + +struct SndAssetBankEntry +{ + unsigned int id; + unsigned int size; + unsigned int offset; + unsigned int frameCount; + char frameRateIndex; + char channelCount; + char looping; + char format; +}; diff --git a/src/ObjWriting.lua b/src/ObjWriting.lua index 22303aed..f045f0f7 100644 --- a/src/ObjWriting.lua +++ b/src/ObjWriting.lua @@ -3,6 +3,7 @@ ObjWriting = {} function ObjWriting:include(includes) if includes:handle(self:name()) then ObjCommon:include(includes) + ObjLoading:include(includes) ZoneCommon:include(includes) includedirs { path.join(ProjectFolder(), "ObjWriting") @@ -14,6 +15,7 @@ function ObjWriting:link(links) links:add(self:name()) links:linkto(Utils) links:linkto(ObjCommon) + links:linkto(ObjLoading) links:linkto(ZoneCommon) links:linkto(minilzo) links:linkto(minizip) diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp new file mode 100644 index 00000000..03734275 --- /dev/null +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.cpp @@ -0,0 +1,111 @@ +#include "AssetDumperSndBank.h" + +#include + +#include "Csv/CsvStream.h" +#include "ObjContainer/SoundBank/SoundBank.h" + +using namespace T6; +namespace fs = std::filesystem; + +std::unique_ptr AssetDumperSndBank::OpenOutputFile(AssetDumpingContext& context, const std::string& outputFileName) const +{ + fs::path assetPath(context.m_base_path); + + fs::path assetName(outputFileName); + auto firstPart = true; + for(const auto& part : assetName) + { + if(firstPart) + { + firstPart = false; + if(part.string() == "raw" + || part.string() == "devraw") + continue; + } + + assetPath.append(part.string()); + } + + auto assetDir(assetPath); + assetDir.remove_filename(); + + create_directories(assetDir); + + auto outputStream = std::make_unique(assetPath, std::ios_base::out | std::ios_base::binary); + + if(outputStream->is_open()) + { + return std::move(outputStream); + } + + return nullptr; +} + +void AssetDumperSndBank::DumpSndBank(AssetDumpingContext& context, const XAssetInfo* sndBankInfo) +{ + const auto* sndBank = sndBankInfo->Asset(); + + // auto* streamAssetBank = SoundBank::Repository.GetContainerByName(SoundBank::GetFileNameForDefinition(true, sndBank->streamAssetBank.zone, sndBank->streamAssetBank.language)); + // SoundBank* loadedAssetBank = nullptr; + // if (sndBank->runtimeAssetLoad && sndBank->loadAssetBank.zone) + // loadedAssetBank = SoundBank::Repository.GetContainerByName(SoundBank::GetFileNameForDefinition(false, sndBank->loadAssetBank.zone, sndBank->loadAssetBank.language)); + + std::map aliasMappings; + for (auto i = 0u; i < sndBank->aliasCount; i++) + { + const auto& aliasList = sndBank->alias[i]; + for (auto j = 0; j < aliasList.count; j++) + { + const auto& alias = aliasList.head[j]; + if (alias.assetId && alias.assetFileName) + aliasMappings[alias.assetId] = alias.assetFileName; + } + } + + for (const auto& [id, filename] : aliasMappings) + { + auto foundEntry = false; + + for (const auto* soundBank : SoundBank::Repository) + { + auto soundFile = soundBank->GetEntryStream(id); + if (soundFile.IsOpen()) + { + auto outFile = OpenOutputFile(context, filename); + if (!outFile) + { + std::cout << "Failed to open sound outputfile: \"" << filename << "\"" << std::endl; + break; + } + + char buffer[2048]; + while (!soundFile.m_stream->eof()) + { + soundFile.m_stream->read(buffer, sizeof(buffer)); + const auto readSize = soundFile.m_stream->gcount(); + outFile->write(buffer, readSize); + } + + foundEntry = true; + break; + } + } + + if(!foundEntry) + { + std::cout << "Could not find data for sound \"" << filename << "\"" << std::endl; + } + } +} + +void AssetDumperSndBank::DumpPool(AssetDumpingContext& context, AssetPool* pool) +{ + for(const auto* assetInfo : *pool) + { + if (!assetInfo->m_name.empty() && assetInfo->m_name[0] == ',') + continue; + + DumpSndBank(context, assetInfo); + } +} diff --git a/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h new file mode 100644 index 00000000..a5b347f1 --- /dev/null +++ b/src/ObjWriting/Game/T6/AssetDumpers/AssetDumperSndBank.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +#include "Dumping/AbstractAssetDumper.h" +#include "Game/T6/T6.h" + +namespace T6 +{ + class AssetDumperSndBank final : public IAssetDumper + { + std::unique_ptr OpenOutputFile(AssetDumpingContext& context, const std::string& outputFileName) const; + void DumpSndBank(AssetDumpingContext& context, const XAssetInfo* sndBankInfo); + + public: + void DumpPool(AssetDumpingContext& context, AssetPool* pool) override; + }; +} diff --git a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp index aeb4e52c..e8f7e229 100644 --- a/src/ObjWriting/Game/T6/ZoneDumperT6.cpp +++ b/src/ObjWriting/Game/T6/ZoneDumperT6.cpp @@ -13,6 +13,7 @@ #include "AssetDumpers/AssetDumperFontIcon.h" #include "AssetDumpers/AssetDumperPhysConstraints.h" #include "AssetDumpers/AssetDumperPhysPreset.h" +#include "AssetDumpers/AssetDumperSndBank.h" #include "AssetDumpers/AssetDumperTracer.h" #include "AssetDumpers/AssetDumperVehicle.h" #include "AssetDumpers/AssetDumperWeapon.h" @@ -46,7 +47,7 @@ bool ZoneDumper::DumpZone(AssetDumpingContext& context) const // DUMP_ASSET_POOL(AssetDumperMaterial, m_material); // DUMP_ASSET_POOL(AssetDumperTechniqueSet, m_technique_set); DUMP_ASSET_POOL(AssetDumperGfxImage, m_image); - // DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank); + DUMP_ASSET_POOL(AssetDumperSndBank, m_sound_bank); // DUMP_ASSET_POOL(AssetDumperSndPatch, m_sound_patch); // DUMP_ASSET_POOL(AssetDumperClipMap, m_clip_map); // DUMP_ASSET_POOL(AssetDumperComWorld, m_com_world);