[apm3] hook video loading, bug fixes

This commit is contained in:
2025-07-27 19:20:36 +02:00
parent bb01e131e9
commit bb0b023ec0
11 changed files with 171 additions and 38 deletions

View File

@ -1,6 +1,6 @@
# Segatools # Segatools
Version: `2025-07-20` Version: `2025-07-27`
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms. Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.

View File

@ -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) static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags)
{ {
// dprintf("Unity: LoadLibraryExW %ls\n", name);
return hook_LoadLibraryW(name); return hook_LoadLibraryW(name);
} }
@ -157,11 +156,6 @@ static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name)
if (hook_load_callback != NULL){ if (hook_load_callback != NULL){
hook_load_callback(result, target_module); 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);
} }
} }

View File

@ -122,6 +122,10 @@ enable=1
; is not cut off. ; is not cut off.
delay=1 delay=1
[video]
; Enables VFS (C:\Mount\Option) path rewrite for AVProVideo.
enable=1
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Custom IO settings ; Custom IO settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------

View File

@ -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); 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( void apm3_hook_config_load(
struct apm3_hook_config *cfg, struct apm3_hook_config *cfg,
const wchar_t *filename) const wchar_t *filename)
@ -110,4 +114,5 @@ void apm3_hook_config_load(
apm3_dll_config_load(&cfg->dll, filename); apm3_dll_config_load(&cfg->dll, filename);
unity_config_load(&cfg->unity, filename); unity_config_load(&cfg->unity, filename);
mount_config_load(&cfg->mount, filename); mount_config_load(&cfg->mount, filename);
video_config_load(&cfg->video, filename);
} }

View File

@ -11,16 +11,13 @@
#include "gfxhook/config.h" #include "gfxhook/config.h"
#include "apm3hook/apm3-dll.h" #include "apm3-dll.h"
#include "mount.h"
#include "video.h"
#include "platform/config.h" #include "platform/config.h"
#include "unityhook/config.h" #include "unityhook/config.h"
struct mount_config {
bool enable;
bool delay;
};
struct apm3_hook_config { struct apm3_hook_config {
struct platform_config platform; struct platform_config platform;
struct aime_config aime; struct aime_config aime;
@ -32,6 +29,7 @@ struct apm3_hook_config {
struct apm3_dll_config dll; struct apm3_dll_config dll;
struct unity_config unity; struct unity_config unity;
struct mount_config mount; struct mount_config mount;
struct video_config video;
}; };
void apm3_dll_config_load( void apm3_dll_config_load(

View File

@ -16,6 +16,7 @@
#include "config.h" #include "config.h"
#include "io4.h" #include "io4.h"
#include "mount.h" #include "mount.h"
#include "video.h"
#include "hook/iohook.h" #include "hook/iohook.h"
#include "hook/process.h" #include "hook/process.h"
@ -52,9 +53,7 @@ void unity_hook_callback(HMODULE hmodule, const wchar_t* p) {
iohook_apply_hooks(hmodule); iohook_apply_hooks(hmodule);
} }
} }
security_hook_insert_hooks(hmodule);
touch_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) 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); touch_screen_hook_init(&apm3_hook_cfg.touch, apm3_hook_mod);
serial_hook_init(); 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 */ /* 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( hr = platform_hook_init(
&apm3_hook_cfg.platform, &apm3_hook_cfg.platform,
"SDEM", "SDEM",
@ -117,20 +129,6 @@ static DWORD CALLBACK apm3_pre_startup(void)
goto fail; 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); unity_hook_init(&apm3_hook_cfg.unity, apm3_hook_mod, unity_hook_callback);
/* Initialize debug helpers */ /* Initialize debug helpers */

View File

@ -28,5 +28,7 @@ shared_library(
'io4.h', 'io4.h',
'mount.c', 'mount.c',
'mount.h', 'mount.h',
'video.c',
'video.h',
], ],
) )

View File

@ -62,15 +62,17 @@ void mount_hook_init(struct vfs_config* vfs_cfg, struct mount_config* mount_cfg)
return; return;
} }
dprintf("Mount: Hook enabled\n"); mount_hook_apply_hooks(NULL);
dprintf("Mount: hook enabled\n");
} }
void mount_hook_apply_hooks(HMODULE module) { void mount_hook_apply_hooks(HMODULE target) {
if (!mcfg->enable) { proc_addr_table_push(
return; target,
} "apmmount.dll",
mount_hooks,
proc_addr_table_push(module, "apmmount.dll", mount_hooks, _countof(mount_hooks)); _countof(mount_hooks));
} }

View File

@ -1,7 +1,12 @@
#pragma once #pragma once
#include "board/aime-dll.h" #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); void mount_hook_init(struct vfs_config* vfs_cfg, struct mount_config* mount_cfg);

115
games/apm3hook/video.c Normal file
View File

@ -0,0 +1,115 @@
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#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);
}

10
games/apm3hook/video.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include <windows.h>
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);