From 097b74d8493602f11a638becf93412b00cf6fbb8 Mon Sep 17 00:00:00 2001 From: Dniel97 Date: Wed, 13 Mar 2024 17:51:58 +0100 Subject: [PATCH] cxb: server support added, bugfixes, thanks @Midorica --- README.md | 6 ++-- aimeio/aimeio.c | 1 - cxbhook/revio.c | 4 +-- dist/cxb/segatools.ini | 9 ++++-- doc/config/common.md | 25 +++++++++++++++- hooklib/dns.c | 67 +++++++++++++++++++++++++++++++++++++++++- idachook/idachook.def | 1 - idacio/xi.c | 4 --- platform/config.c | 8 +++++ platform/dns.c | 7 +++++ platform/dns.h | 1 + platform/nusec.c | 32 ++++++++++---------- 12 files changed, 135 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index a754a74..4e4e0e3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Segatools -Version: `2024-02-27` +Version: `2024-03-13` Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms. @@ -8,7 +8,9 @@ Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platfo * CHUNITHM * up to [CHUNITHM PARADISE LOST](doc/chunihook.md) - * starting from CHUNITHM NEW!! + * starting from CHUNITHM NEW!! +* crossbeats REV. + * up to crossbeats REV. SUNRISE * Initial D * [Initial D Arcade Stage Zero](doc/idzhook.md) * Initial D THE ARCADE diff --git a/aimeio/aimeio.c b/aimeio/aimeio.c index 93f3ebf..17de30e 100644 --- a/aimeio/aimeio.c +++ b/aimeio/aimeio.c @@ -68,7 +68,6 @@ static void aime_io_config_read( cfg->felica_path, _countof(cfg->felica_path), filename); - // dprintf("NFC: felicaPath GetLastError %lx\n", GetLastError()); cfg->felica_gen = GetPrivateProfileIntW( L"aime", diff --git a/cxbhook/revio.c b/cxbhook/revio.c index e72158d..15e2260 100644 --- a/cxbhook/revio.c +++ b/cxbhook/revio.c @@ -154,7 +154,7 @@ static int my_cCommIo_GetTrigger() out &= ~last_triggers; - dprintf("Revio: GetTrigger %X\n", out); + // dprintf("Revio: GetTrigger %X\n", out); last_triggers = out; return out; } @@ -188,7 +188,7 @@ static int my_cCommIo_GetRelease() out &= ~btns; - dprintf("Revio: GetRelease %X\n", out); + // dprintf("Revio: GetRelease %X\n", out); last_triggers = btns; return out; } diff --git a/dist/cxb/segatools.ini b/dist/cxb/segatools.ini index 984f609..40f0ad6 100644 --- a/dist/cxb/segatools.ini +++ b/dist/cxb/segatools.ini @@ -19,10 +19,10 @@ appdata= [aime] ; Aime reader emulation -; CXB is stupid, so we have to make the paths go back one enable=1 +; CXB is stupid, so we have to make the paths go back two directories. This +; will load the file from "resource\DEVICE\aime.txt". aimePath=../DEVICE/aime.txt -felicaPath=../DEVICE/felica.txt [led] ; Emulation for the LED board. Currently it's just dummy responses, @@ -39,6 +39,10 @@ enable=1 ; Note that 127.0.0.1, localhost etc are specifically rejected. default=127.0.0.1 +; Set the title server hostname or IP address here, as the title server +; is hardcoded in the game. +title=https://127.0.0.1:9002 + [netenv] ; Simulate an ideal LAN environment. This may interfere with head-to-head play. ; Crossbeats is extremely picky about its LAN environment, so leaving this @@ -113,6 +117,7 @@ test=0x70 service=0x71 ; Keyboard button to increment coin counter. Default is the F3 key. coin=0x72 + ; Menu up key. Default is up arrow. up=0x26 ; Menu down key. Default is down arrow. diff --git a/doc/config/common.md b/doc/config/common.md index 23be911..59ec2e1 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -153,6 +153,13 @@ setting. Also, loopback addresses are specifically checked for and rejected by the games themselves; this needs to be a LAN or WAN IP (or a hostname that resolves to one). +### `title` + +Default: `title` + +Leave it as `title` to use the title server returned by ALL.Net. Rewrites +the title server hostname for certain games, such as crossbeats REV. + ### `router` Default: Empty string (i.e. use value from `default` setting) @@ -388,13 +395,29 @@ Bit values are: - 3: EXP: Export (for Asian markets) - 4: CHS: China (Simplified Chinese?) +### `billingCa` + +Default: `DEVICE\\ca.crt` + +Set the billing certificate path. This has to match the one used for the +SSL billing server. The DER certificate must fit in 1024 bytes so it must be +small. + +### `billingPub` + +Default: `DEVICE\\billing.pub` + +Set the actual keychip RSA public key path. This public key has to match the +private key `billing.key` of the billing server in order to decrypt/encrypt +the billing transactions. + ### `billingType` Default: `1` Set the billing "type" for the keychip. The type determins what kind of revenue share, if any, the game maker has with SEGA. Some games may be picky and require types other -then 1 (ex. Crossbeats requires billing type 2), so this option is provided if this +then 1 (ex. crossbeats REV. requires billing type 2), so this option is provided if this is an issue. Billing types are: - 0: No billing? diff --git a/hooklib/dns.c b/hooklib/dns.c index 7dd6d0b..e8b0e69 100644 --- a/hooklib/dns.c +++ b/hooklib/dns.c @@ -13,6 +13,8 @@ #include "hook/hr.h" #include "hook/table.h" +#include "util/dprintf.h" + #include "hooklib/dns.h" /* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill" @@ -66,13 +68,19 @@ static int WSAAPI hook_getaddrinfo( const char *pServiceName, const ADDRINFOA *pHints, ADDRINFOA **ppResult); - + static HINTERNET WINAPI hook_WinHttpConnect( HINTERNET hSession, const wchar_t *pwszServerName, INTERNET_PORT nServerPort, DWORD dwReserved); +static bool WINAPI hook_WinHttpCrackUrl( + const wchar_t *pwszUrl, + DWORD dwUrlLength, + DWORD dwFlags, + LPURL_COMPONENTS lpUrlComponents); + /* Link pointers */ static DNS_STATUS (WINAPI *next_DnsQuery_A)( @@ -108,6 +116,12 @@ static HINTERNET (WINAPI *next_WinHttpConnect)( INTERNET_PORT nServerPort, DWORD dwReserved); +static bool (WINAPI *next_WinHttpCrackUrl)( + const wchar_t *pwszUrl, + DWORD dwUrlLength, + DWORD dwFlags, + LPURL_COMPONENTS lpUrlComponents); + static const struct hook_symbol dns_hook_syms_dnsapi[] = { { .name = "DnsQuery_A", @@ -138,13 +152,19 @@ static const struct hook_symbol dns_hook_syms_winhttp[] = { .name = "WinHttpConnect", .patch = hook_WinHttpConnect, .link = (void **) &next_WinHttpConnect, + }, { + .name = "WinHttpCrackUrl", + .patch = hook_WinHttpCrackUrl, + .link = (void **) &next_WinHttpCrackUrl, } + }; static bool dns_hook_initted; static CRITICAL_SECTION dns_hook_lock; static struct dns_hook_entry *dns_hook_entries; static size_t dns_hook_nentries; +static char received_title_url[255]; static void dns_hook_init(void) { @@ -522,3 +542,48 @@ static HINTERNET WINAPI hook_WinHttpConnect( return next_WinHttpConnect(hSession, pwszServerName, nServerPort, dwReserved); } + +// Hook to replace CXB title url +static bool WINAPI hook_WinHttpCrackUrl( + const wchar_t *pwszUrl, + DWORD dwUrlLength, + DWORD dwFlags, + LPURL_COMPONENTS lpUrlComponents) +{ + const struct dns_hook_entry *pos; + size_t i; + + EnterCriticalSection(&dns_hook_lock); + + for (i = 0 ; i < dns_hook_nentries ; i++) { + pos = &dns_hook_entries[i]; + + if (_wcsicmp(pwszUrl, pos->from) == 0) { + wchar_t* toAddr = pos->to; + wchar_t titleBuffer[255]; + + if(wcscmp(toAddr, L"title") == 0) { + size_t wstr_c; + mbstowcs_s(&wstr_c, titleBuffer, 255, received_title_url, strlen(received_title_url)); + toAddr = titleBuffer; + } + + bool result = next_WinHttpCrackUrl( + toAddr, + wcslen(toAddr), + dwFlags, + lpUrlComponents + ); + LeaveCriticalSection(&dns_hook_lock); + return result; + } + } + + LeaveCriticalSection(&dns_hook_lock); + return next_WinHttpCrackUrl( + pwszUrl, + dwUrlLength, + dwFlags, + lpUrlComponents + ); +} diff --git a/idachook/idachook.def b/idachook/idachook.def index 4c944fd..a8b05b5 100644 --- a/idachook/idachook.def +++ b/idachook/idachook.def @@ -13,7 +13,6 @@ EXPORTS amDllVideoSetResolution @3 idac_io_get_api_version idac_io_init - idac_io_poll idac_io_get_opbtns idac_io_get_gamebtns idac_io_get_shifter diff --git a/idacio/xi.c b/idacio/xi.c index 3b912fc..c924153 100644 --- a/idacio/xi.c +++ b/idacio/xi.c @@ -52,10 +52,6 @@ HRESULT idac_xi_init(const struct idac_xi_config *cfg, const struct idac_io_back return S_OK; } -HRESULT idac_io_poll(void) { - return S_OK; -} - static HRESULT idac_xi_config_apply(const struct idac_xi_config *cfg) { /* Deadzones check */ if (cfg->left_stick_deadzone > 32767 || cfg->left_stick_deadzone < 0) { diff --git a/platform/config.c b/platform/config.c index 05f1a0b..fd48a3e 100644 --- a/platform/config.c +++ b/platform/config.c @@ -113,6 +113,14 @@ void dns_config_load(struct dns_config *cfg, const wchar_t *filename) cfg->aimedb, _countof(cfg->aimedb), filename); + + GetPrivateProfileStringW( + L"dns", + L"title", + L"title", + cfg->title, + _countof(cfg->title), + filename); } void hwmon_config_load(struct hwmon_config *cfg, const wchar_t *filename) diff --git a/platform/dns.c b/platform/dns.c index d6d37a7..a658b58 100644 --- a/platform/dns.c +++ b/platform/dns.c @@ -82,6 +82,13 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg) return hr; } + // croosbeats REV. + hr = dns_hook_push(L"https://rev-ent.ac.capcom.jp:443", cfg->title); + + if (FAILED(hr)) { + return hr; + } + // AimePay hr = dns_hook_push(L"api-aime.am-all.net", cfg->startup); diff --git a/platform/dns.h b/platform/dns.h index 416fe73..e822ff3 100644 --- a/platform/dns.h +++ b/platform/dns.h @@ -11,6 +11,7 @@ struct dns_config { wchar_t startup[128]; wchar_t billing[128]; wchar_t aimedb[128]; + wchar_t title[128]; }; HRESULT dns_platform_hook_init(const struct dns_config *cfg); diff --git a/platform/nusec.c b/platform/nusec.c index 6094408..a82a99f 100644 --- a/platform/nusec.c +++ b/platform/nusec.c @@ -14,22 +14,22 @@ #include "util/str.h" enum { - NUSEC_IOCTL_PING = 0x22A114, - NUSEC_IOCTL_ERASE_TRACE_LOG = 0x22E188, - NUSEC_IOCTL_TD_ERASE_USED = 0x22E18C, - NUSEC_IOCTL_ADD_PLAY_COUNT = 0x22E154, - NUSEC_IOCTL_GET_BILLING_CA_CERT = 0x22E1C4, - NUSEC_IOCTL_GET_BILLING_PUBKEY = 0x22E1C8, - NUSEC_IOCTL_GET_NEARFULL = 0x22E20C, - NUSEC_IOCTL_GET_NVRAM_AVAILABLE = 0x22E19C, - NUSEC_IOCTL_GET_NVRAM_GEOMETRY = 0x22E24C, - NUSEC_IOCTL_GET_PLAY_COUNT = 0x22E150, - NUSEC_IOCTL_GET_PLAY_LIMIT = 0x22E204, - NUSEC_IOCTL_GET_TRACE_LOG_DATA = 0x22E194, - NUSEC_IOCTL_GET_TRACE_LOG_STATE = 0x22E198, - NUSEC_IOCTL_PUT_NEARFULL = 0x22E210, - NUSEC_IOCTL_PUT_PLAY_LIMIT = 0x22E208, - NUSEC_IOCTL_PUT_TRACE_LOG_DATA = 0x22E190, + NUSEC_IOCTL_PING = CTL_CODE(0x22, 0x845, METHOD_BUFFERED, FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_PLAY_COUNT = CTL_CODE(0x22, 0x854, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_ADD_PLAY_COUNT = CTL_CODE(0x22, 0x855, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_ERASE_TRACE_LOG = CTL_CODE(0x22, 0x862, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_TD_ERASE_USED = CTL_CODE(0x22, 0x863, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_PUT_TRACE_LOG_DATA = CTL_CODE(0x22, 0x864, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_TRACE_LOG_DATA = CTL_CODE(0x22, 0x865, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_TRACE_LOG_STATE = CTL_CODE(0x22, 0x866, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_NVRAM_AVAILABLE = CTL_CODE(0x22, 0x867, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_BILLING_CA_CERT = CTL_CODE(0x22, 0x871, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_BILLING_PUBKEY = CTL_CODE(0x22, 0x872, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_PLAY_LIMIT = CTL_CODE(0x22, 0x881, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_PUT_PLAY_LIMIT = CTL_CODE(0x22, 0x882, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_NEARFULL = CTL_CODE(0x22, 0x883, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_PUT_NEARFULL = CTL_CODE(0x22, 0x884, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), + NUSEC_IOCTL_GET_NVRAM_GEOMETRY = CTL_CODE(0x22, 0x893, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS), }; struct nusec_log_record {