Improve sound file loading
This commit is contained in:
parent
2617a9ed6e
commit
3a5d262691
@ -7,6 +7,7 @@
|
|||||||
#include "sound.hpp"
|
#include "sound.hpp"
|
||||||
#include "filesystem.hpp"
|
#include "filesystem.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
#include <utils/io.hpp>
|
#include <utils/io.hpp>
|
||||||
#include <utils/memory.hpp>
|
#include <utils/memory.hpp>
|
||||||
@ -22,8 +23,9 @@ namespace sound
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::memory::allocator sound_allocator;
|
utils::memory::allocator sound_allocator;
|
||||||
using loaded_sound_map = std::unordered_map<std::string, game::snd_alias_list_t*>;
|
using loaded_sound_map = std::unordered_map<size_t, game::snd_alias_list_t*>;
|
||||||
utils::concurrency::container<loaded_sound_map, std::recursive_mutex> loaded_sounds;
|
utils::concurrency::container<loaded_sound_map, std::recursive_mutex> loaded_sounds;
|
||||||
|
std::hash<std::string_view> hasher;
|
||||||
|
|
||||||
#define FATAL(...) \
|
#define FATAL(...) \
|
||||||
throw std::runtime_error(utils::string::va(__VA_ARGS__)); \
|
throw std::runtime_error(utils::string::va(__VA_ARGS__)); \
|
||||||
@ -496,25 +498,19 @@ namespace sound
|
|||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sound_exists(const std::string& name)
|
bool sound_exists(const char* name)
|
||||||
{
|
{
|
||||||
return loaded_sounds.access<bool>([&](loaded_sound_map& map)
|
return sound::find_sound(name).sound != nullptr;
|
||||||
{
|
|
||||||
const auto i = map.find(name);
|
|
||||||
if (i != map.end())
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return find_sound(name.data()).sound != nullptr;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::hook::detour db_is_xasset_default_hook;
|
utils::hook::detour db_is_xasset_default_hook;
|
||||||
bool db_is_xasset_default_stub(game::XAssetType type, const char* name)
|
int db_is_xasset_default_stub(game::XAssetType type, const char* name)
|
||||||
{
|
{
|
||||||
if (type == game::ASSET_TYPE_SOUND)
|
if (type != game::ASSET_TYPE_SOUND)
|
||||||
{
|
{
|
||||||
|
return db_is_xasset_default_hook.invoke<bool>(type, name);
|
||||||
|
}
|
||||||
|
|
||||||
const auto res = db_is_xasset_default_hook.invoke<bool>(type, name);
|
const auto res = db_is_xasset_default_hook.invoke<bool>(type, name);
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
@ -524,15 +520,10 @@ namespace sound
|
|||||||
return !sound_exists(name);
|
return !sound_exists(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return db_is_xasset_default_hook.invoke<bool>(type, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::detour db_xasset_exists_hook;
|
utils::hook::detour db_xasset_exists_hook;
|
||||||
bool db_xasset_exists_stub(game::XAssetType type, const char* name)
|
int db_xasset_exists_stub(game::XAssetType type, const char* name)
|
||||||
{
|
{
|
||||||
if (type == game::ASSET_TYPE_SOUND)
|
const auto res = utils::hook::invoke<bool>(0x140417FD0, type, name);
|
||||||
{
|
|
||||||
const auto res = db_xasset_exists_hook.invoke<bool>(type, name);
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -541,9 +532,6 @@ namespace sound
|
|||||||
return sound_exists(name);
|
return sound_exists(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return db_xasset_exists_hook.invoke<bool>(type, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
utils::hook::detour scr_table_lookup_hook;
|
utils::hook::detour scr_table_lookup_hook;
|
||||||
void scr_table_lookup_stub()
|
void scr_table_lookup_stub()
|
||||||
{
|
{
|
||||||
@ -560,7 +548,7 @@ namespace sound
|
|||||||
std::optional<int> new_value{};
|
std::optional<int> new_value{};
|
||||||
loaded_sounds.access([&](loaded_sound_map& map)
|
loaded_sounds.access([&](loaded_sound_map& map)
|
||||||
{
|
{
|
||||||
const auto i = map.find(search_value);
|
const auto i = map.find(hasher(search_value));
|
||||||
if (i == map.end())
|
if (i == map.end())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -609,6 +597,56 @@ namespace sound
|
|||||||
|
|
||||||
return snd_is_music_playing_hook.invoke<bool>(a1);
|
return snd_is_music_playing_hook.invoke<bool>(a1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void load_sound(const std::string& name, const std::string& path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const auto data = utils::io::read_file(path);
|
||||||
|
|
||||||
|
rapidjson::Document j;
|
||||||
|
j.Parse(data.data());
|
||||||
|
|
||||||
|
console::info("[Sound] Loading sound %s\n", name.data());
|
||||||
|
const auto sound = parse_sound_alias_list(j);
|
||||||
|
|
||||||
|
const auto h = hasher(name.data());
|
||||||
|
loaded_sounds.access([&](loaded_sound_map& map)
|
||||||
|
{
|
||||||
|
map[h] = sound;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
console::error("[Sound] Error loading sound %s: %s\n", name.data(), e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void load_sounds()
|
||||||
|
{
|
||||||
|
const auto paths = filesystem::get_search_paths();
|
||||||
|
for (const auto& path : paths)
|
||||||
|
{
|
||||||
|
const auto dir = path + "/sounds";
|
||||||
|
if (!utils::io::directory_exists(dir))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto sound_files = utils::io::list_files(dir);
|
||||||
|
for (const auto& file : sound_files)
|
||||||
|
{
|
||||||
|
const auto last = file.find_last_of("\\/");
|
||||||
|
std::string name = file;
|
||||||
|
if (last != std::string::npos)
|
||||||
|
{
|
||||||
|
name = file.substr(last + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
load_sound(name, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_sound(game::snd_alias_list_t* asset)
|
void dump_sound(game::snd_alias_list_t* asset)
|
||||||
@ -874,52 +912,17 @@ namespace sound
|
|||||||
|
|
||||||
game::XAssetHeader find_sound(const char* name)
|
game::XAssetHeader find_sound(const char* name)
|
||||||
{
|
{
|
||||||
bool found = false;
|
const auto hash = hasher(name);
|
||||||
const auto res = loaded_sounds.access<game::XAssetHeader>([&](loaded_sound_map& map)
|
return loaded_sounds.access<game::XAssetHeader>([&](loaded_sound_map& map)
|
||||||
{
|
{
|
||||||
const auto i = map.find(name);
|
const auto i = map.find(hash);
|
||||||
if (i != map.end())
|
if (i != map.end())
|
||||||
{
|
{
|
||||||
found = true;
|
|
||||||
return static_cast<game::XAssetHeader>(i->second);
|
return static_cast<game::XAssetHeader>(i->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<game::XAssetHeader>(nullptr);
|
return static_cast<game::XAssetHeader>(nullptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string path{};
|
|
||||||
if (!filesystem::find_file("sounds/"s + name, &path))//
|
|
||||||
{
|
|
||||||
return static_cast<game::XAssetHeader>(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto data = utils::io::read_file(path);
|
|
||||||
|
|
||||||
rapidjson::Document j;
|
|
||||||
j.Parse(data.data());
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
console::info("[Sound] Loading sound %s\n", name);
|
|
||||||
const auto sound = parse_sound_alias_list(j);
|
|
||||||
|
|
||||||
loaded_sounds.access([&](loaded_sound_map& map)
|
|
||||||
{
|
|
||||||
map[name] = sound;
|
|
||||||
});
|
|
||||||
|
|
||||||
return static_cast<game::XAssetHeader>(sound);
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
console::error("[Sound] Error loading sound %s: %s\n", name, e.what());
|
|
||||||
return static_cast<game::XAssetHeader>(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
@ -929,6 +932,8 @@ namespace sound
|
|||||||
{
|
{
|
||||||
map.clear();
|
map.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
load_sounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -937,7 +942,7 @@ namespace sound
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
db_is_xasset_default_hook.create(0x1404143C0, db_is_xasset_default_stub);
|
db_is_xasset_default_hook.create(0x1404143C0, db_is_xasset_default_stub);
|
||||||
db_xasset_exists_hook.create(0x140417FD0, db_xasset_exists_stub);
|
utils::hook::call(0x140616DD1, db_xasset_exists_stub);
|
||||||
scr_table_lookup_hook.create(0x1404EFD40, scr_table_lookup_stub);
|
scr_table_lookup_hook.create(0x1404EFD40, scr_table_lookup_stub);
|
||||||
|
|
||||||
// remove raw/sound or raw/language/sound prefix when loading raw sounds
|
// remove raw/sound or raw/language/sound prefix when loading raw sounds
|
||||||
@ -946,6 +951,8 @@ namespace sound
|
|||||||
|
|
||||||
// fix playing non-existing music crashing
|
// fix playing non-existing music crashing
|
||||||
snd_is_music_playing_hook.create(0x1407C58A0, snd_is_music_playing_stub);
|
snd_is_music_playing_hook.create(0x1407C58A0, snd_is_music_playing_stub);
|
||||||
|
|
||||||
|
scheduler::once(clear, scheduler::pipeline::main);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ namespace game
|
|||||||
WEAK symbol<DB_FileSysInterface*()> DB_FSInitialize{0x140272EC0};
|
WEAK symbol<DB_FileSysInterface*()> DB_FSInitialize{0x140272EC0};
|
||||||
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x140413D80};
|
WEAK symbol<int(const RawFile* rawfile)> DB_GetRawFileLen{0x140413D80};
|
||||||
WEAK symbol<int(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x140413C40};
|
WEAK symbol<int(const RawFile* rawfile, char* buf, int size)> DB_GetRawBuffer{0x140413C40};
|
||||||
|
WEAK symbol<XAssetEntry*(XAssetType type, XAssetHeader* header)> DB_LinkXAssetEntry1{0x140414900};
|
||||||
|
|
||||||
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x140618F90};
|
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x140618F90};
|
||||||
WEAK symbol<dvar_t*(int hash)> Dvar_FindMalleableVar{0x140618F00};
|
WEAK symbol<dvar_t*(int hash)> Dvar_FindMalleableVar{0x140618F00};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user