From 0adbb7b60f5134a27558404c6c0ffacd42cb38c2 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 14:19:22 +0300
Subject: audio override
---
.../NorthstarDedicatedTest.vcxproj | 11 +
.../NorthstarDedicatedTest.vcxproj.filters | 11 +
NorthstarDedicatedTest/audio.cpp | 433 +++++++++++++++++++++
NorthstarDedicatedTest/audio.h | 47 +++
NorthstarDedicatedTest/audio_asm.asm | 8 +
NorthstarDedicatedTest/dllmain.cpp | 4 +
NorthstarDedicatedTest/modmanager.cpp | 19 +
7 files changed, 533 insertions(+)
create mode 100644 NorthstarDedicatedTest/audio.cpp
create mode 100644 NorthstarDedicatedTest/audio.h
create mode 100644 NorthstarDedicatedTest/audio_asm.asm
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 299cf2ec..2b1cfb2d 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -34,6 +34,7 @@
+
@@ -60,6 +61,8 @@
pch.h
stdcpp17
$(ProjectDir)include;%(AdditionalIncludeDirectories)
+
+
Windows
@@ -88,6 +91,8 @@
stdcpp17
$(ProjectDir)include;%(AdditionalIncludeDirectories)
MultiThreadedDLL
+
+
Windows
@@ -106,6 +111,7 @@
+
@@ -545,6 +551,7 @@
+
@@ -619,7 +626,11 @@
+
+
+
+
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index aaa99a14..41072c60 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1434,6 +1434,9 @@
Header Files\Client
+
+ Header Files\Client
+
@@ -1556,6 +1559,9 @@
Source Files\Client
+
+ Source Files\Client
+
@@ -1643,4 +1649,9 @@
Header Files\include\openssl\crypto
+
+
+ Source Files\Client
+
+
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
new file mode 100644
index 00000000..6559a12c
--- /dev/null
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -0,0 +1,433 @@
+#include "pch.h"
+#include "audio.h"
+#include "dedicated.h"
+
+#include "rapidjson/error/en.h"
+#include
+#include
+#include
+#include
+#include "convar.h"
+
+extern "C" {
+ // should be called only in LoadSampleMetadata_Hook
+ extern void* __fastcall Audio_GetParentEvent();
+}
+
+ConVar* Cvar_ns_print_played_sounds;
+
+CustomAudioManager g_CustomAudioManager;
+
+EventOverrideData::EventOverrideData()
+{
+ spdlog::warn("Initialised struct EventOverrideData without any data!");
+ LoadedSuccessfully = false;
+}
+
+EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path)
+{
+ if (data.length() <= 0)
+ {
+ spdlog::error("Failed reading audio override file {}: file is empty", path.string());
+ return;
+ }
+
+ fs::path samplesFolder = path;
+ samplesFolder = samplesFolder.replace_extension();
+
+ if (!fs::exists(samplesFolder))
+ {
+ spdlog::error("Failed reading audio override file {}: samples folder doesn't exist; should be named the same as the definition file without JSON extension.", path.string());
+ return;
+ }
+
+ rapidjson_document dataJson;
+ dataJson.Parse(data);
+
+ // fail if parse error
+ if (dataJson.HasParseError())
+ {
+ spdlog::error("Failed reading audio override file {}: encountered parse error \"{}\" at offset {}", path.string(), GetParseError_En(dataJson.GetParseError()), dataJson.GetErrorOffset());
+ return;
+ }
+
+ // fail if it's not a json obj (could be an array, string, etc)
+ if (!dataJson.IsObject())
+ {
+ spdlog::error("Failed reading audio override file {}: file is not a JSON object", path.string());
+ return;
+ }
+
+ // fail if no event ids given
+ if (!dataJson.HasMember("EventId"))
+ {
+ spdlog::error("Failed reading audio override file {}: JSON object does not have the EventId property", path.string());
+ return;
+ }
+
+ // array of event ids
+ if (dataJson["EventId"].IsArray())
+ {
+ for (auto& eventId : dataJson["EventId"].GetArray())
+ {
+ if (!eventId.IsString())
+ {
+ spdlog::error("Failed reading audio override file {}: EventId array has a value of invalid type, all must be strings", path.string());
+ return;
+ }
+
+ EventIds.push_back(eventId.GetString());
+ }
+ }
+ // singular event id
+ else if (dataJson["EventId"].IsString())
+ {
+ EventIds.push_back(dataJson["EventId"].GetString());
+ }
+ // incorrect type
+ else
+ {
+ spdlog::error("Failed reading audio override file {}: EventId property is of invalid type (must be a string or an array of strings)", path.string());
+ return;
+ }
+
+ if (dataJson.HasMember("EventIdRegex"))
+ {
+ // array of event id regex
+ if (dataJson["EventIdRegex"].IsArray())
+ {
+ for (auto& eventId : dataJson["EventIdRegex"].GetArray())
+ {
+ if (!eventId.IsString())
+ {
+ spdlog::error("Failed reading audio override file {}: EventIdRegex array has a value of invalid type, all must be strings", path.string());
+ return;
+ }
+
+ const std::string& regex = eventId.GetString();
+
+ try {
+ EventIdsRegex.push_back({ regex, std::regex(regex) });
+ } catch (...) {
+ spdlog::error("Malformed regex \"{}\" in audio override file {}", regex, path.string());
+ return;
+ }
+ }
+ }
+ // singular event id regex
+ else if (dataJson["EventIdRegex"].IsString())
+ {
+ const std::string& regex = dataJson["EventIdRegex"].GetString();
+ try {
+ EventIdsRegex.push_back({ regex, std::regex(regex) });
+ }
+ catch (...) {
+ spdlog::error("Malformed regex \"{}\" in audio override file {}", regex, path.string());
+ return;
+ }
+ }
+ // incorrect type
+ else
+ {
+ spdlog::error("Failed reading audio override file {}: EventIdRegex property is of invalid type (must be a string or an array of strings)", path.string());
+ return;
+ }
+ }
+
+ if (dataJson.HasMember("AudioSelectionStrategy"))
+ {
+ if (!dataJson["AudioSelectionStrategy"].IsString())
+ {
+ spdlog::error("Failed reading audio override file {}: AudioSelectionStrategy property must be a string", path.string());
+ return;
+ }
+
+ std::string strategy = dataJson["AudioSelectionStrategy"].GetString();
+
+ if (strategy == "sequential")
+ {
+ Strategy = AudioSelectionStrategy::SEQUENTIAL;
+ }
+ else if (strategy == "random")
+ {
+ Strategy = AudioSelectionStrategy::RANDOM;
+ }
+ else
+ {
+ spdlog::error("Failed reading audio override file {}: AudioSelectionStrategy string must be either \"sequential\" or \"random\"", path.string());
+ return;
+ }
+ }
+
+ // load samples
+ for (fs::directory_entry file : fs::recursive_directory_iterator(samplesFolder))
+ {
+ if (file.is_regular_file() && file.path().extension().string() == ".wav")
+ {
+ // Open the file.
+ std::basic_ifstream wavStream(file, std::ios::binary);
+
+ if (wavStream.fail())
+ {
+ spdlog::error("Failed reading audio sample {}", file.path().string());
+ continue;
+ }
+
+ // Read file into a vector and add it to the samples list.
+ Samples.push_back(std::vector((std::istreambuf_iterator(wavStream)), std::istreambuf_iterator()));
+
+ // Close the file.
+ wavStream.close();
+ }
+ }
+
+ /*
+ if (dataJson.HasMember("EnableOnLoopedSounds"))
+ {
+ if (!dataJson["EnableOnLoopedSounds"].IsBool())
+ {
+ spdlog::error("Failed reading audio override file {}: EnableOnLoopedSounds property is of invalid type (must be a bool)", path.string());
+ return;
+ }
+
+ EnableOnLoopedSounds = dataJson["EnableOnLoopedSounds"].GetBool();
+ }
+ */
+
+ if (Samples.size() == 0)
+ spdlog::warn("Audio override {} has no valid samples! Sounds will not play for this event.", path.string());
+
+ spdlog::info("Loaded audio override file {}", path.string());
+
+ LoadedSuccessfully = true;
+}
+
+bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
+{
+ std::ifstream jsonStream(defPath);
+ std::stringstream jsonStringStream;
+
+ // fail if no audio json
+ if (jsonStream.fail())
+ {
+ spdlog::warn("Unable to read audio override from file {}", defPath.string());
+ return false;
+ }
+
+ while (jsonStream.peek() != EOF)
+ jsonStringStream << (char)jsonStream.get();
+
+ jsonStream.close();
+
+ std::shared_ptr data = std::make_shared(jsonStringStream.str(), defPath);
+
+ if (!data->LoadedSuccessfully)
+ return false; // no logging, the constructor has probably already logged
+
+ for (const std::string& eventId : data->EventIds)
+ {
+ spdlog::info("Registering sound event {}", eventId);
+ m_loadedAudioOverrides.insert({ eventId, data });
+ }
+
+ for (const auto& eventIdRegexData : data->EventIdsRegex)
+ {
+ spdlog::info("Registering sound event regex {}", eventIdRegexData.first);
+ m_loadedAudioOverridesRegex.insert({ eventIdRegexData.first, data });
+ }
+
+ return true;
+}
+
+void CustomAudioManager::ClearAudioOverrides()
+{
+ m_loadedAudioOverrides.clear();
+ m_loadedAudioOverridesRegex.clear();
+}
+
+typedef bool (*LoadSampleMetadata_Type)(void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType);
+LoadSampleMetadata_Type LoadSampleMetadata_Original;
+
+// Empty stereo 48000 WAVE file
+unsigned char EMPTY_WAVE[45] = {
+ 0x52, 0x49, 0x46, 0x46, 0x25, 0x00, 0x00, 0x00, 0x57, 0x41, 0x56, 0x45,
+ 0x66, 0x6D, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+ 0x44, 0xAC, 0x00, 0x00, 0x88, 0x58, 0x01, 0x00, 0x02, 0x00, 0x10, 0x00,
+ 0x64, 0x61, 0x74, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00
+};
+
+template
+Iter select_randomly(Iter start, Iter end, RandomGenerator& g) {
+ std::uniform_int_distribution<> dis(0, std::distance(start, end) - 1);
+ std::advance(start, dis(g));
+ return start;
+}
+
+template
+Iter select_randomly(Iter start, Iter end) {
+ static std::random_device rd;
+ static std::mt19937 gen(rd());
+ return select_randomly(start, end, gen);
+}
+
+bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr& data)
+{
+ std::string eventNameString = eventName;
+ std::string eventNameStringBlacklistEntry = ("!" + eventNameString);
+
+ for (const std::string& name : data->EventIds)
+ {
+ if (name == eventNameStringBlacklistEntry)
+ return false; // event blacklisted
+
+ if (name == "*")
+ {
+ // check for bad sounds I guess?
+ // really feel like this should be an option but whatever
+ if (!!strstr(eventName, "_amb_") || !!strstr(eventName, "_emit_"))
+ return false; // would play static noise, I hate this
+ }
+ }
+
+ return true; // good to go
+}
+
+// DO NOT IMLINE THIS FUNCTION
+// See comment below.
+bool __declspec(noinline) __fastcall LoadSampleMetadata_Internal(uintptr_t parentEvent, void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType)
+{
+ char* eventName = (char*)parentEvent + 0x110;
+
+ if (Cvar_ns_print_played_sounds->m_nValue > 0)
+ spdlog::info("[AUDIO] Playing event {}", eventName);
+
+ auto iter = g_CustomAudioManager.m_loadedAudioOverrides.find(eventName);
+ std::shared_ptr overrideData;
+
+ if (iter == g_CustomAudioManager.m_loadedAudioOverrides.end())
+ {
+ // override for that specific event not found, try wildcard
+ iter = g_CustomAudioManager.m_loadedAudioOverrides.find("*");
+
+ if (iter == g_CustomAudioManager.m_loadedAudioOverrides.end())
+ {
+ // not found
+
+ // try regex
+ for (const auto& item : g_CustomAudioManager.m_loadedAudioOverridesRegex)
+ for (const auto& regexData : item.second->EventIdsRegex)
+ if (std::regex_search(eventName, regexData.second))
+ overrideData = item.second;
+
+ if (!overrideData)
+ // not found either
+ return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+ else
+ {
+ // cache found pattern to improve performance
+ g_CustomAudioManager.m_loadedAudioOverrides[eventName] = overrideData;
+ }
+ }
+ else overrideData = iter->second;
+ }
+ else overrideData = iter->second;
+
+ if (!ShouldPlayAudioEvent(eventName, overrideData))
+ return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+
+ void* data = 0;
+ unsigned int dataLength = 0;
+
+ if (overrideData->Samples.size() == 0)
+ {
+ // 0 samples, turn off this particular event.
+
+ // using a dummy empty wave file
+ data = EMPTY_WAVE;
+ dataLength = sizeof(EMPTY_WAVE);
+ }
+ else
+ {
+ std::vector* vec = NULL;
+
+ switch (overrideData->Strategy)
+ {
+ case AudioSelectionStrategy::RANDOM:
+ vec = &*select_randomly(overrideData->Samples.begin(), overrideData->Samples.end());
+ break;
+ case AudioSelectionStrategy::SEQUENTIAL:
+ default:
+ vec = &overrideData->Samples[overrideData->CurrentIndex++];
+ if (overrideData->CurrentIndex >= overrideData->Samples.size())
+ overrideData->CurrentIndex = 0; // reset back to the first sample entry
+ break;
+ }
+
+ if (!vec)
+ spdlog::warn("Could not get sample data from override struct for event {}! Shouldn't happen", eventName);
+ else
+ {
+ data = vec->data();
+ dataLength = vec->size();
+ }
+ }
+
+ if (!data)
+ {
+ spdlog::warn("Could not fetch override sample data for event {}! Using original data instead.", eventName);
+ return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+ }
+
+ audioBuffer = data;
+ audioBufferLength = dataLength;
+
+ // most important change: set the sample class buffer so that the correct audio plays
+ *(void**)((uintptr_t)sample + 0xE8) = audioBuffer;
+ *(unsigned int*)((uintptr_t)sample + 0xF0) = audioBufferLength;
+
+ // 64 - Auto-detect sample type
+ bool res = LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, 64);
+ if (!res)
+ spdlog::error("LoadSampleMetadata failed! The game will crash :(");
+
+ return res;
+}
+
+// DO NOT TOUCH THIS FUNCTION
+// The actual logic of it in a separate function (forcefully not inlined) to preserve the r12 register, which holds the event pointer.
+bool __fastcall LoadSampleMetadata_Hook(void* sample, void* audioBuffer, unsigned int audioBufferLength, int audioType)
+{
+ uintptr_t parentEvent = (uintptr_t)Audio_GetParentEvent();
+
+ // Raw source, used for voice data only
+ if (audioType == 0)
+ return LoadSampleMetadata_Original(sample, audioBuffer, audioBufferLength, audioType);
+
+ return LoadSampleMetadata_Internal(parentEvent, sample, audioBuffer, audioBufferLength, audioType);
+}
+
+typedef bool (*MilesLog_Type)(int level, const char* string);
+MilesLog_Type MilesLog_Original;
+
+void __fastcall MilesLog_Hook(int level, const char* string)
+{
+ spdlog::info("[MSS] {} - {}", level, string);
+}
+
+void InitialiseMilesAudioHooks(HMODULE baseAddress)
+{
+ Cvar_ns_print_played_sounds = RegisterConVar("ns_print_played_sounds", "0", FCVAR_NONE, "");
+
+ if (IsDedicated())
+ return;
+
+ uintptr_t milesAudioBase = (uintptr_t)GetModuleHandleA("mileswin64.dll");
+
+ if (!milesAudioBase)
+ return spdlog::error("miles audio not found :terror:");
+
+ HookEnabler hook;
+
+ ENABLER_CREATEHOOK(hook, (char*)milesAudioBase + 0xF110, &LoadSampleMetadata_Hook, reinterpret_cast(&LoadSampleMetadata_Original));
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x57DAD0, &MilesLog_Hook, reinterpret_cast(&MilesLog_Original));
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/audio.h b/NorthstarDedicatedTest/audio.h
new file mode 100644
index 00000000..67fe342f
--- /dev/null
+++ b/NorthstarDedicatedTest/audio.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include
+#include
+#include
+
+namespace fs = std::filesystem;
+
+enum class AudioSelectionStrategy
+{
+ INVALID = -1,
+ SEQUENTIAL,
+ RANDOM
+};
+
+class EventOverrideData
+{
+public:
+ EventOverrideData(const std::string&, const fs::path&);
+ EventOverrideData();
+public:
+ bool LoadedSuccessfully = false;
+
+ std::vector EventIds = {};
+ std::vector> EventIdsRegex = {};
+
+ std::vector> Samples = {};
+
+ AudioSelectionStrategy Strategy = AudioSelectionStrategy::SEQUENTIAL;
+ size_t CurrentIndex = 0;
+
+ bool EnableOnLoopedSounds = false;
+};
+
+class CustomAudioManager
+{
+public:
+ bool TryLoadAudioOverride(const fs::path&);
+ void ClearAudioOverrides();
+
+ std::unordered_map> m_loadedAudioOverrides = {};
+ std::unordered_map> m_loadedAudioOverridesRegex = {};
+};
+
+extern CustomAudioManager g_CustomAudioManager;
+
+void InitialiseMilesAudioHooks(HMODULE baseAddress);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/audio_asm.asm b/NorthstarDedicatedTest/audio_asm.asm
new file mode 100644
index 00000000..4c527f9d
--- /dev/null
+++ b/NorthstarDedicatedTest/audio_asm.asm
@@ -0,0 +1,8 @@
+public Audio_GetParentEvent
+
+.code
+Audio_GetParentEvent proc
+ mov rax, r12
+ ret
+Audio_GetParentEvent endp
+end
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 83e78f4e..fd82e382 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -30,6 +30,7 @@
#include "memalloc.h"
#include "maxplayers.h"
#include "languagehooks.h"
+#include "audio.h"
bool initialised = false;
@@ -134,6 +135,9 @@ bool InitialiseNorthstar()
AddDllLoadCallback("client.dll", InitialiseMaxPlayersOverride_Client);
AddDllLoadCallback("server.dll", InitialiseMaxPlayersOverride_Server);
+ // audio hooks
+ AddDllLoadCallback("client.dll", InitialiseMilesAudioHooks);
+
// mod manager after everything else
AddDllLoadCallback("engine.dll", InitialiseModManager);
diff --git a/NorthstarDedicatedTest/modmanager.cpp b/NorthstarDedicatedTest/modmanager.cpp
index 23dd2d6e..34bba6af 100644
--- a/NorthstarDedicatedTest/modmanager.cpp
+++ b/NorthstarDedicatedTest/modmanager.cpp
@@ -2,6 +2,7 @@
#include "modmanager.h"
#include "convar.h"
#include "concommand.h"
+#include "audio.h"
#include "rapidjson/error/en.h"
#include "rapidjson/document.h"
@@ -330,6 +331,22 @@ void ModManager::LoadMods()
mod.Pdiff = pdiffStringStream.str();
}
}
+
+ // try to load audio
+ if (fs::exists(mod.ModDirectory / "audio"))
+ {
+ for (fs::directory_entry file : fs::directory_iterator(mod.ModDirectory / "audio"))
+ {
+ if (fs::is_regular_file(file) && file.path().extension().string() == ".json")
+ {
+ if (!g_CustomAudioManager.TryLoadAudioOverride(file.path()))
+ {
+ spdlog::warn("Mod {} has an invalid audio def {}", mod.Name, file.path().filename().string());
+ continue;
+ }
+ }
+ }
+ }
}
// in a seperate loop because we register mod files in reverse order, since mods loaded later should have their files prioritised
@@ -364,6 +381,8 @@ void ModManager::UnloadMods()
m_modFiles.clear();
fs::remove_all(COMPILED_ASSETS_PATH);
+ g_CustomAudioManager.ClearAudioOverrides();
+
if (!m_hasEnabledModsCfg)
m_enabledModsCfg.SetObject();
--
cgit v1.2.3
From c21124cffa63b4bb86a66de51499a2b9da77332e Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 16:56:03 +0300
Subject: fix typo and improve performance
---
NorthstarDedicatedTest/audio.cpp | 28 +++++++++++++++++++---------
NorthstarDedicatedTest/audio.h | 2 +-
2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
index 6559a12c..5aa7354f 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -173,8 +173,18 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
continue;
}
- // Read file into a vector and add it to the samples list.
- Samples.push_back(std::vector((std::istreambuf_iterator(wavStream)), std::istreambuf_iterator()));
+ // Get file size.
+ wavStream.seekg(0, std::ios::end);
+ size_t fileSize = wavStream.tellg();
+ wavStream.seekg(0, std::ios::beg);
+
+ // Allocate enough memory for the file.
+ uint8_t* data = new uint8_t[fileSize];
+
+ // Read the file.
+ wavStream.read(data, fileSize);
+
+ Samples.push_back({ fileSize, std::unique_ptr(data) });
// Close the file.
wavStream.close();
@@ -292,7 +302,7 @@ bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr* vec = NULL;
+ std::pair>* dat = NULL;
switch (overrideData->Strategy)
{
case AudioSelectionStrategy::RANDOM:
- vec = &*select_randomly(overrideData->Samples.begin(), overrideData->Samples.end());
+ dat = &*select_randomly(overrideData->Samples.begin(), overrideData->Samples.end());
break;
case AudioSelectionStrategy::SEQUENTIAL:
default:
- vec = &overrideData->Samples[overrideData->CurrentIndex++];
+ dat = &overrideData->Samples[overrideData->CurrentIndex++];
if (overrideData->CurrentIndex >= overrideData->Samples.size())
overrideData->CurrentIndex = 0; // reset back to the first sample entry
break;
}
- if (!vec)
+ if (!dat)
spdlog::warn("Could not get sample data from override struct for event {}! Shouldn't happen", eventName);
else
{
- data = vec->data();
- dataLength = vec->size();
+ data = dat->second.get();
+ dataLength = dat->first;
}
}
diff --git a/NorthstarDedicatedTest/audio.h b/NorthstarDedicatedTest/audio.h
index 67fe342f..d53f5317 100644
--- a/NorthstarDedicatedTest/audio.h
+++ b/NorthstarDedicatedTest/audio.h
@@ -24,7 +24,7 @@ public:
std::vector EventIds = {};
std::vector> EventIdsRegex = {};
- std::vector> Samples = {};
+ std::vector>> Samples = {};
AudioSelectionStrategy Strategy = AudioSelectionStrategy::SEQUENTIAL;
size_t CurrentIndex = 0;
--
cgit v1.2.3
From 550a5daa072fe1c1a963f3ee0a6b7578a770338a Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 20:15:36 +0300
Subject: fix crash when reloading mods when an override is played
---
.../NorthstarDedicatedTest.vcxproj | 6 ++++--
NorthstarDedicatedTest/audio.cpp | 21 +++++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index 2b1cfb2d..abd50fc8 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -22,13 +22,13 @@
DynamicLibrary
true
- v143
+ v142
Unicode
DynamicLibrary
false
- v143
+ v142
true
Unicode
@@ -63,6 +63,7 @@
$(ProjectDir)include;%(AdditionalIncludeDirectories)
+ Async
Windows
@@ -93,6 +94,7 @@
MultiThreadedDLL
+ Async
Windows
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
index 5aa7354f..d56762e0 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -214,6 +214,9 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
{
+ if (IsDedicated())
+ return true; // silently fail
+
std::ifstream jsonStream(defPath);
std::stringstream jsonStringStream;
@@ -249,8 +252,24 @@ bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
return true;
}
+typedef void (*MilesStopAll_Type)();
+MilesStopAll_Type MilesStopAll;
+
void CustomAudioManager::ClearAudioOverrides()
{
+ if (IsDedicated())
+ return;
+
+ if (m_loadedAudioOverrides.size() > 0 || m_loadedAudioOverridesRegex.size() > 0)
+ {
+ // stop all miles sounds beforehand
+ // miles_stop_all
+ MilesStopAll();
+
+ // this is cancer but it works
+ Sleep(50);
+ }
+
m_loadedAudioOverrides.clear();
m_loadedAudioOverridesRegex.clear();
}
@@ -440,4 +459,6 @@ void InitialiseMilesAudioHooks(HMODULE baseAddress)
ENABLER_CREATEHOOK(hook, (char*)milesAudioBase + 0xF110, &LoadSampleMetadata_Hook, reinterpret_cast(&LoadSampleMetadata_Original));
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x57DAD0, &MilesLog_Hook, reinterpret_cast(&MilesLog_Original));
+
+ MilesStopAll = (MilesStopAll_Type)((char*)baseAddress + 0x580850);
}
\ No newline at end of file
--
cgit v1.2.3
From b9b8fb4cde19b3bdcf6f327b82cc7797af85a8c9 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 20:17:30 +0300
Subject: revert vcxproj
---
NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index abd50fc8..c6f0c8c0 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -22,13 +22,13 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
@@ -63,7 +63,8 @@
$(ProjectDir)include;%(AdditionalIncludeDirectories)
- Async
+
+
Windows
@@ -94,7 +95,8 @@
MultiThreadedDLL
- Async
+
+
Windows
--
cgit v1.2.3
From 1e65bc16915a6dc72b7d63db20742bca6f7faf22 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 20:30:26 +0300
Subject: fix build error on v143
---
NorthstarDedicatedTest/audio.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
index d56762e0..51b74af6 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -165,7 +165,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
if (file.is_regular_file() && file.path().extension().string() == ".wav")
{
// Open the file.
- std::basic_ifstream wavStream(file, std::ios::binary);
+ std::basic_ifstream wavStream(file.path().string(), std::ios::binary);
if (wavStream.fail())
{
--
cgit v1.2.3
From 3094160973554ee0a83ab819576a45c088d3a527 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 4 Jan 2022 21:03:49 +0300
Subject: add a missing bad sound check
---
NorthstarDedicatedTest/audio.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
index 51b74af6..a0f9d047 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -313,7 +313,7 @@ bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr
Date: Tue, 4 Jan 2022 21:05:32 +0300
Subject: fix the beforementioned sound check
---
NorthstarDedicatedTest/audio.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/audio.cpp b/NorthstarDedicatedTest/audio.cpp
index a0f9d047..f5767386 100644
--- a/NorthstarDedicatedTest/audio.cpp
+++ b/NorthstarDedicatedTest/audio.cpp
@@ -313,7 +313,7 @@ bool ShouldPlayAudioEvent(const char* eventName, const std::shared_ptr