refactor/build: Sanitize MF logic

> revert linking to MF libraries on build
> move MF init to be used for tests only
> fix 32-bit builds
> related to #1
This commit is contained in:
[ ]
2025-05-27 20:49:49 +09:00
parent 4a45f4d9c4
commit 88a19a8811
2 changed files with 54 additions and 53 deletions
+1 -1
View File
@@ -635,7 +635,7 @@ add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES})
# do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break
target_link_libraries(spicetools_spice64
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp mfuuid strmiids dxva2
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features mf mfplat mfreadwrite)
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
set_target_properties(spicetools_spice64 PROPERTIES PREFIX "")
set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64")
+53 -52
View File
@@ -7,13 +7,6 @@
#include "avs/core.h"
#include <cstring>
//_BUG: manual symbol lookup, should not link against: mf, mfplat, mfreadwrite
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <mfobjects.h>
#include <shlwapi.h>
void dump_(const char *path, const uint8_t *src, size_t sz)
{
@@ -90,13 +83,22 @@ void deinit()
}
}
// This implementation replicates wine MF wma=>wav playback bug 1:1, follows https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/multimedia/mediafoundation/AudioClip/main.cpp
// Replicates wine MF wma=>wav playback bug 1:1, follows https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/multimedia/mediafoundation/AudioClip/main.cpp
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <mfobjects.h>
#include <shlwapi.h>
namespace hooks::bmsb::mf_broken
{
typedef HRESULT (*MFCreateMFByteStreamOnStream_t)(IStream *, IMFByteStream **);
typedef HRESULT (*MFCreateSourceReaderFromByteStream_t)(IMFByteStream *, IMFAttributes *, IMFSourceReader **);
typedef HRESULT (*MFStartup_t)(ULONG, DWORD);
typedef HRESULT (*MFShutdown_t)();
MFCreateMFByteStreamOnStream_t MFCreateMFByteStreamOnStream;
MFCreateSourceReaderFromByteStream_t MFCreateSourceReaderFromByteStream;
MFStartup_t MFStartup;
MFShutdown_t MFShutdown;
struct wav_hdr
{
char sig_riff[4] = {'R', 'I', 'F', 'F'};
@@ -180,7 +182,6 @@ HRESULT asf_unpack_pcm_s16le(BYTE *dst, IMFSourceReader *srcreader, uint32_t szm
*sz = srcpos;
return hr;
}
HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *dstsz)
{
HRESULT hr = S_OK;
@@ -200,9 +201,15 @@ HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *
PROPVARIANT duration;
srcreader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mediatype);
srcreader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &duration);
#ifdef _WIN64
mediatype->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &a);
mediatype->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &b);
mediatype->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &c);
#else
a = 2;
b = 44100;
c = 16;
#endif
wav_hdr dsthdr = {
.channels=static_cast<uint16_t>(a),
.samplerate=b,
@@ -227,22 +234,23 @@ HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *
shstream->Release();
return hr;
}
bool init()
{
HMODULE mfdll = libutils::try_library("Mfplat.dll");
if (!mfdll) return false;
HMODULE mf_ = libutils::try_library("mf.dll");
HMODULE mfreadwrite_ = libutils::try_library("mfreadwrite.dll");
HMODULE mfplat_ = libutils::try_library("mfplat.dll");
if (!mf_ || !mfreadwrite_ || !mfplat_) return false;
// Missing in includes
MFCreateMFByteStreamOnStream = (MFCreateMFByteStreamOnStream_t) GetProcAddress(mfdll, "MFCreateMFByteStreamOnStream");
// Required by linker
MFCreateMFByteStreamOnStream = (MFCreateMFByteStreamOnStream_t) GetProcAddress(mfplat_, "MFCreateMFByteStreamOnStream");
MFStartup = (MFStartup_t) GetProcAddress(mfplat_, "MFStartup");
MFShutdown = (MFShutdown_t) GetProcAddress(mfplat_, "MFShutdown");
MFCreateSourceReaderFromByteStream = (MFCreateSourceReaderFromByteStream_t) GetProcAddress(mfreadwrite_, "MFCreateSourceReaderFromByteStream");
// MF init checks
if (!MFCreateMFByteStreamOnStream || FAILED(MFStartup(MF_VERSION)))
if (!MFCreateMFByteStreamOnStream || !MFCreateSourceReaderFromByteStream || !MFStartup || !MFShutdown || FAILED(MFStartup(MF_VERSION, MFSTARTUP_FULL)))
return false;
return true;
}
void deinit()
{
MFShutdown();
@@ -777,20 +785,30 @@ void run_tests()
size_t szs3p;
BYTE *wav = nullptr;
uint32_t wavsz = 0;
char sig[5];
sig[4] = '\0';
int id = 29095;
char avspath[AVSPATHMAX];
avs::core::avs_file_t avsmnt = 0;
char sig[5] = " ";
int id = 25073;
if (!mf_broken::init())
{
log_warning("hooks::bmsb", "MF initialization failed, skipping..");
}
#if 0
// s3p/2dx un/packing and wma=>wav transcoder
char sndpath[64];
snprintf(sndpath, 64, "%05d/%05d", id, id);
char *bufs3p = soundbank::read_bank_any(sndpath, ".s3p", &szs3p);
// Filesystem tests, s3p unpacking
snprintf(avspath, sizeof(avspath), "data/sound/%05d", id);
if (soundbank::has_format(avspath, ".ifs")) avsmnt = soundbank::map_ifs(avspath);
snprintf(avspath + strlen(avspath), 7, "/%05d", id);
soundbank::has_format(avspath, ".s3p");
soundbank::has_format(avspath, ".2dx");
soundbank::has_format(avspath, "_pre.2dx");
uint8_t *bufs3p = soundbank::read_bank_any(avspath, ".s3p", &szs3p);
snd_s3p *snds3p = snd_s3p::unpack(bufs3p);
if (avsmnt) avs::core::avs_fs_umount(avsmnt);
// S3P => WMA => WAV => 2DX pipeline
if (snds3p)
{
// S3P/S3V
log_info("hooks:bmsb", "s3p(25073/25006)? => ({}/{})", soundbank::has_format(sndpath, ".s3p"), soundbank::has_format("25006/25006", ".s3p"));
// S3P/S3V metadata
memcpy(sig, snds3p->header()->sig, 4);
log_info("hooks:bmsb", "{}::Bank[S3P]::Signature {}", id, sig);
log_info("hooks:bmsb", "{}::Bank[S3P]::Size {}", id, szs3p);
@@ -833,27 +851,15 @@ void run_tests()
}
// Valid 2DX (trim is not necessary)
log_info("hooks:bmsb", "25073::Bank[2DX]::Dumping");
log_info("hooks:bmsb", "{}::Bank[2DX]::Dumping", id);
snd_2dx::bank *buf2dx = snd2dx->serialize(false);
dump_("ac_25073.2dx", reinterpret_cast<const uint8_t *>(buf2dx), buf2dx->sz());
dump_("ac_soundbank.2dx", reinterpret_cast<const uint8_t *>(buf2dx), buf2dx->sz());
}
else
{
log_info("hooks:bmsb", "Tests failed");
}
#endif
char avspath[AVSPATHMAX] = "data/sound/29095";
soundbank::has_format(avspath, ".ifs");
avs::core::avs_file_t mnt = soundbank::map_ifs(avspath);
strcat(avspath, "/29095");
soundbank::has_format(avspath, ".s3p");
soundbank::has_format(avspath, ".2dx");
soundbank::has_format(avspath, "_pre.2dx");
avs::core::avs_fs_umount(mnt);
return;
// Caching and intermediate 2dx storage detection
BmsbEnumValidSoundbanks_t t = BmsbEnumValidSoundbanks;
@@ -867,10 +873,11 @@ void run_tests()
*(int32_t *) (tmp + 0x3b0) = it;
on_enum_valid_soundbanks(tmp, 3, 0);
}
free(tmp);
BmsbEnumValidSoundbanks = t;
soundbank::flush_cache();
mf_broken::deinit();
}
void init(HINSTANCE hmodule, const char *ext)
@@ -880,10 +887,6 @@ void init(HINSTANCE hmodule, const char *ext)
log_warning("hooks::bmsb", "Debugger detected, skipping..");
return;
}
if (!mf_broken::init())
{
log_warning("hooks::bmsb", "MF initialization failed, skipping..");
}
if (!avcodec::init())
{
log_warning("hooks::bmsb", "AVCodec initialization failed, skipping..");
@@ -945,9 +948,8 @@ void init(HINSTANCE hmodule, const char *ext)
// Tests _REM: tests
detour::trampoline(reinterpret_cast<void *>(avs::core::avs_fs_lstat), reinterpret_cast<void *>(on_avs_fs_lstat), reinterpret_cast<void **>(&avs_fs_lstat_));
detour::trampoline(reinterpret_cast<void *>(avs::core::avs_fs_mount), reinterpret_cast<void *>(on_avs_fs_mount), reinterpret_cast<void **>(&avs_fs_mount_));
if (offset_t::by_ext(ext) == offset_t::by_ext("2023090500"))
if (getenv("SPICE_TESTING") && offset_t::by_ext(ext) == offset_t::by_ext("2023090500"))
run_tests();
}
void deinit(HINSTANCE hmodule)
@@ -956,7 +958,6 @@ void deinit(HINSTANCE hmodule)
soundbank::flush_cache();
delete offset_.guard;
mf_broken::deinit();
}
}