diff --git a/.gitignore b/.gitignore index 8dfb3a6..8b9c0f5 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ build_docker.local.sh # output from build script bin/* dist/* +build/*.dll external/cv2pdb/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bbca6a..310f19b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,19 @@ set_source_files_properties(cfg/manifest.rc PROPERTIES LANGUAGE RC) set_source_files_properties(cfg/icon.rc PROPERTIES LANGUAGE RC) set_source_files_properties(cfg/Win32D.rc PROPERTIES LANGUAGE RC) set_source_files_properties(build/manifest64.rc PROPERTIES LANGUAGE RC) +set_source_files_properties(build/blob.rc PROPERTIES LANGUAGE RC) +add_custom_command( + OUTPUT build/dsdmo.i686.dll + COMMAND sh -c "wget -qO- 'https://web.archive.org/web/20260212204718if_/https://download.zip.dll-files.com/d01cab97ad497201c4ad99eb6e4182b3/dsdmo.zip?token=f7cVie5KOSz-hnFUYC37Ow&expires=1770974229' | bsdtar -xvf - -C '${CMAKE_SOURCE_DIR}/build' -s '/dsdmo.dll/dsdmo.i686.dll/' dsdmo.dll" + COMMENT "Fetching dsdmo.dll blob (i686)" + VERBATIM +) +add_custom_command( + OUTPUT build/dsdmo.x86_64.dll + COMMAND sh -c "wget -qO- 'https://web.archive.org/web/20260212203516if_/https://download.zip.dll-files.com/2627c69b89807078f5fdf63ee104dddf/dsdmo.zip?token=1rLcDAA2LFA6YRyinX0GXg&expires=1770973374' | bsdtar -xvf - -C '${CMAKE_SOURCE_DIR}/build' -s '/dsdmo.dll/dsdmo.x86_64.dll/' dsdmo.dll" + COMMENT "Fetching dsdmo.dll blob (x86_64)" + VERBATIM +) # sources ######### @@ -637,7 +650,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOUR # spice.exe ########### -set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) +set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc build/blob.rc build/dsdmo.i686.dll) add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES}) target_link_libraries(spicetools_spice PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp @@ -652,7 +665,7 @@ endif() # spice_laa.exe ########### -set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc) +set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc build/blob.rc build/dsdmo.i686.dll) add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES}) target_link_libraries(spicetools_spice_laa PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winhttp @@ -684,7 +697,7 @@ endif() # spice64.exe ############# -set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc) +set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc build/blob.rc build/dsdmo.x86_64.dll) add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES}) # do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break diff --git a/build/blob.rc b/build/blob.rc new file mode 100644 index 0000000..942c6dd --- /dev/null +++ b/build/blob.rc @@ -0,0 +1,10 @@ +#ifndef RCDATA +#define RCDATA 10 +#endif + + +#ifdef SPICE64 + DMO_BLOB RCDATA "dsdmo.x86_64.dll" +#else + DMO_BLOB RCDATA "dsdmo.i686.dll" +#endif \ No newline at end of file diff --git a/hooks/wmischook.cpp b/hooks/wmischook.cpp index f18ef69..6966f4f 100644 --- a/hooks/wmischook.cpp +++ b/hooks/wmischook.cpp @@ -167,15 +167,39 @@ void attach(HINSTANCE hmodule) namespace hooks::wmisc::dmoeffector { +typedef HRESULT (STDAPICALLTYPE *DllRegisterServer_t)(); + +HMODULE LoadLibraryRsrc(const char *rsrcname) { + // Unpack library blob + HRSRC hrsrc = FindResourceA(nullptr, rsrcname, RT_RCDATA); + void* rsrcdata = LockResource(LoadResource(nullptr, hrsrc)); + DWORD rsrcsz = SizeofResource(nullptr, hrsrc); + + // _REV: could use tmpfs instead if bmsound_wine provides tempfile wrapper in future + // Store as temporary file (no direct way to in-memory load without involving custom loaders like MemoryModule) + char tempPath[MAX_PATH]; + char tempFile[MAX_PATH]; + GetTempPathA(MAX_PATH, tempPath); + GetTempFileNameA(tempPath, rsrcname, 0, tempFile); + MoveFileExA(tempFile, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT); // wine blocks DeleteFileA operations on LoadLibraryA filepaths + FILE *fh = fopen(tempFile, "wb"); + fwrite(rsrcdata, rsrcsz, 1, fh); + fclose(fh); + + // Map temporary library buffer + HMODULE hmodule = LoadLibraryA(tempFile); + return hmodule; +} void attach(HINSTANCE hmodule) { - //_REM: Disable dmoeffector error printing for line55, could not find unique pattern (9 matches, but patching all of them is harmless) - intptr_t next = (intptr_t) hmodule; - while (next) + HMODULE libdmo = LoadLibraryRsrc("DMO_BLOB"); + if(libdmo) { - next = replace_pattern_from(hmodule, "793ae8????????895424??4c8d05????????488bc8488d15????????41b937000000e8????????ff15????????", "eb3ae8????????895424??4c8d05????????488bc8488d15????????41b937000000e8????????ff15????????", 0, 0, next - reinterpret_cast(hmodule)); - if (next) log_info("hooks::wmisc::dmoeffector", "Muting error message({})", reinterpret_cast(next)); + log_info("hooks::wmisc::dmoeffector", "Registering COM server for DMO({})", reinterpret_cast(libdmo)); + auto DllRegisterServer = (DllRegisterServer_t)GetProcAddress(libdmo, "DllRegisterServer"); + if(DllRegisterServer && SUCCEEDED(DllRegisterServer())) return; } + log_warning("hooks::wmisc::dmoeffector", "Loading embedded dsdmo.dll failed, error code: {}", GetLastError()); } } @@ -195,6 +219,7 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e switch (to_hash(model)) { case to_hash("LDJ"): + dmoeffector::attach(hmodule); thumbnail::attach(hmodule); msacm::attach(hmodule); bmsound::attach(hmodule); @@ -204,12 +229,12 @@ void apply_performance_hacks(HINSTANCE hmodule, const char *model, const char *e bmsound::attach(hmodule); break; case to_hash("KFC"): + dmoeffector::attach(hmodule); msacm::attach(hmodule); bmsound::attach(hmodule); if (extl > 2019020600 && extl < 2021011800) // SDVX5 { cmovieplayer::attach(hmodule); - dmoeffector::attach(hmodule); } break; case to_hash("FORCE"):