#include #include "ILoadedSound.hpp" namespace Assets { void ILoadedSound::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) { Components::FileSystem::File soundFile(std::format("loaded_sound/{}", name)); if (!soundFile.exists()) { header->loadSnd = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).loadSnd; return; } Game::LoadedSound* sound = builder->getAllocator()->allocate(); if (!sound) { Components::Logger::Print("Error allocating memory for sound structure!\n"); return; } Game::LoadedSound* reference = nullptr; if (!reference) reference = Game::DB_FindXAssetHeader(Game::ASSET_TYPE_LOADED_SOUND, "weapons/c4_detpack/c4_drop_dirt1.wav").loadSnd; std::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(Game::ERR_FATAL, "Reading sound '{}' failed, header is invalid!", name); return; } unsigned int chunkSize = reader.read(); unsigned int format = reader.read(); if (format != 0x45564157) // WAVE { Components::Logger::Error(Game::ERR_FATAL, "Reading sound '{}' failed, header is invalid!", name); return; } 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(Game::ERR_FATAL, "Reading sound '{}' failed, invalid format!", name); return; } sound->sound.info.channels = reader.read(); sound->sound.info.rate = reader.read(); sound->sound.info.samples = reader.read(); sound->sound.info.block_size = reader.read(); sound->sound.info.bits = reader.read(); // skip any extra parameters if (chunkSize > 16) { reader.seekRelative(chunkSize - 16); } } break; case 0x61746164: // data sound->sound.info.data_len = chunkSize; sound->sound.data = reader.readArray(chunkSize); break; default: if (chunkSize > 0) { reader.seekRelative(chunkSize); } break; } } if (!sound->sound.info.data_ptr) { Components::Logger::Error(Game::ERR_FATAL, "Reading sound '{}' failed, invalid format!", name); return; } sound->name = builder->getAllocator()->duplicateString(name); header->loadSnd = sound; } void ILoadedSound::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) { AssertSize(Game::LoadedSound, 44); Utils::Stream* buffer = builder->getBuffer(); Game::LoadedSound* asset = header.loadSnd; Game::LoadedSound* dest = buffer->dest(); buffer->save(asset); buffer->pushBlock(Game::XFILE_BLOCK_VIRTUAL); if (asset->name) { buffer->saveString(builder->getAssetName(this->getType(), asset->name)); Utils::Stream::ClearPointer(&dest->name); } { buffer->pushBlock(Game::XFILE_BLOCK_TEMP); if (asset->sound.data) { buffer->saveArray(asset->sound.data, asset->sound.info.data_len); Utils::Stream::ClearPointer(&dest->sound.data); } buffer->popBlock(); } buffer->popBlock(); } }