diff --git a/src/Components/Modules/AssetHandler.cpp b/src/Components/Modules/AssetHandler.cpp index 28327893..e84920bb 100644 --- a/src/Components/Modules/AssetHandler.cpp +++ b/src/Components/Modules/AssetHandler.cpp @@ -398,6 +398,7 @@ namespace Components AssetHandler::RegisterInterface(new Assets::IStringTable()); //AssetHandler::RegisterInterface(new Assets::IXModelSurfs()); AssetHandler::RegisterInterface(new Assets::ILocalizedEntry()); + AssetHandler::RegisterInterface(new Assets::Isnd_alias_list_t()); AssetHandler::RegisterInterface(new Assets::IMaterialPixelShader()); AssetHandler::RegisterInterface(new Assets::IMaterialTechniqueSet()); AssetHandler::RegisterInterface(new Assets::IMaterialVertexShader()); diff --git a/src/Components/Modules/AssetHandler.hpp b/src/Components/Modules/AssetHandler.hpp index 117e25f0..261a05f3 100644 --- a/src/Components/Modules/AssetHandler.hpp +++ b/src/Components/Modules/AssetHandler.hpp @@ -82,6 +82,7 @@ namespace Components #include "AssetInterfaces\IStringTable.hpp" #include "AssetInterfaces\IXModelSurfs.hpp" #include "AssetInterfaces\ILocalizedEntry.hpp" +#include "AssetInterfaces\Isnd_alias_list_t.hpp" #include "AssetInterfaces\IMaterialPixelShader.hpp" #include "AssetInterfaces\IMaterialTechniqueSet.hpp" #include "AssetInterfaces\IMaterialVertexShader.hpp" diff --git a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp index ae78c31b..bf714c18 100644 --- a/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp +++ b/src/Components/Modules/AssetInterfaces/IFxEffectDef.cpp @@ -22,7 +22,7 @@ namespace Assets case 0xA: { - // TODO: Load sound here as soon as soundaliases are supported! + builder->loadAsset(Game::XAssetType::ASSET_TYPE_SOUND, visuals->soundName); break; } diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp new file mode 100644 index 00000000..da87c85b --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.cpp @@ -0,0 +1,176 @@ +#include + +namespace Assets +{ + void Isnd_alias_list_t::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + Game::snd_alias_list_t* asset = header.aliasList; + + for (int i = 0; i < asset->count; ++i) + { + Game::snd_alias_t* alias = &asset->head[i]; + + if (alias->soundFile && alias->soundFile->type == Game::snd_alias_type_t::SAT_LOADED) + { + builder->loadAsset(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, alias->soundFile->data.loaded->name); + } + + if (alias->volumeFalloffCurve) + { + builder->loadAsset(Game::XAssetType::ASSET_TYPE_SNDCURVE, alias->volumeFalloffCurve->filename); + } + } + } + + void Isnd_alias_list_t::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) + { + AssertSize(Game::snd_alias_list_t, 12); + + Utils::Stream* buffer = builder->getBuffer(); + Game::snd_alias_list_t* asset = header.aliasList; + Game::snd_alias_list_t* 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); + } + + if (asset->head) + { + if (builder->hasPointer(asset->head)) + { + dest->head = builder->getPointer(asset->head); + } + else + { + AssertSize(Game::snd_alias_t, 100); + + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(asset->head); + + Game::snd_alias_t* destHead = buffer->dest(); + buffer->saveArray(asset->head, asset->count); + + for (int i = 0; i < asset->count; ++i) + { + Game::snd_alias_t* destAlias = &destHead[i]; + Game::snd_alias_t* alias = &asset->head[i]; + + if (alias->name) + { + buffer->saveString(alias->name); + Utils::Stream::ClearPointer(&destAlias->name); + } + + if (alias->subtitle) + { + buffer->saveString(alias->subtitle); + Utils::Stream::ClearPointer(&destAlias->subtitle); + } + + if (alias->secondaryAliasName) + { + buffer->saveString(alias->secondaryAliasName); + Utils::Stream::ClearPointer(&destAlias->secondaryAliasName); + } + + if (alias->chainAliasName) + { + buffer->saveString(alias->chainAliasName); + Utils::Stream::ClearPointer(&destAlias->chainAliasName); + } + + if (alias->string4) + { + buffer->saveString(alias->string4); + Utils::Stream::ClearPointer(&destAlias->string4); + } + + if (alias->soundFile) + { + if (builder->hasPointer(alias->soundFile)) + { + destAlias->soundFile = builder->getPointer(alias->soundFile); + } + else + { + AssertSize(Game::snd_alias_t, 100); + + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(alias->soundFile); + + Game::SoundFile* destSoundFile = buffer->dest(); + buffer->save(alias->soundFile); + + // Save_SoundFileRef + { + if (alias->soundFile->type == Game::snd_alias_type_t::SAT_LOADED) + { + destSoundFile->data.loaded = builder->requireAsset(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, alias->soundFile->data.loaded->name).sound; + } + else + { + // Save_StreamedSound + { + if (alias->soundFile->data.stream.dir) + { + buffer->saveString(alias->soundFile->data.stream.dir); + Utils::Stream::ClearPointer(&destSoundFile->data.stream.dir); + } + + if (alias->soundFile->data.stream.name) + { + buffer->saveString(alias->soundFile->data.stream.name); + Utils::Stream::ClearPointer(&destSoundFile->data.stream.name); + } + } + } + } + + Utils::Stream::ClearPointer(&destAlias->soundFile); + } + } + + if (alias->volumeFalloffCurve) + { + destAlias->volumeFalloffCurve = builder->requireAsset(Game::XAssetType::ASSET_TYPE_SNDCURVE, alias->volumeFalloffCurve->filename).sndCurve; + } + + if (alias->speakerMap) + { + if (builder->hasPointer(alias->speakerMap)) + { + destAlias->speakerMap = builder->getPointer(alias->speakerMap); + } + else + { + AssertSize(Game::SpeakerMap, 408); + + buffer->align(Utils::Stream::ALIGN_4); + builder->storePointer(alias->speakerMap); + + Game::SpeakerMap* destSoundFile = buffer->dest(); + buffer->save(alias->speakerMap); + + if (alias->speakerMap->name) + { + buffer->saveString(alias->speakerMap->name); + Utils::Stream::ClearPointer(&destSoundFile->name); + } + + Utils::Stream::ClearPointer(&destAlias->speakerMap); + } + } + } + + Utils::Stream::ClearPointer(&dest->head); + } + } + + buffer->popBlock(); + } +} diff --git a/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp new file mode 100644 index 00000000..f1705511 --- /dev/null +++ b/src/Components/Modules/AssetInterfaces/Isnd_alias_list_t.hpp @@ -0,0 +1,11 @@ +namespace Assets +{ + class Isnd_alias_list_t : public Components::AssetHandler::IAsset + { + public: + virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_SOUND; }; + + virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + virtual void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; + }; +} diff --git a/src/Components/Modules/MusicalTalent.cpp b/src/Components/Modules/MusicalTalent.cpp index e06166bb..e240363a 100644 --- a/src/Components/Modules/MusicalTalent.cpp +++ b/src/Components/Modules/MusicalTalent.cpp @@ -19,9 +19,9 @@ namespace Components if (aliases) { - if (aliases->aliases->stream->type == 2) + if (aliases->head->soundFile->type == 2) { - aliases->aliases->stream->file = MusicalTalent::SoundAliasList[Utils::String::ToLower(filename)]; + aliases->head->soundFile->data.stream.name = MusicalTalent::SoundAliasList[Utils::String::ToLower(filename)]; } header.aliasList = aliases; diff --git a/src/Components/Modules/Zones.cpp b/src/Components/Modules/Zones.cpp index 1bc9a36a..9bfc5254 100644 --- a/src/Components/Modules/Zones.cpp +++ b/src/Components/Modules/Zones.cpp @@ -939,10 +939,11 @@ namespace Components for (int i = 0; i < count; ++i) { char* src = &buffer[i * 108]; + char* dest = reinterpret_cast(&tempSounds[i]); - std::memcpy(&tempSounds[i], src + 0, 60); - std::memcpy(&tempSounds[i].pad2[36], src + 68, 20); - std::memcpy(&tempSounds[i].pad2[56], src + 88, 20); + std::memcpy(dest + 0, src + 0, 60); + std::memcpy(dest + 60, src + 68, 20); + std::memcpy(dest + 80, src + 88, 20); AssetHandler::Relocate(src + 0, buffer + (i * 100) + 0, 60); AssetHandler::Relocate(src + 68, buffer + (i * 100) + 60, 20); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index b24ad71e..02bd96eb 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -150,27 +150,108 @@ namespace Game }; #pragma pack(pop) - typedef struct + struct SpeakerLevels { - char type; - char pad[3]; - const char* folder; - const char* file; - } StreamFile; + int speaker; + int numLevels; + float levels[2]; + }; - typedef struct + struct ChannelMap { - char pad[20]; - StreamFile* stream; - char pad2[76]; - } snd_alias_t; + int entryCount; // how many entries are used + SpeakerLevels speakers[6]; + }; - typedef struct + struct SpeakerMap { - const char* name; - snd_alias_t* aliases; - int numAliases; - } snd_alias_list_t; + bool isDefault; + const char *name; + ChannelMap channelMaps[2][2]; + }; + + enum snd_alias_type_t : char + { + SAT_UNKNOWN = 0x0, + SAT_LOADED = 0x1, + SAT_STREAMED = 0x2 + }; + + struct StreamedSound + { + const char *dir; + const char *name; + }; + + struct SndCurve + { + const char *filename; + unsigned __int16 knotCount; + vec2_t knots[16]; + }; + + struct MssSound + { + char unknown1[8]; + int size; + char unknown2[22]; + char *data; // size = soundSize + }; + + struct LoadedSound + { + const char *name; + MssSound mssSound; + }; + + union SoundData + { + LoadedSound* loaded; + StreamedSound stream; + }; + + struct SoundFile // 0xC + { + snd_alias_type_t type; + bool exists; + SoundData data; + }; + + struct snd_alias_t + { + const char *name; + const char *subtitle; + const char *secondaryAliasName; + const char *chainAliasName; + const char *string4; + SoundFile *soundFile; + int sequence; + float volMin; + float volMax; + float pitchMin; + float pitchMax; + float distMin; + float distMax; + int flags; + float slavePercentage; + float probability; + float lfePercentage; + float centerPercentage; + int startDelay; + int pad; + SndCurve *volumeFalloffCurve; + float envelopMin; + float envelopMax; + float envelopPercentage; + SpeakerMap *speakerMap; + }; + + struct snd_alias_list_t + { + const char *name; + snd_alias_t *head; + int count; + }; typedef struct { @@ -1215,27 +1296,6 @@ namespace Game char * compressedData; }; - struct SndCurve - { - const char *filename; - unsigned __int16 knotCount; - vec2_t knots[16]; - }; - - struct MssSound - { - char unknown1[8]; - int size; - char unknown2[22]; - char *data; // size = soundSize - }; - - struct LoadedSound - { - const char *name; - MssSound mssSound; - }; - struct FontEntry { unsigned short character;