diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ee9c7de0c3..c9058ecd52a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,8 +54,6 @@ endif() # Find/Add build dependencies and stubs shared by all projects if((WIN32 OR "${CMAKE_SYSTEM}" MATCHES "Windows") AND ${CMAKE_SIZEOF_VOID_P} EQUAL 4) - include(cmake/miles.cmake) - include(cmake/bink.cmake) include(cmake/dx8.cmake) endif() @@ -84,6 +82,9 @@ if (IS_VS6_BUILD) add_compile_options(/FIUtility/CppMacros.h) endif() +add_subdirectory(Dependencies/Bink) +add_subdirectory(Dependencies/Miles) + add_subdirectory(resources) add_subdirectory(Core) diff --git a/Core/GameEngineDevice/CMakeLists.txt b/Core/GameEngineDevice/CMakeLists.txt index 876148f42d0..99fe2f8c574 100644 --- a/Core/GameEngineDevice/CMakeLists.txt +++ b/Core/GameEngineDevice/CMakeLists.txt @@ -227,10 +227,10 @@ target_link_libraries(corei_gameenginedevice_private INTERFACE ) target_link_libraries(corei_gameenginedevice_public INTERFACE - binkstub + binkloader corei_gameengine_public d3d8lib - milesstub + milesloader ) if(RTS_BUILD_OPTION_FFMPEG) diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index 24545683013..3c7a1f3a853 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -328,6 +328,9 @@ class MilesAudioManager : public AudioManager UnsignedInt m_num3DSamples; UnsignedInt m_numStreams; + Bool m_deviceOpened; + Bool m_milesLoaded; + #if defined(RTS_DEBUG) typedef std::set SetAsciiString; typedef SetAsciiString::iterator SetAsciiStringIt; diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 13a901680c0..00de0110b82 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -67,6 +67,7 @@ #include "Common/file.h" #include +#include "MilesLoader.h" enum { INFINITE_LOOP_COUNT = 1000000 }; @@ -91,6 +92,8 @@ MilesAudioManager::MilesAudioManager() : m_num2DSamples(0), m_num3DSamples(0), m_numStreams(0), + m_deviceOpened(false), + m_milesLoaded(false), m_delayFilter(nullptr), m_binkHandle(nullptr), m_pref3DProvider(AsciiString::TheEmptyString), @@ -1369,6 +1372,18 @@ void MilesAudioManager::openDevice() return; } + m_deviceOpened = true; + + // Load the Miles Sound System on runtime here instead of importing it into the executable. + if (!MilesLoader::load()) + { + DEBUG_LOG(("Failed to load mss32.dll (error %d). Audio will be turned off.", MilesLoader::getLastError())); + setOn(false, AudioAffect_All); + return; + } + + m_milesLoaded = true; + AIL_set_redist_directory("MSS\\"); AIL_startup(); Int retval = 0; @@ -1404,9 +1419,18 @@ void MilesAudioManager::openDevice() //------------------------------------------------------------------------------------------------- void MilesAudioManager::closeDevice() { - freeAllMilesHandles(); - unselectProvider(); - AIL_shutdown(); + if (m_deviceOpened) + { + if (m_milesLoaded) + { + freeAllMilesHandles(); + unselectProvider(); + AIL_shutdown(); + m_milesLoaded = false; + } + MilesLoader::unload(); + m_deviceOpened = false; + } } //------------------------------------------------------------------------------------------------- @@ -2760,7 +2784,7 @@ void MilesAudioManager::initSamplePools() DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 2D samples", i + 1)); if (sample) { AIL_init_sample(sample); - AIL_set_sample_user_data(sample, 0, (void *)(i + 1)); + AIL_set_sample_user_data(sample, 0, i + 1); m_availableSamples.push_back(sample); ++m_num2DSamples; } @@ -2770,7 +2794,7 @@ void MilesAudioManager::initSamplePools() H3DSAMPLE sample = AIL_allocate_3D_sample_handle(m_provider3D[m_selectedProvider].id); DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 3D samples", i + 1)); if (sample) { - AIL_set_3D_user_data(sample, 0, (void *)(i + 1)); + AIL_set_3D_user_data(sample, 0, i + 1); m_available3DSamples.push_back(sample); ++m_num3DSamples; } diff --git a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp index 5044f077710..e75894b3af7 100644 --- a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp +++ b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp @@ -52,6 +52,7 @@ #include "Common/GameMemory.h" #include "Common/GlobalData.h" #include "Common/Registry.h" +#include "BinkLoader.h" //---------------------------------------------------------------------------- // Externals @@ -130,6 +131,12 @@ void BinkVideoPlayer::init() // Need to load the stuff from the ini file. VideoPlayer::init(); + // Load Bink on runtime instead of importing it into the executable. + if (!BinkLoader::load()) + { + DEBUG_LOG(("Failed to load binkw32.dll (error %d). Videos will not play.", BinkLoader::getLastError())); + } + initializeBinkWithMiles(); } @@ -141,6 +148,7 @@ void BinkVideoPlayer::deinit() { TheAudio->releaseHandleForBink(); VideoPlayer::deinit(); + BinkLoader::unload(); } //============================================================================ diff --git a/Core/Libraries/Source/WWVegas/CMakeLists.txt b/Core/Libraries/Source/WWVegas/CMakeLists.txt index e8a6beeb0f2..987575c0075 100644 --- a/Core/Libraries/Source/WWVegas/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/CMakeLists.txt @@ -8,7 +8,7 @@ target_compile_definitions(core_wwcommon INTERFACE target_link_libraries(core_wwcommon INTERFACE d3d8lib - milesstub + milesloader stlport ) diff --git a/Core/Libraries/Source/WWVegas/WWAudio/WWAudio.cpp b/Core/Libraries/Source/WWVegas/WWAudio/WWAudio.cpp index 5deef46192c..15f6bc43e38 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/WWAudio.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/WWAudio.cpp @@ -55,6 +55,7 @@ #include "WWSaveLoad/definitionclassids.h" #include "WWDebug/wwmemlog.h" #include "WWDebug/wwprofile.h" +#include "MilesLoader.h" #ifdef G_CODE_BASE @@ -129,6 +130,13 @@ WWAudioClass::WWAudioClass () { ::InitializeCriticalSection (&MMSLockClass::_MSSLockCriticalSection); + // + // Load the Miles Sound System on runtime instead of importing it into the executable. + // + if (MilesLoader::load () == false) { + WWDEBUG_SAY (("Failed to load mss32.dll (error %d). Audio will not play.", MilesLoader::getLastError ())); + } + // // Start Miles Sound System // @@ -161,6 +169,9 @@ WWAudioClass::~WWAudioClass () WWAudioThreadsClass::End_Delayed_Release_Thread (); Shutdown (); + + MilesLoader::unload (); + _theInstance = nullptr; ::CloseHandle(_TimerSyncEvent); _TimerSyncEvent = nullptr; @@ -231,11 +242,10 @@ WWAudioClass::Open_2D_Device (LPWAVEFORMAT format) AIL_set_preference (AIL_LOCK_PROTECTION, NO); // Try to use DirectSound if possible - S32 success = ::AIL_set_preference (DIG_USE_WAVEOUT, FALSE); - WWASSERT (success == AIL_NO_ERROR); + ::AIL_set_preference (DIG_USE_WAVEOUT, FALSE); // Open the driver - success = ::AIL_waveOutOpen (&m_Driver2D, nullptr, 0, format); + S32 success = ::AIL_waveOutOpen (&m_Driver2D, nullptr, 0, format); // Do we need to switch from direct sound to waveout? if ((success == AIL_NO_ERROR) && @@ -251,8 +261,7 @@ WWAudioClass::Open_2D_Device (LPWAVEFORMAT format) if (success != AIL_NO_ERROR) { // Try to use the default wave out driver - success = ::AIL_set_preference (DIG_USE_WAVEOUT, TRUE); - WWASSERT (success == AIL_NO_ERROR); + ::AIL_set_preference (DIG_USE_WAVEOUT, TRUE); // Open the driver success = ::AIL_waveOutOpen (&m_Driver2D, nullptr, 0, format); @@ -1374,7 +1383,7 @@ WWAudioClass::Allocate_2D_Handles () for (int index = 0; index < m_Max2DSamples; index ++) { HSAMPLE sample = ::AIL_allocate_sample_handle (m_Driver2D); if (sample != nullptr) { - ::AIL_set_sample_user_data (sample, INFO_OBJECT_PTR, nullptr); + ::AIL_set_sample_user_data (sample, INFO_OBJECT_PTR, 0); m_2DSampleHandles.Add (sample); } } @@ -1819,7 +1828,7 @@ WWAudioClass::Allocate_3D_Handles () for (int index = 0; index < m_Max3DSamples; index ++) { H3DSAMPLE sample = ::AIL_allocate_3D_sample_handle (m_Driver3D); if (sample != nullptr) { - ::AIL_set_3D_object_user_data (sample, INFO_OBJECT_PTR, nullptr); + ::AIL_set_3D_object_user_data (sample, INFO_OBJECT_PTR, 0); m_3DSampleHandles.Add (sample); } } diff --git a/Core/Libraries/Source/WWVegas/WWAudio/sound2dhandle.cpp b/Core/Libraries/Source/WWVegas/WWAudio/sound2dhandle.cpp index 1355c05c146..24bd32a852a 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/sound2dhandle.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/sound2dhandle.cpp @@ -292,7 +292,7 @@ void Sound2DHandleClass::Set_Sample_User_Data (S32 i, void *val) { if (SampleHandle != (HSAMPLE)INVALID_MILES_HANDLE) { - ::AIL_set_sample_user_data (SampleHandle, i, val); + ::AIL_set_sample_user_data (SampleHandle, i, (S32)val); } } @@ -308,7 +308,7 @@ Sound2DHandleClass::Get_Sample_User_Data (S32 i) void *retval = nullptr; if (SampleHandle != (HSAMPLE)INVALID_MILES_HANDLE) { - retval = ::AIL_sample_user_data (SampleHandle, i); + retval = (void *)::AIL_sample_user_data (SampleHandle, i); } return retval; diff --git a/Core/Libraries/Source/WWVegas/WWAudio/sound3dhandle.cpp b/Core/Libraries/Source/WWVegas/WWAudio/sound3dhandle.cpp index 79b3e40e64e..049b409592e 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/sound3dhandle.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/sound3dhandle.cpp @@ -291,7 +291,7 @@ void Sound3DHandleClass::Set_Sample_User_Data (S32 i, void *val) { if (SampleHandle != (H3DSAMPLE)INVALID_MILES_HANDLE) { - ::AIL_set_3D_object_user_data (SampleHandle, i, val); + ::AIL_set_3D_object_user_data (SampleHandle, i, (S32)val); } } @@ -307,7 +307,7 @@ Sound3DHandleClass::Get_Sample_User_Data (S32 i) void *retval = nullptr; if (SampleHandle != (H3DSAMPLE)INVALID_MILES_HANDLE) { - retval = AIL_3D_object_user_data (SampleHandle, i); + retval = (void *)AIL_3D_object_user_data (SampleHandle, i); } return retval; diff --git a/Core/Libraries/Source/WWVegas/WWAudio/soundstreamhandle.cpp b/Core/Libraries/Source/WWVegas/WWAudio/soundstreamhandle.cpp index ed71ff8228f..188beb2e511 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/soundstreamhandle.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/soundstreamhandle.cpp @@ -294,7 +294,7 @@ void SoundStreamHandleClass::Set_Sample_User_Data (S32 i, void *val) { if (SampleHandle != (HSAMPLE)INVALID_MILES_HANDLE) { - ::AIL_set_sample_user_data (SampleHandle, i, val); + ::AIL_set_sample_user_data (SampleHandle, i, (S32)val); } } @@ -310,7 +310,7 @@ SoundStreamHandleClass::Get_Sample_User_Data (S32 i) void *retval = nullptr; if (SampleHandle != (HSAMPLE)INVALID_MILES_HANDLE) { - retval = ::AIL_sample_user_data (SampleHandle, i); + retval = (void *)::AIL_sample_user_data (SampleHandle, i); } return retval; diff --git a/Dependencies/Bink/BinkLoader.cpp b/Dependencies/Bink/BinkLoader.cpp new file mode 100644 index 00000000000..de0432eac91 --- /dev/null +++ b/Dependencies/Bink/BinkLoader.cpp @@ -0,0 +1,250 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#include "BinkLoader.h" +#include "bink.h" + +// binkw32.dll exports decorated __stdcall names, which only exist in the 32 bit Windows build. +#if defined(_WIN32) && !defined(_WIN64) +#define BINK_LOADER_SUPPORTED 1 +#else +#define BINK_LOADER_SUPPORTED 0 +#endif + +#if BINK_LOADER_SUPPORTED +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#endif + + +namespace +{ + +typedef HBINK (__stdcall *BinkOpen_t)(const char *name, unsigned int flags); +typedef void (__stdcall *BinkSetSoundTrack_t)(unsigned int total_tracks, unsigned int *tracks); +typedef int (__stdcall *BinkSetSoundSystem_t)(SndOpenCallback open, unsigned long param); +typedef void *(__stdcall *BinkOpenDirectSound_t)(unsigned long param); +typedef void (__stdcall *BinkClose_t)(HBINK handle); +typedef int (__stdcall *BinkWait_t)(HBINK handle); +typedef int (__stdcall *BinkDoFrame_t)(HBINK handle); +typedef int (__stdcall *BinkCopyToBuffer_t)(HBINK handle, void *dest, int destpitch, unsigned int destheight, + unsigned int destx, unsigned int desty, unsigned int flags); +typedef void (__stdcall *BinkSetVolume_t)(HBINK handle, unsigned int trackid, int volume); +typedef void (__stdcall *BinkNextFrame_t)(HBINK handle); +typedef void (__stdcall *BinkGoto_t)(HBINK handle, unsigned int frame, int flags); + +BinkOpen_t BinkOpenPtr = nullptr; +BinkSetSoundTrack_t BinkSetSoundTrackPtr = nullptr; +BinkSetSoundSystem_t BinkSetSoundSystemPtr = nullptr; +BinkOpenDirectSound_t BinkOpenDirectSoundPtr = nullptr; +BinkClose_t BinkClosePtr = nullptr; +BinkWait_t BinkWaitPtr = nullptr; +BinkDoFrame_t BinkDoFramePtr = nullptr; +BinkCopyToBuffer_t BinkCopyToBufferPtr = nullptr; +BinkSetVolume_t BinkSetVolumePtr = nullptr; +BinkNextFrame_t BinkNextFramePtr = nullptr; +BinkGoto_t BinkGotoPtr = nullptr; + +int ReferenceCount = 0; +bool Failed = false; +unsigned long LastError = 0; + +#if BINK_LOADER_SUPPORTED +HMODULE Module = HMODULE(nullptr); + +// Resolves one export into its matching function pointer. The exported names are decorated, +// so they carry the __stdcall argument byte count and must be spelled out verbatim. +#define BINK_RESOLVE(name, decorated) \ + name##Ptr = reinterpret_cast(::GetProcAddress(Module, decorated)) + +static void resolveAll() +{ + BINK_RESOLVE(BinkOpen, "_BinkOpen@8"); + BINK_RESOLVE(BinkSetSoundTrack, "_BinkSetSoundTrack@8"); + BINK_RESOLVE(BinkSetSoundSystem, "_BinkSetSoundSystem@8"); + BINK_RESOLVE(BinkOpenDirectSound, "_BinkOpenDirectSound@4"); + BINK_RESOLVE(BinkClose, "_BinkClose@4"); + BINK_RESOLVE(BinkWait, "_BinkWait@4"); + BINK_RESOLVE(BinkDoFrame, "_BinkDoFrame@4"); + BINK_RESOLVE(BinkCopyToBuffer, "_BinkCopyToBuffer@28"); + BINK_RESOLVE(BinkSetVolume, "_BinkSetVolume@12"); + BINK_RESOLVE(BinkNextFrame, "_BinkNextFrame@4"); + BINK_RESOLVE(BinkGoto, "_BinkGoto@12"); +} +#undef BINK_RESOLVE + +static void freeResources() +{ + if (Module != HMODULE(nullptr)) { + ::FreeLibrary(Module); + Module = HMODULE(nullptr); + } + + BinkOpenPtr = nullptr; + BinkSetSoundTrackPtr = nullptr; + BinkSetSoundSystemPtr = nullptr; + BinkOpenDirectSoundPtr = nullptr; + BinkClosePtr = nullptr; + BinkWaitPtr = nullptr; + BinkDoFramePtr = nullptr; + BinkCopyToBufferPtr = nullptr; + BinkSetVolumePtr = nullptr; + BinkNextFramePtr = nullptr; + BinkGotoPtr = nullptr; +} +#endif // BINK_LOADER_SUPPORTED + +} // namespace + + +bool BinkLoader::isLoaded() +{ +#if BINK_LOADER_SUPPORTED + return Module != HMODULE(nullptr); +#else + return false; +#endif +} + + +bool BinkLoader::isFailed() +{ + return Failed; +} + + +unsigned long BinkLoader::getLastError() +{ + return LastError; +} + + +bool BinkLoader::load() +{ + // Always increment the reference count. + ++ReferenceCount; + + // Optimization: return early if it failed before. + if (Failed) + return false; + + // Return early if someone else already loaded it. + if (ReferenceCount > 1) + return true; + +#if BINK_LOADER_SUPPORTED + // Load binkw32.dll by name, so that the usual module search order applies. + Module = ::LoadLibraryA("binkw32.dll"); + if (Module == HMODULE(nullptr)) { + LastError = ::GetLastError(); + Failed = true; + return false; + } + + resolveAll(); + return true; +#else + Failed = true; + return false; +#endif +} + + +void BinkLoader::unload() +{ + if (ReferenceCount > 0) + --ReferenceCount; + + if (ReferenceCount > 0) + return; + +#if BINK_LOADER_SUPPORTED + freeResources(); +#endif + Failed = false; + LastError = 0; +} + + +// The Bink functions below stand in for the imports of binkw32.dll. An unresolved function +// returns the same neutral value the Bink SDK stub library returned. + +HBINK __stdcall BinkOpen(const char *name, unsigned int flags) +{ + return BinkOpenPtr != nullptr ? BinkOpenPtr(name, flags) : nullptr; +} + +void __stdcall BinkSetSoundTrack(unsigned int total_tracks, unsigned int *tracks) +{ + if (BinkSetSoundTrackPtr != nullptr) + BinkSetSoundTrackPtr(total_tracks, tracks); +} + +int __stdcall BinkSetSoundSystem(SndOpenCallback open, unsigned long param) +{ + return BinkSetSoundSystemPtr != nullptr ? BinkSetSoundSystemPtr(open, param) : 0; +} + +void *__stdcall BinkOpenDirectSound(unsigned long param) +{ + return BinkOpenDirectSoundPtr != nullptr ? BinkOpenDirectSoundPtr(param) : nullptr; +} + +void __stdcall BinkClose(HBINK handle) +{ + if (BinkClosePtr != nullptr) + BinkClosePtr(handle); +} + +int __stdcall BinkWait(HBINK handle) +{ + return BinkWaitPtr != nullptr ? BinkWaitPtr(handle) : 0; +} + +int __stdcall BinkDoFrame(HBINK handle) +{ + return BinkDoFramePtr != nullptr ? BinkDoFramePtr(handle) : 0; +} + +int __stdcall BinkCopyToBuffer(HBINK handle, void *dest, int destpitch, unsigned int destheight, + unsigned int destx, unsigned int desty, unsigned int flags) +{ + return BinkCopyToBufferPtr != nullptr + ? BinkCopyToBufferPtr(handle, dest, destpitch, destheight, destx, desty, flags) + : 0; +} + +void __stdcall BinkSetVolume(HBINK handle, unsigned int trackid, int volume) +{ + if (BinkSetVolumePtr != nullptr) + BinkSetVolumePtr(handle, trackid, volume); +} + +void __stdcall BinkNextFrame(HBINK handle) +{ + if (BinkNextFramePtr != nullptr) + BinkNextFramePtr(handle); +} + +void __stdcall BinkGoto(HBINK handle, unsigned int frame, int flags) +{ + if (BinkGotoPtr != nullptr) + BinkGotoPtr(handle, frame, flags); +} diff --git a/Dependencies/Bink/BinkLoader.h b/Dependencies/Bink/BinkLoader.h new file mode 100644 index 00000000000..25559ab8ab6 --- /dev/null +++ b/Dependencies/Bink/BinkLoader.h @@ -0,0 +1,52 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#pragma once + +// This static class loads and unloads binkw32.dll at runtime. +// +// The Bink functions declared in bink.h are implemented in this class and forward to the +// matching export of the loaded module. Loading the module explicitly, rather than importing +// binkw32.dll into the executable, is what allows the library to be picked up from a working +// directory that was chosen on the command line, because the process no longer needs to +// resolve it before WinMain runs. +// +// When the module is not loaded, every Bink function returns the same neutral value the Bink +// SDK stub library used to return, so a missing binkw32.dll disables video playback instead +// of preventing the program from starting. +// +// Is not thread safe. Every call to load needs a paired call to unload, no matter if the load +// was successful, and both are expected to be called from the main thread while no Bink +// function is in flight. + +class BinkLoader +{ +public: + + // Returns whether binkw32.dll is loaded + static bool isLoaded(); + + // Returns whether binkw32.dll was attempted to be loaded but failed + static bool isFailed(); + + // Returns the system error code of the failed load attempt + static unsigned long getLastError(); + + static bool load(); + static void unload(); +}; diff --git a/Dependencies/Bink/CMakeLists.txt b/Dependencies/Bink/CMakeLists.txt new file mode 100644 index 00000000000..a1e5260bf05 --- /dev/null +++ b/Dependencies/Bink/CMakeLists.txt @@ -0,0 +1,20 @@ +set(BINK_SRC + bink.h + BinkLoader.cpp + BinkLoader.h +) + +## binkloader + +add_library(binkloader STATIC) +set_target_properties(binkloader PROPERTIES OUTPUT_NAME binkloader) + +target_sources(binkloader PRIVATE ${BINK_SRC}) + +target_include_directories(binkloader PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} # include "bink.h" and "BinkLoader.h" +) + +target_link_libraries(binkloader PRIVATE + core_utility +) diff --git a/Dependencies/Bink/bink.h b/Dependencies/Bink/bink.h new file mode 100644 index 00000000000..9c1b733caa8 --- /dev/null +++ b/Dependencies/Bink/bink.h @@ -0,0 +1,71 @@ +/** + * @file + * + * @author OmniBlade + * + * @brief Subset of the binkw32.dll API as used by the W3D engine. + * + * @copyright This is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 2 of the License, or (at your option) any later version. + * A full copy of the GNU General Public License can be found in + * LICENSE + */ + +#pragma once + +#if !defined _MSC_VER +#if !defined(__stdcall) +#if defined __has_attribute && __has_attribute(stdcall) +#define __stdcall __attribute__((stdcall)) +#else +#define __stdcall +#endif +#endif /* !defined __stdcall */ +#endif /* !defined COMPILER_MSVC */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define BINKSURFACE24 1 +#define BINKSURFACE32 3 +#define BINKSURFACE555 9 +#define BINKSURFACE565 10 +#define BINKPRELOADALL 0x00002000 +#define BINKCOPYNOSCALING 0x70000000 + +typedef struct BINK +{ + unsigned int Width; + unsigned int Height; + unsigned int Frames; + unsigned int FrameNum; + unsigned int LastFrameNum; + unsigned int FrameRate; + unsigned int FrameRateDiv; + /* Original struct has more members, but we only need these to match the ABI*/ +} BINK, *HBINK; + +typedef void *(__stdcall *SndOpenCallback)(unsigned long param); +typedef unsigned int u32; + +HBINK __stdcall BinkOpen(const char *name, unsigned int flags); +void __stdcall BinkSetSoundTrack(unsigned int total_tracks, unsigned int *tracks); +int __stdcall BinkSetSoundSystem(SndOpenCallback open, unsigned long param); +void *__stdcall BinkOpenDirectSound(unsigned long param); +void __stdcall BinkClose(HBINK handle); +int __stdcall BinkWait(HBINK handle); +int __stdcall BinkDoFrame(HBINK handle); +int __stdcall BinkCopyToBuffer( + HBINK handle, void *dest, int destpitch, unsigned int destheight, unsigned int destx, unsigned int desty, unsigned int flags); +void __stdcall BinkSetVolume(HBINK handle, unsigned int trackid, int volume); +void __stdcall BinkNextFrame(HBINK handle); +void __stdcall BinkGoto(HBINK handle, unsigned int frame, int flags); + +#define BinkSoundUseDirectSound(x) BinkSetSoundSystem(BinkOpenDirectSound, (unsigned long)x) + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/Dependencies/Miles/CMakeLists.txt b/Dependencies/Miles/CMakeLists.txt new file mode 100644 index 00000000000..4a97fb07307 --- /dev/null +++ b/Dependencies/Miles/CMakeLists.txt @@ -0,0 +1,21 @@ +set(MILES_SRC + mss/mss.h + MilesLoader.cpp + MilesLoader.h +) + +## milesloader + +add_library(milesloader STATIC) +set_target_properties(milesloader PROPERTIES OUTPUT_NAME milesloader) + +target_sources(milesloader PRIVATE ${MILES_SRC}) + +target_include_directories(milesloader PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} # include "mss/mss.h" and "MilesLoader.h" + ${CMAKE_CURRENT_SOURCE_DIR}/mss # include "mss.h" +) + +target_link_libraries(milesloader PRIVATE + core_utility +) diff --git a/Dependencies/Miles/MilesLoader.cpp b/Dependencies/Miles/MilesLoader.cpp new file mode 100644 index 00000000000..035633c732c --- /dev/null +++ b/Dependencies/Miles/MilesLoader.cpp @@ -0,0 +1,1122 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#include "MilesLoader.h" +#include "mss/mss.h" + +// mss32.dll exports decorated __stdcall names, which only exist in the 32 bit Windows build. +#if defined(_WIN32) && !defined(_WIN64) +#define MILES_LOADER_SUPPORTED 1 +#else +#define MILES_LOADER_SUPPORTED 0 +#endif + + +namespace +{ + +typedef F32 (__stdcall *AIL_3D_sample_volume_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_set_3D_sample_volume_t)(H3DSAMPLE sample, F32 volume); +typedef void (__stdcall *AIL_end_3D_sample_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_resume_3D_sample_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_stop_3D_sample_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_start_3D_sample_t)(H3DSAMPLE sample); +typedef U32 (__stdcall *AIL_3D_sample_loop_count_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_set_3D_sample_offset_t)(H3DSAMPLE sample, U32 offset); +typedef U32 (__stdcall *AIL_3D_sample_length_t)(H3DSAMPLE sample); +typedef U32 (__stdcall *AIL_3D_sample_offset_t)(H3DSAMPLE sample); +typedef S32 (__stdcall *AIL_3D_sample_playback_rate_t)(H3DSAMPLE sample); +typedef void (__stdcall *AIL_set_3D_sample_playback_rate_t)(H3DSAMPLE sample, S32 playback_rate); +typedef S32 (__stdcall *AIL_set_3D_sample_file_t)(H3DSAMPLE sample, const void* file_image); +typedef HPROVIDER (__stdcall *AIL_set_sample_processor_t)(HSAMPLE sample, SAMPLESTAGE pipeline_stage, HPROVIDER provider); +typedef void (__stdcall *AIL_set_filter_sample_preference_t)(HSAMPLE sample, const char* name, const void* val); +typedef void (__stdcall *AIL_release_sample_handle_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_close_3D_provider_t)(HPROVIDER lib); +typedef S32 (__stdcall *AIL_set_preference_t)(U32 number, S32 value); +typedef S32 (__stdcall *AIL_waveOutOpen_t)(HDIGDRIVER* driver, LPHWAVEOUT* waveout, S32 id, LPWAVEFORMAT format); +typedef void (__stdcall *AIL_waveOutClose_t)(HDIGDRIVER driver); +typedef void (__stdcall *AIL_set_3D_sample_loop_count_t)(H3DSAMPLE sample, U32 count); +typedef void (__stdcall *AIL_set_stream_playback_rate_t)(HSTREAM stream, S32 rate); +typedef S32 (__stdcall *AIL_stream_playback_rate_t)(HSTREAM stream); +typedef void (__stdcall *AIL_stream_ms_position_t)(HSTREAM sample, S32* total_milliseconds, S32* current_milliseconds); +typedef void (__stdcall *AIL_set_stream_ms_position_t)(HSTREAM stream, S32 pos); +typedef S32 (__stdcall *AIL_stream_loop_count_t)(HSTREAM stream); +typedef void (__stdcall *AIL_set_stream_loop_block_t)(HSTREAM stream, S32 loop_start, S32 loop_end); +typedef void (__stdcall *AIL_set_stream_loop_count_t)(HSTREAM stream, S32 count); +typedef void (__stdcall *AIL_close_stream_t)(HSTREAM stream); +typedef void (__stdcall *AIL_pause_stream_t)(HSTREAM stream, S32 onoff); +typedef AIL_stream_callback (__stdcall *AIL_register_stream_callback_t)(HSTREAM stream, AIL_stream_callback callback); +typedef AIL_3dsample_callback (__stdcall *AIL_register_3D_EOS_callback_t)(H3DSAMPLE sample, AIL_3dsample_callback EOS); +typedef AIL_sample_callback (__stdcall *AIL_register_EOS_callback_t)(HSAMPLE sample, AIL_sample_callback EOS); +typedef void (__stdcall *AIL_start_stream_t)(HSTREAM stream); +typedef void (__stdcall *AIL_set_sample_playback_rate_t)(HSAMPLE sample, S32 playback_rate); +typedef S32 (__stdcall *AIL_sample_playback_rate_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_sample_ms_position_t)(HSAMPLE sample, S32* total_ms, S32* current_ms); +typedef void (__stdcall *AIL_set_sample_ms_position_t)(HSAMPLE sample, S32 pos); +typedef S32 (__stdcall *AIL_sample_loop_count_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_set_sample_loop_count_t)(HSAMPLE sample, S32 count); +typedef void (__stdcall *AIL_end_sample_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_resume_sample_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_stop_sample_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_start_sample_t)(HSAMPLE sample); +typedef void (__stdcall *AIL_init_sample_t)(HSAMPLE sample); +typedef S32 (__stdcall *AIL_set_named_sample_file_t)(HSAMPLE sample, const char* file_name, const void* file_image, S32 file_size, S32 block); +typedef void (__stdcall *AIL_set_3D_sample_effects_level_t)(H3DSAMPLE sample, F32 effect_level); +typedef void (__stdcall *AIL_set_3D_sample_distances_t)(H3DSAMPLE sample, F32 max_dist, F32 min_dist); +typedef void (__stdcall *AIL_set_3D_velocity_vector_t)(H3DPOBJECT obj, F32 x, F32 y, F32 z); +typedef void (__stdcall *AIL_set_3D_position_t)(H3DPOBJECT obj, F32 X, F32 Y, F32 Z); +typedef void (__stdcall *AIL_set_3D_orientation_t)(H3DPOBJECT obj, F32 X_face, F32 Y_face, F32 Z_face, F32 X_up, F32 Y_up, F32 Z_up); +typedef S32 (__stdcall *AIL_WAV_info_t)(const void* data, AILSOUNDINFO* info); +typedef void (__stdcall *AIL_stop_timer_t)(HTIMER timer); +typedef void (__stdcall *AIL_release_timer_handle_t)(HTIMER timer); +typedef void (__stdcall *AIL_shutdown_t)(void); +typedef S32 (__stdcall *AIL_enumerate_filters_t)(HPROENUM* next, HPROVIDER* dest, char** name); +typedef void (__stdcall *AIL_set_file_callbacks_t)(AIL_file_open_callback opencb, AIL_file_close_callback closecb, AIL_file_seek_callback seekcb, AIL_file_read_callback readcb); +typedef void (__stdcall *AIL_release_3D_sample_handle_t)(H3DSAMPLE sample); +typedef H3DSAMPLE (__stdcall *AIL_allocate_3D_sample_handle_t)(HPROVIDER lib); +typedef void (__stdcall *AIL_set_3D_user_data_t)(H3DPOBJECT obj, U32 index, S32 value); +typedef void (__stdcall *AIL_unlock_t)(void); +typedef void (__stdcall *AIL_unlock_mutex_t)(void); +typedef void (__stdcall *AIL_lock_t)(void); +typedef void (__stdcall *AIL_lock_mutex_t)(void); +typedef void (__stdcall *AIL_set_3D_speaker_type_t)(HPROVIDER lib, S32 speaker_type); +typedef void (__stdcall *AIL_close_3D_listener_t)(H3DPOBJECT listener); +typedef S32 (__stdcall *AIL_enumerate_3D_providers_t)(HPROENUM* next, HPROVIDER* dest, char** name); +typedef M3DRESULT (__stdcall *AIL_open_3D_provider_t)(HPROVIDER lib); +typedef char* (__stdcall *AIL_last_error_t)(void); +typedef H3DPOBJECT (__stdcall *AIL_open_3D_listener_t)(HPROVIDER lib); +typedef S32 (__stdcall *AIL_3D_user_data_t)(H3DPOBJECT obj, U32 index); +typedef S32 (__stdcall *AIL_sample_user_data_t)(HSAMPLE sample, U32 index); +typedef HSAMPLE (__stdcall *AIL_allocate_sample_handle_t)(HDIGDRIVER dig); +typedef void (__stdcall *AIL_set_sample_user_data_t)(HSAMPLE sample, U32 index, S32 value); +typedef S32 (__stdcall *AIL_decompress_ADPCM_t)(const AILSOUNDINFO *info, void **outdata, U32 *outsize); +typedef void (__stdcall *AIL_get_DirectSound_info_t)(HSAMPLE sample, AILLPDIRECTSOUND *lplpDS, AILLPDIRECTSOUNDBUFFER *lplpDSB); +typedef void (__stdcall *AIL_mem_free_lock_t)(void *ptr); +typedef HSTREAM (__stdcall *AIL_open_stream_t)(HDIGDRIVER dig, const char *filename, S32 stream_mem); +typedef S32 (__stdcall *AIL_startup_t)(void); +typedef void (__stdcall *AIL_quick_unload_t)(HAUDIO audio); +typedef HAUDIO (__stdcall *AIL_quick_load_and_play_t)(const char *filename, U32 loop_count, S32 wait_request); +typedef void (__stdcall *AIL_quick_set_volume_t)(HAUDIO audio, F32 volume, F32 extravol); +typedef S32 (__stdcall *AIL_quick_startup_t)(S32 use_digital, S32 use_MIDI, U32 output_rate, S32 output_bits, S32 output_channels); +typedef void (__stdcall *AIL_quick_handles_t)(HDIGDRIVER *pdig, HMDIDRIVER *pmdi, HDLSDEVICE *pdls); +typedef void (__stdcall *AIL_sample_volume_pan_t)(HSAMPLE sample, F32 *volume, F32 *pan); +typedef void (__stdcall *AIL_set_3D_sample_occlusion_t)(H3DSAMPLE sample, F32 occlusion); +typedef char * (__stdcall *AIL_set_redist_directory_t)(const char *dir); +typedef S32 (__stdcall *AIL_set_sample_file_t)(HSAMPLE sample, const void *file_image, S32 block); +typedef void (__stdcall *AIL_set_sample_volume_pan_t)(HSAMPLE sample, F32 volume, F32 pan); +typedef void (__stdcall *AIL_set_stream_volume_pan_t)(HSTREAM stream, F32 volume, F32 pan); +typedef void (__stdcall *AIL_stream_volume_pan_t)(HSTREAM stream, F32 *volume, F32 *pan); +typedef U32 (__stdcall *AIL_get_timer_highest_delay_t)(void); + +AIL_3D_sample_volume_t AIL_3D_sample_volumePtr = nullptr; +AIL_set_3D_sample_volume_t AIL_set_3D_sample_volumePtr = nullptr; +AIL_end_3D_sample_t AIL_end_3D_samplePtr = nullptr; +AIL_resume_3D_sample_t AIL_resume_3D_samplePtr = nullptr; +AIL_stop_3D_sample_t AIL_stop_3D_samplePtr = nullptr; +AIL_start_3D_sample_t AIL_start_3D_samplePtr = nullptr; +AIL_3D_sample_loop_count_t AIL_3D_sample_loop_countPtr = nullptr; +AIL_set_3D_sample_offset_t AIL_set_3D_sample_offsetPtr = nullptr; +AIL_3D_sample_length_t AIL_3D_sample_lengthPtr = nullptr; +AIL_3D_sample_offset_t AIL_3D_sample_offsetPtr = nullptr; +AIL_3D_sample_playback_rate_t AIL_3D_sample_playback_ratePtr = nullptr; +AIL_set_3D_sample_playback_rate_t AIL_set_3D_sample_playback_ratePtr = nullptr; +AIL_set_3D_sample_file_t AIL_set_3D_sample_filePtr = nullptr; +AIL_set_sample_processor_t AIL_set_sample_processorPtr = nullptr; +AIL_set_filter_sample_preference_t AIL_set_filter_sample_preferencePtr = nullptr; +AIL_release_sample_handle_t AIL_release_sample_handlePtr = nullptr; +AIL_close_3D_provider_t AIL_close_3D_providerPtr = nullptr; +AIL_set_preference_t AIL_set_preferencePtr = nullptr; +AIL_waveOutOpen_t AIL_waveOutOpenPtr = nullptr; +AIL_waveOutClose_t AIL_waveOutClosePtr = nullptr; +AIL_set_3D_sample_loop_count_t AIL_set_3D_sample_loop_countPtr = nullptr; +AIL_set_stream_playback_rate_t AIL_set_stream_playback_ratePtr = nullptr; +AIL_stream_playback_rate_t AIL_stream_playback_ratePtr = nullptr; +AIL_stream_ms_position_t AIL_stream_ms_positionPtr = nullptr; +AIL_set_stream_ms_position_t AIL_set_stream_ms_positionPtr = nullptr; +AIL_stream_loop_count_t AIL_stream_loop_countPtr = nullptr; +AIL_set_stream_loop_block_t AIL_set_stream_loop_blockPtr = nullptr; +AIL_set_stream_loop_count_t AIL_set_stream_loop_countPtr = nullptr; +AIL_close_stream_t AIL_close_streamPtr = nullptr; +AIL_pause_stream_t AIL_pause_streamPtr = nullptr; +AIL_register_stream_callback_t AIL_register_stream_callbackPtr = nullptr; +AIL_register_3D_EOS_callback_t AIL_register_3D_EOS_callbackPtr = nullptr; +AIL_register_EOS_callback_t AIL_register_EOS_callbackPtr = nullptr; +AIL_start_stream_t AIL_start_streamPtr = nullptr; +AIL_set_sample_playback_rate_t AIL_set_sample_playback_ratePtr = nullptr; +AIL_sample_playback_rate_t AIL_sample_playback_ratePtr = nullptr; +AIL_sample_ms_position_t AIL_sample_ms_positionPtr = nullptr; +AIL_set_sample_ms_position_t AIL_set_sample_ms_positionPtr = nullptr; +AIL_sample_loop_count_t AIL_sample_loop_countPtr = nullptr; +AIL_set_sample_loop_count_t AIL_set_sample_loop_countPtr = nullptr; +AIL_end_sample_t AIL_end_samplePtr = nullptr; +AIL_resume_sample_t AIL_resume_samplePtr = nullptr; +AIL_stop_sample_t AIL_stop_samplePtr = nullptr; +AIL_start_sample_t AIL_start_samplePtr = nullptr; +AIL_init_sample_t AIL_init_samplePtr = nullptr; +AIL_set_named_sample_file_t AIL_set_named_sample_filePtr = nullptr; +AIL_set_3D_sample_effects_level_t AIL_set_3D_sample_effects_levelPtr = nullptr; +AIL_set_3D_sample_distances_t AIL_set_3D_sample_distancesPtr = nullptr; +AIL_set_3D_velocity_vector_t AIL_set_3D_velocity_vectorPtr = nullptr; +AIL_set_3D_position_t AIL_set_3D_positionPtr = nullptr; +AIL_set_3D_orientation_t AIL_set_3D_orientationPtr = nullptr; +AIL_WAV_info_t AIL_WAV_infoPtr = nullptr; +AIL_stop_timer_t AIL_stop_timerPtr = nullptr; +AIL_release_timer_handle_t AIL_release_timer_handlePtr = nullptr; +AIL_shutdown_t AIL_shutdownPtr = nullptr; +AIL_enumerate_filters_t AIL_enumerate_filtersPtr = nullptr; +AIL_set_file_callbacks_t AIL_set_file_callbacksPtr = nullptr; +AIL_release_3D_sample_handle_t AIL_release_3D_sample_handlePtr = nullptr; +AIL_allocate_3D_sample_handle_t AIL_allocate_3D_sample_handlePtr = nullptr; +AIL_set_3D_user_data_t AIL_set_3D_user_dataPtr = nullptr; +AIL_unlock_t AIL_unlockPtr = nullptr; +AIL_unlock_mutex_t AIL_unlock_mutexPtr = nullptr; +AIL_lock_t AIL_lockPtr = nullptr; +AIL_lock_mutex_t AIL_lock_mutexPtr = nullptr; +AIL_set_3D_speaker_type_t AIL_set_3D_speaker_typePtr = nullptr; +AIL_close_3D_listener_t AIL_close_3D_listenerPtr = nullptr; +AIL_enumerate_3D_providers_t AIL_enumerate_3D_providersPtr = nullptr; +AIL_open_3D_provider_t AIL_open_3D_providerPtr = nullptr; +AIL_last_error_t AIL_last_errorPtr = nullptr; +AIL_open_3D_listener_t AIL_open_3D_listenerPtr = nullptr; +AIL_3D_user_data_t AIL_3D_user_dataPtr = nullptr; +AIL_sample_user_data_t AIL_sample_user_dataPtr = nullptr; +AIL_allocate_sample_handle_t AIL_allocate_sample_handlePtr = nullptr; +AIL_set_sample_user_data_t AIL_set_sample_user_dataPtr = nullptr; +AIL_decompress_ADPCM_t AIL_decompress_ADPCMPtr = nullptr; +AIL_get_DirectSound_info_t AIL_get_DirectSound_infoPtr = nullptr; +AIL_mem_free_lock_t AIL_mem_free_lockPtr = nullptr; +AIL_open_stream_t AIL_open_streamPtr = nullptr; +AIL_startup_t AIL_startupPtr = nullptr; +AIL_quick_unload_t AIL_quick_unloadPtr = nullptr; +AIL_quick_load_and_play_t AIL_quick_load_and_playPtr = nullptr; +AIL_quick_set_volume_t AIL_quick_set_volumePtr = nullptr; +AIL_quick_startup_t AIL_quick_startupPtr = nullptr; +AIL_quick_handles_t AIL_quick_handlesPtr = nullptr; +AIL_sample_volume_pan_t AIL_sample_volume_panPtr = nullptr; +AIL_set_3D_sample_occlusion_t AIL_set_3D_sample_occlusionPtr = nullptr; +AIL_set_redist_directory_t AIL_set_redist_directoryPtr = nullptr; +AIL_set_sample_file_t AIL_set_sample_filePtr = nullptr; +AIL_set_sample_volume_pan_t AIL_set_sample_volume_panPtr = nullptr; +AIL_set_stream_volume_pan_t AIL_set_stream_volume_panPtr = nullptr; +AIL_stream_volume_pan_t AIL_stream_volume_panPtr = nullptr; +AIL_get_timer_highest_delay_t AIL_get_timer_highest_delayPtr = nullptr; + +int ReferenceCount = 0; +bool Failed = false; +unsigned long LastError = 0; + +#if MILES_LOADER_SUPPORTED +HMODULE Module = HMODULE(nullptr); + +// Resolves one export into its matching function pointer. The exported names are decorated, so +// they carry the __stdcall argument byte count and must be spelled out verbatim. +#define MILES_RESOLVE(name, decorated) \ + name##Ptr = reinterpret_cast(::GetProcAddress(Module, decorated)) + +static void resolveAll() +{ + MILES_RESOLVE(AIL_3D_sample_volume, "_AIL_3D_sample_volume@4"); + MILES_RESOLVE(AIL_set_3D_sample_volume, "_AIL_set_3D_sample_volume@8"); + MILES_RESOLVE(AIL_end_3D_sample, "_AIL_end_3D_sample@4"); + MILES_RESOLVE(AIL_resume_3D_sample, "_AIL_resume_3D_sample@4"); + MILES_RESOLVE(AIL_stop_3D_sample, "_AIL_stop_3D_sample@4"); + MILES_RESOLVE(AIL_start_3D_sample, "_AIL_start_3D_sample@4"); + MILES_RESOLVE(AIL_3D_sample_loop_count, "_AIL_3D_sample_loop_count@4"); + MILES_RESOLVE(AIL_set_3D_sample_offset, "_AIL_set_3D_sample_offset@8"); + MILES_RESOLVE(AIL_3D_sample_length, "_AIL_3D_sample_length@4"); + MILES_RESOLVE(AIL_3D_sample_offset, "_AIL_3D_sample_offset@4"); + MILES_RESOLVE(AIL_3D_sample_playback_rate, "_AIL_3D_sample_playback_rate@4"); + MILES_RESOLVE(AIL_set_3D_sample_playback_rate, "_AIL_set_3D_sample_playback_rate@8"); + MILES_RESOLVE(AIL_set_3D_sample_file, "_AIL_set_3D_sample_file@8"); + MILES_RESOLVE(AIL_set_sample_processor, "_AIL_set_sample_processor@12"); + MILES_RESOLVE(AIL_set_filter_sample_preference, "_AIL_set_filter_sample_preference@12"); + MILES_RESOLVE(AIL_release_sample_handle, "_AIL_release_sample_handle@4"); + MILES_RESOLVE(AIL_close_3D_provider, "_AIL_close_3D_provider@4"); + MILES_RESOLVE(AIL_set_preference, "_AIL_set_preference@8"); + MILES_RESOLVE(AIL_waveOutOpen, "_AIL_waveOutOpen@16"); + MILES_RESOLVE(AIL_waveOutClose, "_AIL_waveOutClose@4"); + MILES_RESOLVE(AIL_set_3D_sample_loop_count, "_AIL_set_3D_sample_loop_count@8"); + MILES_RESOLVE(AIL_set_stream_playback_rate, "_AIL_set_stream_playback_rate@8"); + MILES_RESOLVE(AIL_stream_playback_rate, "_AIL_stream_playback_rate@4"); + MILES_RESOLVE(AIL_stream_ms_position, "_AIL_stream_ms_position@12"); + MILES_RESOLVE(AIL_set_stream_ms_position, "_AIL_set_stream_ms_position@8"); + MILES_RESOLVE(AIL_stream_loop_count, "_AIL_stream_loop_count@4"); + MILES_RESOLVE(AIL_set_stream_loop_block, "_AIL_set_stream_loop_block@12"); + MILES_RESOLVE(AIL_set_stream_loop_count, "_AIL_set_stream_loop_count@8"); + MILES_RESOLVE(AIL_close_stream, "_AIL_close_stream@4"); + MILES_RESOLVE(AIL_pause_stream, "_AIL_pause_stream@8"); + MILES_RESOLVE(AIL_register_stream_callback, "_AIL_register_stream_callback@8"); + MILES_RESOLVE(AIL_register_3D_EOS_callback, "_AIL_register_3D_EOS_callback@8"); + MILES_RESOLVE(AIL_register_EOS_callback, "_AIL_register_EOS_callback@8"); + MILES_RESOLVE(AIL_start_stream, "_AIL_start_stream@4"); + MILES_RESOLVE(AIL_set_sample_playback_rate, "_AIL_set_sample_playback_rate@8"); + MILES_RESOLVE(AIL_sample_playback_rate, "_AIL_sample_playback_rate@4"); + MILES_RESOLVE(AIL_sample_ms_position, "_AIL_sample_ms_position@12"); + MILES_RESOLVE(AIL_set_sample_ms_position, "_AIL_set_sample_ms_position@8"); + MILES_RESOLVE(AIL_sample_loop_count, "_AIL_sample_loop_count@4"); + MILES_RESOLVE(AIL_set_sample_loop_count, "_AIL_set_sample_loop_count@8"); + MILES_RESOLVE(AIL_end_sample, "_AIL_end_sample@4"); + MILES_RESOLVE(AIL_resume_sample, "_AIL_resume_sample@4"); + MILES_RESOLVE(AIL_stop_sample, "_AIL_stop_sample@4"); + MILES_RESOLVE(AIL_start_sample, "_AIL_start_sample@4"); + MILES_RESOLVE(AIL_init_sample, "_AIL_init_sample@4"); + MILES_RESOLVE(AIL_set_named_sample_file, "_AIL_set_named_sample_file@20"); + MILES_RESOLVE(AIL_set_3D_sample_effects_level, "_AIL_set_3D_sample_effects_level@8"); + MILES_RESOLVE(AIL_set_3D_sample_distances, "_AIL_set_3D_sample_distances@12"); + MILES_RESOLVE(AIL_set_3D_velocity_vector, "_AIL_set_3D_velocity_vector@16"); + MILES_RESOLVE(AIL_set_3D_position, "_AIL_set_3D_position@16"); + MILES_RESOLVE(AIL_set_3D_orientation, "_AIL_set_3D_orientation@28"); + MILES_RESOLVE(AIL_WAV_info, "_AIL_WAV_info@8"); + MILES_RESOLVE(AIL_stop_timer, "_AIL_stop_timer@4"); + MILES_RESOLVE(AIL_release_timer_handle, "_AIL_release_timer_handle@4"); + MILES_RESOLVE(AIL_shutdown, "_AIL_shutdown@0"); + MILES_RESOLVE(AIL_enumerate_filters, "_AIL_enumerate_filters@12"); + MILES_RESOLVE(AIL_set_file_callbacks, "_AIL_set_file_callbacks@16"); + MILES_RESOLVE(AIL_release_3D_sample_handle, "_AIL_release_3D_sample_handle@4"); + MILES_RESOLVE(AIL_allocate_3D_sample_handle, "_AIL_allocate_3D_sample_handle@4"); + MILES_RESOLVE(AIL_set_3D_user_data, "_AIL_set_3D_user_data@12"); + MILES_RESOLVE(AIL_unlock, "_AIL_unlock@0"); + MILES_RESOLVE(AIL_unlock_mutex, "_AIL_unlock_mutex@0"); + MILES_RESOLVE(AIL_lock, "_AIL_lock@0"); + MILES_RESOLVE(AIL_lock_mutex, "_AIL_lock_mutex@0"); + MILES_RESOLVE(AIL_set_3D_speaker_type, "_AIL_set_3D_speaker_type@8"); + MILES_RESOLVE(AIL_close_3D_listener, "_AIL_close_3D_listener@4"); + MILES_RESOLVE(AIL_enumerate_3D_providers, "_AIL_enumerate_3D_providers@12"); + MILES_RESOLVE(AIL_open_3D_provider, "_AIL_open_3D_provider@4"); + MILES_RESOLVE(AIL_last_error, "_AIL_last_error@0"); + MILES_RESOLVE(AIL_open_3D_listener, "_AIL_open_3D_listener@4"); + MILES_RESOLVE(AIL_3D_user_data, "_AIL_3D_user_data@8"); + MILES_RESOLVE(AIL_sample_user_data, "_AIL_sample_user_data@8"); + MILES_RESOLVE(AIL_allocate_sample_handle, "_AIL_allocate_sample_handle@4"); + MILES_RESOLVE(AIL_set_sample_user_data, "_AIL_set_sample_user_data@12"); + MILES_RESOLVE(AIL_decompress_ADPCM, "_AIL_decompress_ADPCM@12"); + MILES_RESOLVE(AIL_get_DirectSound_info, "_AIL_get_DirectSound_info@12"); + MILES_RESOLVE(AIL_mem_free_lock, "_AIL_mem_free_lock@4"); + MILES_RESOLVE(AIL_open_stream, "_AIL_open_stream@12"); + MILES_RESOLVE(AIL_startup, "_AIL_startup@0"); + MILES_RESOLVE(AIL_quick_unload, "_AIL_quick_unload@4"); + MILES_RESOLVE(AIL_quick_load_and_play, "_AIL_quick_load_and_play@12"); + MILES_RESOLVE(AIL_quick_set_volume, "_AIL_quick_set_volume@12"); + MILES_RESOLVE(AIL_quick_startup, "_AIL_quick_startup@20"); + MILES_RESOLVE(AIL_quick_handles, "_AIL_quick_handles@12"); + MILES_RESOLVE(AIL_sample_volume_pan, "_AIL_sample_volume_pan@12"); + MILES_RESOLVE(AIL_set_3D_sample_occlusion, "_AIL_set_3D_sample_occlusion@8"); + MILES_RESOLVE(AIL_set_redist_directory, "_AIL_set_redist_directory@4"); + MILES_RESOLVE(AIL_set_sample_file, "_AIL_set_sample_file@12"); + MILES_RESOLVE(AIL_set_sample_volume_pan, "_AIL_set_sample_volume_pan@12"); + MILES_RESOLVE(AIL_set_stream_volume_pan, "_AIL_set_stream_volume_pan@12"); + MILES_RESOLVE(AIL_stream_volume_pan, "_AIL_stream_volume_pan@12"); + MILES_RESOLVE(AIL_get_timer_highest_delay, "_AIL_get_timer_highest_delay@0"); +} +#undef MILES_RESOLVE + +static void freeResources() +{ + if (Module != HMODULE(nullptr)) { + ::FreeLibrary(Module); + Module = HMODULE(nullptr); + } + + AIL_3D_sample_volumePtr = nullptr; + AIL_set_3D_sample_volumePtr = nullptr; + AIL_end_3D_samplePtr = nullptr; + AIL_resume_3D_samplePtr = nullptr; + AIL_stop_3D_samplePtr = nullptr; + AIL_start_3D_samplePtr = nullptr; + AIL_3D_sample_loop_countPtr = nullptr; + AIL_set_3D_sample_offsetPtr = nullptr; + AIL_3D_sample_lengthPtr = nullptr; + AIL_3D_sample_offsetPtr = nullptr; + AIL_3D_sample_playback_ratePtr = nullptr; + AIL_set_3D_sample_playback_ratePtr = nullptr; + AIL_set_3D_sample_filePtr = nullptr; + AIL_set_sample_processorPtr = nullptr; + AIL_set_filter_sample_preferencePtr = nullptr; + AIL_release_sample_handlePtr = nullptr; + AIL_close_3D_providerPtr = nullptr; + AIL_set_preferencePtr = nullptr; + AIL_waveOutOpenPtr = nullptr; + AIL_waveOutClosePtr = nullptr; + AIL_set_3D_sample_loop_countPtr = nullptr; + AIL_set_stream_playback_ratePtr = nullptr; + AIL_stream_playback_ratePtr = nullptr; + AIL_stream_ms_positionPtr = nullptr; + AIL_set_stream_ms_positionPtr = nullptr; + AIL_stream_loop_countPtr = nullptr; + AIL_set_stream_loop_blockPtr = nullptr; + AIL_set_stream_loop_countPtr = nullptr; + AIL_close_streamPtr = nullptr; + AIL_pause_streamPtr = nullptr; + AIL_register_stream_callbackPtr = nullptr; + AIL_register_3D_EOS_callbackPtr = nullptr; + AIL_register_EOS_callbackPtr = nullptr; + AIL_start_streamPtr = nullptr; + AIL_set_sample_playback_ratePtr = nullptr; + AIL_sample_playback_ratePtr = nullptr; + AIL_sample_ms_positionPtr = nullptr; + AIL_set_sample_ms_positionPtr = nullptr; + AIL_sample_loop_countPtr = nullptr; + AIL_set_sample_loop_countPtr = nullptr; + AIL_end_samplePtr = nullptr; + AIL_resume_samplePtr = nullptr; + AIL_stop_samplePtr = nullptr; + AIL_start_samplePtr = nullptr; + AIL_init_samplePtr = nullptr; + AIL_set_named_sample_filePtr = nullptr; + AIL_set_3D_sample_effects_levelPtr = nullptr; + AIL_set_3D_sample_distancesPtr = nullptr; + AIL_set_3D_velocity_vectorPtr = nullptr; + AIL_set_3D_positionPtr = nullptr; + AIL_set_3D_orientationPtr = nullptr; + AIL_WAV_infoPtr = nullptr; + AIL_stop_timerPtr = nullptr; + AIL_release_timer_handlePtr = nullptr; + AIL_shutdownPtr = nullptr; + AIL_enumerate_filtersPtr = nullptr; + AIL_set_file_callbacksPtr = nullptr; + AIL_release_3D_sample_handlePtr = nullptr; + AIL_allocate_3D_sample_handlePtr = nullptr; + AIL_set_3D_user_dataPtr = nullptr; + AIL_unlockPtr = nullptr; + AIL_unlock_mutexPtr = nullptr; + AIL_lockPtr = nullptr; + AIL_lock_mutexPtr = nullptr; + AIL_set_3D_speaker_typePtr = nullptr; + AIL_close_3D_listenerPtr = nullptr; + AIL_enumerate_3D_providersPtr = nullptr; + AIL_open_3D_providerPtr = nullptr; + AIL_last_errorPtr = nullptr; + AIL_open_3D_listenerPtr = nullptr; + AIL_3D_user_dataPtr = nullptr; + AIL_sample_user_dataPtr = nullptr; + AIL_allocate_sample_handlePtr = nullptr; + AIL_set_sample_user_dataPtr = nullptr; + AIL_decompress_ADPCMPtr = nullptr; + AIL_get_DirectSound_infoPtr = nullptr; + AIL_mem_free_lockPtr = nullptr; + AIL_open_streamPtr = nullptr; + AIL_startupPtr = nullptr; + AIL_quick_unloadPtr = nullptr; + AIL_quick_load_and_playPtr = nullptr; + AIL_quick_set_volumePtr = nullptr; + AIL_quick_startupPtr = nullptr; + AIL_quick_handlesPtr = nullptr; + AIL_sample_volume_panPtr = nullptr; + AIL_set_3D_sample_occlusionPtr = nullptr; + AIL_set_redist_directoryPtr = nullptr; + AIL_set_sample_filePtr = nullptr; + AIL_set_sample_volume_panPtr = nullptr; + AIL_set_stream_volume_panPtr = nullptr; + AIL_stream_volume_panPtr = nullptr; + AIL_get_timer_highest_delayPtr = nullptr; +} +#endif // MILES_LOADER_SUPPORTED + +} // namespace + + +bool MilesLoader::isLoaded() +{ +#if MILES_LOADER_SUPPORTED + return Module != HMODULE(nullptr); +#else + return false; +#endif +} + + +bool MilesLoader::isFailed() +{ + return Failed; +} + + +unsigned long MilesLoader::getLastError() +{ + return LastError; +} + + +bool MilesLoader::load() +{ + // Always increment the reference count. + ++ReferenceCount; + + // Optimization: return early if it failed before. + if (Failed) + return false; + + // Return early if someone else already loaded it. + if (ReferenceCount > 1) + return true; + +#if MILES_LOADER_SUPPORTED + // Load mss32.dll by name, so that the usual module search order applies. + Module = ::LoadLibraryA("mss32.dll"); + if (Module == HMODULE(nullptr)) { + LastError = ::GetLastError(); + Failed = true; + return false; + } + + resolveAll(); + return true; +#else + Failed = true; + return false; +#endif +} + + +void MilesLoader::unload() +{ + if (ReferenceCount > 0) + --ReferenceCount; + + if (ReferenceCount > 0) + return; + +#if MILES_LOADER_SUPPORTED + freeResources(); +#endif + Failed = false; + LastError = 0; +} + + +// The Miles functions below stand in for the imports of mss32.dll. An unresolved function returns +// the same neutral value the Miles SDK stub library returned. + + +F32 __stdcall AIL_3D_sample_volume(H3DSAMPLE sample) +{ + return AIL_3D_sample_volumePtr != nullptr ? AIL_3D_sample_volumePtr(sample) : 0.0f; +} + +void __stdcall AIL_set_3D_sample_volume(H3DSAMPLE sample, F32 volume) +{ + if (AIL_set_3D_sample_volumePtr != nullptr) + AIL_set_3D_sample_volumePtr(sample, volume); +} + +void __stdcall AIL_end_3D_sample(H3DSAMPLE sample) +{ + if (AIL_end_3D_samplePtr != nullptr) + AIL_end_3D_samplePtr(sample); +} + +void __stdcall AIL_resume_3D_sample(H3DSAMPLE sample) +{ + if (AIL_resume_3D_samplePtr != nullptr) + AIL_resume_3D_samplePtr(sample); +} + +void __stdcall AIL_stop_3D_sample(H3DSAMPLE sample) +{ + if (AIL_stop_3D_samplePtr != nullptr) + AIL_stop_3D_samplePtr(sample); +} + +void __stdcall AIL_start_3D_sample(H3DSAMPLE sample) +{ + if (AIL_start_3D_samplePtr != nullptr) + AIL_start_3D_samplePtr(sample); +} + +U32 __stdcall AIL_3D_sample_loop_count(H3DSAMPLE sample) +{ + return AIL_3D_sample_loop_countPtr != nullptr ? AIL_3D_sample_loop_countPtr(sample) : 0; +} + +void __stdcall AIL_set_3D_sample_offset(H3DSAMPLE sample, U32 offset) +{ + if (AIL_set_3D_sample_offsetPtr != nullptr) + AIL_set_3D_sample_offsetPtr(sample, offset); +} + +U32 __stdcall AIL_3D_sample_length(H3DSAMPLE sample) +{ + return AIL_3D_sample_lengthPtr != nullptr ? AIL_3D_sample_lengthPtr(sample) : 0; +} + +U32 __stdcall AIL_3D_sample_offset(H3DSAMPLE sample) +{ + return AIL_3D_sample_offsetPtr != nullptr ? AIL_3D_sample_offsetPtr(sample) : 0; +} + +S32 __stdcall AIL_3D_sample_playback_rate(H3DSAMPLE sample) +{ + return AIL_3D_sample_playback_ratePtr != nullptr ? AIL_3D_sample_playback_ratePtr(sample) : 0; +} + +void __stdcall AIL_set_3D_sample_playback_rate(H3DSAMPLE sample, S32 playback_rate) +{ + if (AIL_set_3D_sample_playback_ratePtr != nullptr) + AIL_set_3D_sample_playback_ratePtr(sample, playback_rate); +} + +S32 __stdcall AIL_set_3D_sample_file(H3DSAMPLE sample, const void* file_image) +{ + return AIL_set_3D_sample_filePtr != nullptr ? AIL_set_3D_sample_filePtr(sample, file_image) : 0; +} + +HPROVIDER __stdcall AIL_set_sample_processor(HSAMPLE sample, SAMPLESTAGE pipeline_stage, HPROVIDER provider) +{ + return AIL_set_sample_processorPtr != nullptr + ? AIL_set_sample_processorPtr(sample, pipeline_stage, provider) + : nullptr; +} + +void __stdcall AIL_set_filter_sample_preference(HSAMPLE sample, const char* name, const void* val) +{ + if (AIL_set_filter_sample_preferencePtr != nullptr) + AIL_set_filter_sample_preferencePtr(sample, name, val); +} + +void __stdcall AIL_release_sample_handle(HSAMPLE sample) +{ + if (AIL_release_sample_handlePtr != nullptr) + AIL_release_sample_handlePtr(sample); +} + +void __stdcall AIL_close_3D_provider(HPROVIDER lib) +{ + if (AIL_close_3D_providerPtr != nullptr) + AIL_close_3D_providerPtr(lib); +} + +S32 __stdcall AIL_set_preference(U32 number, S32 value) +{ + return AIL_set_preferencePtr != nullptr ? AIL_set_preferencePtr(number, value) : 0; +} + +S32 __stdcall AIL_waveOutOpen(HDIGDRIVER* driver, LPHWAVEOUT* waveout, S32 id, LPWAVEFORMAT format) +{ + if (AIL_waveOutOpenPtr != nullptr) + return AIL_waveOutOpenPtr(driver, waveout, id, format); + + if (driver != nullptr) + *driver = nullptr; + if (waveout != nullptr) + *waveout = nullptr; + return 1; +} + +void __stdcall AIL_waveOutClose(HDIGDRIVER driver) +{ + if (AIL_waveOutClosePtr != nullptr) + AIL_waveOutClosePtr(driver); +} + +void __stdcall AIL_set_3D_sample_loop_count(H3DSAMPLE sample, U32 count) +{ + if (AIL_set_3D_sample_loop_countPtr != nullptr) + AIL_set_3D_sample_loop_countPtr(sample, count); +} + +void __stdcall AIL_set_stream_playback_rate(HSTREAM stream, S32 rate) +{ + if (AIL_set_stream_playback_ratePtr != nullptr) + AIL_set_stream_playback_ratePtr(stream, rate); +} + +S32 __stdcall AIL_stream_playback_rate(HSTREAM stream) +{ + return AIL_stream_playback_ratePtr != nullptr ? AIL_stream_playback_ratePtr(stream) : 0; +} + +void __stdcall AIL_stream_ms_position(HSTREAM sample, S32* total_milliseconds, S32* current_milliseconds) +{ + if (AIL_stream_ms_positionPtr != nullptr) + { + AIL_stream_ms_positionPtr(sample, total_milliseconds, current_milliseconds); + return; + } + + if (total_milliseconds != nullptr) + *total_milliseconds = 0; + if (current_milliseconds != nullptr) + *current_milliseconds = 0; +} + +void __stdcall AIL_set_stream_ms_position(HSTREAM stream, S32 pos) +{ + if (AIL_set_stream_ms_positionPtr != nullptr) + AIL_set_stream_ms_positionPtr(stream, pos); +} + +S32 __stdcall AIL_stream_loop_count(HSTREAM stream) +{ + return AIL_stream_loop_countPtr != nullptr ? AIL_stream_loop_countPtr(stream) : 0; +} + +void __stdcall AIL_set_stream_loop_block(HSTREAM stream, S32 loop_start, S32 loop_end) +{ + if (AIL_set_stream_loop_blockPtr != nullptr) + AIL_set_stream_loop_blockPtr(stream, loop_start, loop_end); +} + +void __stdcall AIL_set_stream_loop_count(HSTREAM stream, S32 count) +{ + if (AIL_set_stream_loop_countPtr != nullptr) + AIL_set_stream_loop_countPtr(stream, count); +} + +void __stdcall AIL_close_stream(HSTREAM stream) +{ + if (AIL_close_streamPtr != nullptr) + AIL_close_streamPtr(stream); +} + +void __stdcall AIL_pause_stream(HSTREAM stream, S32 onoff) +{ + if (AIL_pause_streamPtr != nullptr) + AIL_pause_streamPtr(stream, onoff); +} + +AIL_stream_callback __stdcall AIL_register_stream_callback(HSTREAM stream, AIL_stream_callback callback) +{ + return AIL_register_stream_callbackPtr != nullptr ? AIL_register_stream_callbackPtr(stream, callback) : nullptr; +} + +AIL_3dsample_callback __stdcall AIL_register_3D_EOS_callback(H3DSAMPLE sample, AIL_3dsample_callback EOS) +{ + return AIL_register_3D_EOS_callbackPtr != nullptr ? AIL_register_3D_EOS_callbackPtr(sample, EOS) : nullptr; +} + +AIL_sample_callback __stdcall AIL_register_EOS_callback(HSAMPLE sample, AIL_sample_callback EOS) +{ + return AIL_register_EOS_callbackPtr != nullptr ? AIL_register_EOS_callbackPtr(sample, EOS) : nullptr; +} + +void __stdcall AIL_start_stream(HSTREAM stream) +{ + if (AIL_start_streamPtr != nullptr) + AIL_start_streamPtr(stream); +} + +void __stdcall AIL_set_sample_playback_rate(HSAMPLE sample, S32 playback_rate) +{ + if (AIL_set_sample_playback_ratePtr != nullptr) + AIL_set_sample_playback_ratePtr(sample, playback_rate); +} + +S32 __stdcall AIL_sample_playback_rate(HSAMPLE sample) +{ + return AIL_sample_playback_ratePtr != nullptr ? AIL_sample_playback_ratePtr(sample) : 0; +} + +void __stdcall AIL_sample_ms_position(HSAMPLE sample, S32* total_ms, S32* current_ms) +{ + if (AIL_sample_ms_positionPtr != nullptr) + { + AIL_sample_ms_positionPtr(sample, total_ms, current_ms); + return; + } + + if (total_ms != nullptr) + *total_ms = 0; + if (current_ms != nullptr) + *current_ms = 0; +} + +void __stdcall AIL_set_sample_ms_position(HSAMPLE sample, S32 pos) +{ + if (AIL_set_sample_ms_positionPtr != nullptr) + AIL_set_sample_ms_positionPtr(sample, pos); +} + +S32 __stdcall AIL_sample_loop_count(HSAMPLE sample) +{ + return AIL_sample_loop_countPtr != nullptr ? AIL_sample_loop_countPtr(sample) : 0; +} + +void __stdcall AIL_set_sample_loop_count(HSAMPLE sample, S32 count) +{ + if (AIL_set_sample_loop_countPtr != nullptr) + AIL_set_sample_loop_countPtr(sample, count); +} + +void __stdcall AIL_end_sample(HSAMPLE sample) +{ + if (AIL_end_samplePtr != nullptr) + AIL_end_samplePtr(sample); +} + +void __stdcall AIL_resume_sample(HSAMPLE sample) +{ + if (AIL_resume_samplePtr != nullptr) + AIL_resume_samplePtr(sample); +} + +void __stdcall AIL_stop_sample(HSAMPLE sample) +{ + if (AIL_stop_samplePtr != nullptr) + AIL_stop_samplePtr(sample); +} + +void __stdcall AIL_start_sample(HSAMPLE sample) +{ + if (AIL_start_samplePtr != nullptr) + AIL_start_samplePtr(sample); +} + +void __stdcall AIL_init_sample(HSAMPLE sample) +{ + if (AIL_init_samplePtr != nullptr) + AIL_init_samplePtr(sample); +} + +S32 __stdcall AIL_set_named_sample_file(HSAMPLE sample, const char* file_name, const void* file_image, S32 file_size, S32 block) +{ + return AIL_set_named_sample_filePtr != nullptr + ? AIL_set_named_sample_filePtr(sample, file_name, file_image, file_size, block) + : 0; +} + +void __stdcall AIL_set_3D_sample_effects_level(H3DSAMPLE sample, F32 effect_level) +{ + if (AIL_set_3D_sample_effects_levelPtr != nullptr) + AIL_set_3D_sample_effects_levelPtr(sample, effect_level); +} + +void __stdcall AIL_set_3D_sample_distances(H3DSAMPLE sample, F32 max_dist, F32 min_dist) +{ + if (AIL_set_3D_sample_distancesPtr != nullptr) + AIL_set_3D_sample_distancesPtr(sample, max_dist, min_dist); +} + +void __stdcall AIL_set_3D_velocity_vector(H3DPOBJECT obj, F32 x, F32 y, F32 z) +{ + if (AIL_set_3D_velocity_vectorPtr != nullptr) + AIL_set_3D_velocity_vectorPtr(obj, x, y, z); +} + +void __stdcall AIL_set_3D_position(H3DPOBJECT obj, F32 X, F32 Y, F32 Z) +{ + if (AIL_set_3D_positionPtr != nullptr) + AIL_set_3D_positionPtr(obj, X, Y, Z); +} + +void __stdcall AIL_set_3D_orientation(H3DPOBJECT obj, F32 X_face, F32 Y_face, F32 Z_face, F32 X_up, F32 Y_up, F32 Z_up) +{ + if (AIL_set_3D_orientationPtr != nullptr) + AIL_set_3D_orientationPtr(obj, X_face, Y_face, Z_face, X_up, Y_up, Z_up); +} + +S32 __stdcall AIL_WAV_info(const void* data, AILSOUNDINFO* info) +{ + if (AIL_WAV_infoPtr != nullptr) + return AIL_WAV_infoPtr(data, info); + + if (info != nullptr) + { + info->format = 0; + info->data_ptr = nullptr; + info->data_len = 0; + info->rate = 0; + info->bits = 0; + info->channels = 0; + info->samples = 0; + info->block_size = 0; + info->initial_ptr = nullptr; + } + return 0; +} + +void __stdcall AIL_stop_timer(HTIMER timer) +{ + if (AIL_stop_timerPtr != nullptr) + AIL_stop_timerPtr(timer); +} + +void __stdcall AIL_release_timer_handle(HTIMER timer) +{ + if (AIL_release_timer_handlePtr != nullptr) + AIL_release_timer_handlePtr(timer); +} + +void __stdcall AIL_shutdown(void) +{ + if (AIL_shutdownPtr != nullptr) + AIL_shutdownPtr(); +} + +S32 __stdcall AIL_enumerate_filters(HPROENUM* next, HPROVIDER* dest, char** name) +{ + if (AIL_enumerate_filtersPtr != nullptr) + return AIL_enumerate_filtersPtr(next, dest, name); + + if (dest != nullptr) + *dest = nullptr; + if (name != nullptr) + *name = nullptr; + return 0; +} + +void __stdcall AIL_set_file_callbacks(AIL_file_open_callback opencb, AIL_file_close_callback closecb, AIL_file_seek_callback seekcb, AIL_file_read_callback readcb) +{ + if (AIL_set_file_callbacksPtr != nullptr) + AIL_set_file_callbacksPtr(opencb, closecb, seekcb, readcb); +} + +void __stdcall AIL_release_3D_sample_handle(H3DSAMPLE sample) +{ + if (AIL_release_3D_sample_handlePtr != nullptr) + AIL_release_3D_sample_handlePtr(sample); +} + +H3DSAMPLE __stdcall AIL_allocate_3D_sample_handle(HPROVIDER lib) +{ + return AIL_allocate_3D_sample_handlePtr != nullptr ? AIL_allocate_3D_sample_handlePtr(lib) : nullptr; +} + +void __stdcall AIL_set_3D_user_data(H3DPOBJECT obj, U32 index, S32 value) +{ + if (AIL_set_3D_user_dataPtr != nullptr) + AIL_set_3D_user_dataPtr(obj, index, value); +} + +void __stdcall AIL_unlock(void) +{ + if (AIL_unlockPtr != nullptr) + AIL_unlockPtr(); +} + +void __stdcall AIL_unlock_mutex(void) +{ + if (AIL_unlock_mutexPtr != nullptr) + AIL_unlock_mutexPtr(); +} + +void __stdcall AIL_lock(void) +{ + if (AIL_lockPtr != nullptr) + AIL_lockPtr(); +} + +void __stdcall AIL_lock_mutex(void) +{ + if (AIL_lock_mutexPtr != nullptr) + AIL_lock_mutexPtr(); +} + +void __stdcall AIL_set_3D_speaker_type(HPROVIDER lib, S32 speaker_type) +{ + if (AIL_set_3D_speaker_typePtr != nullptr) + AIL_set_3D_speaker_typePtr(lib, speaker_type); +} + +void __stdcall AIL_close_3D_listener(H3DPOBJECT listener) +{ + if (AIL_close_3D_listenerPtr != nullptr) + AIL_close_3D_listenerPtr(listener); +} + +S32 __stdcall AIL_enumerate_3D_providers(HPROENUM* next, HPROVIDER* dest, char** name) +{ + if (AIL_enumerate_3D_providersPtr != nullptr) + return AIL_enumerate_3D_providersPtr(next, dest, name); + + if (dest != nullptr) + *dest = nullptr; + if (name != nullptr) + *name = nullptr; + return 0; +} + +M3DRESULT __stdcall AIL_open_3D_provider(HPROVIDER lib) +{ + return AIL_open_3D_providerPtr != nullptr ? AIL_open_3D_providerPtr(lib) : 1; +} + +char* __stdcall AIL_last_error(void) +{ + return AIL_last_errorPtr != nullptr ? AIL_last_errorPtr() : nullptr; +} + +H3DPOBJECT __stdcall AIL_open_3D_listener(HPROVIDER lib) +{ + return AIL_open_3D_listenerPtr != nullptr ? AIL_open_3D_listenerPtr(lib) : nullptr; +} + +S32 __stdcall AIL_3D_user_data(H3DPOBJECT obj, U32 index) +{ + return AIL_3D_user_dataPtr != nullptr ? AIL_3D_user_dataPtr(obj, index) : 0; +} + +S32 __stdcall AIL_sample_user_data(HSAMPLE sample, U32 index) +{ + return AIL_sample_user_dataPtr != nullptr ? AIL_sample_user_dataPtr(sample, index) : 0; +} + +HSAMPLE __stdcall AIL_allocate_sample_handle(HDIGDRIVER dig) +{ + return AIL_allocate_sample_handlePtr != nullptr ? AIL_allocate_sample_handlePtr(dig) : nullptr; +} + +void __stdcall AIL_set_sample_user_data(HSAMPLE sample, U32 index, S32 value) +{ + if (AIL_set_sample_user_dataPtr != nullptr) + AIL_set_sample_user_dataPtr(sample, index, value); +} + +S32 __stdcall AIL_decompress_ADPCM(const AILSOUNDINFO *info, void **outdata, U32 *outsize) +{ + if (AIL_decompress_ADPCMPtr != nullptr) + return AIL_decompress_ADPCMPtr(info, outdata, outsize); + + if (outdata != nullptr) + *outdata = nullptr; + if (outsize != nullptr) + *outsize = 0; + return 0; +} + +void __stdcall AIL_get_DirectSound_info(HSAMPLE sample, AILLPDIRECTSOUND *lplpDS, AILLPDIRECTSOUNDBUFFER *lplpDSB) +{ + if (AIL_get_DirectSound_infoPtr != nullptr) + { + AIL_get_DirectSound_infoPtr(sample, lplpDS, lplpDSB); + return; + } + + if (lplpDS != nullptr) + *lplpDS = nullptr; + if (lplpDSB != nullptr) + *lplpDSB = nullptr; +} + +void __stdcall AIL_mem_free_lock(void *ptr) +{ + if (AIL_mem_free_lockPtr != nullptr) + AIL_mem_free_lockPtr(ptr); +} + +HSTREAM __stdcall AIL_open_stream(HDIGDRIVER dig, const char *filename, S32 stream_mem) +{ + return AIL_open_streamPtr != nullptr ? AIL_open_streamPtr(dig, filename, stream_mem) : nullptr; +} + +S32 __stdcall AIL_startup(void) +{ + return AIL_startupPtr != nullptr ? AIL_startupPtr() : 0; +} + +void __stdcall AIL_quick_unload(HAUDIO audio) +{ + if (AIL_quick_unloadPtr != nullptr) + AIL_quick_unloadPtr(audio); +} + +HAUDIO __stdcall AIL_quick_load_and_play(const char *filename, U32 loop_count, S32 wait_request) +{ + return AIL_quick_load_and_playPtr != nullptr + ? AIL_quick_load_and_playPtr(filename, loop_count, wait_request) + : nullptr; +} + +void __stdcall AIL_quick_set_volume(HAUDIO audio, F32 volume, F32 extravol) +{ + if (AIL_quick_set_volumePtr != nullptr) + AIL_quick_set_volumePtr(audio, volume, extravol); +} + +S32 __stdcall AIL_quick_startup(S32 use_digital, S32 use_MIDI, U32 output_rate, S32 output_bits, S32 output_channels) +{ + return AIL_quick_startupPtr != nullptr + ? AIL_quick_startupPtr(use_digital, use_MIDI, output_rate, output_bits, output_channels) + : 0; +} + +void __stdcall AIL_quick_handles(HDIGDRIVER *pdig, HMDIDRIVER *pmdi, HDLSDEVICE *pdls) +{ + if (AIL_quick_handlesPtr != nullptr) + { + AIL_quick_handlesPtr(pdig, pmdi, pdls); + return; + } + + if (pdig != nullptr) + *pdig = nullptr; + if (pmdi != nullptr) + *pmdi = nullptr; + if (pdls != nullptr) + *pdls = nullptr; +} + +void __stdcall AIL_sample_volume_pan(HSAMPLE sample, F32 *volume, F32 *pan) +{ + if (AIL_sample_volume_panPtr != nullptr) + { + AIL_sample_volume_panPtr(sample, volume, pan); + return; + } + + if (volume != nullptr) + *volume = 0.0f; + if (pan != nullptr) + *pan = 0.5f; +} + +void __stdcall AIL_set_3D_sample_occlusion(H3DSAMPLE sample, F32 occlusion) +{ + if (AIL_set_3D_sample_occlusionPtr != nullptr) + AIL_set_3D_sample_occlusionPtr(sample, occlusion); +} + +char * __stdcall AIL_set_redist_directory(const char *dir) +{ + return AIL_set_redist_directoryPtr != nullptr ? AIL_set_redist_directoryPtr(dir) : nullptr; +} + +S32 __stdcall AIL_set_sample_file(HSAMPLE sample, const void *file_image, S32 block) +{ + return AIL_set_sample_filePtr != nullptr ? AIL_set_sample_filePtr(sample, file_image, block) : 0; +} + +void __stdcall AIL_set_sample_volume_pan(HSAMPLE sample, F32 volume, F32 pan) +{ + if (AIL_set_sample_volume_panPtr != nullptr) + AIL_set_sample_volume_panPtr(sample, volume, pan); +} + +void __stdcall AIL_set_stream_volume_pan(HSTREAM stream, F32 volume, F32 pan) +{ + if (AIL_set_stream_volume_panPtr != nullptr) + AIL_set_stream_volume_panPtr(stream, volume, pan); +} + +void __stdcall AIL_stream_volume_pan(HSTREAM stream, F32 *volume, F32 *pan) +{ + if (AIL_stream_volume_panPtr != nullptr) + { + AIL_stream_volume_panPtr(stream, volume, pan); + return; + } + + if (volume != nullptr) + *volume = 0.0f; + if (pan != nullptr) + *pan = 0.5f; +} + +U32 __stdcall AIL_get_timer_highest_delay(void) +{ + return AIL_get_timer_highest_delayPtr != nullptr ? AIL_get_timer_highest_delayPtr() : 0; +} diff --git a/Dependencies/Miles/MilesLoader.h b/Dependencies/Miles/MilesLoader.h new file mode 100644 index 00000000000..4029ea35f48 --- /dev/null +++ b/Dependencies/Miles/MilesLoader.h @@ -0,0 +1,54 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program. If not, see . +*/ + +#pragma once + +// This static class loads and unloads mss32.dll at runtime. +// +// The Miles functions declared in mss/mss.h are implemented in this class and forward to +// the matching export of the loaded module. Loading the module explicitly, rather than importing +// mss32.dll into the executable, is what allows the library to be picked up from a working +// directory that was chosen on the command line, because the process no longer needs to resolve +// it before WinMain runs. +// +// A missing export is not an error. The retail mss32.dll does not export every function the +// engine was built against, and an unresolved function returns the same neutral value the Miles +// SDK stub library used to return. A missing mss32.dll therefore disables audio instead of +// preventing the program from starting. +// +// Is not thread safe. Every call to load needs a paired call to unload, no matter if the load +// was successful. Both are expected to be called from the main thread, before AIL_startup has +// created the Miles timer thread and after AIL_shutdown has ended it, which is why the forwarding +// functions can stay free of locking. + +class MilesLoader +{ +public: + + // Returns whether mss32.dll is loaded + static bool isLoaded(); + + // Returns whether mss32.dll was attempted to be loaded but failed + static bool isFailed(); + + // Returns the system error code of the failed load attempt + static unsigned long getLastError(); + + static bool load(); + static void unload(); +}; diff --git a/Dependencies/Miles/mss/mss.h b/Dependencies/Miles/mss/mss.h new file mode 100644 index 00000000000..1203a40e91a --- /dev/null +++ b/Dependencies/Miles/mss/mss.h @@ -0,0 +1,272 @@ +/** + * @file + * + * @author OmniBlade + * + * @brief Subset of the mss32.dll API as used by the W3D engine. + * + * @copyright This is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 3 of the License, or (at your option) any later version. + * A full copy of the GNU General Public License can be found in + * LICENSE + */ + +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifndef WIN32_EXTRA_LEAN +#define WIN32_EXTRA_LEAN +#endif + +#ifndef STRICT +#define STRICT +#endif + +#ifdef _WIN32 +#include +#include +#else +typedef struct WAVEOUT* HWAVEOUT; +typedef struct WAVEHDR* LPWAVEHDR; +typedef struct WAVEFORMAT *LPWAVEFORMAT; +#include + +typedef struct WAVEFORMAT +{ + uint16_t wFormatTag; + uint16_t nChannels; + uint32_t nSamplesPerSec; + uint32_t nAvgBytesPerSec; + uint16_t nBlockAlign; + uint16_t wBitsPerSample; + uint16_t cbSize; +} WAVEFORMAT; + +typedef struct PCMWAVEFORMAT +{ + WAVEFORMAT wf; + uint16_t wBitsPerSample; +} PCMWAVEFORMAT; + +#define WAVE_FORMAT_PCM 0x0001 + +typedef HWAVEOUT *LPHWAVEOUT; +#endif + +#if !defined _MSC_VER +#if !defined(__stdcall) +#if defined __has_attribute && __has_attribute(stdcall) +#define __stdcall __attribute__((stdcall)) +#else +#define __stdcall +#endif +#endif /* !defined __stdcall */ +#endif /* !defined COMPILER_MSVC */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long U32; +typedef long S32; +typedef float F32; + +/* + * These will have been structs in the real SDK headers, but are only accessed through pointers + * so we don't care unless access to the internals is required. + */ +typedef struct h3DPOBJECT +{ + unsigned int junk; +} h3DPOBJECT; +typedef h3DPOBJECT *H3DPOBJECT; +typedef H3DPOBJECT H3DSAMPLE; +typedef struct _SAMPLE *HSAMPLE; +typedef struct _STREAM *HSTREAM; +typedef struct _DIG_DRIVER +{ + char pad[168]; + int emulated_ds; // We only care about this particular member for our purposes. +} DIG_DRIVER; +typedef struct _DIG_DRIVER *HDIGDRIVER; +typedef struct _AUDIO *HAUDIO; +typedef struct _HMDIDRIVER *HMDIDRIVER; +typedef struct _HDLSDEVICE *HDLSDEVICE; +typedef void *HPROVIDER; +typedef S32 HTIMER; +typedef U32 HPROENUM; +typedef S32 M3DRESULT; + +typedef void *AILLPDIRECTSOUND; +typedef void *AILLPDIRECTSOUNDBUFFER; + +typedef struct _AILSOUNDINFO +{ + S32 format; + const void *data_ptr; + U32 data_len; + U32 rate; + S32 bits; + S32 channels; + U32 samples; + U32 block_size; + const void *initial_ptr; +} AILSOUNDINFO; + +typedef enum +{ + DP_ASI_DECODER = 0, // Must be "ASI codec stream" provider + DP_FILTER, // Must be "MSS pipeline filter" provider + DP_MERGE, // Must be "MSS mixer" provider + N_SAMPLE_STAGES, // Placeholder for end of list (= # of valid stages) + SAMPLE_ALL_STAGES // Used to signify all pipeline stages, for shutdown +} SAMPLESTAGE; + +#define AILCALLBACK __stdcall + +#define AIL_set_3D_object_user_data AIL_set_3D_user_data +#define AIL_3D_object_user_data AIL_3D_user_data +#define AIL_3D_open_listener AIL_open_3D_listener + +/* + * Various callback typedefs. + */ +typedef U32(__stdcall *AIL_file_open_callback)(const char *, void**); +typedef void(__stdcall *AIL_file_close_callback)(void*); +typedef S32(__stdcall *AIL_file_seek_callback)(void*, S32, U32); +typedef U32(__stdcall *AIL_file_read_callback)(void*, void *, U32); +typedef void(__stdcall *AIL_stream_callback)(HSTREAM); +typedef void(__stdcall *AIL_3dsample_callback)(H3DPOBJECT); +typedef void(__stdcall *AIL_sample_callback)(HSAMPLE); + +#define DIG_USE_WAVEOUT 15 +#define AIL_LOCK_PROTECTION 18 +#define WAVE_FORMAT_IMA_ADPCM 0x11 +#define ENVIRONMENT_GENERIC 0 +#define HPROENUM_FIRST 0 +#define AIL_NO_ERROR 0 +#define AIL_FILE_SEEK_BEGIN 0 +#define AIL_FILE_SEEK_CURRENT 1 +#define AIL_FILE_SEEK_END 2 +#define AIL_3D_2_SPEAKER 0 +#define AIL_3D_HEADPHONE 1 +#define AIL_3D_SURROUND 2 +#define AIL_3D_4_SPEAKER 3 +#define AIL_3D_51_SPEAKER 4 +#define AIL_3D_71_SPEAKER 5 +#define AIL_MSS_version(a, b) +#define M3D_NOERR 0 + +#ifndef YES +#define YES 1 +#endif + +#ifndef NO +#define NO 0 +#endif + +F32 __stdcall AIL_3D_sample_volume(H3DSAMPLE sample); +void __stdcall AIL_set_3D_sample_volume(H3DSAMPLE sample, F32 volume); +void __stdcall AIL_end_3D_sample(H3DSAMPLE sample); +void __stdcall AIL_resume_3D_sample(H3DSAMPLE sample); +void __stdcall AIL_stop_3D_sample(H3DSAMPLE sample); +void __stdcall AIL_start_3D_sample(H3DSAMPLE sample); +U32 __stdcall AIL_3D_sample_loop_count(H3DSAMPLE sample); +void __stdcall AIL_set_3D_sample_offset(H3DSAMPLE sample, U32 offset); +U32 __stdcall AIL_3D_sample_length(H3DSAMPLE sample); +U32 __stdcall AIL_3D_sample_offset(H3DSAMPLE sample); +S32 __stdcall AIL_3D_sample_playback_rate(H3DSAMPLE sample); +void __stdcall AIL_set_3D_sample_playback_rate(H3DSAMPLE sample, S32 playback_rate); +S32 __stdcall AIL_set_3D_sample_file(H3DSAMPLE sample, const void* file_image); +HPROVIDER __stdcall AIL_set_sample_processor(HSAMPLE sample, SAMPLESTAGE pipeline_stage, HPROVIDER provider); +void __stdcall AIL_set_filter_sample_preference(HSAMPLE sample, const char* name, const void* val); +void __stdcall AIL_release_sample_handle(HSAMPLE sample); +void __stdcall AIL_close_3D_provider(HPROVIDER lib); +S32 __stdcall AIL_set_preference(U32 number, S32 value); +S32 __stdcall AIL_waveOutOpen(HDIGDRIVER* driver, LPHWAVEOUT* waveout, S32 id, LPWAVEFORMAT format); +void __stdcall AIL_waveOutClose(HDIGDRIVER driver); +void __stdcall AIL_set_3D_sample_loop_count(H3DSAMPLE sample, U32 count); +void __stdcall AIL_set_stream_playback_rate(HSTREAM stream, S32 rate); +S32 __stdcall AIL_stream_playback_rate(HSTREAM stream); +void __stdcall AIL_stream_ms_position(HSTREAM sample, S32* total_milliseconds, S32* current_milliseconds); +void __stdcall AIL_set_stream_ms_position(HSTREAM stream, S32 pos); +S32 __stdcall AIL_stream_loop_count(HSTREAM stream); +void __stdcall AIL_set_stream_loop_block(HSTREAM stream, S32 loop_start, S32 loop_end); +void __stdcall AIL_set_stream_loop_count(HSTREAM stream, S32 count); +void __stdcall AIL_close_stream(HSTREAM stream); +void __stdcall AIL_pause_stream(HSTREAM stream, S32 onoff); +AIL_stream_callback __stdcall AIL_register_stream_callback(HSTREAM stream, AIL_stream_callback callback); +AIL_3dsample_callback __stdcall AIL_register_3D_EOS_callback(H3DSAMPLE sample, AIL_3dsample_callback EOS); +AIL_sample_callback __stdcall AIL_register_EOS_callback(HSAMPLE sample, AIL_sample_callback EOS); +void __stdcall AIL_start_stream(HSTREAM stream); +void __stdcall AIL_set_sample_playback_rate(HSAMPLE sample, S32 playback_rate); +S32 __stdcall AIL_sample_playback_rate(HSAMPLE sample); +void __stdcall AIL_sample_ms_position(HSAMPLE sample, S32* total_ms, S32* current_ms); +void __stdcall AIL_set_sample_ms_position(HSAMPLE sample, S32 pos); +S32 __stdcall AIL_sample_loop_count(HSAMPLE sample); +void __stdcall AIL_set_sample_loop_count(HSAMPLE sample, S32 count); +void __stdcall AIL_end_sample(HSAMPLE sample); +void __stdcall AIL_resume_sample(HSAMPLE sample); +void __stdcall AIL_stop_sample(HSAMPLE sample); +void __stdcall AIL_start_sample(HSAMPLE sample); +void __stdcall AIL_init_sample(HSAMPLE sample); +S32 __stdcall AIL_set_named_sample_file( + HSAMPLE sample, const char* file_name, const void* file_image, S32 file_size, S32 block); +void __stdcall AIL_set_3D_sample_effects_level(H3DSAMPLE sample, F32 effect_level); +void __stdcall AIL_set_3D_sample_distances(H3DSAMPLE sample, F32 max_dist, F32 min_dist); +void __stdcall AIL_set_3D_velocity_vector(H3DPOBJECT obj, F32 x, F32 y, F32 z); +void __stdcall AIL_set_3D_position(H3DPOBJECT obj, F32 X, F32 Y, F32 Z); +void __stdcall AIL_set_3D_orientation( + H3DPOBJECT obj, F32 X_face, F32 Y_face, F32 Z_face, F32 X_up, F32 Y_up, F32 Z_up); +S32 __stdcall AIL_WAV_info(const void* data, AILSOUNDINFO* info); +void __stdcall AIL_stop_timer(HTIMER timer); +void __stdcall AIL_release_timer_handle(HTIMER timer); +void __stdcall AIL_shutdown(void); +S32 __stdcall AIL_enumerate_filters(HPROENUM* next, HPROVIDER* dest, char** name); +void __stdcall AIL_set_file_callbacks(AIL_file_open_callback opencb, AIL_file_close_callback closecb, + AIL_file_seek_callback seekcb, AIL_file_read_callback readcb); +void __stdcall AIL_release_3D_sample_handle(H3DSAMPLE sample); +H3DSAMPLE __stdcall AIL_allocate_3D_sample_handle(HPROVIDER lib); +void __stdcall AIL_set_3D_user_data(H3DPOBJECT obj, U32 index, S32 value); +void __stdcall AIL_unlock(void); +void __stdcall AIL_unlock_mutex(void); +void __stdcall AIL_lock(void); +void __stdcall AIL_lock_mutex(void); +void __stdcall AIL_set_3D_speaker_type(HPROVIDER lib, S32 speaker_type); +void __stdcall AIL_close_3D_listener(H3DPOBJECT listener); +S32 __stdcall AIL_enumerate_3D_providers(HPROENUM* next, HPROVIDER* dest, char** name); +M3DRESULT __stdcall AIL_open_3D_provider(HPROVIDER lib); +char* __stdcall AIL_last_error(void); +H3DPOBJECT __stdcall AIL_open_3D_listener(HPROVIDER lib); +S32 __stdcall AIL_3D_user_data(H3DPOBJECT obj, U32 index); +S32 __stdcall AIL_sample_user_data(HSAMPLE sample, U32 index); +HSAMPLE __stdcall AIL_allocate_sample_handle(HDIGDRIVER dig); +void __stdcall AIL_set_sample_user_data(HSAMPLE sample, U32 index, S32 value); +S32 __stdcall AIL_decompress_ADPCM(const AILSOUNDINFO *info, void **outdata, U32 *outsize); +void __stdcall AIL_get_DirectSound_info(HSAMPLE sample, AILLPDIRECTSOUND *lplpDS, AILLPDIRECTSOUNDBUFFER *lplpDSB); +void __stdcall AIL_mem_free_lock(void *ptr); +HSTREAM __stdcall AIL_open_stream(HDIGDRIVER dig, const char *filename, S32 stream_mem); +S32 __stdcall AIL_startup(void); +void __stdcall AIL_quick_unload(HAUDIO audio); +HAUDIO __stdcall AIL_quick_load_and_play(const char *filename, U32 loop_count, S32 wait_request); +void __stdcall AIL_quick_set_volume(HAUDIO audio, F32 volume, F32 extravol); +S32 __stdcall AIL_quick_startup( + S32 use_digital, S32 use_MIDI, U32 output_rate, S32 output_bits, S32 output_channels); +void __stdcall AIL_quick_handles(HDIGDRIVER *pdig, HMDIDRIVER *pmdi, HDLSDEVICE *pdls); +void __stdcall AIL_sample_volume_pan(HSAMPLE sample, F32 *volume, F32 *pan); +void __stdcall AIL_set_3D_sample_occlusion(H3DSAMPLE sample, F32 occlusion); +char *__stdcall AIL_set_redist_directory(const char *dir); +S32 __stdcall AIL_set_sample_file(HSAMPLE sample, const void *file_image, S32 block); +void __stdcall AIL_set_sample_volume_pan(HSAMPLE sample, F32 volume, F32 pan); +void __stdcall AIL_set_stream_volume_pan(HSTREAM stream, F32 volume, F32 pan); +void __stdcall AIL_stream_volume_pan(HSTREAM stream, F32 *volume, F32 *pan); +U32 __stdcall AIL_get_timer_highest_delay(void); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/Generals/Code/Libraries/Source/WWVegas/CMakeLists.txt b/Generals/Code/Libraries/Source/WWVegas/CMakeLists.txt index db5d9ec9286..ca178d24e63 100644 --- a/Generals/Code/Libraries/Source/WWVegas/CMakeLists.txt +++ b/Generals/Code/Libraries/Source/WWVegas/CMakeLists.txt @@ -4,7 +4,7 @@ add_library(g_wwcommon INTERFACE) target_link_libraries(g_wwcommon INTERFACE core_wwcommon d3d8lib - milesstub + milesloader stlport ) diff --git a/Generals/Code/Main/CMakeLists.txt b/Generals/Code/Main/CMakeLists.txt index f40c7434bdf..c9f7ce22d18 100644 --- a/Generals/Code/Main/CMakeLists.txt +++ b/Generals/Code/Main/CMakeLists.txt @@ -8,7 +8,7 @@ else() endif() target_link_libraries(g_generals PRIVATE - binkstub + binkloader comctl32 d3d8 d3dx8 @@ -18,7 +18,7 @@ target_link_libraries(g_generals PRIVATE g_gameenginedevice gi_always imm32 - milesstub + milesloader vfw32 winmm ) diff --git a/Generals/Code/Tools/W3DView/CMakeLists.txt b/Generals/Code/Tools/W3DView/CMakeLists.txt index 4b1c4169642..86db96488b5 100644 --- a/Generals/Code/Tools/W3DView/CMakeLists.txt +++ b/Generals/Code/Tools/W3DView/CMakeLists.txt @@ -10,7 +10,7 @@ target_link_libraries(g_w3dview PRIVATE g_wwvegas gi_always imm32 - milesstub + milesloader Version vfw32 winmm diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/CMakeLists.txt b/GeneralsMD/Code/Libraries/Source/WWVegas/CMakeLists.txt index b7d4208261a..81ee807efe2 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/CMakeLists.txt +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/CMakeLists.txt @@ -4,7 +4,7 @@ add_library(z_wwcommon INTERFACE) target_link_libraries(z_wwcommon INTERFACE core_wwcommon d3d8lib - milesstub + milesloader stlport ) diff --git a/GeneralsMD/Code/Main/CMakeLists.txt b/GeneralsMD/Code/Main/CMakeLists.txt index aabef06450f..99b8962328d 100644 --- a/GeneralsMD/Code/Main/CMakeLists.txt +++ b/GeneralsMD/Code/Main/CMakeLists.txt @@ -8,14 +8,14 @@ else() endif() target_link_libraries(z_generals PRIVATE - binkstub + binkloader comctl32 d3d8 d3dx8 dinput8 dxguid imm32 - milesstub + milesloader vfw32 winmm z_gameengine diff --git a/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt b/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt index bdbaaa4cde6..2de2ab5dbae 100644 --- a/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt +++ b/GeneralsMD/Code/Tools/W3DView/CMakeLists.txt @@ -7,7 +7,7 @@ target_link_libraries(z_w3dview PRIVATE d3d8lib d3dx8 imm32 - milesstub + milesloader Version vfw32 winmm diff --git a/cmake/bink.cmake b/cmake/bink.cmake deleted file mode 100644 index a851f6c8ca3..00000000000 --- a/cmake/bink.cmake +++ /dev/null @@ -1,7 +0,0 @@ -FetchContent_Declare( - bink - GIT_REPOSITORY https://github.com/TheSuperHackers/bink-sdk-stub.git - GIT_TAG 180fc4620ed72fd700347ab837a5271fd0259901 -) - -FetchContent_MakeAvailable(bink) diff --git a/cmake/miles.cmake b/cmake/miles.cmake deleted file mode 100644 index 79ad6b6e28b..00000000000 --- a/cmake/miles.cmake +++ /dev/null @@ -1,7 +0,0 @@ -FetchContent_Declare( - miles - GIT_REPOSITORY https://github.com/TheSuperHackers/miles-sdk-stub.git - GIT_TAG 6e32700d7ba4b4713a03bf1f5ffc3b0ac8d17264 -) - -FetchContent_MakeAvailable(miles)