forked from Dniel97/segatools
idac: added dipswitch support (beta)
This commit is contained in:
parent
da97d23b51
commit
c27ef9674d
31
dist/idac/segatools.ini
vendored
31
dist/idac/segatools.ini
vendored
@ -8,6 +8,12 @@ option=
|
|||||||
; NOTE: This has nothing to do with Windows %APPDATA%.
|
; NOTE: This has nothing to do with Windows %APPDATA%.
|
||||||
appdata=
|
appdata=
|
||||||
|
|
||||||
|
[aime]
|
||||||
|
; Controls emulation of the Aime card reader assembly.
|
||||||
|
enable=1
|
||||||
|
aimePath=DEVICE\aime.txt
|
||||||
|
felicaGen=0
|
||||||
|
|
||||||
[dns]
|
[dns]
|
||||||
; Insert the hostname or IP address of the server you wish to use here.
|
; Insert the hostname or IP address of the server you wish to use here.
|
||||||
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
; Note that 127.0.0.1, localhost etc are specifically rejected.
|
||||||
@ -22,9 +28,32 @@ enable=1
|
|||||||
[keychip]
|
[keychip]
|
||||||
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
|
||||||
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
; If you disable netenv then you must set this to your LAN's IP subnet, and
|
||||||
; that subnet must start with 192.168.
|
; that subnet must start with 192.168. Set it to your LAN's subnet if you
|
||||||
|
; want to play head-to-head using netenv=1.
|
||||||
subnet=192.168.100.0
|
subnet=192.168.100.0
|
||||||
|
|
||||||
|
; Override the keychip's region code. Most games seem to pay attention to the
|
||||||
|
; DS EEPROM region code and not the keychip region code, and this seems to be
|
||||||
|
; a bit mask that controls which Nu PCB region codes this keychip is authorized
|
||||||
|
; for. So it probably only affects the system software and not the game software.
|
||||||
|
; 1: JPN: Japan, 4: EXP: Export (for Asian markets)
|
||||||
|
region=4
|
||||||
|
|
||||||
|
[gpio]
|
||||||
|
; ALLS DIP switches.
|
||||||
|
|
||||||
|
; If multiple machines are present on the same LAN then set this to 1 on
|
||||||
|
; exactly one machine and set this to 0 on all others.
|
||||||
|
dipsw1=1
|
||||||
|
; 0 is the DZero CVT cab and 1 is the SWDC CVT cab.
|
||||||
|
dipsw2=0
|
||||||
|
; Enable the Single Seat mode, always requires dipsw1=1.
|
||||||
|
dipsw3=0
|
||||||
|
; The next two dip switches are the seat settings in bits, where
|
||||||
|
; 00 = Seat 1, 10 = Seat 2, 01 = Seat 3 and 11 = Seat 4
|
||||||
|
dipsw4=0
|
||||||
|
dipsw5=0
|
||||||
|
|
||||||
[aimeio]
|
[aimeio]
|
||||||
; To use a custom card reader IO DLL enter its path here.
|
; To use a custom card reader IO DLL enter its path here.
|
||||||
; Leave empty if you want to use Segatools built-in keyboard input.
|
; Leave empty if you want to use Segatools built-in keyboard input.
|
||||||
|
22
dist/idac/start.bat
vendored
22
dist/idac/start.bat
vendored
@ -2,11 +2,27 @@
|
|||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
|
|
||||||
REM start /min inject.exe -d -k idachook.dll amdaemon.exe -f -c config_aime_high_ex.json config_aime_high_jp.json config_aime_normal_ex.json config_aime_normal_jp.json config_common.json config_ex.json config_jp.json config_laninstall_client_ex.json config_laninstall_client_jp.json config_laninstall_server_ex.json config_laninstall_server_jp.json config_seat_1_ex.json config_seat_1_jp.json config_seat_2_ex.json config_seat_2_jp.json config_seat_3_ex.json config_seat_3_jp.json config_seat_4_ex.json config_seat_4_jp.json config_seat_single_ex.json config_seat_single_jp.json
|
REM set the APP_DIR to the Y drive
|
||||||
start /min inject -d -k idachook.dll amdaemon.exe -f -c config_aime_normal_jp.json config_common.json config_jp.json config_laninstall_server_jp.json config_seat_1_jp.json
|
set APP_DIR=Y:\SDGT
|
||||||
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject.exe -culture=ja launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
|
||||||
|
REM create the APP_DIR if it doesn't exist and redirect it to the TEMP folder
|
||||||
|
if not exist "%APP_DIR%" (
|
||||||
|
subst Y: %TEMP%
|
||||||
|
REM timeout /t 1
|
||||||
|
if not exist "%APP_DIR%" (
|
||||||
|
mkdir "%APP_DIR%"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Mounted the Y:\ drive to the %TEMP%\SDGT folder
|
||||||
|
|
||||||
|
start /min inject -d -k idachook.dll amdaemon.exe -f -c config_aime_high_ex.json config_aime_high_jp.json config_aime_normal_ex.json config_aime_normal_jp.json config_common.json config_ex.json config_jp.json config_laninstall_client_ex.json config_laninstall_client_jp.json config_laninstall_server_ex.json config_laninstall_server_jp.json config_seat_1_ex.json config_seat_1_jp.json config_seat_2_ex.json config_seat_2_jp.json config_seat_3_ex.json config_seat_3_jp.json config_seat_4_ex.json config_seat_4_jp.json config_seat_single_ex.json config_seat_single_jp.json
|
||||||
|
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
|
||||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||||
|
|
||||||
|
REM unmount the APP_DIR
|
||||||
|
subst Y: /d > nul 2>&1
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo Game processes have terminated
|
echo Game processes have terminated
|
||||||
pause
|
pause
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "board/sg-reader.h"
|
#include "board/sg-reader.h"
|
||||||
#include "board/io4.h"
|
#include "board/io4.h"
|
||||||
#include "board/vfd.h"
|
|
||||||
|
|
||||||
#include "hook/process.h"
|
#include "hook/process.h"
|
||||||
|
|
||||||
@ -60,13 +59,6 @@ static DWORD CALLBACK idac_pre_startup(void)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not needed?
|
|
||||||
hr = vfd_hook_init(4);
|
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -8,7 +8,6 @@ shared_library(
|
|||||||
dependencies : [
|
dependencies : [
|
||||||
capnhook.get_variable('hook_dep'),
|
capnhook.get_variable('hook_dep'),
|
||||||
capnhook.get_variable('hooklib_dep'),
|
capnhook.get_variable('hooklib_dep'),
|
||||||
shlwapi_lib,
|
|
||||||
xinput_lib,
|
xinput_lib,
|
||||||
],
|
],
|
||||||
link_with : [
|
link_with : [
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "platform/pcbid.h"
|
#include "platform/pcbid.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#include "platform/vfs.h"
|
#include "platform/vfs.h"
|
||||||
|
#include "platform/dipsw.h"
|
||||||
|
|
||||||
void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
||||||
{
|
{
|
||||||
@ -37,6 +38,7 @@ void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
|||||||
netenv_config_load(&cfg->netenv, filename);
|
netenv_config_load(&cfg->netenv, filename);
|
||||||
nusec_config_load(&cfg->nusec, filename);
|
nusec_config_load(&cfg->nusec, filename);
|
||||||
vfs_config_load(&cfg->vfs, filename);
|
vfs_config_load(&cfg->vfs, filename);
|
||||||
|
dipsw_config_load(&cfg->dipsw, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void amvideo_config_load(struct amvideo_config *cfg, const wchar_t *filename)
|
void amvideo_config_load(struct amvideo_config *cfg, const wchar_t *filename)
|
||||||
@ -317,3 +319,21 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename)
|
|||||||
filename);
|
filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dipsw_config_load(struct dipsw_config *cfg, const wchar_t *filename)
|
||||||
|
{
|
||||||
|
wchar_t name[7];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(filename != NULL);
|
||||||
|
|
||||||
|
cfg->enable = GetPrivateProfileIntW(L"gpio", L"enable", 1, filename);
|
||||||
|
|
||||||
|
wcscpy_s(name, _countof(name), L"dipsw0");
|
||||||
|
|
||||||
|
for (i = 0 ; i < 8 ; i++) {
|
||||||
|
name[5] = L'1' + i;
|
||||||
|
cfg->dipsw[i] = GetPrivateProfileIntW(L"gpio", name, 0, filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "platform/pcbid.h"
|
#include "platform/pcbid.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#include "platform/vfs.h"
|
#include "platform/vfs.h"
|
||||||
|
#include "platform/dipsw.h"
|
||||||
|
|
||||||
void platform_config_load(
|
void platform_config_load(
|
||||||
struct platform_config *cfg,
|
struct platform_config *cfg,
|
||||||
@ -32,3 +33,4 @@ void netenv_config_load(struct netenv_config *cfg, const wchar_t *filename);
|
|||||||
void nusec_config_load(struct nusec_config *cfg, const wchar_t *filename);
|
void nusec_config_load(struct nusec_config *cfg, const wchar_t *filename);
|
||||||
void pcbid_config_load(struct pcbid_config *cfg, const wchar_t *filename);
|
void pcbid_config_load(struct pcbid_config *cfg, const wchar_t *filename);
|
||||||
void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename);
|
void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename);
|
||||||
|
void dipsw_config_load(struct dipsw_config *cfg, const wchar_t *filename);
|
||||||
|
153
platform/dipsw.c
Normal file
153
platform/dipsw.c
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
#include <ntstatus.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
// #include <zlib.h>
|
||||||
|
|
||||||
|
#include "platform/dipsw.h"
|
||||||
|
#include "platform/vfs.h"
|
||||||
|
|
||||||
|
#include "util/dprintf.h"
|
||||||
|
#include "util/str.h"
|
||||||
|
#include "util/crc.h"
|
||||||
|
|
||||||
|
#define DATA_SIZE 503
|
||||||
|
#define BLOCK_SIZE (sizeof(uint32_t) + 4 + 1 + DATA_SIZE)
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t checksum;
|
||||||
|
char padding_1[4];
|
||||||
|
uint8_t dip_switches;
|
||||||
|
char data[DATA_SIZE];
|
||||||
|
} DipSwitchBlock;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DipSwitchBlock dip_switch_block;
|
||||||
|
char *data;
|
||||||
|
} DipSwitches;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static DipSwitches dip_switches;
|
||||||
|
|
||||||
|
static struct dipsw_config dipsw_config;
|
||||||
|
static struct vfs_config vfs_config;
|
||||||
|
|
||||||
|
static void dipsw_read_sysfile(const wchar_t *sys_file);
|
||||||
|
static void dipsw_save_sysfile(const wchar_t *sys_file);
|
||||||
|
|
||||||
|
HRESULT dipsw_init(const struct dipsw_config *cfg, const struct vfs_config *vfs_cfg)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
wchar_t sys_file_path[MAX_PATH];
|
||||||
|
|
||||||
|
assert(cfg != NULL);
|
||||||
|
assert(vfs_cfg != NULL);
|
||||||
|
|
||||||
|
if (!cfg->enable)
|
||||||
|
{
|
||||||
|
return S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&dipsw_config, cfg, sizeof(*cfg));
|
||||||
|
|
||||||
|
sys_file_path[0] = L'\0';
|
||||||
|
// concatenate vfs_config.amfs with L"sysfile.dat"
|
||||||
|
wcsncpy(sys_file_path, vfs_cfg->amfs, MAX_PATH);
|
||||||
|
wcsncat(sys_file_path, L"\\sysfile.dat", MAX_PATH);
|
||||||
|
|
||||||
|
dipsw_read_sysfile(sys_file_path);
|
||||||
|
|
||||||
|
// now write the dipsw_config.dipsw to the dip_switch_block
|
||||||
|
dipsw_save_sysfile(sys_file_path);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dipsw_read_sysfile(const wchar_t *sys_file)
|
||||||
|
{
|
||||||
|
FILE *f = _wfopen(sys_file, L"r");
|
||||||
|
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
dprintf("First run detected, DipSw settings can only be applied AFTER the first run\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long file_size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (file_size != 0x6000)
|
||||||
|
{
|
||||||
|
dprintf("Invalid sysfile.dat file size\n");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dip_switches.data = malloc(file_size);
|
||||||
|
fread(dip_switches.data, 1, file_size, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
// memcpy(dip_switches.dip_switch_block, dip_switches.data + 0x2800, BLOCK_SIZE);
|
||||||
|
memcpy(&dip_switches.dip_switch_block, dip_switches.data + 0x2800, BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dipsw_save_sysfile(const wchar_t *sys_file)
|
||||||
|
{
|
||||||
|
uint8_t dipsw = 0;
|
||||||
|
// open the sysfile.dat for writing in bytes mode
|
||||||
|
FILE *f = _wfopen(sys_file, L"rb+");
|
||||||
|
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the dipsw_config.dipsw to the dip_switch_block
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (dipsw_config.dipsw[i])
|
||||||
|
{
|
||||||
|
// print which dipsw is enabled
|
||||||
|
dprintf("DipSw: DipSw%d=1 set\n", i + 1);
|
||||||
|
dipsw |= (1 << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dip_switches.dip_switch_block.dip_switches = dipsw;
|
||||||
|
|
||||||
|
// calculate the new checksum, skip the old crc32 value
|
||||||
|
// which is at the beginning of the block, thats's why the +4
|
||||||
|
// conver the struct to chars in order for the crc32 calculation to work
|
||||||
|
dip_switches.dip_switch_block.checksum = crc32(
|
||||||
|
(char *)&dip_switches.dip_switch_block + 4, BLOCK_SIZE - 4, 0);
|
||||||
|
|
||||||
|
// build the new dip switch block
|
||||||
|
char block[BLOCK_SIZE];
|
||||||
|
memcpy(block, (char *)&dip_switches.dip_switch_block, BLOCK_SIZE);
|
||||||
|
|
||||||
|
// replace the old block with the new one
|
||||||
|
memcpy(dip_switches.data + 0x2800, block, BLOCK_SIZE);
|
||||||
|
memcpy(dip_switches.data + 0x5800, block, BLOCK_SIZE);
|
||||||
|
|
||||||
|
// print the dip_switch_block in hex
|
||||||
|
/*
|
||||||
|
dprintf("DipSw Block: ");
|
||||||
|
for (size_t i = 0; i < BLOCK_SIZE; i++)
|
||||||
|
{
|
||||||
|
dprintf("%02X ", ((uint8_t *)&dip_switches.dip_switch_block)[i]);
|
||||||
|
}
|
||||||
|
dprintf("\n");
|
||||||
|
*/
|
||||||
|
|
||||||
|
fwrite(dip_switches.data, 1, 0x6000, f);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
15
platform/dipsw.h
Normal file
15
platform/dipsw.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "platform/vfs.h"
|
||||||
|
|
||||||
|
struct dipsw_config {
|
||||||
|
bool enable;
|
||||||
|
bool dipsw[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT dipsw_init(const struct dipsw_config *cfg, const struct vfs_config *vfs_cfg);
|
@ -79,5 +79,13 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg)
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disable api/polling to the original servers
|
||||||
|
|
||||||
|
hr = dns_hook_push(L"amlog.sys-all.net", NULL);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -32,5 +32,7 @@ platform_lib = static_library(
|
|||||||
'platform.h',
|
'platform.h',
|
||||||
'vfs.c',
|
'vfs.c',
|
||||||
'vfs.h',
|
'vfs.h',
|
||||||
|
'dipsw.c',
|
||||||
|
'dipsw.h',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "platform/pcbid.h"
|
#include "platform/pcbid.h"
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#include "platform/vfs.h"
|
#include "platform/vfs.h"
|
||||||
|
#include "platform/dipsw.h"
|
||||||
|
|
||||||
HRESULT platform_hook_init(
|
HRESULT platform_hook_init(
|
||||||
const struct platform_config *cfg,
|
const struct platform_config *cfg,
|
||||||
@ -80,5 +81,11 @@ HRESULT platform_hook_init(
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hr = dipsw_init(&cfg->dipsw, &cfg->vfs);
|
||||||
|
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "platform/nusec.h"
|
#include "platform/nusec.h"
|
||||||
#include "platform/pcbid.h"
|
#include "platform/pcbid.h"
|
||||||
#include "platform/vfs.h"
|
#include "platform/vfs.h"
|
||||||
|
#include "platform/dipsw.h"
|
||||||
|
|
||||||
struct platform_config {
|
struct platform_config {
|
||||||
struct amvideo_config amvideo;
|
struct amvideo_config amvideo;
|
||||||
@ -24,6 +25,7 @@ struct platform_config {
|
|||||||
struct netenv_config netenv;
|
struct netenv_config netenv;
|
||||||
struct nusec_config nusec;
|
struct nusec_config nusec;
|
||||||
struct vfs_config vfs;
|
struct vfs_config vfs;
|
||||||
|
struct dipsw_config dipsw;
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT platform_hook_init(
|
HRESULT platform_hook_init(
|
||||||
|
@ -28,7 +28,9 @@ 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);
|
||||||
|
|
||||||
static wchar_t vfs_nthome_real[MAX_PATH];
|
static wchar_t vfs_nthome_real[MAX_PATH];
|
||||||
static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser";
|
// new home for ALLS
|
||||||
|
static const wchar_t vfs_nthome[] = L"C:\\Users\\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 wchar_t vfs_option[] = L"C:\\Mount\\Option";
|
||||||
@ -273,8 +275,8 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (src[0]) {
|
switch (src[0]) {
|
||||||
case L'D': // later AMDaemon versions default to D: for AMFS if it can't find it
|
// case L'D': // later AMDaemon versions default to D: for AMFS if it can't find it
|
||||||
case L'd':
|
// case L'd':
|
||||||
case L'e':
|
case L'e':
|
||||||
case L'E':
|
case L'E':
|
||||||
redir = vfs_config.amfs;
|
redir = vfs_config.amfs;
|
||||||
|
Loading…
Reference in New Issue
Block a user