cxb: server support added, bugfixes, thanks @Midorica

This commit is contained in:
Dniel97 2024-03-13 17:51:58 +01:00
parent 2590e749ca
commit 097b74d849
Signed by: Dniel97
GPG Key ID: 6180B3C768FB2E08
12 changed files with 135 additions and 30 deletions

View File

@ -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

View File

@ -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",

View File

@ -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;
}

View File

@ -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.

View File

@ -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?

View File

@ -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
);
}

View File

@ -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

View File

@ -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) {

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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 {