[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
Version: `2025-07-20`
Version: `2025-07-27`
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)
{
// 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);
}
}

View File

@ -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
; -----------------------------------------------------------------------------

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);
}
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);
}

View File

@ -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(

View File

@ -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 */

View File

@ -28,5 +28,7 @@ shared_library(
'io4.h',
'mount.c',
'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;
}
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));
}

View File

@ -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);

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);