Vfs: Add ability to redirect arbitary paths (= serial ports) #62

Open
Haruka wants to merge 6 commits from Haruka/segatools:file_redirection into develop
6 changed files with 103 additions and 3 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

You're calling strlen for each path access, multiplied by the number of redirections

You're calling strlen for each path access, multiplied by the number of redirections

corrected, thanks

corrected, thanks
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;
}

View File

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