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 # do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break
target_link_libraries(spicetools_spice64 target_link_libraries(spicetools_spice64
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp mfuuid strmiids dxva2 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 PREFIX "")
set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64") set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64")
+53 -52
View File
@@ -7,13 +7,6 @@
#include "avs/core.h" #include "avs/core.h"
#include <cstring> #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) 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 namespace hooks::bmsb::mf_broken
{ {
typedef HRESULT (*MFCreateMFByteStreamOnStream_t)(IStream *, IMFByteStream **); 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; MFCreateMFByteStreamOnStream_t MFCreateMFByteStreamOnStream;
MFCreateSourceReaderFromByteStream_t MFCreateSourceReaderFromByteStream;
MFStartup_t MFStartup;
MFShutdown_t MFShutdown;
struct wav_hdr struct wav_hdr
{ {
char sig_riff[4] = {'R', 'I', 'F', 'F'}; 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; *sz = srcpos;
return hr; return hr;
} }
HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *dstsz) HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *dstsz)
{ {
HRESULT hr = S_OK; HRESULT hr = S_OK;
@@ -200,9 +201,15 @@ HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *
PROPVARIANT duration; PROPVARIANT duration;
srcreader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mediatype); srcreader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mediatype);
srcreader->GetPresentationAttribute(MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &duration); 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_NUM_CHANNELS, &a);
mediatype->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &b); mediatype->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &b);
mediatype->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &c); mediatype->GetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, &c);
#else
a = 2;
b = 44100;
c = 16;
#endif
wav_hdr dsthdr = { wav_hdr dsthdr = {
.channels=static_cast<uint16_t>(a), .channels=static_cast<uint16_t>(a),
.samplerate=b, .samplerate=b,
@@ -227,22 +234,23 @@ HRESULT asf_to_wav(const BYTE *srcasf, uint32_t srcsz, BYTE **dstwav, uint32_t *
shstream->Release(); shstream->Release();
return hr; return hr;
} }
bool init() bool init()
{ {
HMODULE mfdll = libutils::try_library("Mfplat.dll"); HMODULE mf_ = libutils::try_library("mf.dll");
if (!mfdll) return false; HMODULE mfreadwrite_ = libutils::try_library("mfreadwrite.dll");
HMODULE mfplat_ = libutils::try_library("mfplat.dll");
if (!mf_ || !mfreadwrite_ || !mfplat_) return false;
// Missing in includes // Required by linker
MFCreateMFByteStreamOnStream = (MFCreateMFByteStreamOnStream_t) GetProcAddress(mfdll, "MFCreateMFByteStreamOnStream"); 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 || !MFCreateSourceReaderFromByteStream || !MFStartup || !MFShutdown || FAILED(MFStartup(MF_VERSION, MFSTARTUP_FULL)))
if (!MFCreateMFByteStreamOnStream || FAILED(MFStartup(MF_VERSION)))
return false; return false;
return true; return true;
} }
void deinit() void deinit()
{ {
MFShutdown(); MFShutdown();
@@ -777,20 +785,30 @@ void run_tests()
size_t szs3p; size_t szs3p;
BYTE *wav = nullptr; BYTE *wav = nullptr;
uint32_t wavsz = 0; uint32_t wavsz = 0;
char sig[5]; char avspath[AVSPATHMAX];
sig[4] = '\0'; avs::core::avs_file_t avsmnt = 0;
int id = 29095; char sig[5] = " ";
int id = 25073;
if (!mf_broken::init())
{
log_warning("hooks::bmsb", "MF initialization failed, skipping..");
}
#if 0 // Filesystem tests, s3p unpacking
// s3p/2dx un/packing and wma=>wav transcoder snprintf(avspath, sizeof(avspath), "data/sound/%05d", id);
char sndpath[64]; if (soundbank::has_format(avspath, ".ifs")) avsmnt = soundbank::map_ifs(avspath);
snprintf(sndpath, 64, "%05d/%05d", id, id); snprintf(avspath + strlen(avspath), 7, "/%05d", id);
char *bufs3p = soundbank::read_bank_any(sndpath, ".s3p", &szs3p); 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); snd_s3p *snds3p = snd_s3p::unpack(bufs3p);
if (avsmnt) avs::core::avs_fs_umount(avsmnt);
// S3P => WMA => WAV => 2DX pipeline
if (snds3p) if (snds3p)
{ {
// S3P/S3V // S3P/S3V metadata
log_info("hooks:bmsb", "s3p(25073/25006)? => ({}/{})", soundbank::has_format(sndpath, ".s3p"), soundbank::has_format("25006/25006", ".s3p"));
memcpy(sig, snds3p->header()->sig, 4); memcpy(sig, snds3p->header()->sig, 4);
log_info("hooks:bmsb", "{}::Bank[S3P]::Signature {}", id, sig); log_info("hooks:bmsb", "{}::Bank[S3P]::Signature {}", id, sig);
log_info("hooks:bmsb", "{}::Bank[S3P]::Size {}", id, szs3p); log_info("hooks:bmsb", "{}::Bank[S3P]::Size {}", id, szs3p);
@@ -833,27 +851,15 @@ void run_tests()
} }
// Valid 2DX (trim is not necessary) // 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); 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 else
{ {
log_info("hooks:bmsb", "Tests failed"); 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 // Caching and intermediate 2dx storage detection
BmsbEnumValidSoundbanks_t t = BmsbEnumValidSoundbanks; BmsbEnumValidSoundbanks_t t = BmsbEnumValidSoundbanks;
@@ -867,10 +873,11 @@ void run_tests()
*(int32_t *) (tmp + 0x3b0) = it; *(int32_t *) (tmp + 0x3b0) = it;
on_enum_valid_soundbanks(tmp, 3, 0); on_enum_valid_soundbanks(tmp, 3, 0);
} }
free(tmp); free(tmp);
BmsbEnumValidSoundbanks = t; BmsbEnumValidSoundbanks = t;
soundbank::flush_cache(); soundbank::flush_cache();
mf_broken::deinit();
} }
void init(HINSTANCE hmodule, const char *ext) 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.."); log_warning("hooks::bmsb", "Debugger detected, skipping..");
return; return;
} }
if (!mf_broken::init())
{
log_warning("hooks::bmsb", "MF initialization failed, skipping..");
}
if (!avcodec::init()) if (!avcodec::init())
{ {
log_warning("hooks::bmsb", "AVCodec initialization failed, skipping.."); log_warning("hooks::bmsb", "AVCodec initialization failed, skipping..");
@@ -945,9 +948,8 @@ void init(HINSTANCE hmodule, const char *ext)
// Tests _REM: tests // 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_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_)); 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(); run_tests();
} }
void deinit(HINSTANCE hmodule) void deinit(HINSTANCE hmodule)
@@ -956,7 +958,6 @@ void deinit(HINSTANCE hmodule)
soundbank::flush_cache(); soundbank::flush_cache();
delete offset_.guard; delete offset_.guard;
mf_broken::deinit();
} }
} }