From c9fd320353fe0ea223b99c58b01f60a2022265ff Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Tue, 20 Jun 2023 12:33:58 +1000 Subject: [PATCH 1/6] jbhook1: More effectively setup avs boot config The NVRAM redirection was silently failing because the prop delete/recreate pair didn't work. This just recreates the entire config from scratch instead, which guarantees success every time. By making the NVRAM type "fs", we also make it easier to debug any issues that people may have. --- src/main/jbhook1/avs-boot.c | 58 ++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/src/main/jbhook1/avs-boot.c b/src/main/jbhook1/avs-boot.c index 969fbd8..dccba69 100644 --- a/src/main/jbhook1/avs-boot.c +++ b/src/main/jbhook1/avs-boot.c @@ -52,18 +52,18 @@ static const struct hook_symbol jbhook1_log_gftools_hook_syms2[] = { .link = (void **) &real_ea3_boot}, }; -static void avs_boot_replace_property_uint32( - struct property_node *node, const char *name, uint32_t val) +static void avs_boot_create_property_str( + struct property *config, const char *name, const char *val) { struct property_node *tmp; - tmp = property_search(NULL, node, name); + tmp = property_node_create(config, NULL, PROPERTY_TYPE_STR, name, val); if (tmp) { - property_node_remove(tmp); + property_node_datasize(tmp); + } else { + log_fatal("Could not avs_boot_create_prop_str(%s, %s)", name, val); } - - property_node_create(NULL, node, PSMAP_TYPE_U32, name, val); } static void avs_boot_replace_property_str( @@ -81,11 +81,13 @@ static void avs_boot_replace_property_str( if (tmp) { property_node_datasize(tmp); + } else { + log_fatal("Could not avs_boot_replace_property_str(%s, %s)", name, val); } } static void my_avs_boot( - struct property_node *config, + struct property_node *_config, void *std_heap, size_t sz_std_heap, void *avs_heap, @@ -95,14 +97,44 @@ static void my_avs_boot( { log_info("Called my_avs_boot"); - avs_boot_replace_property_uint32(config, "log/level", 4); - avs_boot_replace_property_str( + // avshelper gates this behind a check that might not always be true + CreateDirectoryA("./CONF", 0); + CreateDirectoryA("./CONF/NVRAM", 0); + CreateDirectoryA("./CONF/RAW", 0); + + // The default config isn't very exciting, and we need to replace the NVRAM + // settings with our own anyway. Trying to edit the config almost always + // fails because of some weird fragmentation issues causing node insert to + // fail, so just recreate the entire thing from scratch. + uint8_t cfg_buf[2048]; + struct property *config = property_create( + PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE | PROPERTY_FLAG_CREATE, + cfg_buf, + sizeof(cfg_buf)); + + log_assert(config); + + property_node_create( + config, NULL, PROPERTY_TYPE_U32, "/config/log/level", 4); + avs_boot_create_property_str(config, "/config/fs/root/device", "."); + avs_boot_create_property_str(config, "/config/fs/raw/device", "./CONF/RAW"); + avs_boot_create_property_str( config, "/config/fs/nvram/device", "./CONF/NVRAM"); - avs_boot_replace_property_str( - config, "/config/fs/raw/device", "./CONF/RAW"); + avs_boot_create_property_str(config, "/config/fs/nvram/fstype", "fs"); + avs_boot_create_property_str(config, "/config/fs/nvram/option", ""); + property_node_create( + config, NULL, PROPERTY_TYPE_U16, "/config/net/nr_protocol", 8); + property_node_create( + config, NULL, PROPERTY_TYPE_U16, "/config/net/nr_socket", 8); + property_node_create( + config, NULL, PROPERTY_TYPE_U8, "/config/net/enable_raw", 1); + + struct property_node *config_node = + property_search(config, NULL, "/config"); + log_assert(config_node); real_avs_boot( - config, + config_node, std_heap, sz_std_heap, avs_heap, @@ -168,4 +200,4 @@ void jbhook1_avs_boot_set_eamuse_addr(const struct net_addr *server_addr) &jbhook1_avs_boot_eamuse_server_addr, server_addr, sizeof(struct net_addr)); -} \ No newline at end of file +} -- 2.54.0 From f4f1a2734d2212b890020cf067c8a92bb3efc842 Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Tue, 20 Jun 2023 12:35:28 +1000 Subject: [PATCH 2/6] jbhook1: If gfx.vertical is set, rotate error messages too By hooking CreateProcessA, we can adjust the commandline to disable any rotation, which displays the error box at the correct place on screen (no additional x/y adjustment is needed) --- src/main/jbhook1/dllmain.c | 79 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/main/jbhook1/dllmain.c b/src/main/jbhook1/dllmain.c index 57d62f7..42f8dc9 100644 --- a/src/main/jbhook1/dllmain.c +++ b/src/main/jbhook1/dllmain.c @@ -47,6 +47,29 @@ my_mwindow_create(HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); static HWND(CDECL *real_mwindow_create)( HINSTANCE, void *, const char *, DWORD, DWORD, BOOL); +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); +static BOOL(STDCALL *real_CreateProcessA)( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); + static const struct hook_symbol init_hook_syms[] = { { .name = "mwindow_create", @@ -55,6 +78,17 @@ static const struct hook_symbol init_hook_syms[] = { }, }; +static const struct hook_symbol kernel32_hook_syms[] = { + { + .name = "CreateProcessA", + .patch = my_CreateProcessA, + .link = (void **) &real_CreateProcessA, + }, +}; + +// so our CreateProcessA hook can check +static bool vertical; + /** * This seems to be a good entry point to intercept before the game calls * anything important (very close to the start of WinMain). @@ -107,6 +141,7 @@ static HWND CDECL my_mwindow_create( jbhook1_log_gftools_init(); fullscreen = !config_gfx.windowed; + vertical = config_gfx.vertical; if (config_gfx.vertical) { DWORD tmp = window_width; @@ -175,9 +210,53 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx) /* Actual hooks for game specific stuff */ + hook_table_apply( + NULL, + "kernel32.dll", + kernel32_hook_syms, + lengthof(kernel32_hook_syms)); + acp_hook_init(); adapter_hook_init(); } return TRUE; } + +static BOOL STDCALL my_CreateProcessA( + LPCSTR lpApplicationName, + LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, + LPSTARTUPINFOA lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) +{ + LPSTR rot_arg; + + // de-rotate the error window if needed. In theory this should parse the + // commandline properly, in practice this works on all the .exe jubeats. + if (vertical && lpCommandLine) { + if ((rot_arg = strstr(lpCommandLine, " -R90 "))) { // jubeat 01 + memcpy(rot_arg, " -R0 ", strlen(" -R0 ")); + } else if ((rot_arg = + strstr(lpCommandLine, " -rot:90 "))) { // jubeat 02 + memcpy(rot_arg, " -rot:0 ", strlen(" -rot:0 ")); + } + } + + return real_CreateProcessA( + lpApplicationName, + lpCommandLine, + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + lpStartupInfo, + lpProcessInformation); +} -- 2.54.0 From 67de6639ef474e1d0ad90bb521cb84cc3421f023 Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Wed, 21 Jun 2023 17:51:19 +1000 Subject: [PATCH 3/6] Make roundplug PCBID/EAMID verification fail a hard error This was previously a soft error, and also said "reverting to default" without actually doing so. We should be forcing correct format. --- src/main/ddrhook1/config-eamuse.c | 25 ++++--------------------- src/main/iidxhook-util/config-eamuse.c | 25 ++++--------------------- src/main/jbhook1/config-eamuse.c | 24 ++++-------------------- src/main/popnhook1/config-eamuse.c | 25 ++++--------------------- 4 files changed, 16 insertions(+), 83 deletions(-) diff --git a/src/main/ddrhook1/config-eamuse.c b/src/main/ddrhook1/config-eamuse.c index 260791d..f50fb36 100644 --- a/src/main/ddrhook1/config-eamuse.c +++ b/src/main/ddrhook1/config-eamuse.c @@ -56,7 +56,6 @@ void ddrhook1_config_eamuse_get( { char server_url[1024]; char *tmp; - char *tmp2; memset(config_eamuse, 0, sizeof(struct ddrhook1_config_eamuse)); @@ -102,16 +101,8 @@ void ddrhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("PCBID verification failed"); + return; } if (!cconfig_util_get_data( @@ -130,15 +121,7 @@ void ddrhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("EAMID verification failed"); + return; } } diff --git a/src/main/iidxhook-util/config-eamuse.c b/src/main/iidxhook-util/config-eamuse.c index f59b03e..adc3c35 100644 --- a/src/main/iidxhook-util/config-eamuse.c +++ b/src/main/iidxhook-util/config-eamuse.c @@ -68,7 +68,6 @@ void iidxhook_util_config_eamuse_get( { char server_url[1024]; char *tmp; - char *tmp2; memset(config_eamuse, 0, sizeof(struct iidxhook_util_config_eamuse)); @@ -127,16 +126,8 @@ void iidxhook_util_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("PCBID verification failed"); + return; } if (!cconfig_util_get_data( @@ -155,15 +146,7 @@ void iidxhook_util_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("EAMID verification failed"); + return; } } diff --git a/src/main/jbhook1/config-eamuse.c b/src/main/jbhook1/config-eamuse.c index dba512e..7ed941c 100644 --- a/src/main/jbhook1/config-eamuse.c +++ b/src/main/jbhook1/config-eamuse.c @@ -102,16 +102,8 @@ void jbhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("PCBID verification failed"); + return; } if (!cconfig_util_get_data( @@ -130,15 +122,7 @@ void jbhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("EAMID verification failed"); + return; } } diff --git a/src/main/popnhook1/config-eamuse.c b/src/main/popnhook1/config-eamuse.c index 98e406b..909911e 100644 --- a/src/main/popnhook1/config-eamuse.c +++ b/src/main/popnhook1/config-eamuse.c @@ -57,7 +57,6 @@ void popnhook1_config_eamuse_get( { char server_url[1024]; char *tmp; - char *tmp2; memset(config_eamuse, 0, sizeof(struct popnhook1_config_eamuse)); @@ -103,16 +102,8 @@ void popnhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->pcbid, false); - log_warning( - "PCBID verification of '%s' failed, fallback to default " - "PCBID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("PCBID verification failed"); + return; } if (!cconfig_util_get_data( @@ -131,15 +122,7 @@ void popnhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - tmp = security_id_to_str( - &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); - tmp2 = security_id_to_str(&config_eamuse->eamid, false); - log_warning( - "EAMID verification of '%s' failed, fallback to default " - "EAMID '%s'", - tmp2, - tmp); - free(tmp); - free(tmp2); + log_fatal("EAMID verification failed"); + return; } } -- 2.54.0 From 6116b072dfba5fec7d3bc84981d5bb52c89173de Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Mon, 14 Aug 2023 23:39:57 +1000 Subject: [PATCH 4/6] Revert "Make roundplug PCBID/EAMID verification fail a hard error" This reverts commit 67de6639ef474e1d0ad90bb521cb84cc3421f023. --- src/main/ddrhook1/config-eamuse.c | 25 +++++++++++++++++++++---- src/main/iidxhook-util/config-eamuse.c | 25 +++++++++++++++++++++---- src/main/jbhook1/config-eamuse.c | 24 ++++++++++++++++++++---- src/main/popnhook1/config-eamuse.c | 25 +++++++++++++++++++++---- 4 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/main/ddrhook1/config-eamuse.c b/src/main/ddrhook1/config-eamuse.c index f50fb36..260791d 100644 --- a/src/main/ddrhook1/config-eamuse.c +++ b/src/main/ddrhook1/config-eamuse.c @@ -56,6 +56,7 @@ void ddrhook1_config_eamuse_get( { char server_url[1024]; char *tmp; + char *tmp2; memset(config_eamuse, 0, sizeof(struct ddrhook1_config_eamuse)); @@ -101,8 +102,16 @@ void ddrhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - log_fatal("PCBID verification failed"); - return; + tmp = security_id_to_str( + &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->pcbid, false); + log_warning( + "PCBID verification of '%s' failed, fallback to default " + "PCBID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } if (!cconfig_util_get_data( @@ -121,7 +130,15 @@ void ddrhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - log_fatal("EAMID verification failed"); - return; + tmp = security_id_to_str( + &DDRHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->eamid, false); + log_warning( + "EAMID verification of '%s' failed, fallback to default " + "EAMID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } } diff --git a/src/main/iidxhook-util/config-eamuse.c b/src/main/iidxhook-util/config-eamuse.c index adc3c35..f59b03e 100644 --- a/src/main/iidxhook-util/config-eamuse.c +++ b/src/main/iidxhook-util/config-eamuse.c @@ -68,6 +68,7 @@ void iidxhook_util_config_eamuse_get( { char server_url[1024]; char *tmp; + char *tmp2; memset(config_eamuse, 0, sizeof(struct iidxhook_util_config_eamuse)); @@ -126,8 +127,16 @@ void iidxhook_util_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - log_fatal("PCBID verification failed"); - return; + tmp = security_id_to_str( + &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->pcbid, false); + log_warning( + "PCBID verification of '%s' failed, fallback to default " + "PCBID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } if (!cconfig_util_get_data( @@ -146,7 +155,15 @@ void iidxhook_util_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - log_fatal("EAMID verification failed"); - return; + tmp = security_id_to_str( + &IIDXHOOK_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->eamid, false); + log_warning( + "EAMID verification of '%s' failed, fallback to default " + "EAMID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } } diff --git a/src/main/jbhook1/config-eamuse.c b/src/main/jbhook1/config-eamuse.c index 7ed941c..dba512e 100644 --- a/src/main/jbhook1/config-eamuse.c +++ b/src/main/jbhook1/config-eamuse.c @@ -102,8 +102,16 @@ void jbhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - log_fatal("PCBID verification failed"); - return; + tmp = security_id_to_str( + &JBHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->pcbid, false); + log_warning( + "PCBID verification of '%s' failed, fallback to default " + "PCBID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } if (!cconfig_util_get_data( @@ -122,7 +130,15 @@ void jbhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - log_fatal("EAMID verification failed"); - return; + tmp = security_id_to_str( + &JBHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->eamid, false); + log_warning( + "EAMID verification of '%s' failed, fallback to default " + "EAMID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } } diff --git a/src/main/popnhook1/config-eamuse.c b/src/main/popnhook1/config-eamuse.c index 909911e..98e406b 100644 --- a/src/main/popnhook1/config-eamuse.c +++ b/src/main/popnhook1/config-eamuse.c @@ -57,6 +57,7 @@ void popnhook1_config_eamuse_get( { char server_url[1024]; char *tmp; + char *tmp2; memset(config_eamuse, 0, sizeof(struct popnhook1_config_eamuse)); @@ -102,8 +103,16 @@ void popnhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->pcbid)) { - log_fatal("PCBID verification failed"); - return; + tmp = security_id_to_str( + &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_PCBID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->pcbid, false); + log_warning( + "PCBID verification of '%s' failed, fallback to default " + "PCBID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } if (!cconfig_util_get_data( @@ -122,7 +131,15 @@ void popnhook1_config_eamuse_get( } if (!security_id_verify(&config_eamuse->eamid)) { - log_fatal("EAMID verification failed"); - return; + tmp = security_id_to_str( + &POPNHOOK1_CONFIG_EAMUSE_DEFAULT_EAMID_VALUE, false); + tmp2 = security_id_to_str(&config_eamuse->eamid, false); + log_warning( + "EAMID verification of '%s' failed, fallback to default " + "EAMID '%s'", + tmp2, + tmp); + free(tmp); + free(tmp2); } } -- 2.54.0 From ec9ad43464f847d0a9adf21edf4e78505fd60830 Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Sun, 20 Aug 2023 15:57:37 +1000 Subject: [PATCH 5/6] Fix missing xml for jb03. Closes #258. --- dist/jb/gamestart-03.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/dist/jb/gamestart-03.bat b/dist/jb/gamestart-03.bat index 8a9ab32..76acc78 100644 --- a/dist/jb/gamestart-03.bat +++ b/dist/jb/gamestart-03.bat @@ -3,6 +3,7 @@ cd /d %~dp0 if not exist dev\nvram mkdir dev\nvram +if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml if not exist dev\raw mkdir dev\raw -- 2.54.0 From 67962abfaf6ae2fb8ca4d03a37b3e02d8aca889d Mon Sep 17 00:00:00 2001 From: Will Toohey Date: Wed, 18 Oct 2023 09:24:58 +1000 Subject: [PATCH 6/6] Fix missing xml for jb04. Fixes booting Ave. --- dist/jb/gamestart-04.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/dist/jb/gamestart-04.bat b/dist/jb/gamestart-04.bat index 33e786b..245e314 100644 --- a/dist/jb/gamestart-04.bat +++ b/dist/jb/gamestart-04.bat @@ -3,6 +3,7 @@ cd /d %~dp0 if not exist dev\nvram mkdir dev\nvram +if not exist dev\nvram\ea3-config.xml copy prop\ea3-config.xml dev\nvram\ea3-config.xml if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml if not exist dev\raw mkdir dev\raw -- 2.54.0