diff --git a/common/platform/config.c b/common/platform/config.c index 4f948d0..d089977 100644 --- a/common/platform/config.c +++ b/common/platform/config.c @@ -24,6 +24,7 @@ #include "platform/vfs.h" #include "platform/system.h" #include "platform/openssl.h" +#include "util/dprintf.h" void platform_config_load(struct platform_config *cfg, const wchar_t *filename) @@ -337,6 +338,32 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename) cfg->option, _countof(cfg->option), filename); + + for (int i = 0; i < MAX_REDIRECTIONS; i++){ + wchar_t key[32]; + wsprintfW(key, L"redirection%dfrom", i); + GetPrivateProfileStringW( + L"vfs", + key, + L"", + cfg->redirections_from[i], + _countof(cfg->redirections_from[i]), + filename); + wsprintfW(key, L"redirection%dto", i); + GetPrivateProfileStringW( + L"vfs", + key, + L"", + cfg->redirections_to[i], + _countof(cfg->redirections_to[i]), + filename); + + cfg->redirections_from_len[i] = (int)wcslen(cfg->redirections_from[i]); + + if (cfg->redirections_from_len[i] > 0) { + dprintf("Vfs: Set up custom redirection from %ls to %ls\n", cfg->redirections_from[i], cfg->redirections_to[i]); + } + } } void system_config_load(struct system_config *cfg, const wchar_t *filename) diff --git a/common/platform/vfs.c b/common/platform/vfs.c index 22f0583..97f7c13 100644 --- a/common/platform/vfs.c +++ b/common/platform/vfs.c @@ -36,6 +36,10 @@ static HRESULT vfs_path_hook_apm( const wchar_t *src, wchar_t *dest, size_t *count); +static HRESULT vfs_custom_path_hook( + const wchar_t *src, + wchar_t *dest, + size_t *count); static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes); static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes); @@ -217,6 +221,12 @@ HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id) } } + hr = path_hook_push(vfs_custom_path_hook); + + if (FAILED(hr)) { + return hr; + } + hr = reg_hook_push_key( HKEY_LOCAL_MACHINE, L"SYSTEM\\SEGA\\SystemProperty\\mount", @@ -601,3 +611,49 @@ static wchar_t* hook_AppImage_getOptionMountRootPath() return path; } + +static HRESULT vfs_custom_path_hook( + const wchar_t *src, + wchar_t *dest, + size_t *count){ + + assert(src != NULL); + assert(count != NULL); + + /* Case-insensitive check to see if src starts with one of our custom paths */ + + for (int i = 0; i < MAX_REDIRECTIONS; i++){ + + wchar_t* from = vfs_config.redirections_from[i]; + wchar_t* to = vfs_config.redirections_to[i]; + + if (from[0] == '\0' || to[0] == '\0'){ + return S_FALSE; + } + + if (path_compare_w(src, from, vfs_config.redirections_from_len[i]) != 0) { + continue; + } + + size_t required = wcslen(to) + 1; + +#if defined(LOG_CUSTOM_VFS) + dprintf("Vfs: Redirection matched: %ls -> %ls\n", from, to); +#endif + + if (dest != NULL) { + + if (required > *count) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + wcscpy_s(dest, *count, to); + } + + *count = required; + + break; + } + + return S_OK; +} diff --git a/common/platform/vfs.h b/common/platform/vfs.h index a7e513f..7502053 100644 --- a/common/platform/vfs.h +++ b/common/platform/vfs.h @@ -5,11 +5,16 @@ #include #include +#define MAX_REDIRECTIONS 64 + struct vfs_config { bool enable; wchar_t amfs[MAX_PATH]; wchar_t appdata[MAX_PATH]; wchar_t option[MAX_PATH]; + wchar_t redirections_from[MAX_REDIRECTIONS][MAX_PATH]; + int redirections_from_len[MAX_REDIRECTIONS]; + wchar_t redirections_to[MAX_REDIRECTIONS][MAX_PATH]; }; HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id); diff --git a/doc/config/common.md b/doc/config/common.md index 3e9361e..666be50 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -722,3 +722,16 @@ Enabling full virtualization will virtualize ALL writes to the C:\ drive. Using unless you know what you're doing! The Windows directory is always excluded from virtualization. + +### `redirection#from`, `redirection#to` + +Default: Empty string + +Advanced feature intended for owners of real hardware. This allows arbitrary file reads to be redirected to other paths. Since serial ports are also "file" reads, this can be used to redirect hardcoded COM ports to other ports. Up to 64 redirections can be used by incrementing the number in the key: `redirection1from`, `redirection2from`, ... + +Example for redirecting COM 5 to COM 10: + +``` +redirection0from=\\.\COM5 +redirection0to=\\.\COM10 +``` \ No newline at end of file diff --git a/meson.build b/meson.build index b4376bb..1e88269 100644 --- a/meson.build +++ b/meson.build @@ -88,6 +88,9 @@ endif if get_option('log_all') or get_option('log_ewf') add_project_arguments('-DLOG_EWF', language : 'c') endif +if get_option('log_all') or get_option('log_custom_vfs') + add_project_arguments('-DLOG_CUSTOM_VFS', language: 'c') +endif shlwapi_lib = cc.find_library('shlwapi') dinput8_lib = cc.find_library('dinput8') diff --git a/meson_options.txt b/meson_options.txt index 7cce000..957503d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -83,3 +83,8 @@ option('log_ewf', value : false, description : 'Enable debug logging for file system virtualization' ) +option('log_custom_vfs', + type : 'boolean', + value : false, + description : 'Enable debug logging for custom path redirections' +)