forked from Hay1tsme/segatools
Vfs: Add ability to redirect arbitary paths (= serial ports) #62
@ -604,3 +604,16 @@ Default: Empty string
|
||||
Configure the location of the "Option" data mount point. This mount point is
|
||||
optional (hence the name, probably) and contains directories which contain
|
||||
minor over-the-air content updates.
|
||||
|
||||
### `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
|
||||
```
|
@ -82,6 +82,9 @@ endif
|
||||
if get_option('log_all') or get_option('log_clock')
|
||||
add_project_arguments('-DLOG_CLOCK', 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')
|
||||
|
@ -69,7 +69,12 @@ option('log_mercury_slider',
|
||||
description : 'Enable debug logging for the WACCA Slider'
|
||||
)
|
||||
option('log_clock',
|
||||
type : 'boolean',
|
||||
value : false,
|
||||
description : 'Enable debug logging for clock APIs'
|
||||
type : 'boolean',
|
||||
value : false,
|
||||
description : 'Enable debug logging for clock APIs'
|
||||
)
|
||||
option('log_custom_vfs',
|
||||
type : 'boolean',
|
||||
value : false,
|
||||
description : 'Enable debug logging for custom path redirections'
|
||||
)
|
||||
|
@ -333,6 +333,28 @@ 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]);
|
||||
}
|
||||
}
|
||||
|
||||
void system_config_load(struct system_config *cfg, const wchar_t *filename)
|
||||
|
@ -31,6 +31,10 @@ static HRESULT vfs_path_hook_option(
|
||||
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);
|
||||
|
||||
@ -204,6 +208,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",
|
||||
@ -541,3 +551,45 @@ 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 vfs_option */
|
||||
|
||||
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) {
|
||||
Haruka marked this conversation as resolved
Outdated
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t required = wcslen(to);
|
||||
if (required > *count) {
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
#if defined(LOG_CUSTOM_VFS)
|
||||
dprintf("Vfs: Redirection matched: %S -> %S\n", from, to);
|
||||
#endif
|
||||
|
||||
if (dest != NULL) {
|
||||
wcscpy_s(dest, *count, to);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -5,11 +5,16 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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);
|
||||
|
Reference in New Issue
Block a user
You're calling strlen for each path access, multiplied by the number of redirections
corrected, thanks