diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp index 12bab83e..7788ec4f 100644 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp +++ b/src/Components/Modules/AssetInterfaces/ILoadedSound.cpp @@ -2,6 +2,96 @@ namespace Assets { + void ILoadedSound::load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) + { + Components::FileSystem::File soundFile(Utils::String::VA("sounds/%s", name.data())); + if (!soundFile.exists()) { + header->loadSnd = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).loadSnd; + } + + Game::LoadedSound* sound = builder->getAllocator()->allocate(); + if (!sound) + { + Components::Logger::Print("Error allocating memory for sound structure!\n"); + return; + } + + static Game::LoadedSound* reference = nullptr; + if (!reference) + reference = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_LOADED_SOUND, "weapons/c4_detpack/c4_drop_dirt1.wav").loadSnd; + + memcpy(sound, reference, sizeof(Game::LoadedSound)); + sound->sound.data = nullptr; + + Utils::Stream::Reader reader(builder->getAllocator(), soundFile.getBuffer()); + + unsigned int chunkIDBuffer = reader.read(); + if (chunkIDBuffer != 0x46464952) // RIFF + { + Components::Logger::Error(0, "Reading sound '%s' failed, header is invalid!", name.data()); + } + + unsigned int chunkSize = reader.read(); + + unsigned int format = reader.read(); + if (format != 0x45564157) // WAVE + { + Components::Logger::Error(0, "Reading sound '%s' failed, header is invalid!", name.data()); + } + + while (!sound->sound.data && !reader.end()) + { + chunkIDBuffer = reader.read(); + chunkSize = reader.read(); + + switch (chunkIDBuffer) + { + case 0x20746D66: // fmt + if (chunkSize >= 16) + { + sound->sound.info.format = reader.read(); + if (sound->sound.info.format != 1 && sound->sound.info.format != 17) + { + Components::Logger::Error(0, "Reading sound '%s' failed, invalid format!", name.data()); + } + + sound->sound.info.channels = reader.read(); + sound->sound.info.samples = reader.read(); + sound->sound.info.rate = reader.read(); + sound->sound.info.block_size = reader.read(); + sound->sound.info.bits = reader.read(); + + // skip any extra parameters + if (chunkSize > 16) + { + reader.seek(chunkSize - 16); + } + } + break; + + case 0x61746164: // data + sound->sound.info.data_len = chunkSize; + sound->sound.data = reader.readArray(chunkSize); + break; + + default: + if (chunkSize > 0) + { + reader.seek(chunkSize); + } + break; + } + } + + if (!sound->sound.info.data_ptr) + { + Components::Logger::Error(0, "Reading sound '%s' failed, invalid format!", name.data()); + } + + sound->name = _strdup(name.c_str()); + header->loadSnd = sound; + } + void ILoadedSound::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { AssertSize(Game::LoadedSound, 44); @@ -22,18 +112,18 @@ namespace Assets { buffer->pushBlock(Game::XFILE_BLOCK_TEMP); - if (asset->mssSound.data) + if (asset->sound.data) { - if (builder->hasPointer(asset->mssSound.data)) + if (builder->hasPointer(asset->sound.data)) { - dest->mssSound.data = builder->getPointer(asset->mssSound.data); + dest->sound.data = builder->getPointer(asset->sound.data); } else { - builder->storePointer(asset->mssSound.data); + builder->storePointer(asset->sound.data); - buffer->saveArray(asset->mssSound.data, asset->mssSound.size); - Utils::Stream::ClearPointer(&dest->mssSound.data); + buffer->saveArray(asset->sound.data, asset->sound.info.data_len); + Utils::Stream::ClearPointer(&dest->sound.data); } } diff --git a/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp b/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp index 6bdf7dee..bc011afb 100644 --- a/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp +++ b/src/Components/Modules/AssetInterfaces/ILoadedSound.hpp @@ -7,6 +7,7 @@ namespace Assets public: virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_LOADED_SOUND; }; + virtual void load(Game::XAssetHeader* header, std::string name, Components::ZoneBuilder::Zone* builder) override; virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; }; } diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index a501def1..8b64af60 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -193,18 +193,31 @@ namespace Game vec2_t knots[16]; }; - struct MssSound + struct _AILSOUNDINFO { - char unknown1[8]; - int size; - char unknown2[22]; - char *data; // size = soundSize + int format; + const void *data_ptr; + unsigned int data_len; + unsigned int rate; + int bits; + int channels; + unsigned int samples; + unsigned int block_size; + const void *initial_ptr; }; + /* 526 */ + struct MssSound + { + _AILSOUNDINFO info; + char *data; + }; + + /* 527 */ struct LoadedSound { const char *name; - MssSound mssSound; + MssSound sound; }; union SoundData