6 Commits

Author SHA1 Message Date
25e954fb55 Merge pull request 'print vfd message instead of dump hex' (#13) from Sucareto/segatools:develop into develop
Reviewed-on: Dniel97/segatools#13
2024-04-29 19:48:35 +00:00
a8c6ac70e4 Merge pull request '[unity] Fix Unity config path' (#12) from beerpsi/segatools:fix/unity/wrong-config-path into develop
Reviewed-on: Dniel97/segatools#12
2024-04-29 19:41:53 +00:00
eb1ec0e261 idac: updated start.bat script 2024-04-29 21:34:30 +02:00
482a6e530a print vfd message 2024-04-30 02:19:10 +08:00
65173e1fa6 [unity] Fix Unity config path 2024-04-29 23:12:10 +07:00
4041844ea9 mai2/mu3/cm: Integrate UnityDoorstop with segatools (#11)
[UnityDoorstop](https://github.com/NeighTools/UnityDoorstop) is a tool to execute managed code (.NET DLLs) before Unity does, useful for modding frameworks such as BepInEx.

This PR integrates parts of its code into segatools, so loading BepInEx is as simple as adding 2 lines to `segatools.ini`:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```

This PR also factors out the Unity path redirection hooks to its own module.

Reviewed-on: Dniel97/segatools#11
Co-authored-by: beerpsi <beerpsi@duck.com>
Co-committed-by: beerpsi <beerpsi@duck.com>
2024-04-15 19:30:28 +00:00
3 changed files with 72 additions and 28 deletions

View File

@ -26,6 +26,7 @@ static HRESULT vfd_handle_irp(struct irp *irp);
static struct uart vfd_uart;
static uint8_t vfd_written[512];
static uint8_t vfd_readable[512];
UINT codepage;
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
{
@ -41,6 +42,7 @@ HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
vfd_uart.readable.bytes = vfd_readable;
vfd_uart.readable.nbytes = sizeof(vfd_readable);
codepage = GetACP();
dprintf("VFD: hook enabled.\n");
return iohook_push_handler(vfd_handle_irp);
@ -62,8 +64,60 @@ static HRESULT vfd_handle_irp(struct irp *irp)
return hr;
}
dprintf("VFD TX:\n");
dump_iobuf(&vfd_uart.written);
uint8_t cmd = 0;
uint8_t str_1[512];
uint8_t str_2[512];
uint8_t str_1_len = 0;
uint8_t str_2_len = 0;
for (size_t i = 0; i < vfd_uart.written.pos; i++) {
if (vfd_uart.written.bytes[i] == 0x1B) {
i++;
cmd = vfd_uart.written.bytes[i];
if (cmd == 0x30) {
i += 3;
}
else if (cmd == 0x50) {
i++;
}
continue;
}
if (cmd == 0x30) {
str_1[str_1_len++] = vfd_uart.written.bytes[i];
}
else if (cmd == 0x50) {
str_2[str_2_len++] = vfd_uart.written.bytes[i];
}
}
if (str_1_len) {
str_1[str_1_len++] = '\0';
if (codepage != 932) {
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_1, str_1_len, buffer, str_1_len);
char str_recode[str_1_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_1_len, str_recode, str_1_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
}
else {
dprintf("VFD: %s\n", str_1);
}
}
if (str_2_len) {
str_2[str_2_len++] = '\0';
if (codepage != 932) {
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len);
char str_recode[str_2_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
} else {
dprintf("VFD: %s\n", str_2);
}
}
// dprintf("VFD TX:\n");
// dump_iobuf(&vfd_uart.written);
vfd_uart.written.pos = 0;
return hr;

25
dist/idac/start.bat vendored
View File

@ -2,20 +2,6 @@
pushd %~dp0
REM set the APP_DIR to the Y drive
set APP_DIR=Y:\SDGT
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
set AMDAEMON_CFG=config_common.json ^
config_ex.json ^
config_jp.json ^
@ -40,11 +26,14 @@ config_seat_single_jp.json ^
config_hook.json
start "AM Daemon" /min inject -d -k idachook.dll amdaemon.exe -c %AMDAEMON_CFG%
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
REM unmount the APP_DIR
subst Y: /d > nul 2>&1
rem JP
rem inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=ja launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
rem EXP
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
taskkill /f /im amdaemon.exe > nul 2>&1
echo.
echo Game processes have terminated

View File

@ -66,21 +66,22 @@ void doorstop_invoke(void* domain) {
if (mono_domain_set_config) {
#define CONFIG_EXT L".config"
wchar_t exe_path[MAX_PATH];
size_t exe_path_len = GetModuleFileNameW(NULL, exe_path, MAX_PATH);
wchar_t *folder_name = wcsdup(exe_path);
wchar_t config_path[MAX_PATH];
size_t config_path_len = GetModuleFileNameW(NULL, config_path, MAX_PATH);
wchar_t *folder_name = wcsdup(config_path);
PathCchRemoveFileSpec(folder_name, exe_path_len + 1);
PathCchRemoveFileSpec(folder_name, config_path_len + 1);
wmemcpy(config_path + config_path_len, CONFIG_EXT, sizeof(CONFIG_EXT) / sizeof(CONFIG_EXT[0]));
char *exe_path_n = narrow(exe_path);
char *config_path_n = narrow(config_path);
char *folder_name_n = narrow(folder_name);
dprintf("Unity: Setting config paths: base dir: %s; config path: %s\n", folder_name_n, exe_path_n);
dprintf("Unity: Setting config paths: base dir: %s; config path: %s\n", folder_name_n, config_path_n);
mono_domain_set_config(domain, folder_name_n, exe_path_n);
mono_domain_set_config(domain, folder_name_n, config_path_n);
free(folder_name);
free(exe_path_n);
free(config_path_n);
free(folder_name_n);
#undef CONFIG_EXT