Files
グローランプ 89bd77e306 IO: Resolve IO DLL paths from environment variables (#119)
## Summary

Adds a unified mechanism for locating third-party IO DLLs through environment
variables, on top of the existing per-game `[xxxio] path=` INI setting.

## Changes

For each IO DLL, the path is resolved in this order:

1. The section-specific INI value, e.g. `[mai2io] path=`.
2. The section-specific environment variable, e.g. `SEGATOOLS_MAI2IO_PATH`.
3. `SEGATOOLS_IO_ROOT` joined with the default IO DLL filename, e.g.
   `%SEGATOOLS_IO_ROOT%\mai2io.dll`.
4. Empty path, which keeps the built-in IO implementation (unchanged default).

INI and environment-variable paths are run through Windows environment-variable
expansion, so values such as `%SEGATOOLS_IO_ROOT%\mai2io.dll` are valid in the
INI directly.

Reviewed-on: https://gitea.tendokyu.moe/TeamTofuShop/segatools/pulls/119
Co-authored-by: グローランプ <130208311+Gl0w1amp@users.noreply.github.com>
Co-committed-by: グローランプ <130208311+Gl0w1amp@users.noreply.github.com>
2026-07-08 20:23:08 +00:00

123 lines
3.5 KiB
C

#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "board/aime-dll.h"
#include "board/config.h"
#include "board/sg-reader.h"
#include "board/vfd.h"
#include "util/dprintf.h"
#include "util/io-path.h"
// Check windows
#if _WIN32 || _WIN64
#if _WIN64
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
// Check GCC
#if __GNUC__
#if __x86_64__ || __ppc64__
#define ENV64BIT
#else
#define ENV32BIT
#endif
#endif
static void aime_dll_config_load(struct aime_dll_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
// Workaround for x64/x86 external IO dlls
// path32 for 32bit, path64 for 64bit
// for else.. is that possible? idk
if (cfg->path64) {
#if defined(ENV32BIT)
// Always empty, due to amdaemon being 64 bit in 32 bit mode
memset(cfg->path, 0, sizeof(cfg->path));
#elif defined(ENV64BIT)
io_path_config_load(
cfg->path,
_countof(cfg->path),
L"aimeio",
L"path",
L"SEGATOOLS_AIMEIO_PATH",
L"aimeio.dll",
filename);
#else
#error "Unknown environment"
#endif
} else {
io_path_config_load(
cfg->path,
_countof(cfg->path),
L"aimeio",
L"path",
L"SEGATOOLS_AIMEIO_PATH",
L"aimeio.dll",
filename);
}
}
void aime_config_load(struct aime_config *cfg, const wchar_t *filename) {
aime_config_load_bykey(cfg, filename, L"aime");
}
void aime_config_load_bykey(struct aime_config *cfg, const wchar_t *filename, const wchar_t* config_key)
{
assert(cfg != NULL);
assert(filename != NULL);
aime_dll_config_load(&cfg->dll, filename);
cfg->enable = GetPrivateProfileIntW(config_key, L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(config_key, L"portNo", 0, filename);
cfg->high_baudrate = GetPrivateProfileIntW(config_key, L"highBaud", 1, filename);
cfg->gen = GetPrivateProfileIntW(config_key, L"gen", 0, filename);
cfg->proxy_flag = GetPrivateProfileIntW(config_key, L"proxyFlag", 2, filename);
cfg->mobile_felica = GetPrivateProfileIntW(config_key, L"mobileFelica", 0, filename);
GetPrivateProfileStringW(
config_key,
L"authdataPath",
L"DEVICE\\authdata.bin",
cfg->authdata_path,
_countof(cfg->authdata_path),
filename);
}
void io4_config_load(struct io4_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"io4", L"enable", 1, filename);
cfg->foreground_only = GetPrivateProfileIntW(L"io4", L"foreground", 1, filename);
}
void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(L"vfd", L"portNo", 0, filename);
cfg->utf_conversion = GetPrivateProfileIntW(L"vfd", L"utfConversion", 0, filename);
}
void ffb_config_load(struct ffb_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"ffb", L"enable", 1, filename);
}