forked from Dniel97/segatools
platform/vfs.c: add option path redirection
Optional for now, since not all games or configurations may need it. It may be better eventually to refactor hooklib/path.c to allow for static path remapping, to minimize boilerplate code around the functions.
This commit is contained in:
parent
54cd2f6e9a
commit
e97f6b5d8d
2
dist/chuni/segatools.ini
vendored
2
dist/chuni/segatools.ini
vendored
@ -1,6 +1,8 @@
|
|||||||
[vfs]
|
[vfs]
|
||||||
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||||
amfs=
|
amfs=
|
||||||
|
; Insert the path to the game Option directory here (contains Axxx directories)
|
||||||
|
option=
|
||||||
; Create an empty directory somewhere and insert the path here.
|
; Create an empty directory somewhere and insert the path here.
|
||||||
; This directory may be shared between multiple SEGA games.
|
; This directory may be shared between multiple SEGA games.
|
||||||
; NOTE: This has nothing to do with Windows %APPDATA%.
|
; NOTE: This has nothing to do with Windows %APPDATA%.
|
||||||
|
2
dist/idz/segatools.ini
vendored
2
dist/idz/segatools.ini
vendored
@ -1,6 +1,8 @@
|
|||||||
[vfs]
|
[vfs]
|
||||||
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
|
||||||
amfs=
|
amfs=
|
||||||
|
; Insert the path to the game Option directory here (contains OPxx directories)
|
||||||
|
option=
|
||||||
; Create an empty directory somewhere and insert the path here.
|
; Create an empty directory somewhere and insert the path here.
|
||||||
; This directory may be shared between multiple SEGA games.
|
; This directory may be shared between multiple SEGA games.
|
||||||
; NOTE: This has nothing to do with Windows %APPDATA%.
|
; NOTE: This has nothing to do with Windows %APPDATA%.
|
||||||
|
@ -295,5 +295,13 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename)
|
|||||||
cfg->appdata,
|
cfg->appdata,
|
||||||
_countof(cfg->appdata),
|
_countof(cfg->appdata),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
|
GetPrivateProfileStringW(
|
||||||
|
L"vfs",
|
||||||
|
L"option",
|
||||||
|
L"",
|
||||||
|
cfg->option,
|
||||||
|
_countof(cfg->option),
|
||||||
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,10 @@ static HRESULT vfs_path_hook_nthome(
|
|||||||
const wchar_t *src,
|
const wchar_t *src,
|
||||||
wchar_t *dest,
|
wchar_t *dest,
|
||||||
size_t *count);
|
size_t *count);
|
||||||
|
static HRESULT vfs_path_hook_option(
|
||||||
|
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_amfs(void *bytes, uint32_t *nbytes);
|
||||||
static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
||||||
|
|
||||||
@ -26,6 +30,9 @@ static wchar_t vfs_nthome_real[MAX_PATH];
|
|||||||
static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser\\";
|
static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser\\";
|
||||||
static const size_t vfs_nthome_len = _countof(vfs_nthome) - 1;
|
static const size_t vfs_nthome_len = _countof(vfs_nthome) - 1;
|
||||||
|
|
||||||
|
static const wchar_t vfs_option[] = L"C:\\Mount\\Option\\";
|
||||||
|
static const size_t vfs_option_len = _countof(vfs_option) - 1;
|
||||||
|
|
||||||
static const struct reg_hook_val vfs_reg_vals[] = {
|
static const struct reg_hook_val vfs_reg_vals[] = {
|
||||||
{
|
{
|
||||||
.name = L"AMFS",
|
.name = L"AMFS",
|
||||||
@ -65,6 +72,10 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
|||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->option[0] == L'\0') {
|
||||||
|
dprintf("Vfs: WARNING: OPTION path not specified in INI file\n");
|
||||||
|
}
|
||||||
|
|
||||||
home_ok = GetEnvironmentVariableW(
|
home_ok = GetEnvironmentVariableW(
|
||||||
L"USERPROFILE",
|
L"USERPROFILE",
|
||||||
vfs_nthome_real,
|
vfs_nthome_real,
|
||||||
@ -80,9 +91,13 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
|||||||
|
|
||||||
memcpy(&vfs_config, config, sizeof(*config));
|
memcpy(&vfs_config, config, sizeof(*config));
|
||||||
|
|
||||||
|
vfs_slashify(vfs_nthome_real, _countof(vfs_nthome_real));
|
||||||
vfs_slashify(vfs_config.amfs, _countof(vfs_config.amfs));
|
vfs_slashify(vfs_config.amfs, _countof(vfs_config.amfs));
|
||||||
vfs_slashify(vfs_config.appdata, _countof(vfs_config.appdata));
|
vfs_slashify(vfs_config.appdata, _countof(vfs_config.appdata));
|
||||||
vfs_slashify(vfs_nthome_real, _countof(vfs_nthome_real));
|
|
||||||
|
if (vfs_config.option[0] != L'\0') {
|
||||||
|
vfs_slashify(vfs_config.option, _countof(vfs_config.option));
|
||||||
|
}
|
||||||
|
|
||||||
hr = vfs_mkdir_rec(vfs_config.amfs);
|
hr = vfs_mkdir_rec(vfs_config.amfs);
|
||||||
|
|
||||||
@ -114,6 +129,8 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
|||||||
dprintf("Vfs: Failed to create %S: %x\n", temp, (int) hr);
|
dprintf("Vfs: Failed to create %S: %x\n", temp, (int) hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Not auto-creating option directory as it is normally a read-only mount */
|
||||||
|
|
||||||
hr = path_hook_push(vfs_path_hook);
|
hr = path_hook_push(vfs_path_hook);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@ -126,6 +143,14 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vfs_config.option[0] != L'\0') {
|
||||||
|
hr = path_hook_push(vfs_path_hook_option);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hr = reg_hook_push_key(
|
hr = reg_hook_push_key(
|
||||||
HKEY_LOCAL_MACHINE,
|
HKEY_LOCAL_MACHINE,
|
||||||
L"SYSTEM\\SEGA\\SystemProperty\\mount",
|
L"SYSTEM\\SEGA\\SystemProperty\\mount",
|
||||||
@ -241,7 +266,7 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
|||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cut off E:\ prefix, replace with redir path, count NUL terminator */
|
/* Cut off <prefix>\, replace with redir path, count NUL terminator */
|
||||||
|
|
||||||
redir_len = wcslen(redir);
|
redir_len = wcslen(redir);
|
||||||
required = wcslen(src) - 3 + redir_len + 1;
|
required = wcslen(src) - 3 + redir_len + 1;
|
||||||
@ -296,6 +321,42 @@ static HRESULT vfs_path_hook_nthome(
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT vfs_path_hook_option(
|
||||||
|
const wchar_t *src,
|
||||||
|
wchar_t *dest,
|
||||||
|
size_t *count)
|
||||||
|
{
|
||||||
|
size_t required;
|
||||||
|
size_t redir_len;
|
||||||
|
|
||||||
|
assert(src != NULL);
|
||||||
|
assert(count != NULL);
|
||||||
|
|
||||||
|
/* Case-insensitive check to see if src starts with vfs_option */
|
||||||
|
|
||||||
|
if (path_compare_w(src, vfs_option, vfs_option_len) != 0) {
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cut off the matched prefix, add the replaced prefix, count NUL */
|
||||||
|
|
||||||
|
redir_len = wcslen(vfs_config.option);
|
||||||
|
required = wcslen(src) - vfs_option_len + redir_len + 1;
|
||||||
|
|
||||||
|
if (dest != NULL) {
|
||||||
|
if (required > *count) {
|
||||||
|
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy_s(dest, *count, vfs_config.option);
|
||||||
|
wcscpy_s(dest + redir_len, *count - redir_len, src + vfs_option_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
*count = required;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes)
|
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes)
|
||||||
{
|
{
|
||||||
return reg_hook_read_wstr(bytes, nbytes, vfs_config.amfs);
|
return reg_hook_read_wstr(bytes, nbytes, vfs_config.amfs);
|
||||||
|
@ -9,6 +9,7 @@ struct vfs_config {
|
|||||||
bool enable;
|
bool enable;
|
||||||
wchar_t amfs[MAX_PATH];
|
wchar_t amfs[MAX_PATH];
|
||||||
wchar_t appdata[MAX_PATH];
|
wchar_t appdata[MAX_PATH];
|
||||||
|
wchar_t option[MAX_PATH];
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT vfs_hook_init(const struct vfs_config *config);
|
HRESULT vfs_hook_init(const struct vfs_config *config);
|
||||||
|
Loading…
Reference in New Issue
Block a user