From bb0b023ec051e4d69cb893cd95e7ed81f7c6272b Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Sun, 27 Jul 2025 19:20:36 +0200 Subject: [PATCH] [apm3] hook video loading, bug fixes --- README.md | 2 +- common/unityhook/hook.c | 6 -- dist/apm3/segatools.ini | 4 ++ games/apm3hook/config.c | 5 ++ games/apm3hook/config.h | 10 ++-- games/apm3hook/dllmain.c | 30 +++++----- games/apm3hook/meson.build | 2 + games/apm3hook/mount.c | 16 +++--- games/apm3hook/mount.h | 9 ++- games/apm3hook/video.c | 115 +++++++++++++++++++++++++++++++++++++ games/apm3hook/video.h | 10 ++++ 11 files changed, 171 insertions(+), 38 deletions(-) create mode 100644 games/apm3hook/video.c create mode 100644 games/apm3hook/video.h diff --git a/README.md b/README.md index 532e16a..bb50ce0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Segatools -Version: `2025-07-20` +Version: `2025-07-27` Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms. diff --git a/common/unityhook/hook.c b/common/unityhook/hook.c index 94d1a5b..0683a6a 100644 --- a/common/unityhook/hook.c +++ b/common/unityhook/hook.c @@ -95,7 +95,6 @@ static void dll_hook_insert_hooks(HMODULE target) { static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags) { - // dprintf("Unity: LoadLibraryExW %ls\n", name); return hook_LoadLibraryW(name); } @@ -157,11 +156,6 @@ static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name) if (hook_load_callback != NULL){ hook_load_callback(result, target_module); } - - // Not needed? - // serial_hook_apply_hooks(result); - // Unity will crash during option loading when we hook this twice - // iohook_apply_hooks(result); } } diff --git a/dist/apm3/segatools.ini b/dist/apm3/segatools.ini index 74bdd12..502cea9 100644 --- a/dist/apm3/segatools.ini +++ b/dist/apm3/segatools.ini @@ -122,6 +122,10 @@ enable=1 ; is not cut off. delay=1 +[video] +; Enables VFS (C:\Mount\Option) path rewrite for AVProVideo. +enable=1 + ; ----------------------------------------------------------------------------- ; Custom IO settings ; ----------------------------------------------------------------------------- diff --git a/games/apm3hook/config.c b/games/apm3hook/config.c index 06ab9ff..6b0b5cd 100644 --- a/games/apm3hook/config.c +++ b/games/apm3hook/config.c @@ -93,6 +93,10 @@ void mount_config_load(struct mount_config *cfg, const wchar_t *filename) { cfg->delay = GetPrivateProfileIntW(L"mount", L"delay", 1, filename); } +void video_config_load(struct video_config *cfg, const wchar_t *filename) { + cfg->enable = GetPrivateProfileIntW(L"video", L"enable", 1, filename); +} + void apm3_hook_config_load( struct apm3_hook_config *cfg, const wchar_t *filename) @@ -110,4 +114,5 @@ void apm3_hook_config_load( apm3_dll_config_load(&cfg->dll, filename); unity_config_load(&cfg->unity, filename); mount_config_load(&cfg->mount, filename); + video_config_load(&cfg->video, filename); } diff --git a/games/apm3hook/config.h b/games/apm3hook/config.h index b336677..8ff2cc3 100644 --- a/games/apm3hook/config.h +++ b/games/apm3hook/config.h @@ -11,16 +11,13 @@ #include "gfxhook/config.h" -#include "apm3hook/apm3-dll.h" +#include "apm3-dll.h" +#include "mount.h" +#include "video.h" #include "platform/config.h" #include "unityhook/config.h" -struct mount_config { - bool enable; - bool delay; -}; - struct apm3_hook_config { struct platform_config platform; struct aime_config aime; @@ -32,6 +29,7 @@ struct apm3_hook_config { struct apm3_dll_config dll; struct unity_config unity; struct mount_config mount; + struct video_config video; }; void apm3_dll_config_load( diff --git a/games/apm3hook/dllmain.c b/games/apm3hook/dllmain.c index 57298c6..ab937e0 100644 --- a/games/apm3hook/dllmain.c +++ b/games/apm3hook/dllmain.c @@ -16,6 +16,7 @@ #include "config.h" #include "io4.h" #include "mount.h" +#include "video.h" #include "hook/iohook.h" #include "hook/process.h" @@ -52,9 +53,7 @@ void unity_hook_callback(HMODULE hmodule, const wchar_t* p) { iohook_apply_hooks(hmodule); } } - security_hook_insert_hooks(hmodule); touch_hook_insert_hooks(hmodule); - // mount_hook_apply_hooks(&apm3_hook_cfg.mount, hmodule); } static DWORD CALLBACK apm3_pre_startup(void) @@ -73,8 +72,21 @@ static DWORD CALLBACK apm3_pre_startup(void) touch_screen_hook_init(&apm3_hook_cfg.touch, apm3_hook_mod); serial_hook_init(); + /* Hook external DLL APIs */ + + mount_hook_init(&apm3_hook_cfg.platform.vfs, &apm3_hook_cfg.mount); + av_pro_video_hook_init(&apm3_hook_cfg.video); + /* Initialize emulation hooks */ + struct dipsw_config new_dipsw_config[8] = { + {L"LAN Install", L"Server", L"Client"}, + }; + + // Set the system dip switch configuration + memcpy(apm3_hook_cfg.platform.system.dipsw_config, new_dipsw_config, + sizeof(new_dipsw_config)); + hr = platform_hook_init( &apm3_hook_cfg.platform, "SDEM", @@ -117,20 +129,6 @@ static DWORD CALLBACK apm3_pre_startup(void) goto fail; } - hr = security_hook_init(); - - if (FAILED(hr)) { - goto fail; - } - - touch_screen_hook_init(&apm3_hook_cfg.touch, apm3_hook_mod); - - mount_hook_init(&apm3_hook_cfg.platform.vfs, &apm3_hook_cfg.mount); - - security_hook_insert_hooks(NULL); - - mount_hook_apply_hooks(NULL); - unity_hook_init(&apm3_hook_cfg.unity, apm3_hook_mod, unity_hook_callback); /* Initialize debug helpers */ diff --git a/games/apm3hook/meson.build b/games/apm3hook/meson.build index 520b8f2..f5e2132 100644 --- a/games/apm3hook/meson.build +++ b/games/apm3hook/meson.build @@ -28,5 +28,7 @@ shared_library( 'io4.h', 'mount.c', 'mount.h', + 'video.c', + 'video.h', ], ) diff --git a/games/apm3hook/mount.c b/games/apm3hook/mount.c index 2b894f4..c1b855e 100644 --- a/games/apm3hook/mount.c +++ b/games/apm3hook/mount.c @@ -62,15 +62,17 @@ void mount_hook_init(struct vfs_config* vfs_cfg, struct mount_config* mount_cfg) return; } - dprintf("Mount: Hook enabled\n"); + mount_hook_apply_hooks(NULL); + + dprintf("Mount: hook enabled\n"); } -void mount_hook_apply_hooks(HMODULE module) { - if (!mcfg->enable) { - return; - } - - proc_addr_table_push(module, "apmmount.dll", mount_hooks, _countof(mount_hooks)); +void mount_hook_apply_hooks(HMODULE target) { + proc_addr_table_push( + target, + "apmmount.dll", + mount_hooks, + _countof(mount_hooks)); } diff --git a/games/apm3hook/mount.h b/games/apm3hook/mount.h index 6ab2827..bf3bd69 100644 --- a/games/apm3hook/mount.h +++ b/games/apm3hook/mount.h @@ -1,7 +1,12 @@ #pragma once #include "board/aime-dll.h" -#include "config.h" +#include "platform/vfs.h" -void mount_hook_apply_hooks(HMODULE module); +struct mount_config { + bool enable; + bool delay; +}; + +void mount_hook_apply_hooks(HMODULE target); void mount_hook_init(struct vfs_config* vfs_cfg, struct mount_config* mount_cfg); diff --git a/games/apm3hook/video.c b/games/apm3hook/video.c new file mode 100644 index 0000000..12a10d4 --- /dev/null +++ b/games/apm3hook/video.c @@ -0,0 +1,115 @@ +#include +#include +#include + +#include "video.h" + +#include "hook/procaddr.h" + +#include "hooklib/dll.h" +#include "hooklib/path.h" + +#include "util/dprintf.h" + +static void* WINAPI hook_OpenSource( + void* instance, + const wchar_t* path, + int videoApiIndex, + bool useHardwareDecoding, + bool generateTextureMips, + bool hintAlphaChannel, + bool useLowLatency, + const wchar_t* forceAudioOutputDeviceName, + bool useUnityAudio, + bool forceResample, + int sampleRate, + const wchar_t** preferredFilter, + uint32_t numFilters, + int audioChannelMode, + uint32_t sourceSampleRate, + uint32_t sourceChannels +); + +static void* (WINAPI *next_OpenSource)( + void* instance, + const wchar_t* path, + int videoApiIndex, + bool useHardwareDecoding, + bool generateTextureMips, + bool hintAlphaChannel, + bool useLowLatency, + const wchar_t* forceAudioOutputDeviceName, + bool useUnityAudio, + bool forceResample, + int sampleRate, + const wchar_t** preferredFilter, + uint32_t numFilters, + int audioChannelMode, + uint32_t sourceSampleRate, + uint32_t sourceChannels +); + +static const struct hook_symbol av_pro_video_syms[] = { + { + .name = "OpenSource", + .patch = hook_OpenSource, + .link = (void **) &next_OpenSource, + } +}; + +void av_pro_video_hook_init(struct video_config* video_cfg) +{ + assert(video_cfg != NULL); + + if (!video_cfg->enable) { + return; + } + + av_pro_video_hook_insert_hooks(NULL); + + dprintf("Video: hook enabled.\n"); +} + +void av_pro_video_hook_insert_hooks(HMODULE target) +{ + proc_addr_table_push( + target, + "AVProVideo.dll", + av_pro_video_syms, + _countof(av_pro_video_syms)); +} + +static void* WINAPI hook_OpenSource( + void* instance, + const wchar_t* path, + int videoApiIndex, + bool useHardwareDecoding, + bool generateTextureMips, + bool hintAlphaChannel, + bool useLowLatency, + const wchar_t* forceAudioOutputDeviceName, + bool useUnityAudio, + bool forceResample, + int sampleRate, + const wchar_t** preferredFilter, + uint32_t numFilters, + int audioChannelMode, + uint32_t sourceSampleRate, + uint32_t sourceChannels +) { + wchar_t *trans; + BOOL ok; + + ok = path_transform_w(&trans, path); + + if (!ok) { + dprintf("AVProVideo: Path transformation error\n"); + return NULL; + } + + return next_OpenSource( + instance, trans ? trans : path, videoApiIndex, useHardwareDecoding, generateTextureMips, + hintAlphaChannel, useLowLatency, forceAudioOutputDeviceName, useUnityAudio, + forceResample, sampleRate, preferredFilter, numFilters, audioChannelMode, + sourceSampleRate, sourceChannels); +} diff --git a/games/apm3hook/video.h b/games/apm3hook/video.h new file mode 100644 index 0000000..9f61e0d --- /dev/null +++ b/games/apm3hook/video.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +struct video_config { + bool enable; +}; + +void av_pro_video_hook_init(struct video_config* video_cfg); +void av_pro_video_hook_insert_hooks(HMODULE target);