From 50737e60116941b6cf7a4753b16f9e30d12b98af Mon Sep 17 00:00:00 2001 From: Bottersnike Date: Fri, 19 May 2023 15:16:07 +0100 Subject: [PATCH] Large amount of stuff leading up to fully networking maimai --- src/micetools/dll/comdevice.c | 18 +- src/micetools/dll/comdevice.h | 16 +- src/micetools/dll/devices/meson.build | 2 + src/micetools/dll/devices/nfc/bng.c | 127 ++++ src/micetools/dll/devices/nfc/bng.h | 12 + src/micetools/dll/devices/nfc/felica.c | 423 +++++++++++ src/micetools/dll/devices/nfc/felica.h | 365 +++++++++ src/micetools/dll/devices/nfc/mifare.h | 15 + src/micetools/dll/devices/nfc/nfc.h | 65 ++ src/micetools/dll/devices/ser_tn32msec.c | 717 +++++++++++------- src/micetools/dll/devices/ser_tn32msec.h | 72 ++ src/micetools/dll/devices/smb_at24c64an.c | 15 +- src/micetools/dll/dllmain.c | 8 +- src/micetools/dll/gui/gui.c | 58 +- src/micetools/dll/hooks/drive/disks.c | 46 +- src/micetools/dll/hooks/drive/drive.c | 2 + src/micetools/dll/hooks/drive/drive.h | 26 +- src/micetools/dll/hooks/drive/hooks.c | 6 +- src/micetools/dll/hooks/files.c | 74 +- src/micetools/dll/hooks/files.h | 20 +- src/micetools/dll/hooks/network.c | 63 +- src/micetools/dll/hooks/network.h | 2 + src/micetools/dll/hooks/processes.c | 11 +- src/micetools/launcher/main.c | 38 +- src/micetools/lib/_am.h | 4 +- src/micetools/lib/am/amCmos.c | 71 ++ src/micetools/lib/am/amCmos.h | 40 +- src/micetools/lib/am/amDipsw.c | 118 +++ src/micetools/lib/am/amDipsw.h | 23 +- src/micetools/lib/am/amDongle.h | 6 +- src/micetools/lib/am/amEeprom.h | 2 +- src/micetools/lib/am/amInstall.h | 2 +- src/micetools/lib/am/amNetwork.h | 1 + src/micetools/lib/am/amOemstring.h | 2 +- src/micetools/lib/am/amPlatform.c | 12 +- src/micetools/lib/am/amPlatform.h | 6 +- src/micetools/lib/am/amSerialId.h | 2 +- src/micetools/lib/am/amSram.h | 2 +- src/micetools/lib/am/meson.build | 10 + src/micetools/lib/ami/amiCrc.h | 2 +- src/micetools/lib/ami/amiDebug.h | 2 +- src/micetools/lib/ami/amiTimer.h | 2 +- src/micetools/lib/mice/blowfish.c | 233 ++++++ src/micetools/lib/mice/blowfish.h | 5 + src/micetools/lib/mice/config.def | 7 + src/micetools/lib/mice/des.c | 179 +++++ src/micetools/lib/mice/des.h | 7 + src/micetools/lib/mice/exe.c | 32 +- src/micetools/lib/mice/ioctl.h | 7 + src/micetools/lib/mice/kcf.h | 2 +- src/micetools/lib/mice/meson.build | 4 + src/micetools/lib/mice/micefs.c | 8 +- src/micetools/lib/mice/solitaire.c | 143 ++++ src/micetools/lib/mice/solitaire.h | 3 + src/micetools/lib/mice/spad.c | 224 ++++++ src/micetools/lib/mice/spad.h | 4 + src/micetools/micekeychip/callbacks/billing.c | 39 +- .../micekeychip/callbacks/tracedata.c | 15 +- src/micetools/segastructs.h | 6 +- src/micetools/util/meson.build | 14 + src/micetools/util/micedump/cmos.c | 57 ++ src/micetools/util/micedump/kc_mxkeychip.c | 7 +- src/micetools/util/micedump/kc_pic.c | 6 +- src/micetools/util/micedump/main.c | 2 + src/micetools/util/micedump/micedump.h | 19 +- src/micetools/util/micedump/platform.c | 4 +- src/micetools/util/micereset.c | 54 ++ src/micetools/util/storagecraft.c | 277 ++++++- src/patches/maimai_dump_.patch | 2 + 69 files changed, 3423 insertions(+), 445 deletions(-) create mode 100644 src/micetools/dll/devices/nfc/bng.c create mode 100644 src/micetools/dll/devices/nfc/bng.h create mode 100644 src/micetools/dll/devices/nfc/felica.c create mode 100644 src/micetools/dll/devices/nfc/felica.h create mode 100644 src/micetools/dll/devices/nfc/mifare.h create mode 100644 src/micetools/dll/devices/nfc/nfc.h create mode 100644 src/micetools/dll/devices/ser_tn32msec.h create mode 100644 src/micetools/lib/am/amCmos.c create mode 100644 src/micetools/lib/am/amDipsw.c create mode 100644 src/micetools/lib/mice/blowfish.c create mode 100644 src/micetools/lib/mice/blowfish.h create mode 100644 src/micetools/lib/mice/des.c create mode 100644 src/micetools/lib/mice/des.h create mode 100644 src/micetools/lib/mice/solitaire.c create mode 100644 src/micetools/lib/mice/solitaire.h create mode 100644 src/micetools/lib/mice/spad.c create mode 100644 src/micetools/lib/mice/spad.h create mode 100644 src/micetools/util/micedump/cmos.c create mode 100644 src/micetools/util/micereset.c diff --git a/src/micetools/dll/comdevice.c b/src/micetools/dll/comdevice.c index 945f726..d2e7831 100644 --- a/src/micetools/dll/comdevice.c +++ b/src/micetools/dll/comdevice.c @@ -81,10 +81,10 @@ short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes } return ringbuf_read(&com->in, buffer, bytes); } -short comdev_read(com_device_t* com, unsigned char* buffer, short bytes) { +short comdev_read(com_device_t* com, LPVOID buffer, short bytes) { return ringbuf_read(&com->in, buffer, bytes); } -bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes) { +bool comdev_write(com_device_t* com, LPCVOID buffer, short bytes) { bool ret = ringbuf_write(&com->out, buffer, bytes); SetEvent(com->dataOutReady); return ret; @@ -93,7 +93,7 @@ short comdev_available(com_device_t* com) { return ringbuf_available(&com->in); BYTE comdev_peek(com_device_t* com) { return com->in.buffer[com->in.read]; } // Read data from a com device, unescaping as we go -void comio_read(com_device_t* com, BYTE* data, BYTE len) { +void comio_read(com_device_t* com, LPVOID data, BYTE len) { BYTE one_byte; for (; len; len--) { comdev_read_blocking(com, &one_byte, 1); @@ -101,14 +101,14 @@ void comio_read(com_device_t* com, BYTE* data, BYTE len) { comdev_read_blocking(com, &one_byte, 1); one_byte++; } - *(data++) = one_byte; + *(((LPBYTE)data)++) = one_byte; } } // Write data to a com device, escaping as we go -void comio_write(com_device_t* com, BYTE* data, BYTE len) { +void comio_write(com_device_t* com, LPCVOID data, BYTE len) { BYTE one_byte; for (; len; len--) { - one_byte = *(data++); + one_byte = *(((LPBYTE)data)++); if (one_byte == COMIO_MARK || one_byte == COMIO_SYNC) { BYTE mark = COMIO_MARK; comdev_write(com, &mark, 1); @@ -117,7 +117,7 @@ void comio_write(com_device_t* com, BYTE* data, BYTE len) { comdev_write(com, &one_byte, 1); } } -unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { +unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, LPVOID data) { BYTE one_byte; do { if (comdev_available(com) < (sizeof *head + 1)) { @@ -140,7 +140,7 @@ unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* d comio_read(com, &sum, 1); return sum; } -void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data) { +void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, LPCVOID data) { BYTE one_byte; one_byte = COMIO_SYNC; comdev_write(com, &one_byte, 1); @@ -161,7 +161,7 @@ void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE le // Checksum one_byte = 0; for (BYTE i = 0; i < sizeof resp; i++) one_byte += ((LPBYTE)&resp)[i]; - for (BYTE i = 0; i < len; i++) one_byte += data[i]; + for (BYTE i = 0; i < len; i++) one_byte += ((LPBYTE)data)[i]; comio_write(com, &one_byte, 1); } diff --git a/src/micetools/dll/comdevice.h b/src/micetools/dll/comdevice.h index 978da06..9c749ca 100644 --- a/src/micetools/dll/comdevice.h +++ b/src/micetools/dll/comdevice.h @@ -22,6 +22,7 @@ struct com_device { }; com_device_t* com_devices[NUM_COM_PORTS]; +#pragma pack(push, 1) typedef struct { BYTE frame_length; BYTE dst; @@ -38,6 +39,7 @@ typedef struct { BYTE status; BYTE length; } comio_resp_head_t; +#pragma pack(pop) #define COMIO_SYNC 0xE0 #define COMIO_MARK 0xD0 @@ -45,17 +47,17 @@ typedef struct { #define COMIO_STATUS_OK 0 #define COMIO_STATUS_NG 1 -short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes); -short comdev_read(com_device_t* com, unsigned char* buffer, short bytes); -bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes); +short comdev_read_blocking(com_device_t* com, LPVOID buffer, short bytes); +short comdev_read(com_device_t* com, LPVOID buffer, short bytes); +bool comdev_write(com_device_t* com, LPCVOID buffer, short bytes); short comdev_available(com_device_t* com); BYTE comdev_peek(com_device_t* com); -void comio_read(com_device_t* com, BYTE* data, BYTE len); -void comio_write(com_device_t* com, BYTE* data, BYTE len); +void comio_read(com_device_t* com, LPVOID data, BYTE len); +void comio_write(com_device_t* com, LPCVOID data, BYTE len); -unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data); -void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data); +unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, LPVOID data); +void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, LPCVOID data); com_device_t* new_com_device(BYTE port); BOOL attach_com_device(BYTE port, FnComDeviceThread* thread); diff --git a/src/micetools/dll/devices/meson.build b/src/micetools/dll/devices/meson.build index cd3cb92..18e0a96 100644 --- a/src/micetools/dll/devices/meson.build +++ b/src/micetools/dll/devices/meson.build @@ -1,6 +1,8 @@ devices_files = files( '_ds_sha.c', '_devices.c', + 'nfc/felica.c', + 'nfc/bng.c', # Serial devices 'ser_led_bd.c', 'ser_maitouch.c', diff --git a/src/micetools/dll/devices/nfc/bng.c b/src/micetools/dll/devices/nfc/bng.c new file mode 100644 index 0000000..0f3d55a --- /dev/null +++ b/src/micetools/dll/devices/nfc/bng.c @@ -0,0 +1,127 @@ +#include "bng.h" + +#include + +#include "../../../lib/mice/blowfish.h" +#include "../../../lib/mice/des.h" + +// Are these SEGA-specific or used for all FeliCa cards? +// Commentary: The MAC validation code in bnacard can take a key as an argument +// and uses the below key if NULL is passed (which it is). +// The NbgiAccessCode library names this `ucFK` which doesn't feel +// like a name someone would pick out of the blue. +DWORD64 CK_GEN_KEY[3] = { 0x1223491caf37206d, 0x5f3f1d16badd58a2, 0xc2f2ea946a755ee7 }; + +#pragma pack(push, 1) +typedef struct BNG_SIGNED_BLOCK { + WORD m_BNAVersion; + BYTE m_Name[6]; + DWORD m_BFLeft; + DWORD m_BFRight; +} BNG_SIGNED_BLOCK, *PBNG_SIGNED_BLOCK; +#pragma pack(pop) + +typedef struct { + char m_Name[8]; + BYTE m_Key[56]; + BYTE Unk40[72]; +} BLOWFISH_KEY; + +static BLOWFISH_KEY DataKeyNBGIC[3] = { + { + .m_Name = { 'N', 'B', 'G', 'I', 'C', '0', '\0', '\0' }, + .m_Key = { 0x6b, 0xf9, 0xe0, 0x22, 0x4b, 0x14, 0xa9, 0x51, 0xd4, 0x3d, 0xb6, 0x2d, + 0x2a, 0x99, 0x47, 0xd8, 0xb2, 0x78, 0x80, 0x35, 0x8e, 0x71, 0x16, 0xeb, + 0xa0, 0x00, 0x01, 0x3e, 0x8c, 0xfe, 0xf6, 0x09, 0x02, 0xa9, 0x59, 0x5d, + 0x4c, 0x25, 0xfe, 0xff, 0x74, 0x3f, 0xc8, 0xd8, 0xe0, 0x75, 0x6a, 0xe6, + 0x18, 0xef, 0x8b, 0x72, 0x12, 0xde, 0x5a, 0x4b }, + .Unk40 = { 0x97, 0xba, 0xa5, 0x1b, 0x46, 0x04, 0x87, 0x43, 0x9f, 0x21, 0x5b, 0xe9, + 0xe1, 0xd0, 0x98, 0x72, 0x27, 0x91, 0x31, 0xba, 0x8a, 0x82, 0x8f, 0xab, + 0x50, 0x7f, 0x44, 0x7f, 0x8b, 0xc5, 0xe3, 0x4a, 0xc3, 0x32, 0xb7, 0xcb, + 0xd8, 0x4f, 0xb1, 0x4c, 0x45, 0x21, 0x20, 0xe2, 0xa0, 0x71, 0x38, 0x4d, + 0xe6, 0x95, 0x89, 0xc1, 0x5b, 0x04, 0x14, 0xc6, 0x9d, 0xcd, 0x03, 0x1c, + 0xd0, 0xa8, 0x15, 0x3a, 0xf4, 0x6d, 0x3d, 0xea, 0x84, 0xec, 0xcd, 0x40 }, + }, + { + .m_Name = { 'N', 'B', 'G', 'I', 'C', '1', '\0', '\0' }, + .m_Key = { 0x5e, 0x6b, 0xb1, 0x92, 0xc0, 0x52, 0x2f, 0x4c, 0xa0, 0x29, 0x6a, 0x1c, + 0x98, 0x62, 0xfb, 0xeb, 0xac, 0xf5, 0xe1, 0xd7, 0x66, 0xe6, 0x34, 0x69, + 0x40, 0x47, 0x5b, 0x96, 0xfe, 0x17, 0x89, 0x3d, 0x18, 0xae, 0x98, 0xf8, + 0xbd, 0x6d, 0xfa, 0x12, 0xd6, 0xcd, 0xf5, 0x81, 0x7b, 0x78, 0xd6, 0x60, + 0x71, 0x8f, 0x7a, 0x28, 0xca, 0x3c, 0xfd, 0x2f }, + .Unk40 = { 0xa6, 0x29, 0x78, 0x80, 0x63, 0xae, 0xa3, 0xa7, 0x84, 0xdd, 0x24, 0x60, + 0x62, 0x86, 0x10, 0x97, 0x80, 0x75, 0xb4, 0x3d, 0x44, 0x81, 0xc9, 0x9f, + 0xf4, 0x4a, 0xf7, 0xfd, 0xe4, 0xc8, 0x96, 0xcb, 0x9c, 0x2f, 0x3b, 0x6d, + 0x95, 0xfe, 0x49, 0x54, 0x9d, 0x36, 0xea, 0x58, 0xcb, 0xf4, 0x0e, 0x06, + 0x42, 0xfa, 0x6f, 0xb5, 0x1b, 0xc7, 0x88, 0x50, 0xea, 0x7b, 0x5f, 0x60, + 0x56, 0xdb, 0x6f, 0x03, 0xd7, 0x84, 0x75, 0x4e, 0x07, 0x9d, 0xbc, 0x05 }, + }, + { + .m_Name = { 'N', 'B', 'G', 'I', 'C', '2', '\0', '\0' }, + .m_Key = { 0xde, 0x15, 0x00, 0x6f, 0x45, 0xe2, 0x73, 0x66, 0xaa, 0x74, 0x8f, 0x98, + 0x14, 0x6e, 0x05, 0x7b, 0x52, 0x18, 0x29, 0xd5, 0x0a, 0x65, 0xa9, 0x0c, + 0xfe, 0xca, 0xd3, 0x8e, 0x04, 0xcf, 0x3e, 0x72, 0x31, 0xfb, 0x76, 0x50, + 0xfb, 0x8c, 0x67, 0x09, 0x95, 0x08, 0xff, 0xf0, 0xc2, 0x97, 0x31, 0x5f, + 0xde, 0x6c, 0x54, 0x32, 0xec, 0x8e, 0x2c, 0x6c }, + .Unk40 = { 0xc0, 0x6c, 0xa9, 0x7d, 0xd1, 0x10, 0x35, 0xc2, 0xa8, 0x6d, 0x52, 0xfc, + 0x0a, 0x8c, 0x1a, 0xf7, 0xd1, 0x61, 0xea, 0x40, 0x49, 0x86, 0x7f, 0x37, + 0x3f, 0xd1, 0x84, 0x2e, 0x98, 0xd9, 0x6d, 0x2c, 0x5e, 0x80, 0xe0, 0xe1, + 0x92, 0x7c, 0xf2, 0x09, 0xef, 0x11, 0x44, 0x29, 0xe9, 0x4b, 0xb9, 0x3a, + 0x87, 0x27, 0x5c, 0xa8, 0x05, 0xca, 0xfc, 0xcd, 0x3f, 0x21, 0x91, 0x17, + 0xf5, 0x05, 0x6b, 0x82, 0x6b, 0x47, 0xdc, 0x06, 0x75, 0x1f, 0x04, 0x30 }, + }, +}; + +void NbgiWriteBNESignedBlock(PNFC_CARD lpCard, BYTE block, BYTE nKey, LPBYTE lpData) { + if (nKey > 2) return; + PBNG_SIGNED_BLOCK lpBlock = (PBNG_SIGNED_BLOCK)&lpCard->m_FeliCaData.m_UserBlocks[block].bytes; + lpBlock->m_BNAVersion = 0x200; + memcpy(lpBlock->m_Name, DataKeyNBGIC[nKey].m_Name, 6); + + lpData[7] = lpData[0] ^ lpData[1] ^ lpData[2] ^ lpData[3] ^ lpData[4] ^ lpData[5] ^ lpData[6]; + + DWORD dataLeft = ((LPDWORD)lpData)[0]; + DWORD dataRight = ((LPDWORD)lpData)[1]; + BlowfishSetKey(DataKeyNBGIC[nKey].m_Key, _countof(DataKeyNBGIC[nKey].m_Key)); + BlowfishEncrypt(&dataLeft, &dataRight); + lpBlock->m_BFLeft = dataLeft; + lpBlock->m_BFRight = dataRight; +} + +static inline DWORD64 _FelicaMacCKNested(DWORD64 data, DWORD64 key) { + data = Mice3Des_3K(data, CK_GEN_KEY); + data ^= key; + data = Mice3Des_3K(data, CK_GEN_KEY); + return data; +} + +void FelicaMacGenerateCK(DWORD64* ID, KEY_PAIR lpKeys) { + DWORD64 data = Mice3Des_3K(0x0, CK_GEN_KEY); + + BOOL will_overflow = ((LPBYTE)&data)[0] & 0x80; + + // Binary rotate left 1. While `<<= 1` would be lovely here, the carries + // are expected to be performed (incorrectly) to the right. + for (BYTE i = 0; i < 8; i++) { + if (i != 0 && ((LPBYTE)&data)[i] & 0x80) ((LPBYTE)&data)[i - 1] |= 1; + ((LPBYTE)&data)[i] <<= 1; + } + if (will_overflow) ((LPBYTE)&data)[7] ^= 0x1b; + + DWORD64 idKey = data ^ ID[1]; + lpKeys[0] = _byteswap_uint64(_FelicaMacCKNested(ID[0], idKey)); + ((LPBYTE)&ID[0])[0] ^= 0x80; + lpKeys[1] = _byteswap_uint64(_FelicaMacCKNested(ID[0], idKey)); + ((LPBYTE)&ID[0])[0] ^= 0x80; // Undo our modification above +} +void FelicaMacGenerateSK(DWORD64* random, KEY_PAIR ck, KEY_PAIR lpSk) { + lpSk[0] = Mice3Des_2K(_byteswap_uint64(random[0]), ck); + lpSk[1] = lpSk[0] ^ _byteswap_uint64(random[1]); + lpSk[1] = Mice3Des_2K(lpSk[1], ck); +} +DWORD64 FelicaMacGenerateMAC(DWORD64* data, KEY_PAIR sk, DWORD64* random) { + DWORD64 mac = data[0] ^ random[0]; + mac = Mice3Des_2K(_byteswap_uint64(mac), sk); + mac = mac ^ _byteswap_uint64(data[1]); + return Mice3Des_2K(mac, sk); +} diff --git a/src/micetools/dll/devices/nfc/bng.h b/src/micetools/dll/devices/nfc/bng.h new file mode 100644 index 0000000..6b9af04 --- /dev/null +++ b/src/micetools/dll/devices/nfc/bng.h @@ -0,0 +1,12 @@ +#pragma once +#include + +#include "nfc.h" + +typedef DWORD64 KEY_PAIR[2]; + +void NbgiWriteBNESignedBlock(PNFC_CARD lpCard, BYTE block, BYTE nKey, LPBYTE lpData); + +void FelicaMacGenerateCK(DWORD64* ID, KEY_PAIR lpKeys); +void FelicaMacGenerateSK(DWORD64* random, KEY_PAIR ck, KEY_PAIR lpSk); +DWORD64 FelicaMacGenerateMAC(DWORD64* data, KEY_PAIR sk, DWORD64* random); diff --git a/src/micetools/dll/devices/nfc/felica.c b/src/micetools/dll/devices/nfc/felica.c new file mode 100644 index 0000000..f1c9914 --- /dev/null +++ b/src/micetools/dll/devices/nfc/felica.c @@ -0,0 +1,423 @@ +#include "../../../lib/mice/spad.h" +#include "../_devices.h" +#include "../ser_tn32msec.h" +#include "bng.h" +#include "nfc.h" + +static const BYTE PMmTiming[6] = { 0x00, 0x00, 0x00, 0x01, 0x43, 0x00 }; +#define DFC_BNG_EDY_0 0x8C +#define DFC_BNG_EDY_1 0xA2 +#define DFC_BNG_LITE_0 0x00 +#define DFC_BNG_LITE_1 0x3A +#define DFC_KNM_LITES_0 0x00 +#define DFC_KNM_LITES_1 0x68 +#define DFC_BNE_LITES_0 0x00 +#define DFC_BNE_LITES_1 0x2A +#define DFC_SEGA_LITES_0 0x00 +#define DFC_SEGA_LITES_1 0x78 +#define DFC_TEST_0 0x00 +#define DFC_TEST_1 0x00 +static const BYTE ID_Arbitrary[6] = { 0x05, 0x73, 0x02, 0x01, 0x02, 0x00 }; + +inline static void _FelicaDumpChars(LPBYTE lpBytes, BYTE nBytes) { + printf("|"); + for (int i = 0; i < nBytes; i++) { + BYTE chr = lpBytes[i]; + if (' ' < chr && chr <= '~') + printf("%c", chr); + else + printf("."); + } + printf("|"); +} + +static void _FelicaDumpBlock(PNFC_CARD lpCard, BYTE block, BYTE nBytes, LPCSTR lpName) { + PFelicaBlock_t lpBlock; + if (block < 0xf) + lpBlock = &lpCard->m_FeliCaData.m_UserBlocks[block]; + else + lpBlock = &lpCard->m_FeliCaData.m_SystemBlocks[block - 0x80]; + + printf("[%02X] ", block); + for (int i = 0; i < 8; i++) { + if (i < nBytes) + printf("%02X ", lpBlock->bytes[i]); + else + printf("-- "); + } + if (lpName) + printf("(%s)", lpName); + else + _FelicaDumpChars(lpBlock->bytes, 8); + printf("\n "); + + for (int i = 8; i < 16; i++) { + if (i < nBytes) + printf("%02X ", lpBlock->bytes[i]); + else + printf("-- "); + } + if (!lpName) _FelicaDumpChars(&(lpBlock->bytes[8]), 8); + printf("\n"); +} + +void FelicaDumpCard(PNFC_CARD lpCard) { + for (BYTE block = 0; block < 15; block++) { + _FelicaDumpBlock(lpCard, block, 16, NULL); + } + _FelicaDumpBlock(lpCard, 0x80, 16, "RC"); + _FelicaDumpBlock(lpCard, 0x81, 8, "MAC"); + _FelicaDumpBlock(lpCard, 0x82, 16, "ID"); + _FelicaDumpBlock(lpCard, 0x83, 16, "D_ID"); + _FelicaDumpBlock(lpCard, 0x84, 2, "SER_C"); + _FelicaDumpBlock(lpCard, 0x85, 2, "SYS_C"); + _FelicaDumpBlock(lpCard, 0x86, 2, "CKV"); + _FelicaDumpBlock(lpCard, 0x87, 16, "CK"); + _FelicaDumpBlock(lpCard, 0x88, 13, "MC"); +} + +void FelicaPopulate(PNFC_CARD lpCard, PFELICA_ID lpFelicaId, PACCESS_CODE lpAccessCode) { + ZeroMemory(&lpCard->m_FeliCaData, sizeof lpCard->m_FeliCaData); + + lpCard->m_Header.m_Type = CardType_FeliCa; + lpCard->m_Header.m_IdLen = sizeof(lpCard->m_FeliCa); + memcpy(&lpCard->m_FeliCa.m_IDm, lpFelicaId, sizeof *lpFelicaId); + + // TODO: Toggle between suica and AIC mode. + lpCard->m_FeliCaData.m_EmuMode = FelicaEmulationMode_AIC; + lpCard->m_FeliCaData.m_AICVendor = FelicaAICVendor_Konami; + + lpCard->m_FeliCa.m_PMm[0] = 0x00; + switch (lpCard->m_FeliCaData.m_EmuMode) { + case FelicaEmulationMode_Suica: + lpCard->m_FeliCa.m_PMm[1] = FelicaChipType_Mobile_Ver10; + lpCard->m_FeliCaData.m_SystemBlock_SYS_C.m_SYS_C = _byteswap_ushort(FelicaSystem_Suica); + + // DFC shouldn't matter for Suica + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_TEST_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_TEST_1; + break; + case FelicaEmulationMode_AIC: + lpCard->m_FeliCaData.m_SystemBlock_SYS_C.m_SYS_C = + _byteswap_ushort(FelicaSystem_FelicaLite); + + /** + * The DFC code is used to identify the card manufacturer. Each + * manufacturer uses a different derivation algorithm for FeliCa ID + * to Access Code conversion, which AiMeDB is able to validate + * based on this information. + * + * This validation is performed as part of + * AiMe_DB_com_get_AiMeAccountS, added in AiMeDB version 4.0.0 + * + * To the best of my knowledge this was added long after RingEdge + * was a dead platform, so isn't something we will need to concern + * ourselves with here. + * + * Maimai itself only does a check for if this is + * FelicaAICVendor_BandaiNamco_LiteS, in which case special + * handling is required. + * + * TODO: Right now things seem to test bad if it's _not_ a BNE card?? + */ + switch (lpCard->m_FeliCaData.m_AICVendor) { + case FelicaAICVendor_BandaiNamcoGames: + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_BNG_LITE_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_BNG_LITE_1; + break; + case FelicaAICVendor_BandaiNamcoEntertainment: { + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_BNE_LITES_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_BNE_LITES_1; + + BYTE block0D[8] = { + // TODO: Work backwards and figure out where the key is coming from + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, /*sum*/ 0x00, + }; + NbgiWriteBNESignedBlock(lpCard, 0x0D, 0, block0D); + + break; + } + case FelicaAICVendor_SEGA: + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_SEGA_LITES_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_SEGA_LITES_1; + break; + case FelicaAICVendor_Konami: + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_KNM_LITES_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_KNM_LITES_1; + break; + default: + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_TEST_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_TEST_1; + break; + } + + // Write the card IC type into the PMm + switch (lpCard->m_FeliCaData.m_AICVendor) { + case FelicaAICVendor_BandaiNamcoGames: + lpCard->m_FeliCa.m_PMm[1] = FelicaChipType_Lite; + break; + case FelicaAICVendor_BandaiNamcoEntertainment: + case FelicaAICVendor_SEGA: + case FelicaAICVendor_Konami: + default: + lpCard->m_FeliCa.m_PMm[1] = FelicaChipType_LiteS; + break; + } + break; + case FelicaEmulationMode_BNG: + default: + lpCard->m_FeliCa.m_PMm[1] = FelicaChipType_STD_RC_S915; + lpCard->m_FeliCaData.m_SystemBlock_SYS_C.m_SYS_C = _byteswap_ushort(FelicaSystem_NDEF); + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[0] = DFC_BNG_EDY_0; + lpCard->m_FeliCaData.m_SystemBlock_ID.m_DFC[1] = DFC_BNG_EDY_1; + break; + } + memcpy(&(lpCard->m_FeliCa.m_PMm[2]), PMmTiming, sizeof PMmTiming); + + if (lpAccessCode) { + BYTE block0[16]; + memcpy(&(block0[6]), lpAccessCode->m_AC, 10); + Spad0Encrypt(block0, block0); + memcpy(lpCard->m_FeliCaData.m_UserBlocks[0].bytes, block0, 16); + } + + memset(lpCard->m_FeliCaData.m_UserBlocks[0x0e].bytes, 0xFF, 16); + + memcpy(&lpCard->m_FeliCaData.m_SystemBlock_ID.m_FelicaId, lpFelicaId, sizeof *lpFelicaId); + memcpy(lpCard->m_FeliCaData.m_SystemBlock_ID.m_Arbitrary, ID_Arbitrary, sizeof ID_Arbitrary); + + memcpy(&lpCard->m_FeliCaData.m_SystemBlock_D_ID.m_FelicaId, lpFelicaId, sizeof *lpFelicaId); + memcpy(lpCard->m_FeliCaData.m_SystemBlock_D_ID.m_PMm, lpCard->m_FeliCa.m_PMm, + sizeof lpCard->m_FeliCa.m_PMm); + +#if 0 + FelicaDumpCard(lpCard); +#endif +} + +void FelicaPoll(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard) { + FelicaPollRequest request = lpReq->m_Poll.m_Request; + + lpResponse->m_FelicaLen = FelicaRespSize(lpResponse->m_Poll); + lpResponse->m_FelicaCommand = FelicaCommand_Poll_Response; + memcpy(&lpResponse->m_IDm, &lpReq->m_IDm, sizeof lpReq->m_IDm); + memcpy(lpResponse->m_Poll.m_PMm, lpCard->m_FeliCa.m_PMm, sizeof lpCard->m_FeliCa.m_PMm); + + switch (request) { + case FelicaPollRequest_SystemCode: + lpResponse->m_Poll.m_Value = lpCard->m_FeliCaData.m_SystemBlock_SYS_C.m_SYS_C; + break; + default: + log_error(plfAime, "Unhnaldled poll request: %02x", request); + lpResponse->m_FelicaLen -= 2; + break; + } +} + +void FelicaReadNoEnc(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard) { + BYTE readIndex = 0; + BYTE serviceN = lpReq->m_ReadNoEnc.m_Rest[readIndex++]; + for (BYTE i = 0; i < serviceN; i++) { + WORD service = *(LPWORD)(&lpReq->m_ReadNoEnc.m_Rest[readIndex++]); + readIndex++; + } + BYTE blockCount = lpReq->m_ReadNoEnc.m_Rest[readIndex++]; + + lpResponse->m_FelicaLen = FelicaRespSize(lpResponse->m_ReadNoEnc) + 16 * blockCount; + lpResponse->m_FelicaCommand = FelicaCommand_ReadNoEnc_Response; + memcpy(&lpResponse->m_IDm, &lpReq->m_ReadNoEnc.m_IDm, sizeof lpReq->m_ReadNoEnc.m_IDm); + lpResponse->m_ReadNoEnc.m_Status1 = FelicaStatus1_Success; + lpResponse->m_ReadNoEnc.m_Status2 = FelicaStatus2_Success; + lpResponse->m_ReadNoEnc.m_BlockCount = blockCount; + BYTE writeIndex = 0; + + for (BYTE i = 0; i < blockCount; i++) { + BYTE blHeader = lpReq->m_ReadNoEnc.m_Rest[readIndex++]; + BOOL isExtended = !(blHeader & 0x80); + BYTE serviceCodeOrder = blHeader & 0x0f; + BYTE accessMode = (blHeader & 0x70) >> 4; + + WORD blockNumber; + if (isExtended) { + blockNumber = *(LPWORD)(&lpReq->m_ReadNoEnc.m_Rest[readIndex++]); + readIndex++; + } else { + blockNumber = lpReq->m_ReadNoEnc.m_Rest[readIndex++]; + } + + if (blockNumber < 0xf) { + memcpy(&lpResponse->m_ReadNoEnc.m_BlockData[writeIndex], + lpCard->m_FeliCaData.m_UserBlocks[blockNumber].bytes, 16); + + log_warning(plfAime, "Felica read: s:%x block:%04x", serviceCodeOrder, blockNumber); + writeIndex += 16; + } else if (blockNumber >= 0x80 && blockNumber < 0x89) { + if (blockNumber - 0x80 == FelicaSystemBlock_MAC) { + log_info(plfAime, "MAC challenge requested"); + DWORD64 ID[2] = { 0 }; + memcpy(ID, &lpCard->m_FeliCaData.m_SystemBlock_ID, 16); + + KEY_PAIR CK, SK; + DWORD64* RC = (DWORD64*)&lpCard->m_FeliCaData.m_SystemBlock_RC.m_RC; + FelicaMacGenerateCK(ID, CK); + FelicaMacGenerateSK(RC, CK, SK); + DWORD64 mac = FelicaMacGenerateMAC(ID, SK, RC); + + mac = _byteswap_uint64(mac); + + memcpy(&lpResponse->m_ReadNoEnc.m_BlockData[writeIndex], &mac, 8); + memset(&lpResponse->m_ReadNoEnc.m_BlockData[writeIndex + 8], 0, 8); + log_warning(plfAime, "Felica read: s:%x block:%04x", serviceCodeOrder, blockNumber); + writeIndex += 16; + } else { + memcpy(&lpResponse->m_ReadNoEnc.m_BlockData[writeIndex], + lpCard->m_FeliCaData.m_SystemBlocks[blockNumber - 0x80].bytes, 16); + log_warning(plfAime, "Felica read: s:%x block:%04x", serviceCodeOrder, blockNumber); + writeIndex += 16; + } + } else { + // Invalid block, but we're already committed to the success state because I'm lazy, + // so just write a bunch of nulls. + memset(&lpResponse->m_ReadNoEnc.m_BlockData[writeIndex], 0, 16); + log_warning(plfAime, "Felica read: s:%x block:%04x", serviceCodeOrder, blockNumber); + writeIndex += 16; + } + } +} +void FelicaWriteNoEnc(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, + PNFC_CARD lpCard) { + BYTE readIndex = 0; + BYTE serviceN = lpReq->m_WriteNoEnc.m_Rest[readIndex++]; + for (BYTE i = 0; i < serviceN; i++) { + WORD service = *(LPWORD)(&lpReq->m_WriteNoEnc.m_Rest[readIndex++]); + readIndex++; + } + BYTE blockCount = lpReq->m_WriteNoEnc.m_Rest[readIndex++]; + + for (BYTE i = 0; i < blockCount; i++) { + BYTE blHeader = lpReq->m_WriteNoEnc.m_Rest[readIndex++]; + BOOL isExtended = !(blHeader & 0x80); + BYTE serviceCodeOrder = blHeader & 0x0f; + BYTE accessMode = (blHeader & 0x70) >> 4; + + WORD blockNumber; + if (isExtended) { + blockNumber = *(LPWORD)(&lpReq->m_WriteNoEnc.m_Rest[readIndex++]); + readIndex++; + } else { + blockNumber = lpReq->m_WriteNoEnc.m_Rest[readIndex++]; + } + + log_warning(plfAime, "Felica write: s:%x block:%04x", serviceCodeOrder, blockNumber); + + // TODO: Access controls! + if (blockNumber < 0xf) { + memcpy(lpCard->m_FeliCaData.m_UserBlocks[blockNumber].bytes, + &lpReq->m_WriteNoEnc.m_Rest[readIndex], 16); + readIndex += 16; + } else if (blockNumber >= 0x80 && blockNumber < 0x89) { + memcpy(lpCard->m_FeliCaData.m_SystemBlocks[blockNumber - 0x80].bytes, + &lpReq->m_WriteNoEnc.m_Rest[readIndex], 16); + readIndex += 16; + } else { + // Invalid block, but I'd rather just steamroll through it for the sake of + // compatability, so don't error. + readIndex += 16; + } + } + + lpResponse->m_FelicaLen = FelicaRespSize(lpResponse->m_WriteNoEnc); + lpResponse->m_FelicaCommand = FelicaCommand_WriteNoEnc_Response; + memcpy(&lpResponse->m_IDm, &lpReq->m_WriteNoEnc.m_IDm, sizeof lpReq->m_WriteNoEnc.m_IDm); + lpResponse->m_WriteNoEnc.m_Status1 = FelicaStatus1_Success; + lpResponse->m_WriteNoEnc.m_Status2 = FelicaStatus2_Success; +} +void FelicaSystemCode(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, + PNFC_CARD lpCard) { + lpResponse->m_FelicaLen = FelicaRespSize(lpResponse->m_SystemCode); + lpResponse->m_FelicaCommand = FelicaCommand_RequestSystemCode_Response; + memcpy(&lpResponse->m_IDm, &lpReq->m_SystemCode.m_IDm, sizeof lpReq->m_SystemCode.m_IDm); + lpResponse->m_SystemCode.m_SystemsCount = 1; + lpResponse->m_SystemCode.m_SystemCode = lpCard->m_FeliCaData.m_SystemBlock_SYS_C.m_SYS_C; +} +void FelicaMobileActive2(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, + PNFC_CARD lpCard) { + lpResponse->m_FelicaLen = FelicaRespSize(lpResponse->m_Active2); + lpResponse->m_FelicaCommand = FelicaCommand_MobileActive2_Response; + + switch (lpReq->m_Active2.m_Val) { + case 0: // Alive check + lpResponse->m_Active2.m_Data = 0; + break; + case 1: // OS Version + switch (lpCard->m_FeliCa.m_PMm[1]) { + case FelicaChipType_Mobile_Ver10: + lpResponse->m_Active2.m_Data = 1; + break; + case FelicaChipType_Mobile_Ver20: + lpResponse->m_Active2.m_Data = 0; + break; + default: + // I have no idea what other chips return + lpResponse->m_Active2.m_Data = 0; + break; + } + break; + case 2: + lpResponse->m_Active2.m_Data = 0xff; + break; + } +} + +void FelicaEncap(com_device_t* dev, comio_recv_head_t* req, LPBYTE lpPacket, PNFC_CARD lpCard) { + if (lpCard->m_Header.m_Type != CardType_FeliCa) { + log_error(plfAime, "Reader %02x requested a FeliCa encap on a non-FeliCa card!", req->dst); + comio_reply(dev, req, TN32Error_CardError, 0, NULL); + return; + } + + PFelicaEncapRequest lpReq = (PFelicaEncapRequest)lpPacket; + FelicaEncapResponse fResponse; + + FelicaCommand felicaCmd = lpReq->m_FelicaCommand; + fResponse.m_FelicaCommand = felicaCmd + 1; + fResponse.m_FelicaLen = 0; + + /** + * Suica devices will: + * - FelicaCommand_Poll + * - FelicaCommand_RequestSystemCode + * - FelicaCommand_MobileActive2 + * + * Others (maimai does not appear to disambiguate?) will: + * - FelicaCommand_Poll + * - FelicaCommand_ReadNoEnc (block 82) + * - FelicaCommand_WriteNoEnc (block 80) + * - FelicaCommand_ReadNoEnc (block 82,21) + * - FelicaCommand_ReadNoEnc (block 0D) + */ + + log_game(plfAime, "FeliCa command: %02x", felicaCmd); + switch (felicaCmd) { + case FelicaCommand_Poll: + FelicaPoll(lpReq, &fResponse, lpCard); + break; + case FelicaCommand_ReadNoEnc: + FelicaReadNoEnc(lpReq, &fResponse, lpCard); + break; + case FelicaCommand_WriteNoEnc: + FelicaWriteNoEnc(lpReq, &fResponse, lpCard); + break; + case FelicaCommand_RequestSystemCode: + FelicaSystemCode(lpReq, &fResponse, lpCard); + break; + case FelicaCommand_MobileActive2: + FelicaMobileActive2(lpReq, &fResponse, lpCard); + break; + default: + log_error(plfAime, "Unknown FeliCa command: %02x", felicaCmd); + break; + } + + comio_reply(dev, req, TN32Error_OK, fResponse.m_FelicaLen, &fResponse); +} diff --git a/src/micetools/dll/devices/nfc/felica.h b/src/micetools/dll/devices/nfc/felica.h new file mode 100644 index 0000000..da7c3b8 --- /dev/null +++ b/src/micetools/dll/devices/nfc/felica.h @@ -0,0 +1,365 @@ +#include + +#include "../_devices.h" + +typedef struct FELICA_ID { + BYTE m_ID[8]; +} FELICA_ID, *PFELICA_ID; + +enum FelicaCommand { + FelicaCommand_Poll = 0x00, + FelicaCommand_Poll_Response = 0x01, + FelicaCommand_RequestService = 0x02, + FelicaCommand_RequestService_Response = 0x03, + FelicaCommand_RequestResponse = 0x04, + FelicaCommand_RequestResponse_Response = 0x05, + FelicaCommand_ReadNoEnc = 0x06, + FelicaCommand_ReadNoEnc_Response = 0x07, + FelicaCommand_WriteNoEnc = 0x08, + FelicaCommand_WriteNoEnc_Response = 0x09, + FelicaCommand_Search = 0x0a, + FelicaCommand_Search_Response = 0x0b, + FelicaCommand_RequestSystemCode = 0x0c, + FelicaCommand_RequestSystemCode_Response = 0x0d, + FelicaCommand_Authentication1 = 0x10, + FelicaCommand_Authentication1_Response = 0x11, + FelicaCommand_Authentication2 = 0x12, + FelicaCommand_Authentication2_Response = 0x13, + FelicaCommand_Read = 0x14, + FelicaCommand_Read_Response = 0x15, + FelicaCommand_Write = 0x16, + FelicaCommand_Write_Response = 0x17, + + FelicaCommand_GetNodeProperty = 0x28, + FelicaCommand_GetNodeProperty_Response = 0x29, + + FelicaCommand_RequestServiceV2 = 0x32, + FelicaCommand_RequestServiceV2_Response = 0x33, + FelicaCommand_InternalAuthAndRead = 0x34, + FelicaCommand_InternalAuthAndRead_Response = 0x35, + FelicaCommand_ExternalAuthAndRead = 0x36, + FelicaCommand_ExternalAuthAndRead_Response = 0x37, + FelicaCommand_GetSystemStatus = 0x38, + FelicaCommand_GetSystemStatus_Response = 0x39, + FelicaCommand_RequestSpecVersion = 0x3c, + FelicaCommand_RequestSpecVersion_Response = 0x3d, + FelicaCommand_ResetMode = 0x3e, + FelicaCommand_ResetMode_Response = 0x3f, + FelicaCommand_Authentication1V2 = 0x40, + FelicaCommand_Authentication1V2_Response = 0x41, + FelicaCommand_Authentication2V2 = 0x42, + FelicaCommand_Authentication2V2_Response = 0x43, + FelicaCommand_ReadV2 = 0x44, + FelicaCommand_ReadV2_Response = 0x45, + FelicaCommand_WriteV2 = 0x46, + FelicaCommand_WriteV2_Response = 0x47, + + FelicaCommand_UpdateRandomID = 0x4C, + FelicaCommand_UpdateRandomID_Response = 0x4D, + + FelicaCommand_SetNodeProperty = 0x78, + FelicaCommand_SetNodeProperty_Response = 0x79, + + FelicaCommand_MobileActive2 = 0xa4, + FelicaCommand_MobileActive2_Response = 0xa5, +}; +typedef BYTE FelicaCommand; + +enum FelicaSystem { + FelicaSystem_Any = 0xffff, + + FelicaSystem_NDEF = 0x12fc, + FelicaSystem_Emulator = 0x4000, + FelicaSystem_FelicaLite = 0x88b4, + FelicaSystem_FelicaSecureID = 0x957a, + FelicaSystem_JISX_Start = 0xaaa0, + FelicaSystem_JISX_End = 0xaafe, + FelicaSystem_CommonArea = 0xfe00, + FelicaSystem_FelicaPlug = 0xfee1, + + FelicaSystem_Edy = 0xfe00, + FelicaSystem_Cyberne = 0x0003, + FelicaSystem_Suica = 0x0003, + FelicaSystem_Pasmo = 0x0003, +}; +typedef WORD FelicaSystem; + +enum FelicaService { + FelicaService_SuicaInOut = 0x108f, + FelicaService_SuicaHistory = 0x090f, + FelicaService_FelicaLiteRO = 0x0b00, + FelicaService_FelicaLiteEW = 0x0900, +}; +typedef WORD FelicaService; + +enum FelicaPollRequest { + FelicaPollRequest_NoRequest = 0x00, + FelicaPollRequest_SystemCode = 0x01, + FelicaPollRequest_CommPerformance = 0x02, +}; +typedef BYTE FelicaPollRequest; + +enum FelicaStatus1 { + FelicaStatus1_Success = 0x00, + // Everything between here is dynamically generated, and I cba + FelicaStatus1_Fatal = 0xFF, +}; +typedef BYTE FelicaStatus1; + +enum FelicaStatus2 { + // Generic + FelicaStatus2_Success = 0x00, + FelicaStatus2_Overflow = 0x01, + FelicaStatus2_CashbackExceeded = 0x02, + FelicaStatus2_PurseOutOfRange = 0x03, + FelicaStatus2_MemoryError = 0x70, + FelicaStatus2_RewritesExceeded = 0x71, + // Card specific + FelicaStatus2_IllegalServiceNumber = 0xA1, + FelicaStatus2_IllegalCommandPacket = 0xA2, + FelicaStatus2_IllegalBlockList = 0xA3, + FelicaStatus2_IllegalService = 0xA4, + FelicaStatus2_AccessDenied = 0xA5, + FelicaStatus2_IllegalServiceCode = 0xA6, + FelicaStatus2_IllegalBlockListAccess = 0xA7, + FelicaStatus2_IllegalBlockNumber = 0xA8, + FelicaStatus2_DataWriteFailure = 0xA9, + FelicaStatus2_KeyChangeFailure = 0xAA, + FelicaStatus2_IllegalParity = 0xAB, + FelicaStatus2_IllegalParameter = 0xAC, + FelicaStatus2_ServiceExists = 0xAD, + FelicaStatus2_IllegalSystemCode = 0xAE, + FelicaStatus2_TooManyWrites = 0xAF, + FelicaStatus2_IllegalPackage = 0xC0, + FelicaStatus2_PackageDiscrepancy = 0xC1, + FelicaStatus2_CommandDisabled = 0xC2, + FelicaStatus2_IllegalNodeProperty = 0xC3, +}; +typedef BYTE FelicaStatus2; + +// https://www.sony.net/Products/felica/business/tech-support/list.html +enum FelicaChipType { + FelicaChipType_STD_RC_S915 = 0x01, + FelicaChipType_STD_RC_S952 = 0x08, + FelicaChipType_STD_RC_S953 = 0x09, + FelicaChipType_STD_RC_S960 = 0x0D, + FelicaChipType_STD_RC_S962 = 0x20, + FelicaChipType_STD_RC_SA00_1 = 0x32, + FelicaChipType_STD_RC_SA20_1 = 0x44, + FelicaChipType_STD_RC_SA20_2 = 0x45, + + FelicaChipType_Mobile_Ver10 = 0x06, // And 07h + FelicaChipType_Mobile_Ver20 = 0x10, // Up to 13h + FelicaChipType_Mobile_Ver30 = 0x14, // And 15h + FelicaChipType_Mobile_Ver40 = 0x17, + FelicaChipType_Mobile_Ver41 = 0x18, // Up to 1Fh + + FelicaChipType_Lite = 0xf0, // RC-S965 + FelicaChipType_LiteS = 0xf1, // RC-S966 + + FelicaChipType_Link_LiteS = 0xf2, // RC-S967 + FelicaChipType_Link_Plug = 0xe1, // RC-S967 + FelicaChipType_Link_NFC_DEP = 0xff, // RC-S967 + + FelicaChipType_Plug = 0xe0, // RC-S926 +}; +typedef BYTE FelicaChipType; + +/** + * Multiple vendors make use of FeliCa cards for their amusement cards, but we + * can disamiguate them based on the specific FeliCa chip they use. + * + * Mobile phones will be using the Mobile chip versions. The specific OS + * version only matters for when the game is requesting to send mail or open a + * URL in the browser. + * + * The now-common Amusement IC cards all use FeliCa Lite or FeliCa LiteS. We + * choose to emulate our AIC cards as LiteS (RC-S966). + * + * Banapasses (BNG) also use FeliCa, however use FeliCa standard. We're going + * to keep things simple and just emulate RC-S915. + */ +typedef enum FelicaEmulationMode { + // Emulate a Suica mobile phone (FelicaChipType_Mobile_Ver**) + FelicaEmulationMode_Suica, // TODO: Which OS version do we want to emulate? + // Emulate an AmusementIC card (FelicaChipType_LiteS) + FelicaEmulationMode_AIC, + // Emulate a Banapass card (FelicaChipType_STD_RC_S915) + FelicaEmulationMode_BNG, +} FelicaEmulationMode; + +typedef enum FelicaAICVendor { + FelicaAICVendor_BandaiNamcoGames, // FeliCa Lite, never used afaik + FelicaAICVendor_BandaiNamcoEntertainment, // FeliCa LiteS + FelicaAICVendor_SEGA, // FeliCa LiteS + FelicaAICVendor_Konami, // FeliCa LiteS +} FelicaAICVendor; + +#define FelicaSystemBlock_RC 0x00 +#define FelicaSystemBlock_MAC 0x01 +#define FelicaSystemBlock_ID 0x02 +#define FelicaSystemBlock_D_ID 0x03 +#define FelicaSystemBlock_SER_C 0x04 +#define FelicaSystemBlock_SYS_C 0x05 +#define FelicaSystemBlock_CKV 0x06 +#define FelicaSystemBlock_CK 0x07 +#define FelicaSystemBlock_MC 0x08 + +#pragma pack(push, 1) +typedef struct FelicaBlock { + BYTE bytes[16]; +} FelicaBlock_t, *PFelicaBlock_t; +typedef struct FelicaBlock_RC { + union { + struct { + DWORD64 m_RC1; + DWORD64 m_RC2; + }; + DWORD64 m_RC[2]; + }; +} FelicaBlock_RC; +typedef struct FelicaBlock_MAC { + BYTE m_MAC[8]; + BYTE Rsv08[8]; +} FelicaBlock_MAC; +typedef struct FelicaBlock_ID { + FELICA_ID m_FelicaId; + BYTE m_DFC[2]; + BYTE m_Arbitrary[6]; +} FelicaBlock_ID; +typedef struct FelicaBlock_D_ID { + FELICA_ID m_FelicaId; + BYTE m_PMm[8]; +} FelicaBlock_D_ID; +typedef struct FelicaBlock_SER_C { + BYTE m_SER_C[2]; + BYTE Rsv02[14]; +} FelicaBlock_SER_C; +typedef struct FelicaBlock_SYS_C { + WORD m_SYS_C; + BYTE Rsv02[14]; +} FelicaBlock_SYS_C; +typedef struct FelicaBlock_CKV { + BYTE m_CKV[2]; + BYTE Rsv02[14]; +} FelicaBlock_CKV; +typedef struct FelicaBlock_CK { + BYTE m_CK1[8]; + BYTE m_CK2[8]; +} FelicaBlock_CK; +typedef struct FelicaBlock_MC { + // I really don't want to map this all out, and don't think I need to. + // So I'm not going to. + // Page 30 on the below URL if ever actually needed. + // https://www.sony.net/Products/felica/business/tech-support/data/fls_usmnl_1.31.pdf + BYTE Rsv00[16]; +} FelicaBlock_MC; + +typedef struct FelicaMemory { + FelicaEmulationMode m_EmuMode; + FelicaAICVendor m_AICVendor; + FelicaBlock_t m_UserBlocks[15]; + union { + FelicaBlock_t m_SystemBlocks[9]; + struct { + FelicaBlock_RC m_SystemBlock_RC; + FelicaBlock_MAC m_SystemBlock_MAC; + FelicaBlock_ID m_SystemBlock_ID; + FelicaBlock_D_ID m_SystemBlock_D_ID; + FelicaBlock_SER_C m_SystemBlock_SER_C; + FelicaBlock_SYS_C m_SystemBlock_SYS_C; + FelicaBlock_CKV m_SystemBlock_CKV; + FelicaBlock_CK m_SystemBlock_CK; + FelicaBlock_MC m_SystemBlock_MC; + }; + }; +} FelicaMemory_t; + +typedef struct FelicaRequest_Poll { + FelicaSystem m_SystemCode; + FelicaPollRequest m_Request; + BYTE m_TimeSlot; +} FelicaRequest_Poll, *PFelicaRequest_Poll; +typedef struct FelicaResponse_Poll { + BYTE m_PMm[8]; + WORD m_Value; +} FelicaResponse_Poll, *PFelicaResponse_Poll; + +typedef struct FelicaRequest_ReadNoEnc { + FELICA_ID m_IDm; + BYTE m_Rest[]; +} FelicaRequest_ReadNoEnc, *PFelicaRequest_ReadNoEnc; +typedef struct FelicaResponse_ReadNoEnc { + BYTE m_Status1; + BYTE m_Status2; + BYTE m_BlockCount; + BYTE m_BlockData[]; +} FelicaResponse_ReadNoEnc, *PFelicaResponse_ReadNoEnc; + +typedef struct FelicaRequest_WriteNoEnc { + FELICA_ID m_IDm; + BYTE m_Rest[]; +} FelicaRequest_WriteNoEnc, *PFelicaRequest_WriteNoEnc; +typedef struct FelicaResponse_WriteNoEnc { + BYTE m_Status1; + BYTE m_Status2; +} FelicaResponse_WriteNoEnc, *PFelicaResponse_WriteNoEnc; + +typedef struct FelicaRequest_SystemCode { + FELICA_ID m_IDm; +} FelicaRequest_SystemCode, *PFelicaRequest_SystemCode; +typedef struct FelicaResponse_SystemCode { + BYTE m_SystemsCount; + WORD m_SystemCode; +} FelicaResponse_SystemCode, *PFelicaResponse_SystemCode; + +typedef struct FelicaRequest_Active2 { + FELICA_ID m_IDm; + BYTE m_Val; +} FelicaRequest_Active2, *PFelicaRequest_Active2; +typedef struct FelicaResponse_Active2 { + BYTE m_Data; +} FelicaResponse_Active2, *PFelicaResponse_Active2; + +typedef struct FelicaEncapRequest { + FELICA_ID m_IDm; + BYTE m_FelicaLen; + BYTE m_FelicaCommand; + union { + FelicaRequest_Poll m_Poll; + FelicaRequest_ReadNoEnc m_ReadNoEnc; + FelicaRequest_WriteNoEnc m_WriteNoEnc; + FelicaRequest_SystemCode m_SystemCode; + FelicaRequest_Active2 m_Active2; + BYTE m_Body[238]; + }; +} FelicaEncapRequest, *PFelicaEncapRequest; +typedef struct FelicaEncapResponse { + BYTE m_FelicaLen; + BYTE m_FelicaCommand; + FELICA_ID m_IDm; + union { + FelicaResponse_Poll m_Poll; + FelicaResponse_ReadNoEnc m_ReadNoEnc; + FelicaResponse_WriteNoEnc m_WriteNoEnc; + FelicaResponse_SystemCode m_SystemCode; + FelicaResponse_Active2 m_Active2; + BYTE m_Body[246]; + }; +} FelicaEncapResponse, *PFelicaEncapResponse; +#pragma pack(pop) + +#define FelicaRespSize(x) (10 + sizeof x) + +#ifndef _NFC_H +typedef struct NFC_CARD NFC_CARD, *PNFC_CARD; +typedef struct ACCESS_CODE ACCESS_CODE, *PACCESS_CODE; +#define _NFC_H +#endif + +void FelicaPoll(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard); +void FelicaReadNoEnc(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard); +void FelicaWriteNoEnc(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard); +void FelicaSystemCode(PFelicaEncapRequest lpReq, PFelicaEncapResponse lpResponse, PNFC_CARD lpCard); +void FelicaEncap(com_device_t* dev, comio_recv_head_t* req, LPBYTE lpPacket, PNFC_CARD lpCard); +void FelicaPopulate(PNFC_CARD lpCard, PFELICA_ID lpFelicaId, PACCESS_CODE lpAccessCode); diff --git a/src/micetools/dll/devices/nfc/mifare.h b/src/micetools/dll/devices/nfc/mifare.h new file mode 100644 index 0000000..0b6360d --- /dev/null +++ b/src/micetools/dll/devices/nfc/mifare.h @@ -0,0 +1,15 @@ +#include + +#pragma pack(push, 1) +typedef struct MifareBlock { + BYTE bytes[16]; +} MifareBlock_t; + +typedef struct MifareSector { + MifareBlock_t blocks[4]; +} MifareSector_t; + +typedef struct MifareMemory_t { + MifareSector_t sectors[16]; +} MifareMemory_t; +#pragma pack(pop) diff --git a/src/micetools/dll/devices/nfc/nfc.h b/src/micetools/dll/devices/nfc/nfc.h new file mode 100644 index 0000000..62069f1 --- /dev/null +++ b/src/micetools/dll/devices/nfc/nfc.h @@ -0,0 +1,65 @@ +#pragma once +#include + +#include "felica.h" +#include "mifare.h" + +enum CardType { + CardType_Unknown = 0x00, + CardType_Mifare = 0x10, + CardType_FeliCa = 0x20, +}; +typedef BYTE CardType; + +struct ACCESS_CODE { + BYTE m_AC[10]; +}; + +#ifndef _NFC_H +typedef struct NFC_CARD NFC_CARD, *PNFC_CARD; +typedef struct ACCESS_CODE ACCESS_CODE, *PACCESS_CODE; +#define _NFC_H +#endif + +#pragma pack(push, 1) +struct NFC_CARD { + struct { + BYTE m_Type; + BYTE m_IdLen; + } m_Header; + union { + struct { + union { + FELICA_ID m_IDm; + struct { + WORD m_Code; // Manufacturer code + WORD m_Machine; // Manufacturer machine + INT16 m_Date; // Days since 2000-01-01 + WORD m_Serial; // Daily serial + }; + }; + union { + BYTE m_PMm[8]; + struct { + BYTE m_RomType; + FelicaChipType m_ICType; + BYTE m_Response[6]; // Response time information + }; + }; + } m_FeliCa; + struct { + DWORD m_Uid; + } m_Mifare; + struct { + BYTE Unk00[7]; + } m_Amiibo; + }; + union { + MifareMemory_t m_MifareData; + FelicaMemory_t m_FeliCaData; + }; +}; +#pragma pack(pop) + +#define NFC_FeliCaSize (sizeof((PNFC_CARD)0)->m_Header + sizeof((PNFC_CARD)0)->m_FeliCa) +#define NFC_MifareSize (sizeof((PNFC_CARD)0)->m_Header + sizeof((PNFC_CARD)0)->m_Mifare) diff --git a/src/micetools/dll/devices/ser_tn32msec.c b/src/micetools/dll/devices/ser_tn32msec.c index 698f62f..71bd2c0 100644 --- a/src/micetools/dll/devices/ser_tn32msec.c +++ b/src/micetools/dll/devices/ser_tn32msec.c @@ -1,218 +1,290 @@ +/* +FeliCa Lite: + AIC cards starting with 300x, 302x, and 303x contain their AIC number in block 0D +*/ + +#include "ser_tn32msec.h" + +#include "../../lib/mice/solitaire.h" #include "_devices.h" +#include "nfc/nfc.h" -static BYTE read_one(com_device_t* dev) { - while (!comdev_available(dev)) Sleep(50); - BYTE data; - comdev_read(dev, &data, 1); - return data; +static BYTE extra[0xff]; + +BYTE cardLED_RGB_P1[3]; +BYTE cardLED_RGB_P2[3]; + +static char* OpcodeNames[256]; + +typedef enum TN32_FwVer { + TN32_FwVer_10 = 0x10, // 1.0 + TN32_FwVer_12 = 0x12, // 1.2 +} TN32_FwVer; + +TN32_FwVer FIRMWARE_VERSION = TN32_FwVer_10; + +static const char FWVer00[] = "TN32MSEC003S F/W Ver0.0"; // Not a real firmware version +static const char FWVer10[] = "TN32MSEC003S F/W Ver1.0"; +static const char FWVer12[] = "TN32MSEC003S F/W Ver1.2"; +static const char HWVer[] = "TN32MSEC003S H/W Ver3.0"; + +NFC_CARD nfcCardReaderP1; +NFC_CARD nfcCardReaderP2; +#define READER_P1_ADDR 0x00 +#define READER_P2_ADDR 0x01 +#define READER_P1_LED_ADDR 0x08 +#define READER_P2_LED_ADDR 0x09 + +CHAR cardIdentifier1P[32]; +CHAR cardIdentifier2P[32]; +static LPCSTR GetCardIdentifier(DWORD player) { + LPCSTR card = player == 0 ? MiceConfig.aime.player1_card : MiceConfig.aime.player2_card; + LPCSTR cardFile = + player == 0 ? MiceConfig.aime.player1_cardfile : MiceConfig.aime.player2_cardfile; + LPSTR cardIdentifier = player == 0 ? cardIdentifier1P : cardIdentifier2P; + + if (_PathFileExistsA(cardFile)) { + log_info(plfAime, "Reading P%d card from %s", player + 1, cardFile); + + HANDLE hFile = + _CreateFileA(cardFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_warning(plfAime, "Failed to open %s for reading", cardFile); + } else { + DWORD nRead; + if (!_ReadFile(hFile, cardIdentifier, 32, &nRead, NULL)) { + log_error(plfAime, "Failed to read from %s", cardFile); + } else { + card = cardIdentifier; + } + _CloseHandle(hFile); + } + } else if (card == NULL || strlen(card) == 0) { + log_error(plfAime, + "No card specified for Player %d. Either specify a card in settings, or place a " + "card ID into %s", + player + 1, cardFile); + } + + return card == NULL ? "" : card; } -BYTE extra[0xff]; - /** - * 51 and 55 are guesses based on the code. Makes sense given their opcodes - * too. - * TODO: Validate against a real board + * @brief Convert a card identification string to either an access code or felica ID + * + * Supported card formats: + * Access codes (AiMe Mifare cards): + * "1234-1234-1234-1234-1234" + * "1234 1234 1234 1234 1234" + * "12341234123412341234" + * FeliCa IDm (AIC cards): + * "0134567890123456" + * "01 34 56 78 90 12 34 56" */ -enum TN32_Opcode { - TN32Op_GetFWVersion = 0x30, - TN32Op_GetHWVersion = 0x32, +static CardType TN32GetCardInfo(LPCSTR lpIdentifier, PACCESS_CODE lpAccessCode, + PFELICA_ID lpFelicaId) { + DWORD nChars; + DWORD len = strlen(lpIdentifier); - TN32Op_RadioOn = 0x40, - TN32Op_RadioOff = 0x41, - TN32Op_Poll = 0x42, - TN32Op_MifareSelectTag = 0x43, - TN32Op_CardHalt = 0x44, - - TN32Op_SetKeyBana = 0x50, - TN32Op_GetKeyBana = 0x51, - TN32Op_ReadBlock = 0x52, - TN32Op_WriteBlock = 0x53, - TN32Op_SetKeyAime = 0x54, - TN32Op_GetKeyAime = 0x55, - - // Firmware update - TN32Op_EnterUpdaterMode = 0x60, - TN32Op_SendHex = 0x61, - TN32Op_Reset = 0x62, - TN32Op_SendBindata = 0x63, - TN32Op_BindataExec = 0x64, - - // Felica - TN32Op_FelicaPush = 0x70, - TN32Op_FelicaEncap = 0x71, - - // No responses to either - Led_SetColour = 0x80, - Led_SetColourRGB = 0x81, - - Led_GetInfo = 0xf0, - Led_FirmwareSum = 0xf2, - Led_SendHex = 0xf3, - Led_EnterBootMode = 0xf4, - Led_Reset = 0xf5, -}; - -char* OpcodeNames[256]; - -const char FWVer[] = "TN32MSEC003S F/W Ver1.2"; -const char HWVer[] = "TN32MSEC003S H/W Ver3.0"; - -#define CardType_Mifare 0x10 -#define CardType_FeliCa 0x20 - -#pragma pack(push, 1) -typedef struct NFCMifare { - BYTE type; - BYTE id_len; - DWORD uid; -} NFCMifare_t; - -typedef struct NFCFelica { - BYTE type; - BYTE id_len; - uint64_t IDm; - uint64_t PMm; -} NFCFelica_t; - -typedef struct MifareBlock { - BYTE bytes[16]; -} MifareBlock_t; - -typedef struct MifareSector { - MifareBlock_t blocks[4]; -} MifareSector_t; - -typedef struct MifareMemory_t { - MifareSector_t sectors[16]; -} MifareMemory_t; - -typedef struct FelicaBlock { - BYTE bytes[16]; -} FelicaBlock_t; - -typedef struct FelicaMemory { - FelicaBlock_t dataBlocks[15]; - FelicaBlock_t systemBlocks[9]; -} FelicaMemory_t; -#pragma pack(pop) - -MifareMemory_t mifareMemory; -FelicaMemory_t felicaMemory; -BYTE luid[10] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89 }; -#define PMm_VALUE 0x00F1000000014300ULL - -#define FelicaSystemBlock_RC 0x00 -#define FelicaSystemBlock_MAC 0x01 -#define FelicaSystemBlock_ID 0x02 -#define FelicaSystemBlock_D_ID 0x03 -#define FelicaSystemBlock_SER_C 0x04 -#define FelicaSystemBlock_SYS_C 0x05 -#define FelicaSystemBlock_CKV 0x06 -#define FelicaSystemBlock_CK 0x07 -#define FelicaSystemBlock_MC 0x08 - -void populate_felica(NFCFelica_t* card) { - card->type = CardType_FeliCa; - card->id_len = sizeof(card->IDm) + sizeof(card->PMm); - card->IDm = _byteswap_uint64(0x012E4CD8A30A39B3ULL); - card->PMm = _byteswap_uint64(PMm_VALUE); - - // Key name - felicaMemory.dataBlocks[0x0D].bytes[0] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[1] = 0x02; - felicaMemory.dataBlocks[0x0D].bytes[2] = 'N'; - felicaMemory.dataBlocks[0x0D].bytes[3] = 'B'; - felicaMemory.dataBlocks[0x0D].bytes[4] = 'G'; - felicaMemory.dataBlocks[0x0D].bytes[5] = 'I'; - felicaMemory.dataBlocks[0x0D].bytes[6] = 'C'; - felicaMemory.dataBlocks[0x0D].bytes[7] = '0'; - // Setup the fake blowfish data - felicaMemory.dataBlocks[0x0D].bytes[8] = 0x89; - felicaMemory.dataBlocks[0x0D].bytes[9] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[10] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[11] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[12] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[13] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[14] = 0x00; - felicaMemory.dataBlocks[0x0D].bytes[15] = 0x00; - - BYTE block0[16] = { - 0xC2, 0x1C, 0xCB, 0xC7, 0x58, 0xCA, 0x81, 0xB7, - 0xC0, 0x0B, 0x8E, 0x3A, 0x45, 0x43, 0xFE, 0xFC, - }; - memcpy(felicaMemory.dataBlocks[0].bytes, block0, 16); - memset(felicaMemory.dataBlocks[0x0e].bytes, 0xFF, 16); - BYTE blockID[16] = { - // IDd (=IDm) - 0x01, 0x2E, 0x4C, 0xD8, 0xA3, 0x0A, 0x39, 0xB3, - // ID - 0x00, 0x2a, 0x05, 0x73, 0x02, 0x01, 0x03, 0x00, - // ^DFC^ ^~~~~~ arbitary value - }; - memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_ID].bytes, blockID, 16); - BYTE blockDID[16] = { - // IDd (=IDm) - 0x01, - 0x2E, - 0x4C, - 0xD8, - 0xA3, - 0x0A, - 0x39, - 0xB3, - // PMm - 0x00, - 0xF1, - 0x00, - 0x00, - 0x00, - 0x01, - 0x43, - 0x00, - }; - memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_D_ID].bytes, blockDID, 16); + if (len == 24) { + if (sscanf_s(lpIdentifier, + "%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%n", + &lpAccessCode->m_AC[0], &lpAccessCode->m_AC[1], &lpAccessCode->m_AC[2], + &lpAccessCode->m_AC[3], &lpAccessCode->m_AC[4], &lpAccessCode->m_AC[5], + &lpAccessCode->m_AC[6], &lpAccessCode->m_AC[7], &lpAccessCode->m_AC[8], + &lpAccessCode->m_AC[9], &nChars) == 10 && + nChars == 24) { + return CardType_Mifare; + } + if (sscanf_s(lpIdentifier, + "%02hhx%02hhx %02hhx%02hhx %02hhx%02hhx %02hhx%02hhx %02hhx%02hhx%n", + &lpAccessCode->m_AC[0], &lpAccessCode->m_AC[1], &lpAccessCode->m_AC[2], + &lpAccessCode->m_AC[3], &lpAccessCode->m_AC[4], &lpAccessCode->m_AC[5], + &lpAccessCode->m_AC[6], &lpAccessCode->m_AC[7], &lpAccessCode->m_AC[8], + &lpAccessCode->m_AC[9], &nChars) == 10 && + nChars == 24) { + return CardType_Mifare; + } + } else if (len == 20) { + if (sscanf_s(lpIdentifier, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n", + &lpAccessCode->m_AC[0], &lpAccessCode->m_AC[1], &lpAccessCode->m_AC[2], + &lpAccessCode->m_AC[3], &lpAccessCode->m_AC[4], &lpAccessCode->m_AC[5], + &lpAccessCode->m_AC[6], &lpAccessCode->m_AC[7], &lpAccessCode->m_AC[8], + &lpAccessCode->m_AC[9], &nChars) == 10 && + nChars == 20) + return CardType_Mifare; + } else if (len == 16) { + if (sscanf_s(lpIdentifier, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n", + &lpFelicaId->m_ID[0], &lpFelicaId->m_ID[1], &lpFelicaId->m_ID[2], + &lpFelicaId->m_ID[3], &lpFelicaId->m_ID[4], &lpFelicaId->m_ID[5], + &lpFelicaId->m_ID[6], &lpFelicaId->m_ID[7], &nChars) == 8 && + nChars == 16) + return CardType_FeliCa; + } else if (len == 23) { + if (sscanf_s(lpIdentifier, "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx%n", + &lpFelicaId->m_ID[0], &lpFelicaId->m_ID[1], &lpFelicaId->m_ID[2], + &lpFelicaId->m_ID[3], &lpFelicaId->m_ID[4], &lpFelicaId->m_ID[5], + &lpFelicaId->m_ID[6], &lpFelicaId->m_ID[7], &nChars) == 8 && + nChars == 23) + return CardType_FeliCa; + } + return CardType_Unknown; } -void populate_mifare(NFCMifare_t* card) { - card->type = CardType_Mifare; - card->id_len = sizeof(card->uid); - card->uid = _byteswap_ulong(0x01020304); - // TODO: Better state haha - // Flash the card memory +#define ACKEY_ACCESSCODE_LEN 20 +#define ACKEY_ACCESSHEADER_ID_LEN 5 +#define ACKEY_SERIAL_LEN 8 + +static DWORD AccessCodeToSerial(PACCESS_CODE lpAccessCode) { + char accessCode[ACKEY_ACCESSCODE_LEN + 1]; + sprintf_s(accessCode, sizeof accessCode, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + lpAccessCode->m_AC[0], lpAccessCode->m_AC[1], lpAccessCode->m_AC[2], + lpAccessCode->m_AC[3], lpAccessCode->m_AC[4], lpAccessCode->m_AC[5], + lpAccessCode->m_AC[6], lpAccessCode->m_AC[7], lpAccessCode->m_AC[8], + lpAccessCode->m_AC[9]); + + char hashed_id_wrk[ACKEY_SERIAL_LEN + 1]; + char id_wrk[ACKEY_SERIAL_LEN + 1]; + + memcpy_s(hashed_id_wrk, sizeof(hashed_id_wrk), &accessCode[ACKEY_ACCESSHEADER_ID_LEN], + ACKEY_SERIAL_LEN); + hashed_id_wrk[ACKEY_SERIAL_LEN] = '\0'; + + SolitaireCipherDecode(&accessCode[ACKEY_ACCESSHEADER_ID_LEN + ACKEY_SERIAL_LEN], hashed_id_wrk, + id_wrk); + return atoi(id_wrk); +} + +static void MifarePopulate(PNFC_CARD lpCard, PACCESS_CODE lpAccessCode) { + lpCard->m_Header.m_IdLen = sizeof(lpCard->m_Mifare); + DWORD nSerial = AccessCodeToSerial(lpAccessCode); + lpCard->m_Mifare.m_Uid = nSerial; + + printf("Serial: %d\n", nSerial); + + // Block 0: Manufacture data (only used by BNG) + + // Block 1: Game ID information (kCARD_DETECT_KEY_B_READ_1) + const char GAME_ID[4] = { 'S', 'B', 'S', 'D' }; + memcpy_s(&lpCard->m_MifareData.sectors[0].blocks[1].bytes[0], + sizeof lpCard->m_MifareData.sectors[0].blocks[1].bytes, GAME_ID, 4); + lpCard->m_MifareData.sectors[0].blocks[1].bytes[12] = (nSerial >> 24) & 0xff; + lpCard->m_MifareData.sectors[0].blocks[1].bytes[13] = (nSerial >> 16) & 0xff; + lpCard->m_MifareData.sectors[0].blocks[1].bytes[14] = (nSerial >> 8) & 0xff; + lpCard->m_MifareData.sectors[0].blocks[1].bytes[15] = nSerial & 0xff; + + // Block 2: Access code (kCARD_DETECT_KEY_B_READ_2) + memcpy_s(&lpCard->m_MifareData.sectors[0].blocks[2].bytes[6], + sizeof lpCard->m_MifareData.sectors[0].blocks[2].bytes - 6, lpAccessCode->m_AC, + sizeof lpAccessCode->m_AC); +} +void AmiiboPopulate(PNFC_CARD lpCard) { + // What _is_ the ID though? + lpCard->m_Header.m_IdLen = sizeof(lpCard->m_Mifare); + + // Write the card for (BYTE i = 0; i < 10; i++) { - BYTE b = luid[i]; - mifareMemory.sectors[0].blocks[2].bytes[i + 6] = b; - mifareMemory.sectors[0].blocks[1].bytes[i + 6] = b; + lpCard->m_MifareData.sectors[0].blocks[21].bytes[i] = 0; } } -void nfc_poll(com_device_t* dev, comio_recv_head_t* req) { +BYTE TN32PopulateCard(PNFC_CARD lpCard, LPCSTR lpIdentifier) { + ACCESS_CODE accessCode; + FELICA_ID felicaId; + + CardType type = TN32GetCardInfo(lpIdentifier, &accessCode, &felicaId); + if (type == CardType_Unknown) { + log_error(plfAime, "Unable to parse card: %s", lpIdentifier); + return 0; + } + + lpCard->m_Header.m_Type = type; + if (type == CardType_Mifare) { + log_info(plfAime, + "Inserting card: %02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx", + accessCode.m_AC[0], accessCode.m_AC[1], accessCode.m_AC[2], accessCode.m_AC[3], + accessCode.m_AC[4], accessCode.m_AC[5], accessCode.m_AC[6], accessCode.m_AC[7], + accessCode.m_AC[8], accessCode.m_AC[9]); + + MifarePopulate(lpCard, &accessCode); + return NFC_MifareSize; + } else if (type == CardType_FeliCa) { + log_info(plfAime, "Inserting card: %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", + felicaId.m_ID[0], felicaId.m_ID[1], felicaId.m_ID[2], felicaId.m_ID[3], + felicaId.m_ID[4], felicaId.m_ID[5], felicaId.m_ID[6], felicaId.m_ID[7]); + + // TODO: FeliCa AIC cards can take an access code in their first block, + // and we support this. Figure out a nice way to allow this to be + // specified by users. That said, I'm not sure if anything in the Ring + // series actually uses this. + + FelicaPopulate(lpCard, &felicaId, NULL); + return NFC_FeliCaSize; + } + + return 0; +} + +static void nfc_poll(com_device_t* dev, comio_recv_head_t* req) { BYTE data[256]; + data[0] = 0; BYTE nbytes = 1; - // felica present - if (GetAsyncKeyState('L') < 0) { - NFCFelica_t card; - populate_felica(&card); - memcpy(data + nbytes, &card, sizeof card); - nbytes += sizeof card; - data[0]++; - } - // mifare (aime, bana) present - if (GetAsyncKeyState('P') < 0) { - NFCMifare_t card; - populate_mifare(&card); - memcpy(data + nbytes, &card, sizeof card); - nbytes += sizeof card; - data[0]++; - } + BOOL p1 = req->dst == READER_P1_ADDR; - comio_reply(dev, req, COMIO_STATUS_OK, nbytes, data); + PNFC_CARD lpCard = p1 ? &nfcCardReaderP1 : &nfcCardReaderP2; + + SHORT key = GetAsyncKeyState(p1 ? 'P' : 'L'); + if (key < 0) { + LPCSTR cardId = GetCardIdentifier(p1 ? 0 : 1); + BYTE nCardBytes = TN32PopulateCard(lpCard, cardId); + if (nCardBytes) { + memcpy(data + nbytes, lpCard, nCardBytes); + nbytes += nCardBytes; + data[0]++; + } + } + comio_reply(dev, req, TN32Error_OK, nbytes, data); } -BYTE AIME_KEY[6]; -BYTE BANA_KEY[6]; +// Games don't expect this to be preloaded, but we might as well +BYTE AIME_KEY[6] = { 0x57, 0x43, 0x43, 0x46, 0x76, 0x32 }; +BYTE BANA_KEY[6] = { 0x60, 0x90, 0xd0, 0x06, 0x32, 0xf5 }; + +void MifareBlockRead(com_device_t* dev, comio_recv_head_t* req, LPBYTE lpPacket, PNFC_CARD lpCard) { + // langth = 4 bytes uid + 1 byte block + if (req->length != 5) { + log_warning(plfAime, "Mifare read packet bad: %d", req->length); + comio_reply(dev, req, TN32Error_InvalidData, 0, NULL); + return; + } + + if (lpCard->m_Header.m_Type != CardType_Mifare) { + log_error(plfAime, "Reader %02x requested a Mifare read on a non-Mifare card!", req->dst); + comio_reply(dev, req, TN32Error_CardError, 0, NULL); + return; + } + + DWORD uid = *((LPDWORD)(&lpPacket[0])); + BYTE blockNo = lpPacket[4]; + + if (blockNo > 3) { + log_warning(plfAime, "Mifare block out of range: %d", blockNo); + comio_reply(dev, req, TN32Error_CardError, 0, NULL); + return; + } + if (lpCard->m_Mifare.m_Uid != uid) { + log_error(plfAime, + "Reader %02x requested to read card %08x. Currently present card is %08x.", uid, + lpCard->m_Mifare.m_Uid); + comio_reply(dev, req, TN32Error_CardError, 0, NULL); + return; + } + + log_misc(plfAime, "Read mifare block: %d", blockNo); + MifareBlock_t* block = &(lpCard->m_MifareData.sectors[0].blocks[blockNo]); + comio_reply(dev, req, TN32Error_OK, sizeof *block, block->bytes); +} DWORD WINAPI aime_bd_thread(com_device_t* dev) { static int fwNumBytes = 0; @@ -224,80 +296,167 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { comio_recv_head_t req; unsigned char sum = comio_next_req(dev, &req, extra); - log_info(plfAime, "(%d) %02x(%d) = %s", req.dst, req.op, req.length, OpcodeNames[req.op]); + log_trace(plfAime, "(%d) %02x(%d) = %s", req.dst, req.op, req.length, OpcodeNames[req.op]); + + // Proxy 1P reader to hardware COM1. Used for debugging; preserved because it might end up + // useful again in the future. Allowing proxying to hardware a first-party feature could be + // cool down the line, but would need much much nicer code than this :D + /* + if (req.dst == READER_P1_ADDR) { + HANDLE hCom = _CreateFileA("\\\\.\\COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, 0, NULL); + DWORD nWrote; + BYTE data = 0xE0; + BYTE mark = 0xD0; + _WriteFile(hCom, &data, 1, &nWrote, NULL); + for (int i = 0; i < sizeof req; i++) { + data = ((LPBYTE)&req)[i]; + if (data == 0xE0 || data == 0xD0) { + _WriteFile(hCom, &mark, 1, &nWrote, NULL); + data--; + } + _WriteFile(hCom, &data, 1, &nWrote, NULL); + } + for (int i = 0; i < req.length; i++) { + data = extra[i]; + if (data == 0xE0 || data == 0xD0) { + _WriteFile(hCom, &mark, 1, &nWrote, NULL); + data--; + } + _WriteFile(hCom, &data, 1, &nWrote, NULL); + } + data = sum; + if (data == 0xE0 || data == 0xD0) { + _WriteFile(hCom, &mark, 1, &nWrote, NULL); + data--; + } + _WriteFile(hCom, &data, 1, &nWrote, NULL); + + Sleep(250); + BYTE readBuf[4096]; + DWORD nRead; + _ReadFile(hCom, readBuf, 4096, &nRead, NULL); + log_game(plfAime, "Transact read: %d", nRead); + for (DWORD i = 0; i < nRead; i++) printf("%02x ", readBuf[i]); + puts(""); + + comdev_write(dev, readBuf, nRead); + + _CloseHandle(hCom); + continue; + } + */ + + if (req.dst == READER_P1_ADDR || req.dst == READER_P2_ADDR) { + PNFC_CARD lpCard = req.dst == READER_P1_ADDR ? &nfcCardReaderP1 : &nfcCardReaderP2; - if (req.dst == 0x00 || req.dst == 0x01) { // Aime readers switch (req.op) { - case TN32Op_Reset: - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); - break; + // Core case TN32Op_GetFWVersion: - // BYTE fver = 0x10; - // comio_reply(dev, &req, COMIO_STATUS_OK, 1, &fver); - comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1, (LPBYTE)FWVer); + if (FIRMWARE_VERSION == TN32_FwVer_10) + comio_reply(dev, &req, TN32Error_OK, sizeof FWVer10 - 1, (LPBYTE)FWVer10); + else if (FIRMWARE_VERSION == TN32_FwVer_12) + comio_reply(dev, &req, TN32Error_OK, sizeof FWVer12 - 1, (LPBYTE)FWVer12); + else + comio_reply(dev, &req, TN32Error_OK, sizeof FWVer00 - 1, (LPBYTE)FWVer00); break; case TN32Op_GetHWVersion: - // BYTE hver = 0x10; - // comio_reply(dev, &req, COMIO_STATUS_OK, 1, &hver); - comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1, (LPBYTE)HWVer); + comio_reply(dev, &req, TN32Error_OK, sizeof HWVer - 1, (LPBYTE)HWVer); break; - case TN32Op_SetKeyAime: - if (req.length != sizeof AIME_KEY) { - comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); - } else { - memcpy(AIME_KEY, extra, sizeof AIME_KEY); - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); - log_info(plfAime, "Aime key: %02x %02x %02x %02x %02x %02x", AIME_KEY[0], - AIME_KEY[1], AIME_KEY[2], AIME_KEY[3], AIME_KEY[4], AIME_KEY[5]); - } - break; - case TN32Op_SetKeyBana: - if (req.length != sizeof BANA_KEY) { - comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); - } else { - memcpy(BANA_KEY, extra, sizeof BANA_KEY); - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); - - log_info(plfAime, "Bana key: %02x %02x %02x %02x %02x %02x", BANA_KEY[0], - BANA_KEY[1], BANA_KEY[2], BANA_KEY[3], BANA_KEY[4], BANA_KEY[5]); - } - break; + // Radio case TN32Op_RadioOn: radio = true; - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; case TN32Op_RadioOff: radio = false; - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; - case TN32Op_Poll: + case TN32Op_CardDetect: nfc_poll(dev, &req); break; - - case TN32Op_GetKeyBana: - case TN32Op_GetKeyAime: - if (req.length != 5) { - // - } - case TN32Op_CardHalt: - case TN32Op_MifareSelectTag: - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + // TODO: What's this? + comio_reply(dev, &req, TN32Error_OK, 0, NULL); + break; + case TN32Op_CardSelect: + // TODO: Card stacks, for games that need those + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; + // Mifare + case TN32Op_MifareKeySetA: + if (req.length != sizeof BANA_KEY) { + comio_reply(dev, &req, TN32Error_InvalidData, 0, NULL); + } else { + memcpy(BANA_KEY, extra, sizeof BANA_KEY); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); + + log_misc(plfAime, "Bana key: %02x %02x %02x %02x %02x %02x", BANA_KEY[0], + BANA_KEY[1], BANA_KEY[2], BANA_KEY[3], BANA_KEY[4], BANA_KEY[5]); + } + break; + case TN32Op_MifareKeySetB: + if (req.length != sizeof AIME_KEY) { + comio_reply(dev, &req, TN32Error_InvalidData, 0, NULL); + } else { + memcpy(AIME_KEY, extra, sizeof AIME_KEY); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); + + log_misc(plfAime, "Aime key: %02x %02x %02x %02x %02x %02x", AIME_KEY[0], + AIME_KEY[1], AIME_KEY[2], AIME_KEY[3], AIME_KEY[4], AIME_KEY[5]); + } + break; + case TN32Op_MifareRead: + /** + * All Mifare reads AiMeLib can perform: + * + * kCARD_DETECT_KEY_B_READ_0: [0] + * kCARD_DETECT_KEY_B_READ_1: [1] + * kCARD_DETECT_KEY_B_READ_2: [2] + * kCARD_DETECT_KEY_A_READ_0: [0] + * kCARD_DETECT_KEY_A_READ_1: [1] + * kCARD_DETECT_KEY_A_READ_2: [2] + * + * kCARD_DETECT_NAUTH_READ: [21] Amiibo things + * https://www.reddit.com/r/amiibo/comments/38rdll/my_research_on_amiibo_id_this_time_about/ + * > Pages 21 and 22 are character IDs + * https://www.reddit.com/r/amiibo/comments/38p4a0/my_research_on_amiibo_id_including_variants_types/ + * + * Supporting Amiibos is probably not worth doing until we find a game that + * actually uses them! + */ + MifareBlockRead(dev, &req, extra, lpCard); + break; + case TN32Op_MifareWrite: + // TODO: Do we want to support writing? + comio_reply(dev, &req, TN32Error_InvalidCommand, 0, NULL); + break; + case TN32Op_MifareAuthorizeA: + case TN32Op_MifareAuthorizeB: + // TODO: We probably should? + if (req.length != 5) { + } + comio_reply(dev, &req, TN32Error_OK, 0, NULL); + break; + + // Firmware control case TN32Op_EnterUpdaterMode: - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; case TN32Op_SendHex: // null-terminated line of the firmware hex! - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); log_info(plfAime, "Recv firmware: %s", extra); break; + case TN32Op_Reset: + comio_reply(dev, &req, TN32Error_OK, 0, NULL); + break; case TN32Op_SendBindata: fwNumBytes = 0; - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; case TN32Op_BindataExec: // Raw binary firmware data @@ -319,35 +478,61 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { if (fwNumBytes >= 0x3000) ; else - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; - // TODO: These - case TN32Op_ReadBlock: - comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); + // Felica + case TN32Op_FelicaPush: + // TODO: Implement mail and url opening? + comio_reply(dev, &req, TN32Error_InvalidCommand, 0, NULL); break; case TN32Op_FelicaEncap: - comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); + if (FIRMWARE_VERSION == TN32_FwVer_12) { + FelicaEncap(dev, &req, extra, lpCard); + } else { + /** + * Firmware version 1.0 has no support for FeliCa + * proxying, and just returns Invalid Command for 70h + * and 71h. maimai is absolutely happy with this, and + * will just use the IDm from the Poll request without + * querying the card further. + * + * In fact, maimai _cannot_ function with newer + * firmware, due to an outdated restriction within + * AiMeLib that only allows BNG cards. + */ + comio_reply(dev, &req, TN32Error_InvalidCommand, 0, NULL); + } break; } - } else if (req.dst == 0x08 || req.dst == 0x09) { + } else if (req.dst == READER_P1_LED_ADDR || req.dst == READER_P2_LED_ADDR) { // LED sub-boards switch (req.op) { case Led_Reset: - comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + comio_reply(dev, &req, TN32Error_OK, 0, NULL); break; case Led_GetInfo: - // TODO: I'm not sure what this actually means. - // 838-15084 is probably a part number - comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12"); + // Format: + // 0xff-delimited board info string + // 1 byte, board version + comio_reply(dev, &req, TN32Error_OK, 9, (BYTE*)"15084\xff\x10"); + break; + case Led_SetColour: + log_misc(plfAime, "Set LED: %02x @ %02x intensity", extra[0], extra[1]); break; case Led_SetColourRGB: log_misc(plfAime, "Set LED: #%02x%02x%02x", extra[0], extra[1], extra[2]); - printf( - "\033[48;2;%d;%d;%dm " - " \033[0m", - extra[0], extra[1], extra[2]); - // No response expected here! + // TODO: Bring this back, in a nicer way + + if (req.dst == READER_P1_LED_ADDR) { + cardLED_RGB_P1[0] = extra[0]; + cardLED_RGB_P1[1] = extra[1]; + cardLED_RGB_P1[2] = extra[2]; + } else { + cardLED_RGB_P2[0] = extra[0]; + cardLED_RGB_P2[1] = extra[1]; + cardLED_RGB_P2[2] = extra[2]; + } break; } } @@ -362,15 +547,15 @@ void install_aime_bd() { OpcodeNames[TN32Op_GetHWVersion] = "GetHWVersion"; OpcodeNames[TN32Op_RadioOn] = "RadioOn"; OpcodeNames[TN32Op_RadioOff] = "RadioOff"; - OpcodeNames[TN32Op_Poll] = "Poll"; - OpcodeNames[TN32Op_MifareSelectTag] = "MifareSelectTag"; + OpcodeNames[TN32Op_CardDetect] = "CardDetect"; + OpcodeNames[TN32Op_CardSelect] = "CardSelect"; OpcodeNames[TN32Op_CardHalt] = "CardHalt"; - OpcodeNames[TN32Op_SetKeyBana] = "SetKeyBana"; - OpcodeNames[TN32Op_GetKeyBana] = "GetKeyBana"; - OpcodeNames[TN32Op_ReadBlock] = "ReadBlock"; - OpcodeNames[TN32Op_WriteBlock] = "WriteBlock"; - OpcodeNames[TN32Op_SetKeyAime] = "SetKeyAime"; - OpcodeNames[TN32Op_GetKeyAime] = "GetKeyAime"; + OpcodeNames[TN32Op_MifareKeySetA] = "MifareKeySetA"; + OpcodeNames[TN32Op_MifareAuthorizeA] = "MifareAuthorizeA"; + OpcodeNames[TN32Op_MifareRead] = "MifareRead"; + OpcodeNames[TN32Op_MifareWrite] = "MifareWrite"; + OpcodeNames[TN32Op_MifareKeySetB] = "MifareKeySetB"; + OpcodeNames[TN32Op_MifareAuthorizeB] = "MifareAuthorizeB"; OpcodeNames[TN32Op_EnterUpdaterMode] = "EnterUpdaterMode"; OpcodeNames[TN32Op_SendHex] = "SendHex"; OpcodeNames[TN32Op_Reset] = "Reset"; diff --git a/src/micetools/dll/devices/ser_tn32msec.h b/src/micetools/dll/devices/ser_tn32msec.h new file mode 100644 index 0000000..fc31625 --- /dev/null +++ b/src/micetools/dll/devices/ser_tn32msec.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include "nfc/nfc.h" + +enum TN32Error { + TN32Error_OK, + TN32Error_CardError, + TN32Error_NoAccept, + TN32Error_InvalidCommand, + TN32Error_InvalidData, + TN32Error_SumError, + TN32Error_HexError, +}; +typedef BYTE TN32Error; +enum TN32ErrorLED { + TN32ErrorLED_OK, + TN32ErrorLED_CommandUnknown, + TN32ErrorLED_OverflowErr, + TN32ErrorLED_ParityErr, + TN32ErrorLED_OverrunErr, + TN32ErrorLED_FramingErr, + TN32ErrorLED_SumErr, + TN32ErrorLED_ParameterErr, + TN32ErrorLED_HexErr, +}; +typedef BYTE TN32ErrorLED; + +/** + * 51 and 55 are guesses based on the code. Makes sense given their opcodes + * too. + * TODO: Validate against a real board + */ +enum TN32_Opcode { + TN32Op_GetFWVersion = 0x30, + TN32Op_GetHWVersion = 0x32, + + TN32Op_RadioOn = 0x40, + TN32Op_RadioOff = 0x41, + TN32Op_CardDetect = 0x42, + TN32Op_CardSelect = 0x43, + TN32Op_CardHalt = 0x44, + + TN32Op_MifareKeySetA = 0x50, // BNG key + TN32Op_MifareAuthorizeA = 0x51, + TN32Op_MifareRead = 0x52, + TN32Op_MifareWrite = 0x53, + TN32Op_MifareKeySetB = 0x54, // AiMe key + TN32Op_MifareAuthorizeB = 0x55, + + // Firmware update + TN32Op_EnterUpdaterMode = 0x60, + TN32Op_SendHex = 0x61, + TN32Op_Reset = 0x62, + TN32Op_SendBindata = 0x63, + TN32Op_BindataExec = 0x64, + + // Felica + TN32Op_FelicaPush = 0x70, + TN32Op_FelicaEncap = 0x71, + + // No responses to either + Led_SetColour = 0x80, + Led_SetColourRGB = 0x81, + + Led_GetInfo = 0xf0, + Led_FirmwareSum = 0xf2, + Led_SendHex = 0xf3, + Led_EnterBootMode = 0xf4, + Led_Reset = 0xf5, +}; diff --git a/src/micetools/dll/devices/smb_at24c64an.c b/src/micetools/dll/devices/smb_at24c64an.c index 8fc88ed..defe5d8 100644 --- a/src/micetools/dll/devices/smb_at24c64an.c +++ b/src/micetools/dll/devices/smb_at24c64an.c @@ -42,13 +42,16 @@ void set_eeprom_static_config() { .m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8), .m_Rental = MiceConfig.sysconf.rental, }; - strcpy_s(Static.m_strSerialId, sizeof Static.m_strSerialId, MiceConfig.sysconf.serial); + ZeroMemory(Static.m_strSerialId, sizeof Static.m_strSerialId); + DWORD len = strlen(MiceConfig.sysconf.serial); + if (len > sizeof Static.m_strSerialId - 1) len = sizeof Static.m_strSerialId - 1; + memcpy(Static.m_strSerialId, MiceConfig.sysconf.serial, len); fix_crc(Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_REG], &Static, sizeof Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_DUP], &Static, sizeof Static); } -void build_eeprom() { // return; +void build_eeprom() { // return; log_info(plfEeprom, "Building default EEPROM file"); memset(EEPROM_DATA, 0xff, EEPROM_SIZE); @@ -97,10 +100,10 @@ void eeprom_fixup() { set_eeprom_static_config(); set_eeprom_network_config(); - AmHistory.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8); - fix_crc(AmHistory); - memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_REG], &AmHistory, sizeof AmHistory); - memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_DUP], &AmHistory, sizeof AmHistory); + // AmHistory.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8); + // fix_crc(AmHistory); + // memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_REG], &AmHistory, sizeof AmHistory); + // memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_DUP], &AmHistory, sizeof AmHistory); } void ensure_valid_eeprom() { diff --git a/src/micetools/dll/dllmain.c b/src/micetools/dll/dllmain.c index 8695ae5..906c8df 100644 --- a/src/micetools/dll/dllmain.c +++ b/src/micetools/dll/dllmain.c @@ -143,7 +143,7 @@ void init_injection(HMODULE hModule) { if (success) success &= MiceFSAddDevLayers(); - MiceFSSetCwd(RING_MOUNT_GAME); + MiceFSSetCwd(RING_MOUNT_GAME "\\"); // Setup default COM devices init_com_devices(); @@ -187,8 +187,10 @@ void init_injection(HMODULE hModule) { // OPENSSL_add_all_algorithms_noconf (old exe) // ((void (*)(void))(0x00459770 + imageOffset))(); - // OPENSSL_add_all_algorithms_noconf (new exe) - ((void (*)(void))(0x00463480 + imageOffset))(); + // OPENSSL_add_all_algorithms_noconf (pink exe) + // ((void (*)(void))(0x00463480 + imageOffset))(); + + // TODO: Find finale offset } setup_hooks(); diff --git a/src/micetools/dll/gui/gui.c b/src/micetools/dll/gui/gui.c index 6d9ee82..b6a6c02 100644 --- a/src/micetools/dll/gui/gui.c +++ b/src/micetools/dll/gui/gui.c @@ -76,6 +76,7 @@ static bool showFps = false; static bool showEeprom = false; static bool showSram = false; static bool showControl = false; +static bool showCardP1 = false; void InitImGui(unsigned int hookType, IDirect3DDevice9* pDevice) { if (hookType == UI_HOOK_DX9) { @@ -117,6 +118,34 @@ void InitImGui(unsigned int hookType, IDirect3DDevice9* pDevice) { } } +extern BYTE cardLED_RGB_P1[3]; +extern BYTE cardLED_RGB_P2[3]; +void hud_card(ImGuiKey open_key) { + if (igIsKeyPressed_Bool(open_key, false)) showCardP1 = !showCardP1; + if (!showCardP1) return; + + igBegin("Card Reader", NULL, 0); + + ImVec4 col; + col.w = 1.0f; + + col.x = cardLED_RGB_P1[0] / 511.0f; + col.y = cardLED_RGB_P1[1] / 511.0f; + col.z = cardLED_RGB_P1[2] / 511.0f; + igPushStyleColor_Vec4(ImGuiCol_Button, col); + igButton("Insert card P1", vec0); + igPopStyleColor(1); + + col.x = cardLED_RGB_P2[0] / 511.0f; + col.y = cardLED_RGB_P2[1] / 511.0f; + col.z = cardLED_RGB_P2[2] / 511.0f; + igPushStyleColor_Vec4(ImGuiCol_Button, col); + igButton("Insert card P2", vec0); + igPopStyleColor(1); + + igEnd(); +} + void hud_fps() { if (igBegin("FPS", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | @@ -898,6 +927,26 @@ void tab_main_keybinds() { } } +void tab_main_aime_cards() { + igText( + "Specify the cards to be inserted when using the TN32MSEC AiMe reader module.\nCards can be " + "specified as either an NFC ID or an access code.\nIf a card file is present, it will be " + "used preferentially."); + + igColumns(2, "AimeWindow", true); + igSeparator(); + + bool changed = false; + changed |= AddSettingString("Player 1 Card ID", NULL, &MiceConfig.aime.player1_card); + changed |= AddSettingString("Player 2 Card ID", NULL, &MiceConfig.aime.player2_card); + changed |= AddSettingString("Player 1 Card File", NULL, &MiceConfig.aime.player1_cardfile); + changed |= AddSettingString("Player 2 Card File", NULL, &MiceConfig.aime.player2_cardfile); + + igEndColumns(); + + if (changed) save_current_config(); +} + void hud_control(ImGuiKey open_key) { if (igIsKeyPressed_Bool(open_key, false)) showControl = !showControl; if (!showControl) return; @@ -919,6 +968,12 @@ void hud_control(ImGuiKey open_key) { igEndChild(); igEndTabItem(); } + if (igBeginTabItem("AiMe Cards", NULL, 0)) { + igBeginChild_Str("AiMe Cards", vec0, FALSE, 0); + tab_main_aime_cards(); + igEndChild(); + igEndTabItem(); + } if (igBeginTabItem("Settings", NULL, 0)) { igBeginChild_Str("Settings", vec0, FALSE, 0); tab_main_settings(); @@ -935,7 +990,7 @@ void hud_control(ImGuiKey open_key) { void __stdcall hud_gui(unsigned int hookType, IDirect3DDevice9* dev) { static bool lastAnyOpen = false; - bool anyOpen = showControl || showEeprom || showSram; + bool anyOpen = showControl || showEeprom || showSram || showCardP1; if (anyOpen != lastAnyOpen) { changeCursorState = anyOpen ? 1 : 0; lastAnyOpen = anyOpen; @@ -964,6 +1019,7 @@ void __stdcall hud_gui(unsigned int hookType, IDirect3DDevice9* dev) { hud_eeprom(ImGuiKey_F11); hud_sram(ImGuiKey_F10); hud_control(ImGuiKey_F4); + hud_card(ImGuiKey_F5); if (hookType == UI_HOOK_DX9) { igEndFrame(); diff --git a/src/micetools/dll/hooks/drive/disks.c b/src/micetools/dll/hooks/drive/disks.c index fc1ee42..baae292 100644 --- a/src/micetools/dll/hooks/drive/disks.c +++ b/src/micetools/dll/hooks/drive/disks.c @@ -62,6 +62,26 @@ physical_disk_t UPDATE_USB = { }, .m_Extended = {{ 0 }}, }; +physical_disk_t DOWNLOAD_USB = { + .m_BusType = BusTypeUsb, + .m_VID = "13FE", + .m_PID = "4200", + .m_BlockSize = BLOCK_SIZE_FLASH, + .m_TotalSize = 64 * 1024 * ((1024 * 1024) / BLOCK_SIZE_FLASH), + .m_IsFormatted = true, + .m_DiskType = DiskType_Flash, + .m_Partitions = { + // 59050 MB update partitions + { + .m_Size = 0xe6b410, + .m_Filesystem = MBR_FS_NTFS, + .m_Volume = { + .m_Name = "SEGA_DL", + }, + }, + }, + .m_Extended = {{ 0 }}, +}; physical_disk_t LOG_USB = { .m_BusType = BusTypeUsb, .m_VID = "13FE", @@ -83,6 +103,27 @@ physical_disk_t LOG_USB = { }, .m_Extended = {{ 0 }}, }; +physical_disk_t MAI_USB_DONGLE = { + .m_BusType = BusTypeUsb, + .m_VID = "13FE", + .m_PID = "4200", + .m_BlockSize = BLOCK_SIZE_FLASH, + .m_TotalSize = 16 * 1024 * ((1024 * 1024) / BLOCK_SIZE_FLASH), + .m_IsFormatted = true, + .m_DiskType = DiskType_Flash, + .m_Partitions = { + // 4 GB partition + { + .m_Size = 0x100000, + .m_Filesystem = MBR_FS_NTFS, + .m_Volume = { + .m_Name = "USBDONGLE", + .m_MountPoint = 'U', + }, + }, + }, + .m_Extended = {{ 0 }}, +}; physical_disk_t ALPHA_DVD = { .m_BusType = BusTypeScsi, .m_DeviceType = DeviceTypeCdRom, @@ -124,9 +165,12 @@ physical_disk_t APM_HDD = { physical_disk_t* PHYSICAL_DISKS[] = { &SSD, - &UPDATE_USB, + // &UPDATE_USB, + // &DOWNLOAD_USB, // &APM_HDD, + // &MAI_USB_DONGLE, + // &LOG_USB, // &ALPHA_DVD, }; diff --git a/src/micetools/dll/hooks/drive/drive.c b/src/micetools/dll/hooks/drive/drive.c index 0d6d69a..e0254e4 100644 --- a/src/micetools/dll/hooks/drive/drive.c +++ b/src/micetools/dll/hooks/drive/drive.c @@ -366,6 +366,8 @@ inline static BOOL matchVolume(disk_volume_t* volume, LPCSTR lpRootPathName, DWO if (match & VOL_MATCH_DOS_DEVICE && volume->m_MountPoint) { if (char_lower(volume->m_MountPoint) == char_lower(lpRootPathName[0])) { if (lpRootPathName[1] == ':' && lpRootPathName[2] == '\0') return TRUE; + if (lpRootPathName[1] == ':' && lpRootPathName[2] == '\\' && lpRootPathName[3] == '\0') + return TRUE; } } return FALSE; diff --git a/src/micetools/dll/hooks/drive/drive.h b/src/micetools/dll/hooks/drive/drive.h index d94fc8c..b8927ca 100644 --- a/src/micetools/dll/hooks/drive/drive.h +++ b/src/micetools/dll/hooks/drive/drive.h @@ -113,20 +113,24 @@ void hook_drives(); #define MBR_FS_NTFS 0x07 #define MBR_FS_EXT_LBA 0x0F +#define MBR_BOOTSTRAP_SIZE 446 + #pragma pack(push, 1) -typedef struct mbr { - BYTE bootstrap_code[446]; - struct { - BYTE status; - BYTE start_chs[3]; - BYTE type; - BYTE end_chs[3]; - DWORD lba; - DWORD sectors; - } partitions[4]; +typedef struct MBR_PARTITION { + BYTE status; + BYTE start_chs[3]; + BYTE type; + BYTE end_chs[3]; + DWORD lba; + DWORD sectors; +} MBR_PARTITION, *PMBR_PARTITION; +typedef struct MBR_HEADER { + BYTE bootstrap_code[MBR_BOOTSTRAP_SIZE]; + MBR_PARTITION partitions[4]; BYTE sig[2]; -} mbr_t; +} MBR_HEADER, *PMBR_HEADER; #pragma pack(pop) +typedef MBR_HEADER mbr_t; #define IOCTL_CDROM_GET_DRIVE_GEOMETRY 0x2404c // #include causes errors diff --git a/src/micetools/dll/hooks/drive/hooks.c b/src/micetools/dll/hooks/drive/hooks.c index e1db0a6..cc7b339 100644 --- a/src/micetools/dll/hooks/drive/hooks.c +++ b/src/micetools/dll/hooks/drive/hooks.c @@ -89,6 +89,7 @@ BOOL WINAPI FakeGetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameB LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { disk_volume_t* volume = getVolumeByPath(lpRootPathName, VOL_MATCH_ALL); + log_game(plfDrive, "GetVolumeInformationA(%s) = %p", lpRootPathName, volume); if (volume == NULL) return FALSE; if (lpVolumeSerialNumber) *lpVolumeSerialNumber = volume->m_pDrive->m_SerialNumber; @@ -130,7 +131,8 @@ BOOL WINAPI FakeGetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint, L DWORD cchBufferLength) { log_trace(plfDrive, "GetVolumeNameForVolumeMountPointA(%s)", lpszVolumeMountPoint); - disk_volume_t* volume = getVolumeByPath(lpszVolumeMountPoint, VOL_MATCH_PATH); + disk_volume_t* volume = + getVolumeByPath(lpszVolumeMountPoint, VOL_MATCH_PATH | VOL_MATCH_DOS_DEVICE); if (volume == NULL) { SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; @@ -141,7 +143,7 @@ BOOL WINAPI FakeGetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint, L } BOOL WINAPI FakeGetVolumePathNamesForVolumeNameA(LPCSTR lpszVolumeName, LPCH lpszVolumePathNames, DWORD cchBufferLength, PDWORD lpcchReturnLength) { - log_trace(plfDrive, "GetVolumeNameForVolumeMountPointA(%s)", lpszVolumeName); + log_trace(plfDrive, "FakeGetVolumePathNamesForVolumeNameA(%s)", lpszVolumeName); disk_volume_t* volume = getVolumeByPath(lpszVolumeName, VOL_MATCH_GUID); if (volume == NULL) { diff --git a/src/micetools/dll/hooks/files.c b/src/micetools/dll/hooks/files.c index 21aa106..45cb22c 100644 --- a/src/micetools/dll/hooks/files.c +++ b/src/micetools/dll/hooks/files.c @@ -128,7 +128,10 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d MiceFSRedirectPathW(lpFileName, &lpFileName); handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - log_misc(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle); + if (handle == INVALID_HANDLE_VALUE) + log_warning(plfHooks, "CreateFileW(%ls) failed", lpFileName); + else + log_misc(plfHooks, "CreateFileW(%ls) -> 0x%p", lpFileName, handle); return handle; } @@ -149,7 +152,10 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw MiceFSRedirectPathA(lpFileName, &lpFileName); HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - log_misc(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle); + if (handle == INVALID_HANDLE_VALUE) + log_warning(plfHooks, "CreateFileA(%s) failed", lpFileName); + else + log_misc(plfHooks, "CreateFileA(%s) -> 0x%p", lpFileName, handle); return handle; } @@ -320,17 +326,33 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) { return TrueCloseHandle(hObject); } -int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) { - MiceFSRedirectPathA((char*)path, &path); - return True_stat64i32(path, buffer); -}; + +void FileTimeToTimet(__time64_t* t, LPFILETIME pft) { + ULARGE_INTEGER time_value; + time_value.HighPart = pft->dwHighDateTime; + time_value.LowPart = pft->dwLowDateTime; + *t = (time_value.QuadPart - 116444736000000000LL) / 10000000LL; +} + +int WINAPIV Fake_stat64i32(const char* path, _stat64i32_t* buffer) { + MiceFSRedirectPathA(path, &path); + + // NOTE: We can't use True_stat64i32 because it has issues with another other than dir-relative + // child paths + + WIN32_FILE_ATTRIBUTE_DATA fileInformation; + if (!GetFileAttributesEx(path, GetFileExInfoStandard, &fileInformation)) return -1; + + // TODO: Populate other values. ALLNetProc and OpenSSL only need st_size. atime/ctime are free + // so were added too. + buffer->st_size = fileInformation.nFileSizeLow; + FileTimeToTimet(&buffer->st_atime, &fileInformation.ftLastAccessTime); + FileTimeToTimet(&buffer->st_ctime, &fileInformation.ftCreationTime); + + return 0x800; +} DWORD WINAPI FakeGetFileAttributesA(LPCSTR lpFileName) { - // The game quits out if MiniDump is present! - if (PathEqual(lpFileName, "Y:\\MiniDump\\")) { - return 0; - } - MiceFSRedirectPathA(lpFileName, &lpFileName); return TrueGetFileAttributesA(lpFileName); } @@ -338,18 +360,36 @@ DWORD WINAPI FakeGetFileAttributesW(LPCWSTR lpFileName) { MiceFSRedirectPathW(lpFileName, &lpFileName); return TrueGetFileAttributesW(lpFileName); } +BOOL WINAPI FakeCreateDirectoryA(LPCSTR lpFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { + MiceFSRedirectPathA(lpFileName, &lpFileName); + return TrueCreateDirectoryA(lpFileName, lpSecurityAttributes); +} +BOOL WINAPI FakeCreateDirectoryW(LPCWSTR lpFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { + MiceFSRedirectPathW(lpFileName, &lpFileName); + return TrueCreateDirectoryW(lpFileName, lpSecurityAttributes); +} HANDLE WINAPI FakeFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData) { MiceFSRedirectPathA(lpFileName, &lpFileName); return TrueFindFirstFileA(lpFileName, lpFindFileData); } DWORD WINAPI FakeGetCurrentDirectoryA(DWORD nBufferLength, LPSTR lpBuffer) { - strcpy_s(lpBuffer, nBufferLength, MiceFSGetCwd()); - return strnlen_s(lpBuffer, nBufferLength); + LPCSTR cwd = MiceFSGetCwd(); + DWORD length = strlen(cwd); + if (nBufferLength < length + 1) { + return length + 1; + } + strcpy_s(lpBuffer, nBufferLength, cwd); + return length; } DWORD WINAPI FakeGetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer) { - MultiByteToWideChar(CP_ACP, 0, MiceFSGetCwd(), -1, lpBuffer, nBufferLength); - return wcsnlen_s(lpBuffer, nBufferLength); + LPCSTR cwd = MiceFSGetCwd(); + DWORD length = strlen(cwd); + if (nBufferLength < (length + 1) * 2) { + return (length + 1) * 2; + } + MultiByteToWideChar(CP_ACP, 0, cwd, -1, lpBuffer, nBufferLength); + return length; } void hook_io() { @@ -380,6 +420,10 @@ void hook_io() { (void**)&TrueGetFileAttributesA); hook("Kernel32.dll", "GetFileAttributesW", FakeGetFileAttributesW, (void**)&TrueGetFileAttributesW); + hook("Kernel32.dll", "CreateDirectoryA", FakeCreateDirectoryA, + (void**)&TrueCreateDirectoryA); + hook("Kernel32.dll", "CreateDirectoryW", FakeCreateDirectoryW, + (void**)&TrueCreateDirectoryW); hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32); } diff --git a/src/micetools/dll/hooks/files.h b/src/micetools/dll/hooks/files.h index 0dc5d37..2a52971 100644 --- a/src/micetools/dll/hooks/files.h +++ b/src/micetools/dll/hooks/files.h @@ -5,6 +5,20 @@ #define _MICE_FILES extern #endif +typedef struct { + unsigned int st_dev; + unsigned short st_ino; + unsigned short st_mode; + short st_nlink; + short st_uid; + short st_gid; + unsigned int st_rdev; + long st_size; + __time64_t st_atime; + __time64_t st_mtime; + __time64_t st_ctime; +} _stat64i32_t; + _MICE_FILES HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, @@ -40,6 +54,11 @@ _MICE_FILES BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName); _MICE_FILES HANDLE(WINAPI* TrueFindFirstFileA)(LPCSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData); _MICE_FILES DWORD(WINAPI* TrueGetFileAttributesA)(LPCSTR lpFileName); _MICE_FILES DWORD(WINAPI* TrueGetFileAttributesW)(LPCWSTR lpFileName); +_MICE_FILES BOOL(WINAPI* TrueCreateDirectoryA)(LPCSTR lpFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes); +_MICE_FILES BOOL(WINAPI* TrueCreateDirectoryW)(LPCWSTR lpFileName, + LPSECURITY_ATTRIBUTES lpSecurityAttributes); + _MICE_FILES DWORD(WINAPI* TrueGetCurrentDirectoryA)(DWORD nBufferLength, LPSTR lpBuffer); _MICE_FILES DWORD(WINAPI* TrueGetCurrentDirectoryW)(DWORD nBufferLength, LPWSTR lpBuffer); @@ -65,7 +84,6 @@ typedef BOOL(FnReadFile)(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBy typedef BOOL(FnGetFileSizeEx)(file_context_t* ctx, PLARGE_INTEGER lpFileSize); -typedef struct _stat64i32 _stat64i32_t; static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer); #define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile) diff --git a/src/micetools/dll/hooks/network.c b/src/micetools/dll/hooks/network.c index 24f2d2f..2fcf27b 100644 --- a/src/micetools/dll/hooks/network.c +++ b/src/micetools/dll/hooks/network.c @@ -75,7 +75,7 @@ DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) typedef struct { char* name; - unsigned int* address; + const unsigned int* address; } dns; dns INTERCEPT_DNS[] = { @@ -114,7 +114,7 @@ DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID } } } - log_warning(plfNetwork, "DNS passthrough for %s", pszName); + log_info(plfNetwork, "DNS passthrough for %s", pszName); return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved); }; @@ -129,17 +129,41 @@ INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, lpAddress->sa_family = AF_INET; PULONG addr = &(((SOCKADDR_IN*)lpAddress)->sin_addr.S_un.S_addr); - *addr = _byteswap_ulong( - *INTERCEPT_DNS[i] - .address); //(192UL) | (168UL << 8) | (103UL << 16) | (200UL << 24); + *addr = _byteswap_ulong(*INTERCEPT_DNS[i].address); return ERROR_SUCCESS; } } - log_warning(plfNetwork, "WSA DNS passthrough for %s", AddressString); + log_info(plfNetwork, "WSA DNS passthrough for %s", AddressString); return TrueWSAStringToAddressA(AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength); } +INT WINAPI Fake_getaddrinfo(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, + PADDRINFOA* ppResult) { + if (!pNodeName) return True_getaddrinfo(pNodeName, pServiceName, pHints, ppResult); + + for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) { + if (strcmp(pNodeName, INTERCEPT_DNS[i].name) == 0) { + char szNewAddress[16]; + sprintf_s(szNewAddress, sizeof szNewAddress, "%d.%d.%d.%d", + (*INTERCEPT_DNS[i].address >> 24) & 0xff, + (*INTERCEPT_DNS[i].address >> 16) & 0xff, + (*INTERCEPT_DNS[i].address >> 8) & 0xff, *INTERCEPT_DNS[i].address & 0xff); + szNewAddress[sizeof szNewAddress - 1] = '\0'; + + log_info(plfNetwork, "GAI DNS Replacing %s with %s:%s", pNodeName, szNewAddress, + pServiceName); + return True_getaddrinfo(szNewAddress, pServiceName, pHints, ppResult); + } + } + + // Exclude a few known services + if (strcmp(pNodeName, "0.0.0.0") != 0 && strcmp(pNodeName, "127.0.0.0") != 0 && + strcmp(pNodeName, "240.0.0.0") != 0) + log_info(plfNetwork, "GAI DNS passthrough for %s:%s", pNodeName, pServiceName); + return True_getaddrinfo(pNodeName, pServiceName, pHints, ppResult); +} + int __stdcall Fake_socket(int domain, int type, int protocol) { int sock = True_socket(domain, type, protocol); log_trace(plfNetwork, "Creating new socket: %d/%s/%d -> %d", domain, @@ -179,9 +203,9 @@ int __stdcall Fake_sendto(SOCKET s, const char* buf, int len, int flags, const P memcpy(&toLocalhost, to, sizeof toLocalhost); toLocalhost.sin_addr.S_un.S_addr = 0x0100007f; // 127.0.0.1 - log_warning(plfNetwork, "(probable) Ping to: %d.%d.%d.%d (%d). Redirecting to localhost", - addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, addr >> 24, - ((PSOCKADDR_IN)to)->sin_port, seq); + log_info(plfNetwork, "(probable) Ping to: %d.%d.%d.%d (%d). Redirecting to localhost", + addr & 0xff, (addr >> 8) & 0xff, (addr >> 16) & 0xff, addr >> 24, + ((PSOCKADDR_IN)to)->sin_port, seq); return True_sendto(s, buf, len, flags, (PSOCKADDR)&toLocalhost, tolen); } @@ -189,13 +213,32 @@ int __stdcall Fake_sendto(SOCKET s, const char* buf, int len, int flags, const P return True_sendto(s, buf, len, flags, to, tolen); } +ULONG WINAPI FakeGetAdaptersAddresses(ULONG Family, ULONG Flags, PVOID Reserved, + PIP_ADAPTER_ADDRESSES AdapterAddresses, PULONG SizePointer) { + if (SizePointer == NULL || *SizePointer < sizeof *AdapterAddresses) { + if (SizePointer != NULL) *SizePointer = sizeof *AdapterAddresses; + return ERROR_BUFFER_OVERFLOW; + } + AdapterAddresses->PhysicalAddressLength = 6; + AdapterAddresses->PhysicalAddress[0] = MAC_PREFIX_0; + AdapterAddresses->PhysicalAddress[1] = MAC_PREFIX_1; + AdapterAddresses->PhysicalAddress[2] = MAC_PREFIX_2; + AdapterAddresses->PhysicalAddress[3] = (MiceConfig.network.mac >> 16) & 0xff; + AdapterAddresses->PhysicalAddress[4] = (MiceConfig.network.mac >> 8) & 0xff; + AdapterAddresses->PhysicalAddress[5] = MiceConfig.network.mac & 0xff; + + return ERROR_SUCCESS; +}; + void hook_network() { hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect); hook("Ws2_32.dll", "socket", Fake_socket, (void**)&True_socket); hook("Ws2_32.dll", "bind", Fake_bind, (void**)&True_bind); - hook("Ws2_32.dll", "sendto", Fake_sendto, (void**)&True_sendto); + hook("Ws2_32.dll", "getaddrinfo", Fake_getaddrinfo, (void**)&True_getaddrinfo); + // hook("Ws2_32.dll", "sendto", Fake_sendto, (void**)&True_sendto); hook("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA, (void**)&TrueWSAStringToAddressA); hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable); hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A); + hook("Iphlpapi.dll", "GetAdaptersAddresses", FakeGetAdaptersAddresses, NULL); } diff --git a/src/micetools/dll/hooks/network.h b/src/micetools/dll/hooks/network.h index 49743e2..3325acc 100644 --- a/src/micetools/dll/hooks/network.h +++ b/src/micetools/dll/hooks/network.h @@ -6,6 +6,8 @@ static int(WINAPI* True_connect)(SOCKET s, const SOCKADDR* name, int namelen); static int(WINAPI* True_bind)(SOCKET s, const SOCKADDR* addr, int namelen); static int(WINAPI* True_sendto)(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen); +static INT(WINAPI* True_getaddrinfo)(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA* pHints, + PADDRINFOA* ppResult); static DWORD(WINAPI* TrueGetIfTable)(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder); diff --git a/src/micetools/dll/hooks/processes.c b/src/micetools/dll/hooks/processes.c index 8acf008..5521e5b 100644 --- a/src/micetools/dll/hooks/processes.c +++ b/src/micetools/dll/hooks/processes.c @@ -15,8 +15,9 @@ BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, lpProcessInformation); } - if (strcmp(lpCommandLine, "s:\\mxkeychip.exe") == 0 || - strcmp(lpCommandLine, "C:\\WINDOWS\\system32\\regini.exe S:\\default_regset.txt") == 0) { + if (lpCommandLine && + (strcmp(lpCommandLine, "s:\\mxkeychip.exe") == 0 || + strcmp(lpCommandLine, "C:\\WINDOWS\\system32\\regini.exe S:\\default_regset.txt") == 0)) { if (lpProcessInformation) { lpProcessInformation->hProcess = CreateEventA(NULL, FALSE, TRUE, NULL); lpProcessInformation->hThread = CreateEventA(NULL, FALSE, TRUE, NULL); @@ -51,7 +52,11 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPPROCESS_INFORMATION lpProcessInformation) { log_info(plfProcesses, "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); - if (wcsncmp(lpCommandLine, L"chkdsk.exe", wcslen(L"chkdsk.exe")) == 0) { + // if (lpCommandLine && (wcscmp(lpCommandLine, L"chkdsk.exe") == 0 || + // wcscmp(lpCommandLine, L"ALLNetProc_Win.exe") == 0 || + // wcscmp(lpCommandLine, L"ALLNetProc_Ring.exe") == 0 || + // wcscmp(lpCommandLine, L"ALLNetProc.exe") == 0)) { + if (lpCommandLine && (wcscmp(lpCommandLine, L"chkdsk.exe") == 0)) { if (lpProcessInformation) { lpProcessInformation->hProcess = CreateEventA(NULL, FALSE, TRUE, NULL); lpProcessInformation->hThread = CreateEventA(NULL, FALSE, TRUE, NULL); diff --git a/src/micetools/launcher/main.c b/src/micetools/launcher/main.c index 01f9514..e5ef804 100644 --- a/src/micetools/launcher/main.c +++ b/src/micetools/launcher/main.c @@ -24,7 +24,7 @@ static void print_help(char* exe) { static bool parse_cmdline(int argc, char* argv[]) { for (int i = 1; i < argc; i++) { - if (strcmp(argv[i], "-h") == 0) { + if (strcmp(argv[i], "--mice-h") == 0) { print_help(argv[0]); } else if (strcmp(argv[i], "-b") == 0) { if (i + 1 == argc) print_help(argv[0]); @@ -92,7 +92,7 @@ static DWORD WINAPI MiceMailslotWatcher(HANDLE* pSlot) { HANDLE hLogFile = INVALID_HANDLE_VALUE; if (MiceConfig.mice.log_to_file) { - hLogFile = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_READ, NULL, + hLogFile = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); if (hLogFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "Failed to initialise logging: open %s failed: %d", @@ -174,7 +174,41 @@ BOOL WINAPI MiceHandlerRoutine(DWORD CtrlType) { ExitProcess(terminate(0)); } +#include "../lib/mice/spad.h" + int main(int argc, char* argv[]) { + // unsigned char spad_new_bytes[16] = { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x06, + // 0x94, 0x87, 0x82, 0x60, 0x37, 0x73, 0x12, 0x13, + // }; + // unsigned char spn[16]; + // Spad0Encrypt(spn, spad_new_bytes); + // for (int i = 0; i < 8; i++) printf("%02x", spn[i]); + // puts(""); + // for (int i = 8; i < 16; i++) printf("%02x", spn[i]); + // puts(""); + + // puts("--"); + + // unsigned char back_out[16]; + // Spad0Decrypt(back_out, spn); + // for (int i = 0; i < 8; i++) printf("%02x", back_out[i]); + // puts(""); + // for (int i = 8; i < 16; i++) printf("%02x", back_out[i]); + // puts(""); + + // unsigned char bng[16] = { + // 0xE6, 0xBC, 0x6D, 0x56, 0x83, 0xF6, 0xB6, 0x48, + // 0x4C, 0x24, 0xE4, 0x83, 0xD5, 0xE8, 0x93, 0x7F, + // }; + // Spad0Decrypt(back_out, bng); + // for (int i = 0; i < 8; i++) printf("%02x", back_out[i]); + // puts(""); + // for (int i = 8; i < 16; i++) printf("%02x", back_out[i]); + // puts(""); + + // return -1; + load_mice_config(); if (!setup_mailslot()) return 1; setup_logging(); diff --git a/src/micetools/lib/_am.h b/src/micetools/lib/_am.h index 3dafe6b..ea30b75 100644 --- a/src/micetools/lib/_am.h +++ b/src/micetools/lib/_am.h @@ -2,9 +2,9 @@ #define AM_LIB_C_HEADER(name, storage_type) \ int name##DebugLevel = 0; \ - struct _##storage_type name; \ + struct storage_type name; \ char* name##Version = #name " Ver.mice" MICE_VERSION " Build:" __DATE__ " " __TIME__; #define AM_LIB_H_HEADER(name, storage_type) \ extern int name##DebugLevel; \ - extern struct _##storage_type name; \ + extern struct storage_type name; \ extern char* name##Version; diff --git a/src/micetools/lib/am/amCmos.c b/src/micetools/lib/am/amCmos.c new file mode 100644 index 0000000..bc65736 --- /dev/null +++ b/src/micetools/lib/am/amCmos.c @@ -0,0 +1,71 @@ +#include "amCmos.h" + +AM_LIB_C_HEADER(amCmos, AM_CMOS) + +AM_CMOS_STATUS amCmosInit(AM_CMOS_CONFIG *lpConfig) { + if (amCmos.m_bInit != 0) return AM_CMOS_STATUS_ERR_ALREADY_INIT; + if (lpConfig == NULL) return AM_CMOS_STATUS_ERR_INVALID_PARAM; + + HANDLE hMutex = CreateMutexA(NULL, 0, "AM_CMOS_MUTEX"); + if (hMutex == NULL) return AM_CMOS_STATUS_ERR_SYS; + + HANDLE hCmos = CreateFileA("\\\\.\\mxcmos", 0xc0000000, 3, NULL, 3, 0, NULL); + if (hCmos == INVALID_HANDLE_VALUE) { + CloseHandle(hMutex); + return AM_CMOS_STATUS_ERR_OPEN_FAILED; + } + + amCmos.m_bInit = TRUE; + amCmos.m_hMutex = hMutex; + amCmos.m_hCmos = hCmos; + + memcpy(&amCmos.m_Config, lpConfig, sizeof *lpConfig); + + return AM_CMOS_STATUS_OK; +} + +AM_CMOS_STATUS amCmosExit(void) { + if (amCmos.m_bInit == 0) return AM_CMOS_STATUS_ERR_NO_INIT; + + if (amCmos.m_hMutex != NULL) { + CloseHandle(amCmos.m_hMutex); + amCmos.m_hMutex = NULL; + } + if (amCmos.m_hCmos != INVALID_HANDLE_VALUE) { + CloseHandle(amCmos.m_hCmos); + amCmos.m_hCmos = INVALID_HANDLE_VALUE; + } + + amCmos.m_bInit = FALSE; + return AM_CMOS_STATUS_OK; +} + +AM_CMOS_STATUS amCmosReadByteInRearpart(BYTE nIndex, LPBYTE lpData) { + if (amCmos.m_bInit == 0) return AM_CMOS_STATUS_ERR_NO_INIT; + + if (lpData == NULL || nIndex > 0x7f) return AM_CMOS_STATUS_ERR_INVALID_PARAM; + + if (WaitForSingleObject(amCmos.m_hMutex, 0) != WAIT_OBJECT_0) return AM_CMOS_STATUS_ERR_LOCK; + + BYTE request[2]; + request[0] = nIndex; + request[1] = 0; + + DWORD nBytesReturned; + BOOL bErr = DeviceIoControl(amCmos.m_hCmos, IOCTL_MXCMOS_READ, request, sizeof request, lpData, + 1, &nBytesReturned, NULL); + + int iRet = 0; + if (!bErr) { + iRet = AM_CMOS_STATUS_ERR_SYS; + } else { + iRet = nBytesReturned == 1 ? AM_CMOS_STATUS_OK : AM_CMOS_STATUS_ERR_SYS; + } + + if (!ReleaseMutex(amCmos.m_hMutex)) { + if (amCmosDebugLevel > 0) + amiDebugLog("ReleaseMutex Error!! Error Code is %ld!!", GetLastError()); + return AM_CMOS_STATUS_ERR_SYS; + } + return iRet; +} diff --git a/src/micetools/lib/am/amCmos.h b/src/micetools/lib/am/amCmos.h index def3bb4..71e70e5 100644 --- a/src/micetools/lib/am/amCmos.h +++ b/src/micetools/lib/am/amCmos.h @@ -1,3 +1,39 @@ -void amCmosReadByteInRearpart(void); -void amCmosSetPartition(void); +#pragma once + +#include + +#include "../../dll/smbus.h" +#include "../_am.h" + +AM_LIB_H_HEADER(amCmos, AM_CMOS) + +typedef enum { + AM_CMOS_STATUS_OK = 0, + AM_CMOS_STATUS_NG = -1, + AM_CMOS_STATUS_ERR_INVALID_PARAM = -2, + AM_CMOS_STATUS_ERR_NO_INIT = -3, + AM_CMOS_STATUS_ERR_ALREADY_INIT = -4, + AM_CMOS_STATUS_ERR_SYS = -5, + AM_CMOS_STATUS_ERR_OPEN_FAILED = -6, + AM_CMOS_STATUS_ERR_LOCK = -7, +} AM_CMOS_STATUS; + +typedef struct AM_CMOS_CONFIG { + BYTE index[4]; + BYTE m_MbrCount; +} AM_CMOS_CONFIG; + +typedef struct AM_CMOS { + BOOL m_bInit; + HANDLE m_hMutex; + HANDLE m_hCmos; + AM_CMOS_CONFIG m_Config; +} AM_CMOS; + + +AM_CMOS_STATUS amCmosInit(AM_CMOS_CONFIG* lpConfig); +AM_CMOS_STATUS amCmosExit(void); + +AM_CMOS_STATUS amCmosReadByteInRearpart(BYTE param_1, LPBYTE param_2); void amCmosWriteByteInRearpart(void); +void amCmosSetPartition(void); diff --git a/src/micetools/lib/am/amDipsw.c b/src/micetools/lib/am/amDipsw.c new file mode 100644 index 0000000..1f0cbbd --- /dev/null +++ b/src/micetools/lib/am/amDipsw.c @@ -0,0 +1,118 @@ +#include "amDipsw.h" + +#include + +AM_LIB_C_HEADER(amDipsw, AM_DIPSW) + +int amDipswCreateMutex(AM_DIPSW *this) { + SECURITY_ATTRIBUTES securityAttributes; + SECURITY_DESCRIPTOR securityDescriptor; + SID_IDENTIFIER_AUTHORITY sid; + + PSID *ppSid = &this->m_Sid; + sid.Value[0] = '\0'; + sid.Value[1] = '\0'; + sid.Value[2] = '\0'; + sid.Value[3] = '\0'; + sid.Value[4] = '\0'; + sid.Value[5] = '\x01'; + if (!AllocateAndInitializeSid(&sid, '\x01', 0, 0, 0, 0, 0, 0, 0, 0, ppSid)) { + if (amDipswDebugLevel > 0) amiDebugLog("AllocateAndInitializeSid Error in amDipswInit."); + *ppSid = NULL; + goto fail_cleanup; + } + if (!InitializeSecurityDescriptor(&securityDescriptor, 1)) { + if (amDipswDebugLevel > 0) + amiDebugLog("InitializeSecurityDescriptor Error in amDipswInit."); + + goto fail_cleanup; + } + if (!SetSecurityDescriptorDacl(&securityDescriptor, 1, NULL, 0)) { + if (amDipswDebugLevel > 0) amiDebugLog("SetSecurityDescriptorDacl Error in amDipswInit."); + goto fail_cleanup; + } + securityAttributes.lpSecurityDescriptor = &securityDescriptor; + securityAttributes.nLength = 0xc; + securityAttributes.bInheritHandle = 0; + + HANDLE mutex = CreateMutexA(&securityAttributes, 0, "Global\\AM_PCA9535_MUTEX"); + this->m_Mutex = mutex; + if (mutex != NULL) return 0; + if (amDipswDebugLevel > 0) amiDebugLog("CreateMutexA Error(%ld).", GetLastError()); + +fail_cleanup: + if (this->m_Mutex != NULL) { + CloseHandle(this->m_Mutex); + this->m_Mutex = NULL; + } + if (*ppSid != NULL) { + FreeSid(*ppSid); + *ppSid = NULL; + } + return -5; +} + +HANDLE amDipswCreateDeviceFile(GUID *guid, DWORD memberIndex, char *name) { + HDEVINFO deviceInfoSet; + BOOL BVar3; + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + SP_DEVICE_INTERFACE_DETAIL_DATA_A deviceInterfaceDetailData[204]; + + if (guid == NULL) { + if (amDipswDebugLevel > 0) amiDebugLog("PARAM Error."); + + return INVALID_HANDLE_VALUE; + } + deviceInfoSet = SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + if (deviceInfoSet == INVALID_HANDLE_VALUE) { + if (amDipswDebugLevel > 0) amiDebugLog("SetupDiGetClassDevs Error(%ld).", GetLastError()); + return INVALID_HANDLE_VALUE; + } + + char szFilename[260]; + ZeroMemory(szFilename, 4); + deviceInterfaceData.cbSize = 0x1c; + if (!SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, guid, memberIndex, &deviceInterfaceData)) { + if (amDipswDebugLevel > 0) + amiDebugLog("SetupDiEnumDeviceInterfaces Error(%ld).", GetLastError()); + } else { + deviceInterfaceDetailData[0].cbSize = 5; + if (SetupDiGetDeviceInterfaceDetailA(deviceInfoSet, &deviceInterfaceData, + deviceInterfaceDetailData, 0x400, NULL, NULL)) { + strcpy_s(szFilename, 4, deviceInterfaceDetailData[0].DevicePath); + if (name != NULL) { + strcat_s(szFilename, 4, "\\"); + strcat_s(szFilename, 4, name); + } + SetupDiDestroyDeviceInfoList(deviceInfoSet); + return CreateFileA(szFilename, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_SUPPORTS_GHOSTING, NULL); + } + if (amDipswDebugLevel > 0) amiDebugLog("SetupDiGetClassDevs Error(%ld).", GetLastError()); + } + SetupDiDestroyDeviceInfoList(deviceInfoSet); + return INVALID_HANDLE_VALUE; +} + +void amDipswExit(void); +void amDipswGetDriverVerision(void); +void amDipswInit(void); +void amDipswModifyByte(void); +void amDipswModifyByteEx(void); +void amDipswModifyByteInternal(void); +void amDipswModifyByteInternalEx(void); +void amDipswMxsmbusStatusCheck(void); +void amDipswReadByte(void); +void amDipswReadByteInternal(void); +void amDipswReadByteInternalEx(void); +void amDipswRequestGetDipsw(void); +void amDipswRequestGetPushsw(void); +void amDipswRequestReadByte(void); +void amDipswRequestSetJvsIoctl(void); +void amDipswRequestSetLed(void); +void amDipswResponse(void); +void amDipswResponseInternalEx(void); +void amDipswWriteByte(void); +void amDipswWriteByteInternal(void); +void amDipswWriteByteInternalEx(void); diff --git a/src/micetools/lib/am/amDipsw.h b/src/micetools/lib/am/amDipsw.h index 611df61..d2d03cc 100644 --- a/src/micetools/lib/am/amDipsw.h +++ b/src/micetools/lib/am/amDipsw.h @@ -1,5 +1,24 @@ -void amDipswCreateDeviceFile(void); -void amDipswCreateMutex(void); +#pragma once + +#include + +#include "../_am.h" + +AM_LIB_H_HEADER(amDipsw, AM_DIPSW) + +typedef struct AM_DIPSW { + BOOL m_Init; + HANDLE m_Mutex; + HANDLE m_Handle; + BYTE m_Addr; + // + OVERLAPPED m_Overlapped; + PSID m_Sid; +} AM_DIPSW; + +int amDipswCreateMutex(AM_DIPSW *this); +HANDLE amDipswCreateDeviceFile(GUID *guid, DWORD memberIndex, char *name); + void amDipswExit(void); void amDipswGetDriverVerision(void); void amDipswInit(void); diff --git a/src/micetools/lib/am/amDongle.h b/src/micetools/lib/am/amDongle.h index 60503a9..64470fd 100644 --- a/src/micetools/lib/am/amDongle.h +++ b/src/micetools/lib/am/amDongle.h @@ -5,12 +5,12 @@ #include "../_am.h" #include "../libpcp/pcpa.h" -typedef struct _AM_DONGLE_DS_CHALLENGE { +typedef struct AM_DONGLE_DS_CHALLENGE { byte challenge[7]; byte pages[4][20]; } AM_DONGLE_DS_CHALLENGE; -typedef struct _AM_DONGLE_SSD_CHALLENGE { +typedef struct AM_DONGLE_SSD_CHALLENGE { byte challenge[16]; byte response[16]; } AM_DONGLE_SSD_CHALLENGE; @@ -25,7 +25,7 @@ typedef enum { AM_DONGLE_SEQ_DONE = 8, } AM_DONGLE_SEQ; -typedef struct _AM_DONGLE { +typedef struct AM_DONGLE { BOOL m_init; BOOL done_init; BOOL available; diff --git a/src/micetools/lib/am/amEeprom.h b/src/micetools/lib/am/amEeprom.h index 84e2d3f..8391677 100644 --- a/src/micetools/lib/am/amEeprom.h +++ b/src/micetools/lib/am/amEeprom.h @@ -26,7 +26,7 @@ typedef struct { int WriteTimeout; } AM_EEPROM_TIMEOUT; -typedef struct _AM_EEPROM { +typedef struct AM_EEPROM { BOOL m_init; AM_EEPROM_TIMEOUT m_timeout; HANDLE m_mutex; diff --git a/src/micetools/lib/am/amInstall.h b/src/micetools/lib/am/amInstall.h index 559fd48..808938b 100644 --- a/src/micetools/lib/am/amInstall.h +++ b/src/micetools/lib/am/amInstall.h @@ -144,7 +144,7 @@ typedef enum { AM_INSTALL_REQUEST_18 = 18, } AM_INSTALL_REQUEST; -typedef struct _AM_INSTALL { +typedef struct AM_INSTALL { BOOL m_init; AM_INSTALL_SEQ m_nextSeq; AM_INSTALL_REQUEST m_requestCode; diff --git a/src/micetools/lib/am/amNetwork.h b/src/micetools/lib/am/amNetwork.h index 87b7f7a..f23c2bc 100644 --- a/src/micetools/lib/am/amNetwork.h +++ b/src/micetools/lib/am/amNetwork.h @@ -13,3 +13,4 @@ void amNetworkResponseCheck(void); void amNetworkSendAndRecvEx(void); void amNetworkSendRequest(void); void amNetworkSetCommandModifyProperty(void); +void amNetworkPcpAddCommandInterface(void); \ No newline at end of file diff --git a/src/micetools/lib/am/amOemstring.h b/src/micetools/lib/am/amOemstring.h index 0a04288..78eca42 100644 --- a/src/micetools/lib/am/amOemstring.h +++ b/src/micetools/lib/am/amOemstring.h @@ -14,7 +14,7 @@ typedef struct { DWORD m_elementCount; } AM_COLUMBA_REQUEST; -typedef struct _AM_OEMSTRING { +typedef struct AM_OEMSTRING { BOOL m_loaded; CHAR m_biosVersion[32]; CHAR m_biosDate[11]; diff --git a/src/micetools/lib/am/amPlatform.c b/src/micetools/lib/am/amPlatform.c index 41320d6..56ab2db 100644 --- a/src/micetools/lib/am/amPlatform.c +++ b/src/micetools/lib/am/amPlatform.c @@ -158,12 +158,12 @@ AM_PLATFORM_STATUS amPlatformGetPlatformId(AM_PLATFORM_PLATFORM_ID *platformId) strncpy_s(amPlatform.m_platformId.strPlatformId, sizeof amPlatform.m_platformId.strPlatformId, oemstringPlatform, 0xffffffff); } else if (amOemstringGetManufacturer(oemstringManufacturer) == AM_OEMSTRING_STATUS_OK) { - if (strcmp(oemstringManufacturer, "NEC") == 0) { + if (strcmp(oemstringManufacturer, MANUFACTURER_RE) == 0) { strncpy_s(amPlatform.m_platformId.strPlatformId, sizeof amPlatform.m_platformId.strPlatformId, PLATFORM_RINGEDGE, 0xffffffff); - } else if (strcmp(oemstringManufacturer, "Supermicro") == 0 || - strcmp(oemstringManufacturer, "Advantech") == 0) { + } else if (strcmp(oemstringManufacturer, MANUFACTURER_RW_1) == 0 || + strcmp(oemstringManufacturer, MANUFACTURER_RW_2) == 0) { strncpy_s(amPlatform.m_platformId.strPlatformId, sizeof amPlatform.m_platformId.strPlatformId, PLATFORM_RINGWIDE, 0xffffffff); @@ -198,9 +198,9 @@ AM_PLATFORM_STATUS amPlatformGetBoardType(AM_PLATFORM_BOARD_TYPE *boardType) { } if (strcmp(platformId.strPlatformId, PLATFORM_RINGWIDE) == 0) { - if (strcmp(oemstringManufacturer, "Supermicro") == 0) { + if (strcmp(oemstringManufacturer, MANUFACTURER_RW_1) == 0) { *boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RW_SPEC_1; - } else if (strcmp(oemstringManufacturer, "Advantech") == 0) { + } else if (strcmp(oemstringManufacturer, MANUFACTURER_RW_2) == 0) { *boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RW_SPEC_2; } else { *boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_UNKNOWN; @@ -211,7 +211,7 @@ AM_PLATFORM_STATUS amPlatformGetBoardType(AM_PLATFORM_BOARD_TYPE *boardType) { } if (strcmp(platformId.strPlatformId, PLATFORM_RINGEDGE) == 0) { - if (strcmp(oemstringManufacturer, "NEC") == 0) { + if (strcmp(oemstringManufacturer, MANUFACTURER_RE) == 0) { ZeroMemory(oemstring4, sizeof oemstring4); if (amOemstringGetOemstring(oemstring4, 4) != AM_OEMSTRING_STATUS_OK) { diff --git a/src/micetools/lib/am/amPlatform.h b/src/micetools/lib/am/amPlatform.h index 7afa9a0..ddcac21 100644 --- a/src/micetools/lib/am/amPlatform.h +++ b/src/micetools/lib/am/amPlatform.h @@ -10,6 +10,10 @@ AM_LIB_H_HEADER(amPlatform, AM_PLATFORM) #define PLATFORM_RINGEDGE "AAL" #define PLATFORM_RINGEDGE2 "AAL2" // Also AAS in places +#define MANUFACTURER_RE "NEC" +#define MANUFACTURER_RW_1 "Supermicro" +#define MANUFACTURER_RW_2 "Advantech" + typedef struct { char strPlatformId[4]; } AM_PLATFORM_PLATFORM_ID; @@ -22,7 +26,7 @@ typedef enum { AM_PLATFORM_BOARD_TYPE_UNKNOWN = 4, } AM_PLATFORM_BOARD_TYPE; -typedef struct _AM_PLATFORM { +typedef struct AM_PLATFORM { BOOL m_boardTypeCached; AM_PLATFORM_BOARD_TYPE m_boardType; BOOL m_platformIdCached; diff --git a/src/micetools/lib/am/amSerialId.h b/src/micetools/lib/am/amSerialId.h index bcb243e..ff78406 100644 --- a/src/micetools/lib/am/amSerialId.h +++ b/src/micetools/lib/am/amSerialId.h @@ -6,7 +6,7 @@ AM_LIB_H_HEADER(amSerialId, AM_SERIAL_ID) -typedef struct _AM_SERIAL_ID { +typedef struct AM_SERIAL_ID { unsigned char Rsv00; } AM_SERIAL_ID; diff --git a/src/micetools/lib/am/amSram.h b/src/micetools/lib/am/amSram.h index 7b6e6a3..17dcded 100644 --- a/src/micetools/lib/am/amSram.h +++ b/src/micetools/lib/am/amSram.h @@ -6,7 +6,7 @@ AM_LIB_H_HEADER(amSram, AM_SRAM) -typedef struct _AM_SRAM { +typedef struct AM_SRAM { DWORD m_init; HANDLE m_handle; LARGE_INTEGER m_size; diff --git a/src/micetools/lib/am/meson.build b/src/micetools/lib/am/meson.build index 99c1b68..aed63d7 100644 --- a/src/micetools/lib/am/meson.build +++ b/src/micetools/lib/am/meson.build @@ -68,3 +68,13 @@ amInstall = static_library( libpcp, ], ) + +amCmos = static_library( + 'amCmos', + sources: [ + 'amCmos.c', + ], + link_with: [ + amiDebug, + ], +) diff --git a/src/micetools/lib/ami/amiCrc.h b/src/micetools/lib/ami/amiCrc.h index b48d98d..8adb591 100644 --- a/src/micetools/lib/ami/amiCrc.h +++ b/src/micetools/lib/ami/amiCrc.h @@ -6,7 +6,7 @@ AM_LIB_H_HEADER(amiCrc, AMI_CRC) -typedef struct _AMI_CRC { +typedef struct AMI_CRC { uint32_t m_init; uint32_t m_table[256]; } AMI_CRC; diff --git a/src/micetools/lib/ami/amiDebug.h b/src/micetools/lib/ami/amiDebug.h index c76bc6c..8ff41e2 100644 --- a/src/micetools/lib/ami/amiDebug.h +++ b/src/micetools/lib/ami/amiDebug.h @@ -6,7 +6,7 @@ #include "../_am.h" -typedef struct _AM_DEBUG { +typedef struct AM_DEBUG { unsigned char Rsv00; } AM_DEBUG; AM_LIB_H_HEADER(amiDebug, AM_DEBUG) diff --git a/src/micetools/lib/ami/amiTimer.h b/src/micetools/lib/ami/amiTimer.h index 3e1000f..9fe672c 100644 --- a/src/micetools/lib/ami/amiTimer.h +++ b/src/micetools/lib/ami/amiTimer.h @@ -6,7 +6,7 @@ AM_LIB_H_HEADER(amiTimer, AMI_TIMER) -typedef struct _AMI_TIMER { +typedef struct AMI_TIMER { unsigned char Rsv00; } AMI_TIMER; diff --git a/src/micetools/lib/mice/blowfish.c b/src/micetools/lib/mice/blowfish.c new file mode 100644 index 0000000..3d95851 --- /dev/null +++ b/src/micetools/lib/mice/blowfish.c @@ -0,0 +1,233 @@ +#include "blowfish.h" + +static DWORD INIT_BLOWFISH_P[18] = { + 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, + 0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, + 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B, +}; +static DWORD INIT_BLOWFISH_S[4][256] = { + { + + 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, + 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, + 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, + 0xC25A59B5, 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, + 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, + 0x55605C60, 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, + 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, + 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677, + 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, + 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, + 0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, + 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, + 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, 0x66CA593E, + 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, + 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, + 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, + 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, + 0x196A2463, 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C, + 0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3, 0xC0CBA857, + 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279, + 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8, 0x3C7516DF, 0xFD616B15, 0x2F501EC8, + 0xAD0552AB, 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, + 0x1A87562E, 0xDF1769DB, 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, + 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B, + 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, + 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4, 0x95DBDA4D, 0xAE909198, + 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, + 0xF2122B64, 0x8888B812, 0x900DF01C, 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, + 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, + 0xCE89E299, 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, 0x165FA266, 0x80957705, + 0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF, 0xEBCDAF0C, + 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF, + 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA, 0x78C14389, 0xD95A537F, 0x207D5BA2, + 0x02E5B9C5, 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, + 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, + 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664, + 0x53B02D5D, 0xA99F8FA1, 0x8BA4799, 0x6E85076A, + }, + { + 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, + 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1, 0x193602A5, 0x75094C29, + 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, + 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1, 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, + 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, + 0xAA500737, 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D, + 0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD, 0xD19113F9, + 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7, + 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41, 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, + 0x183EB331, 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, + 0x5679B072, 0xBCAF89AF, 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, + 0x2E6B7124, 0x501ADDE6, 0x9F84CD87, 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C, + 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908, 0xDD433B37, + 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD, 0x71DFF89E, 0x10314E55, + 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509, 0xF28FE6ED, + 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E, 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, + 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F, 0x803E89D6, 0x5266C825, 0x2E4CC978, + 0x9C10B36A, 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D, + 0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66, 0xE3BC4595, + 0xA67BC883, 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802, + 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84, 0x1521B628, 0x29076170, 0xECDD4775, + 0x619F1510, 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF, 0xB5735C90, 0x4C70A239, + 0xD59E9E0B, 0xCBAADE14, 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, + 0x19BDF0CA, 0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7, + 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77, 0x11ED935F, + 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99, 0x57F584A5, 0x1B227263, + 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, + 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73, 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, + 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, + 0x41CD2105, 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, 0xCF62A1F2, 0x5B8D2646, + 0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285, 0x095BBF00, + 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061, + 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB, 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, + 0xCE77326E, 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, + 0x5A04ABFC, 0x800BCADC, 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, + 0x105588CD, 0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20, + 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7, + }, + { + 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7, 0xBCF46B2E, + 0xD4A20068, 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF, 0x1E39F62E, 0x97244546, + 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, + 0x03BD9785, 0x7FAC6DD0, 0x31CB8504, 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, + 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, + 0x27A18DEE, 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC, + 0xCE78A399, 0x406B2A42, 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B, 0x1DC9FAF7, + 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB, + 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527, 0x55533A3A, 0x20838D87, 0xFE6BA9B7, + 0xD096954B, 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, + 0x5EF47E1C, 0x9029317C, 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, + 0xE4C66D22, 0x48C1133F, 0xC70F86DC, 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17, + 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60, 0xDFF8E8A3, + 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115, 0x6B2395E0, 0x333E92E1, + 0x3B240B62, 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728, 0xD0127845, + 0x95B794FD, 0x647D0862, 0xE7CCF5F0, 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, + 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, + 0xDB6E6B0D, 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3, + 0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3, 0xBB132F88, + 0x515BAD24, 0x7B9479BF, 0x763BD6EB, 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D, + 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C, 0x6A124237, 0xB79251E7, 0x06A1BBE6, + 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9, 0x44421659, 0x0A121386, + 0xD90CEC6E, 0xD5ABEA2A, 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, + 0xF0F7C086, 0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC, + 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, 0x77A057BE, 0xBDE8AE24, 0x55464299, + 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2, 0x5366F9C3, 0xC8B38E74, + 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2, 0x466E598E, + 0x20B45770, 0x8CD55591, 0xC902DE4C, 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, + 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, + 0x1D6EFE10, 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, 0xDCB7DA83, 0x573906FE, + 0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027, 0x9AF88C27, + 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62, + 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634, 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, + 0xCE591D76, 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, + 0x1AC15BB4, 0xD39EB8FC, 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, + 0xB161E6F8, 0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837, + 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0, + }, + { + 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742, 0xD3822740, + 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B, 0xB78C1B6B, 0x21A19045, + 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8, 0x530FF8EE, + 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6, 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, + 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, + 0x9CF2D0A4, 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1, + 0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59, 0x80E4A915, + 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51, + 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28, 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, + 0x5A88F54C, 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, + 0xF8D56629, 0x79132E28, 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, + 0x88F46DBA, 0x03A16125, 0x0564F0BD, 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A, + 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5, 0x03563482, + 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F, 0x4DE81751, 0x3830DC8E, + 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32, 0xA8B6E37E, + 0xC3293D46, 0x48DE5369, 0x6413E680, 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, + 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, + 0x6BB4E3BB, 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB, + 0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370, 0x740E0D8D, + 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84, + 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048, 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, + 0x277227F8, 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, + 0x2F32C9B7, 0xA01FBAC9, 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, + 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F, + 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, + 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1, 0xB6C1075E, 0xE3056A0C, + 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964, 0x9F1F9532, + 0xE0D392DF, 0xD3A0342B, 0x8971F21E, 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, + 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, + 0xCD3E7E6F, 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, 0xF523F357, 0xA6327623, + 0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC, 0xDE966292, + 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A, + 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6, 0x71126905, 0xB2040222, 0xB6CBCF7C, + 0xCD769C2B, 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, + 0x77AFA1C5, 0x20756060, 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, + 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F, + 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6, + + } +}; +static DWORD BLOWFISH_P[18]; +static DWORD BLOWFISH_S[4][256]; + +static inline DWORD _BlowfishF(DWORD x) { + DWORD h = BLOWFISH_S[0][x >> 24] + BLOWFISH_S[1][x >> 16 & 0xff]; + return (h ^ BLOWFISH_S[2][x >> 8 & 0xff]) + BLOWFISH_S[3][x & 0xff]; +} + +static inline void swap(LPDWORD x, LPDWORD y) { + DWORD tmp = *x; + *x = *y; + *y = tmp; +} + +void BlowfishEncrypt(LPDWORD lpLeft, LPDWORD lpRight) { + for (short r = 0; r < 16; r++) { + *lpLeft ^= BLOWFISH_P[r]; + *lpRight ^= _BlowfishF(*lpLeft); + swap(lpLeft, lpRight); + } + swap(lpLeft, lpRight); + *lpRight ^= BLOWFISH_P[16]; + *lpLeft ^= BLOWFISH_P[17]; +} + +void BlowfishDecrypt(LPDWORD lpLeft, LPDWORD lpRight) { + for (short r = 17; r > 1; r--) { + *lpLeft ^= BLOWFISH_P[r]; + *lpRight ^= _BlowfishF(*lpLeft); + swap(lpLeft, lpRight); + } + swap(lpLeft, lpRight); + *lpRight ^= BLOWFISH_P[1]; + *lpLeft ^= BLOWFISH_P[0]; +} + +void BlowfishSetKey(LPBYTE lpKey, DWORD nKeyLen) { + memcpy(BLOWFISH_P, INIT_BLOWFISH_P, sizeof BLOWFISH_P); + memcpy(BLOWFISH_S, INIT_BLOWFISH_S, sizeof BLOWFISH_S); + + // Initialise P-box + DWORD k; + for (short i = 0, p = 0; i < 18; i++) { + k = 0; + for (short j = 0; j < 4; j++) { + k = (k << 8) | lpKey[p]; + p = (p + 1) % nKeyLen; + } + BLOWFISH_P[i] ^= k; + } + + // Key expansion + DWORD l = 0, r = 0; + for (short i = 0; i < 18; i += 2) { + BlowfishEncrypt(&l, &r); + BLOWFISH_P[i] = l; + BLOWFISH_P[i + 1] = r; + } + for (short i = 0; i < 4; i++) { + for (short j = 0; j < 256; j += 2) { + BlowfishEncrypt(&l, &r); + BLOWFISH_S[i][j] = l; + BLOWFISH_S[i][j + 1] = r; + } + } +} diff --git a/src/micetools/lib/mice/blowfish.h b/src/micetools/lib/mice/blowfish.h new file mode 100644 index 0000000..380b516 --- /dev/null +++ b/src/micetools/lib/mice/blowfish.h @@ -0,0 +1,5 @@ +#include + +void BlowfishEncrypt(LPDWORD lpLeft, LPDWORD lpRight); +void BlowfishDecrypt(LPDWORD lpLeft, LPDWORD lpRight); +void BlowfishSetKey(LPBYTE lpKey, DWORD nKeyLen); diff --git a/src/micetools/lib/mice/config.def b/src/micetools/lib/mice/config.def index 742afe3..591e9fd 100644 --- a/src/micetools/lib/mice/config.def +++ b/src/micetools/lib/mice/config.def @@ -114,6 +114,13 @@ CFG_str(devices, com7, "", "") CFG_str(devices, com8, "", "") ENDSECTION(devices) +SECTION(aime, "Aime cards used when a TN32MSEC reader is attached\nSpecify either an access code or FeliCa ID") +CFG_str(aime, player1_card, "", "") +CFG_str(aime, player1_cardfile, "aime1.txt", "") +CFG_str(aime, player2_card, "", "") +CFG_str(aime, player2_cardfile, "aime2.txt", "") +ENDSECTION(aime) + #undef CFG_str #undef CFG_int #undef CFG_bool diff --git a/src/micetools/lib/mice/des.c b/src/micetools/lib/mice/des.c new file mode 100644 index 0000000..428ae48 --- /dev/null +++ b/src/micetools/lib/mice/des.c @@ -0,0 +1,179 @@ +#include +#include + +#include "des.h" + +static BYTE IP[] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, 62, 54, 46, 38, 30, 22, + 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, + 27, 19, 11, 3, 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7, +}; +static BYTE PI[] = { + 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, 38, 6, 46, 14, 54, 22, + 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, + 51, 19, 59, 27, 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25, +}; +static BYTE E[] = { + 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1, +}; +static BYTE P[] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25, +}; + +static BYTE SBOX[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, + 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, + 3, 10, 5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13, + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, + 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, + 9, 3, 2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9, + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, + 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, + 5, 10, 14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12, + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, + 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, + 5, 2, 8, 4, 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14, + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, + 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, + 6, 3, 0, 14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3, + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, + 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, + 1, 13, 11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13, + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, + 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, + 0, 5, 9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12, + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, + 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, + 15, 3, 5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11, + }, +}; +static BYTE PC1[] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4, +}; +static BYTE PC2[] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32, +}; +static BYTE ITERATION_SHIFT[] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; + +#define DesModeDecrypt 0 +#define DesModeEncrypt 1 + +DWORD64 MiceDesCrypt(DWORD64 nData, DWORD64 nKey, BYTE mode) { + nData = _byteswap_uint64(nData); + nKey = _byteswap_uint64(nKey); + DWORD64 init_perm_res = 0; + for (int i = 0; i < 64; i++) { + init_perm_res <<= 1; + init_perm_res |= (nData >> (64 - IP[i])) & 1; + } + + DWORD L = (DWORD)(init_perm_res >> 32) & 0xffffffff; + DWORD R = (DWORD)init_perm_res & 0xffffffff; + + DWORD64 permuted_choice_1 = 0; + for (int i = 0; i < 56; i++) { + permuted_choice_1 <<= 1; + permuted_choice_1 |= (nKey >> (64 - PC1[i])) & 1; + } + + DWORD C = (DWORD)((permuted_choice_1 >> 28) & 0x0fffffff); + DWORD D = (DWORD)(permuted_choice_1 & 0x0fffffff); + + DWORD64 sub_key[16] = { 0 }; + for (int i = 0; i < 16; i++) { + for (int j = 0; j < ITERATION_SHIFT[i]; j++) { + C = 0x0fffffff & (C << 1) | 1 & (C >> 27); + D = 0x0fffffff & (D << 1) | 1 & (D >> 27); + } + + DWORD64 permuted_choice_2 = (((DWORD64)C) << 28) | (DWORD64)D; + + sub_key[i] = 0; + + for (int j = 0; j < 48; j++) { + sub_key[i] <<= 1; + sub_key[i] |= (permuted_choice_2 >> (56 - PC2[j])) & 1; + } + } + + for (int i = 0; i < 16; i++) { + DWORD64 s_input = 0; + + for (int j = 0; j < 48; j++) { + s_input <<= 1; + s_input |= (DWORD64)((R >> (32 - E[j])) & 1); + } + + s_input ^= sub_key[mode == DesModeDecrypt ? 15 - i : i]; + DWORD s_output = 0; + for (int j = 0; j < 8; j++) { + BYTE row = (BYTE)((s_input & (0x0000840000000000 >> (6 * j))) >> (42 - 6 * j)); + row = (row >> 4) | row & 0x01; + BYTE column = (BYTE)((s_input & (0x0000780000000000 >> (6 * j))) >> (43 - 6 * j)); + + s_output <<= 4; + s_output |= (DWORD)(SBOX[j][16 * row + column] & 0x0f); + } + + DWORD f_function_res = 0; + for (int j = 0; j < 32; j++) { + f_function_res <<= 1; + f_function_res |= (s_output >> (32 - P[j])) & 1; + } + DWORD temp = R; + R = L ^ f_function_res; + L = temp; + } + + DWORD64 pre = (((DWORD64)R) << 32) | (DWORD64)L; + DWORD64 result = 0; + for (int i = 0; i < 64; i++) { + result <<= 1; + result |= (pre >> (64 - PI[i])) & 1; + } + return _byteswap_uint64(result); +} +DWORD64 MiceDesEncrypt(DWORD64 nData, DWORD64 nKey) { + return MiceDesCrypt(nData, nKey, DesModeEncrypt); +} +DWORD64 MiceDesDecrypt(DWORD64 nData, DWORD64 nKey) { + return MiceDesCrypt(nData, nKey, DesModeDecrypt); +} + +DWORD64 Mice3Des_3K(DWORD64 nData, DWORD64 lpKeys[3]) { + nData = MiceDesEncrypt(nData, lpKeys[0]); + nData = MiceDesDecrypt(nData, lpKeys[1]); + return MiceDesEncrypt(nData, lpKeys[2]); +} +DWORD64 Mice3Des_2K(DWORD64 nData, DWORD64 lpKeys[2]) { + nData = MiceDesEncrypt(nData, lpKeys[0]); + nData = MiceDesDecrypt(nData, lpKeys[1]); + return MiceDesEncrypt(nData, lpKeys[0]); +} +DWORD64 Mice3Des_1K(DWORD64 nData, DWORD64 nKey) { + nData = MiceDesEncrypt(nData, nKey); + nData = MiceDesDecrypt(nData, nKey); + return MiceDesEncrypt(nData, nKey); +} diff --git a/src/micetools/lib/mice/des.h b/src/micetools/lib/mice/des.h new file mode 100644 index 0000000..e4bb7a3 --- /dev/null +++ b/src/micetools/lib/mice/des.h @@ -0,0 +1,7 @@ +#include + +DWORD64 MiceDesEncrypt(DWORD64 nData, DWORD64 nKey); +DWORD64 MiceDesDecrypt(DWORD64 nData, DWORD64 nKey); +DWORD64 Mice3Des_3K(DWORD64 nData, DWORD64 lpKeys[3]); +DWORD64 Mice3Des_2K(DWORD64 nData, DWORD64 lpKeys[2]); +DWORD64 Mice3Des_1K(DWORD64 nData, DWORD64 nKey); diff --git a/src/micetools/lib/mice/exe.c b/src/micetools/lib/mice/exe.c index d104d56..a2d873b 100644 --- a/src/micetools/lib/mice/exe.c +++ b/src/micetools/lib/mice/exe.c @@ -11,7 +11,7 @@ bool inject_debug_wait(HANDLE process) { do { Sleep(1000); if (FAILED(CheckRemoteDebuggerPresent(process, &present))) { - log_error(plfBoot, "Fatal: CheckRemoteDebuggerPresent failed: %d", GetLastError()); + log_error(plfBoot, "CheckRemoteDebuggerPresent failed: %d", GetLastError()); return false; } } while (!present); @@ -24,33 +24,33 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument, DWORD* result LPVOID arg_addr = VirtualAllocEx(process, NULL, nchars + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (arg_addr == NULL) { - log_error(plfProcesses, "Fatal: VirtualAllocEx failed: %d", GetLastError()); + log_error(plfProcesses, "VirtualAllocEx failed: %d", GetLastError()); return false; } if (FAILED(WriteProcessMemory(process, arg_addr, argument, nchars + 1, NULL))) { - log_error(plfProcesses, "Fatal: WriteProcessMemory failed: %d", GetLastError()); + log_error(plfProcesses, "WriteProcessMemory failed: %d", GetLastError()); return false; } HANDLE remote_thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)function, arg_addr, 0, NULL); if (remote_thread == INVALID_HANDLE_VALUE) { - log_error(plfProcesses, "Fatal: CreateRemoteThread failed: %d", GetLastError()); + log_error(plfProcesses, "CreateRemoteThread failed: %d", GetLastError()); return false; } if (WaitForSingleObject(remote_thread, INFINITE) != WAIT_OBJECT_0) { - log_error(plfProcesses, "Fatal: WaitForSingleObject failed: %d", GetLastError()); + log_error(plfProcesses, "WaitForSingleObject failed: %d", GetLastError()); return false; } if (FAILED(GetExitCodeThread(remote_thread, result))) { - log_error(plfProcesses, "Fatal: GetExitCodeThread failed: %d", GetLastError()); + log_error(plfProcesses, "GetExitCodeThread failed: %d", GetLastError()); return false; } if (*result == 0) { - log_error(plfProcesses, "Fatal: GetExitCodeThread failed: result == 0"); + log_error(plfProcesses, "GetExitCodeThread failed: result == 0"); return false; } @@ -59,13 +59,13 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument, DWORD* result bool inject_dll(HANDLE process, LPCSTR inject) { HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); if (kernel32 == NULL) { - log_error(plfProcesses, "Fatal: GetModuleHandleA failed: %d", GetLastError()); + log_error(plfProcesses, "GetModuleHandleA failed: %d", GetLastError()); return false; } LPVOID addr_LoadLibraryA = (LPVOID)GetProcAddress(kernel32, "LoadLibraryA"); if (addr_LoadLibraryA == NULL) { - log_error(plfProcesses, "Fatal: GetProcAddress failed: %d", GetLastError()); + log_error(plfProcesses, "GetProcAddress failed: %d", GetLastError()); return false; } @@ -90,14 +90,14 @@ BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BO // Does the exe we're starting exist? found = SearchPathA(NULL, path, NULL, 0, NULL, NULL); if (found == 0) { - log_error(plfProcesses, "Fatal: Cannot start %s: not found", path); + log_error(plfProcesses, "Cannot start %s: not found", path); goto abort; } if (inject != NULL) { // Does the DLL we want to inject exist? found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL); if (found == 0) { - log_error(plfProcesses, "Fatal: Cannot inject %s: not found", inject); + log_error(plfProcesses, "Cannot inject %s: not found", inject); goto abort; } } @@ -106,7 +106,7 @@ BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BO flags |= CREATE_SUSPENDED; if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, flags, NULL, NULL, &startupInfo, &processInformation)) { - log_error(plfProcesses, "Fatal: CreateProcessA(%s, %s) failed: %d", path, cmdline, + log_error(plfProcesses, "CreateProcessA(%s, %s) failed: %d", path, cmdline, GetLastError()); goto abort; } @@ -140,7 +140,7 @@ BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BO // Injection completed, let the program continue execution if (FAILED(ResumeThread(processInformation.hThread))) { - log_error(plfProcesses, "Fatal: ResumeThread failed: %d", GetLastError()); + log_error(plfProcesses, "ResumeThread failed: %d", GetLastError()); goto abort; } @@ -153,14 +153,14 @@ BOOL start_and_inject(HANDLE hJob, LPCSTR path, LPSTR cmdline, LPCSTR inject, BO abort: if (processInformation.hProcess && processInformation.hProcess != INVALID_HANDLE_VALUE) { if (!CloseHandle(processInformation.hThread) && GetLastError() != ERROR_INVALID_HANDLE) - log_error(plfProcesses, "Fatal: CloseHandle(hProcess) failed: %d", GetLastError()); + log_error(plfProcesses, "CloseHandle(hProcess) failed: %d", GetLastError()); if (!TerminateProcess(processInformation.hProcess, 1)) - log_error(plfProcesses, "Fatal: TerminateProcess failed: %d", GetLastError()); + log_error(plfProcesses, "TerminateProcess failed: %d", GetLastError()); } if (processInformation.hThread && processInformation.hThread != INVALID_HANDLE_VALUE) { if (!CloseHandle(processInformation.hThread) && GetLastError() != ERROR_INVALID_HANDLE) - log_error(plfProcesses, "Fatal: CloseHandle(hThread) failed: %d", GetLastError()); + log_error(plfProcesses, "CloseHandle(hThread) failed: %d", GetLastError()); } return FALSE; diff --git a/src/micetools/lib/mice/ioctl.h b/src/micetools/lib/mice/ioctl.h index c6830a9..5716f19 100644 --- a/src/micetools/lib/mice/ioctl.h +++ b/src/micetools/lib/mice/ioctl.h @@ -85,6 +85,13 @@ #define IOCTL_MXPARALLEL_READ_FLAGS \ (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) +// amCmosReadByteInRearpart +#define IOCTL_MXCMOS_READ \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) +// amCmosWriteByteInRearpart +#define IOCTL_MXCMOS_WRITE \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) + // CrackProof #define IOCTL_CRACKPROOF_10 CTL_CODE(FILE_DEVICE_HTSYS, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_CRACKPROOF_11 CTL_CODE(FILE_DEVICE_HTSYS, 0x811, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/src/micetools/lib/mice/kcf.h b/src/micetools/lib/mice/kcf.h index f9d4cbc..b61e198 100644 --- a/src/micetools/lib/mice/kcf.h +++ b/src/micetools/lib/mice/kcf.h @@ -5,7 +5,7 @@ #include "../../segastructs.h" #pragma pack(push, 1) -typedef struct _AM_KCF { +typedef struct AM_KCF { AM_APPBOOT m_Header; BYTE m_AppData[216]; BYTE m_Seed[16]; diff --git a/src/micetools/lib/mice/meson.build b/src/micetools/lib/mice/meson.build index 738da92..9b9748a 100644 --- a/src/micetools/lib/mice/meson.build +++ b/src/micetools/lib/mice/meson.build @@ -8,6 +8,10 @@ mice_lib = static_library( 'config.c', 'kcf.c', 'micefs.c', + 'des.c', + 'blowfish.c', + 'solitaire.c', + 'spad.c', ], link_with: [ inih.get_variable('lib_inih'), diff --git a/src/micetools/lib/mice/micefs.c b/src/micetools/lib/mice/micefs.c index b1c6b76..88a78be 100644 --- a/src/micetools/lib/mice/micefs.c +++ b/src/micetools/lib/mice/micefs.c @@ -118,6 +118,8 @@ BOOL MiceFSAddDevLayers(VOID) { BOOL success = TRUE; for (int i = 0; i < 26; i++) { + if (i == 2) continue; // TODO: DON'T SKIP C + szMountPoint[0] = 'A' + (char)i; szMountPoint[1] = ':'; szMountPoint[2] = '\\'; @@ -134,7 +136,7 @@ BOOL MiceFSAddRingedgeLayers(BOOL bIsOsupdate) { // Windows file systems success &= MiceFSAddLayer(RING_MOUNT_OS, "mount/os"); - success &= MiceFSAddLayer(RING_MOUNT_EXTEND, "mount/extend"); + // success &= MiceFSAddLayer(RING_MOUNT_EXTEND, "mount/extend"); success &= MiceFSAddLayer(RING_MOUNT_RECOVERY, "mount/os_recovery"); // TrueCrypt Volumes @@ -145,8 +147,8 @@ BOOL MiceFSAddRingedgeLayers(BOOL bIsOsupdate) { success &= MiceFSAddLayer(RING_MOUNT_OS_UPDATE, "mount/os_update"); success &= MiceFSAddLayer(RING_MOUNT_OS_DEFAULT_DRVIERS, "mount/os_default_drivers"); } else { - success &= MiceFSAddLayer(RING_MOUNT_EXTEND_VOL, "mount/extend/extend"); - success &= MiceFSAddLayer(RING_MOUNT_EXTEND2_VOL, "mount/extend/extend2"); + // success &= MiceFSAddLayer(RING_MOUNT_EXTEND_VOL, "mount/extend/extend"); + // success &= MiceFSAddLayer(RING_MOUNT_EXTEND2_VOL, "mount/extend/extend2"); } // geminifs diff --git a/src/micetools/lib/mice/solitaire.c b/src/micetools/lib/mice/solitaire.c new file mode 100644 index 0000000..23eb1aa --- /dev/null +++ b/src/micetools/lib/mice/solitaire.c @@ -0,0 +1,143 @@ +#include "solitaire.h" + +#include + +#define DECK_SIZE 22 +#define JOKER_A 21 +#define JOKER_B 22 + +typedef struct { + char m_Deck[DECK_SIZE]; +} DECK, *PDECK; + +static DECK SOL_INIT_DECK = { + .m_Deck = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }, +}; + +#define char2num(c) ((c) - '0' + 1) +static inline char num2char(char num) { + while (num < 1) num = num + 10; + return (num - 1) % 10 + '0'; +} + +static void SolMoveCard(PDECK lpDeck, char card) { + int p = 0; + + for (int i = 0; i < DECK_SIZE; i++) { + if (lpDeck->m_Deck[i] == card) { + p = i; + break; + } + } + + if (p < DECK_SIZE - 1) { + lpDeck->m_Deck[p] = lpDeck->m_Deck[p + 1]; + lpDeck->m_Deck[p + 1] = card; + } else { + for (int i = DECK_SIZE - 1; i > 1; i--) lpDeck->m_Deck[i] = lpDeck->m_Deck[i - 1]; + lpDeck->m_Deck[1] = card; + } +} + +static void SolCutDeck(PDECK lpDeck, char point) { + DECK tmp; + + memcpy(tmp.m_Deck, &lpDeck->m_Deck[point], DECK_SIZE - point - 1); + memcpy(&tmp.m_Deck[DECK_SIZE - point - 1], lpDeck->m_Deck, point); + memcpy(lpDeck->m_Deck, tmp.m_Deck, DECK_SIZE - 1); +} + +static void SolSwapOutsideJoker(PDECK lpDeck) { + int j1 = -1; + int j2 = -1; + DECK tmp; + + for (int i = 0; i < DECK_SIZE; i++) { + if (lpDeck->m_Deck[i] == JOKER_A || lpDeck->m_Deck[i] == JOKER_B) { + if (j1 == -1) { + j1 = i; + } else { + j2 = i; + } + } + } + + if (0 < DECK_SIZE - j2 - 1) memcpy(tmp.m_Deck, &lpDeck->m_Deck[j2 + 1], DECK_SIZE - j2 - 1); + tmp.m_Deck[DECK_SIZE - j2 - 1] = lpDeck->m_Deck[j1]; + if (0 < j2 - j1 - 1) memcpy(&tmp.m_Deck[DECK_SIZE - j2], &lpDeck->m_Deck[j1 + 1], j2 - j1 - 1); + tmp.m_Deck[DECK_SIZE - j1 - 1] = lpDeck->m_Deck[j2]; + if (0 < j1) memcpy(&tmp.m_Deck[DECK_SIZE - j1], lpDeck->m_Deck, j1); + memcpy(lpDeck->m_Deck, tmp.m_Deck, DECK_SIZE); +} + +static void SolCutByBottomCard(PDECK lpDeck) { + char p = lpDeck->m_Deck[DECK_SIZE - 1]; + if (p == JOKER_B) p = JOKER_A; + SolCutDeck(lpDeck, p); +} + +static char SolGetTopCardNum(PDECK lpDeck) { + char p = lpDeck->m_Deck[0]; + if (p == JOKER_B) p = JOKER_A; + return lpDeck->m_Deck[p]; +} + +static void SolDeckHash(PDECK lpDeck) { + char p; + + do { + SolMoveCard(lpDeck, JOKER_A); + SolMoveCard(lpDeck, JOKER_B); + SolMoveCard(lpDeck, JOKER_B); + SolSwapOutsideJoker(lpDeck); + SolCutByBottomCard(lpDeck); + + p = SolGetTopCardNum(lpDeck); + } while (p == JOKER_A || p == JOKER_B); +} + +static void SolCreateDeck(PDECK lpDeck, const char *key) { + memcpy_s(lpDeck, sizeof *lpDeck, &SOL_INIT_DECK, sizeof SOL_INIT_DECK); + int p = 0; + while (key[p] != '\0') { + SolDeckHash(lpDeck); + char c = char2num(key[p]); + SolCutDeck(lpDeck, c); + p++; + } +} + +void SolitaireCipherEncode(const char *szKey, const char *szSrc, char *szDst) { + DECK deck; + SolCreateDeck(&deck, szKey); + + int i = 0; + while (szSrc[i] != '\0') { + SolDeckHash(&deck); + char p = SolGetTopCardNum(&deck); + szDst[i] = num2char(char2num(szSrc[i]) + p); + i++; + } + szDst[i] = '\0'; +} + +void SolitaireCipherDecode(const char *szKey, const char *szSrc, char *szDst) { + DECK deck; + SolCreateDeck(&deck, szKey); + + int i = 0; + while (szSrc[i] != '\0') { + SolDeckHash(&deck); + char p = SolGetTopCardNum(&deck); + szDst[i] = num2char(char2num(szSrc[i]) - p); + i++; + } + szDst[i] = '\0'; +} + +void SolitaireCipher(int nMode, const char *szKey, const char *szSrc, char *szDst) { + if (nMode == 0) + SolitaireCipherEncode(szKey, szSrc, szDst); + else if (nMode == 1) + SolitaireCipherDecode(szKey, szSrc, szDst); +} diff --git a/src/micetools/lib/mice/solitaire.h b/src/micetools/lib/mice/solitaire.h new file mode 100644 index 0000000..34ea802 --- /dev/null +++ b/src/micetools/lib/mice/solitaire.h @@ -0,0 +1,3 @@ +void SolitaireCipherDecode(const char *szKey, const char *szSrc, char *szDst); +void SolitaireCipherEncode(const char *szKey, const char *szSrc, char *szDst); +void SolitaireCipher(int mode, const char *key, const char *src_str, char *dest_str); diff --git a/src/micetools/lib/mice/spad.c b/src/micetools/lib/mice/spad.c new file mode 100644 index 0000000..2b8b39f --- /dev/null +++ b/src/micetools/lib/mice/spad.c @@ -0,0 +1,224 @@ +#include "spad.h" + +#include + +#define HASH_ADD 5 + +BYTE SPAD0_SPN_TABLE[9][256] = { + { + 175, 168, 99, 169, 36, 192, 241, 190, 231, 179, 172, 22, 133, 185, 17, 111, 16, 49, + 50, 174, 177, 120, 35, 210, 162, 202, 249, 43, 69, 184, 60, 98, 26, 109, 130, 140, + 0, 217, 226, 122, 70, 25, 42, 204, 19, 167, 228, 183, 132, 155, 142, 255, 251, 139, + 3, 137, 48, 41, 211, 135, 1, 191, 53, 218, 89, 92, 205, 9, 127, 112, 65, 129, + 108, 95, 83, 194, 114, 212, 121, 72, 149, 180, 91, 57, 68, 157, 253, 81, 113, 246, + 215, 213, 45, 159, 237, 51, 234, 170, 90, 23, 106, 186, 189, 233, 156, 206, 77, 124, + 24, 59, 13, 238, 12, 128, 161, 10, 143, 181, 107, 247, 63, 209, 71, 37, 198, 54, + 232, 125, 123, 62, 243, 153, 117, 5, 28, 224, 207, 52, 187, 158, 235, 145, 173, 38, + 141, 199, 102, 8, 230, 88, 64, 20, 166, 197, 250, 18, 236, 196, 240, 33, 138, 134, + 214, 225, 6, 182, 96, 116, 46, 227, 254, 39, 47, 94, 244, 178, 104, 40, 86, 239, + 154, 97, 34, 163, 201, 11, 2, 150, 79, 219, 229, 144, 74, 76, 146, 203, 152, 105, + 208, 87, 100, 14, 55, 80, 171, 188, 222, 118, 7, 200, 61, 73, 252, 119, 148, 248, + 193, 151, 101, 58, 75, 131, 110, 115, 136, 30, 93, 4, 84, 103, 223, 21, 176, 195, + 147, 44, 56, 221, 245, 164, 85, 15, 78, 29, 160, 31, 32, 165, 220, 67, 242, 216, + 126, 82, 27, 66, + }, + { + 3, 75, 184, 151, 183, 143, 13, 113, 220, 73, 167, 144, 255, 160, 157, 248, 35, 95, + 32, 108, 17, 249, 105, 142, 239, 203, 240, 20, 223, 27, 122, 198, 54, 91, 197, 147, + 182, 40, 53, 178, 59, 209, 236, 243, 159, 128, 100, 37, 5, 207, 84, 175, 70, 63, + 150, 6, 229, 16, 251, 170, 222, 98, 65, 81, 89, 231, 41, 181, 77, 61, 242, 55, + 106, 232, 22, 139, 92, 168, 30, 87, 226, 9, 235, 50, 201, 46, 180, 241, 164, 118, + 211, 193, 165, 112, 96, 18, 177, 234, 102, 225, 74, 146, 161, 109, 58, 244, 213, 111, + 218, 216, 10, 88, 24, 99, 43, 163, 93, 103, 119, 107, 57, 195, 219, 76, 2, 186, + 206, 187, 85, 1, 23, 133, 39, 228, 48, 114, 200, 141, 252, 120, 25, 185, 67, 45, + 8, 155, 26, 217, 205, 38, 250, 130, 204, 127, 117, 121, 158, 101, 254, 237, 145, 199, + 49, 208, 82, 42, 72, 132, 116, 221, 125, 233, 174, 110, 51, 71, 214, 80, 12, 83, + 166, 189, 34, 172, 138, 4, 137, 66, 64, 179, 69, 90, 68, 230, 169, 29, 196, 129, + 227, 21, 31, 86, 135, 212, 62, 15, 149, 215, 224, 148, 171, 36, 104, 7, 162, 152, + 123, 238, 245, 176, 136, 192, 56, 156, 153, 94, 173, 210, 60, 44, 33, 202, 140, 126, + 28, 97, 194, 52, 124, 47, 11, 131, 154, 79, 190, 78, 188, 115, 19, 0, 246, 14, + 134, 191, 253, 247, + }, + { + 65, 7, 147, 138, 64, 255, 14, 47, 84, 252, 172, 212, 30, 176, 200, 137, 223, 0, + 100, 79, 243, 203, 44, 192, 143, 110, 23, 191, 149, 153, 42, 13, 81, 173, 75, 202, + 247, 105, 85, 56, 76, 198, 104, 195, 163, 31, 131, 62, 11, 112, 199, 178, 78, 207, + 254, 77, 253, 139, 180, 150, 206, 249, 241, 211, 67, 96, 174, 213, 179, 219, 74, 185, + 229, 234, 106, 72, 93, 167, 135, 218, 184, 6, 45, 148, 193, 102, 36, 38, 177, 154, + 37, 8, 92, 89, 166, 175, 39, 146, 136, 242, 237, 27, 28, 17, 210, 34, 22, 118, + 86, 103, 20, 159, 238, 95, 220, 91, 164, 70, 221, 16, 51, 41, 127, 90, 201, 151, + 132, 133, 66, 188, 171, 119, 60, 161, 194, 170, 55, 73, 97, 53, 156, 134, 25, 87, + 94, 230, 226, 160, 4, 109, 209, 168, 157, 236, 2, 189, 216, 71, 98, 26, 5, 125, + 1, 63, 24, 111, 117, 68, 228, 122, 246, 169, 232, 114, 244, 107, 251, 126, 235, 54, + 82, 222, 121, 35, 141, 231, 113, 99, 152, 108, 217, 233, 59, 19, 144, 3, 120, 116, + 32, 129, 186, 52, 50, 250, 123, 49, 214, 61, 48, 10, 227, 18, 142, 15, 29, 187, + 165, 115, 83, 130, 128, 181, 215, 225, 58, 43, 208, 224, 33, 190, 205, 21, 101, 182, + 239, 204, 145, 245, 12, 196, 46, 158, 88, 240, 197, 155, 57, 9, 162, 124, 69, 183, + 40, 140, 248, 80, + }, + { + 118, 205, 22, 127, 233, 107, 149, 58, 78, 187, 110, 204, 210, 179, 105, 169, 114, 175, + 199, 130, 56, 111, 188, 55, 166, 40, 54, 189, 195, 207, 133, 70, 10, 153, 99, 151, + 131, 86, 136, 161, 2, 100, 172, 121, 85, 101, 255, 194, 239, 122, 89, 43, 28, 224, + 140, 143, 90, 228, 180, 159, 252, 247, 69, 71, 74, 234, 192, 13, 235, 200, 120, 201, + 103, 3, 5, 49, 20, 222, 211, 115, 250, 31, 182, 80, 19, 4, 183, 123, 73, 26, + 249, 23, 77, 79, 134, 32, 193, 253, 160, 165, 72, 225, 60, 96, 242, 11, 48, 15, + 76, 238, 141, 109, 190, 142, 198, 246, 216, 8, 148, 27, 42, 181, 158, 162, 147, 245, + 34, 168, 52, 38, 167, 124, 236, 63, 14, 59, 178, 244, 41, 206, 46, 66, 129, 50, + 37, 95, 102, 219, 125, 215, 231, 45, 67, 106, 91, 25, 173, 62, 155, 197, 171, 132, + 196, 108, 51, 218, 251, 138, 17, 84, 254, 87, 75, 61, 126, 9, 163, 145, 64, 191, + 104, 229, 185, 243, 150, 248, 81, 202, 154, 176, 152, 174, 30, 156, 94, 232, 0, 57, + 18, 220, 12, 16, 139, 93, 214, 44, 39, 213, 97, 135, 83, 186, 35, 113, 47, 29, + 116, 137, 157, 221, 53, 21, 208, 68, 177, 203, 240, 98, 88, 164, 119, 227, 24, 212, + 230, 128, 209, 170, 144, 112, 1, 36, 241, 33, 217, 6, 117, 184, 65, 92, 146, 223, + 237, 7, 226, 82, + }, + { + 170, 148, 153, 116, 146, 214, 28, 70, 71, 121, 47, 86, 122, 247, 181, 10, 201, 6, + 215, 250, 64, 17, 165, 255, 31, 232, 0, 140, 221, 183, 66, 110, 53, 240, 190, 194, + 29, 202, 182, 142, 226, 68, 78, 159, 81, 129, 139, 76, 93, 89, 56, 211, 143, 37, + 179, 9, 49, 173, 11, 107, 14, 80, 187, 216, 150, 136, 222, 73, 234, 180, 74, 154, + 48, 109, 44, 15, 205, 246, 126, 79, 82, 217, 251, 40, 7, 99, 25, 164, 238, 1, + 248, 235, 210, 245, 61, 13, 145, 91, 103, 184, 87, 243, 43, 230, 104, 22, 123, 111, + 101, 195, 118, 227, 60, 46, 65, 62, 207, 84, 225, 23, 167, 69, 45, 90, 252, 198, + 130, 239, 203, 120, 172, 52, 186, 113, 39, 34, 242, 18, 63, 26, 36, 168, 193, 158, + 199, 24, 228, 95, 254, 108, 175, 200, 55, 197, 119, 189, 2, 41, 125, 253, 94, 131, + 233, 191, 42, 92, 115, 229, 218, 231, 236, 128, 106, 3, 88, 59, 33, 19, 209, 83, + 112, 147, 188, 161, 16, 244, 100, 133, 135, 176, 97, 177, 241, 67, 98, 196, 249, 162, + 174, 212, 4, 134, 223, 38, 208, 171, 54, 30, 75, 224, 96, 144, 204, 152, 149, 58, + 156, 155, 21, 27, 51, 141, 77, 35, 157, 132, 206, 178, 5, 166, 12, 185, 20, 72, + 213, 163, 117, 8, 124, 237, 127, 220, 137, 102, 169, 192, 57, 114, 32, 151, 138, 160, + 85, 105, 219, 50, + }, + { + 222, 90, 27, 105, 60, 66, 163, 81, 64, 56, 241, 23, 40, 28, 184, 172, 232, 153, + 69, 160, 18, 104, 206, 21, 201, 71, 109, 200, 70, 78, 30, 166, 17, 248, 62, 49, + 250, 230, 45, 253, 50, 20, 156, 1, 177, 237, 87, 113, 227, 48, 207, 14, 231, 204, + 55, 74, 120, 171, 29, 150, 234, 37, 133, 32, 73, 77, 117, 82, 238, 239, 175, 84, + 51, 249, 9, 158, 129, 225, 115, 42, 242, 61, 34, 19, 146, 139, 240, 192, 132, 13, + 168, 4, 220, 141, 187, 44, 148, 3, 245, 209, 208, 46, 93, 235, 94, 98, 111, 33, + 176, 145, 254, 203, 10, 236, 183, 47, 52, 36, 214, 233, 102, 130, 198, 25, 31, 217, + 193, 167, 246, 136, 2, 135, 7, 221, 216, 103, 197, 185, 41, 164, 194, 101, 211, 83, + 170, 59, 121, 224, 114, 215, 6, 26, 88, 147, 126, 12, 144, 110, 116, 15, 76, 11, + 228, 108, 67, 210, 65, 54, 189, 219, 53, 89, 95, 169, 159, 85, 128, 57, 142, 243, + 213, 229, 99, 195, 119, 162, 91, 123, 127, 174, 186, 161, 16, 223, 75, 43, 155, 22, + 188, 0, 199, 24, 251, 100, 255, 244, 247, 190, 5, 86, 205, 8, 79, 106, 154, 118, + 122, 181, 149, 202, 80, 125, 124, 107, 165, 196, 58, 138, 39, 218, 182, 97, 35, 134, + 112, 72, 151, 157, 252, 143, 92, 68, 178, 173, 131, 191, 38, 212, 179, 96, 152, 226, + 63, 140, 180, 137, + }, + { + 25, 46, 93, 122, 91, 124, 126, 57, 239, 139, 47, 204, 134, 27, 194, 140, 32, 251, + 89, 95, 33, 205, 159, 148, 167, 11, 186, 14, 71, 123, 165, 6, 183, 216, 201, 38, + 240, 157, 104, 242, 94, 18, 58, 101, 176, 92, 226, 34, 153, 130, 16, 245, 68, 80, + 116, 161, 249, 66, 168, 37, 77, 234, 8, 62, 150, 146, 196, 45, 162, 35, 52, 169, + 69, 107, 121, 127, 200, 76, 67, 103, 41, 4, 250, 181, 30, 5, 198, 180, 175, 29, + 187, 247, 48, 237, 236, 171, 64, 224, 152, 233, 75, 17, 135, 21, 24, 190, 238, 120, + 177, 2, 87, 144, 50, 142, 97, 203, 60, 230, 215, 117, 49, 185, 84, 54, 225, 221, + 108, 151, 98, 172, 65, 137, 156, 96, 246, 99, 188, 20, 125, 119, 213, 9, 149, 223, + 23, 74, 12, 43, 82, 56, 254, 182, 51, 164, 81, 115, 109, 79, 179, 191, 113, 235, + 105, 63, 19, 0, 28, 111, 155, 53, 202, 163, 42, 118, 141, 128, 1, 22, 3, 61, + 229, 131, 112, 143, 90, 88, 136, 243, 227, 15, 195, 7, 70, 255, 73, 253, 232, 206, + 133, 209, 220, 241, 184, 211, 110, 212, 160, 173, 114, 218, 231, 59, 132, 248, 210, 40, + 222, 193, 26, 100, 145, 10, 228, 197, 36, 106, 214, 83, 199, 129, 44, 192, 147, 217, + 13, 166, 219, 174, 207, 244, 85, 102, 31, 55, 252, 189, 72, 170, 78, 86, 39, 158, + 208, 138, 178, 154, + }, + { + 84, 217, 66, 80, 184, 116, 171, 50, 166, 36, 72, 111, 240, 126, 215, 48, 180, 109, + 6, 162, 136, 214, 89, 57, 76, 44, 175, 110, 168, 43, 102, 92, 185, 28, 231, 83, + 25, 86, 138, 17, 216, 97, 95, 7, 3, 218, 181, 176, 8, 208, 39, 69, 0, 195, + 245, 177, 121, 107, 196, 91, 33, 226, 85, 61, 160, 254, 49, 154, 54, 15, 236, 203, + 187, 114, 41, 26, 249, 118, 135, 106, 174, 201, 82, 183, 235, 123, 243, 5, 148, 4, + 1, 198, 161, 244, 55, 227, 251, 193, 79, 186, 158, 128, 40, 47, 90, 246, 145, 62, + 207, 65, 173, 190, 182, 51, 155, 252, 206, 192, 104, 238, 63, 81, 191, 78, 210, 73, + 169, 247, 143, 134, 200, 42, 103, 56, 228, 77, 199, 46, 99, 127, 239, 223, 151, 170, + 93, 98, 11, 112, 209, 230, 19, 153, 146, 248, 211, 18, 60, 100, 132, 167, 10, 178, + 156, 234, 27, 204, 94, 67, 30, 205, 141, 147, 225, 113, 59, 242, 163, 35, 233, 194, + 221, 152, 139, 115, 150, 87, 34, 53, 14, 165, 172, 12, 212, 159, 9, 219, 58, 22, + 96, 229, 137, 133, 45, 119, 29, 129, 32, 197, 122, 237, 202, 20, 131, 250, 31, 38, + 24, 71, 157, 2, 224, 88, 16, 253, 37, 117, 188, 70, 222, 164, 21, 64, 120, 52, + 74, 23, 213, 13, 105, 101, 220, 75, 124, 149, 232, 142, 255, 125, 144, 140, 130, 108, + 179, 189, 68, 241, + }, + { + 195, 11, 184, 21, 0, 164, 61, 217, 253, 22, 233, 8, 32, 230, 141, 196, 71, 56, + 37, 147, 94, 170, 236, 42, 16, 110, 88, 149, 38, 83, 4, 30, 146, 158, 47, 139, + 189, 10, 105, 169, 59, 65, 240, 208, 218, 106, 161, 113, 19, 99, 239, 144, 148, 176, + 235, 231, 220, 115, 185, 120, 122, 228, 199, 109, 127, 163, 172, 133, 80, 243, 145, 234, + 54, 250, 155, 142, 247, 174, 193, 67, 28, 192, 202, 143, 78, 162, 49, 18, 116, 44, + 157, 241, 173, 63, 104, 187, 53, 154, 124, 3, 251, 9, 35, 39, 212, 77, 23, 222, + 76, 238, 118, 156, 160, 225, 117, 219, 91, 17, 167, 33, 175, 2, 66, 75, 131, 211, + 206, 159, 205, 204, 48, 43, 82, 34, 203, 89, 125, 20, 249, 177, 112, 84, 224, 129, + 90, 29, 14, 74, 244, 132, 237, 150, 26, 215, 201, 130, 137, 45, 135, 51, 226, 92, + 81, 58, 27, 246, 229, 216, 50, 13, 95, 114, 136, 214, 183, 198, 221, 31, 128, 55, + 100, 181, 123, 223, 255, 210, 64, 252, 96, 5, 182, 102, 97, 200, 40, 153, 188, 165, + 52, 25, 248, 254, 36, 72, 209, 12, 85, 98, 107, 134, 179, 186, 138, 46, 111, 166, + 103, 101, 1, 232, 24, 62, 126, 119, 41, 140, 242, 7, 108, 168, 121, 79, 68, 70, + 6, 194, 171, 15, 180, 178, 190, 152, 213, 73, 227, 245, 207, 151, 93, 191, 87, 60, + 57, 197, 69, 86, + } +}; +BYTE SPAD0_SPN_INV_TABLE[9][256]; +BOOL _SPAD0_SPN_INV_TABLE_INIT = FALSE; + +void Spad0Encrypt(LPBYTE spad0_encrypted, const BYTE* spad0) { + if (spad0_encrypted != spad0) + memcpy(spad0_encrypted, spad0, 16); + + int hashLoopCount = (spad0[15] >> 4) + 7; + int hashTableNo = spad0[15] & 0x7; + + // Primary encryption loop + for (int i = 0; i < hashLoopCount; i++) { + for (int j = 0; j < 15; j++) + spad0_encrypted[j] = SPAD0_SPN_TABLE[hashTableNo][spad0_encrypted[j]]; + + // Rotate the first 15 bytes left by 5 bits + BYTE prior = spad0_encrypted[0]; + for (int j = 14; j >= 0; j--) { + BYTE new = ((spad0_encrypted[j] & 0x7) << 5) | (prior >> 3); + prior = spad0_encrypted[j]; + spad0_encrypted[j] = new; + } + + hashTableNo = (hashTableNo + HASH_ADD) & 0x7; + } + + // Apply the outer encryption layer to mask the parameters + for (int i = 0; i < 16; i++) spad0_encrypted[i] = SPAD0_SPN_TABLE[8][spad0_encrypted[i]]; +} + +void Spad0Decrypt(LPBYTE spad0, const BYTE* spad0_encrypted) { + // Build the inversed table + if (!_SPAD0_SPN_INV_TABLE_INIT) { + for (int i = 0; i < 9; i++) + for (int j = 0; j < 256; j++) SPAD0_SPN_INV_TABLE[i][SPAD0_SPN_TABLE[i][j]] = (BYTE)j; + _SPAD0_SPN_INV_TABLE_INIT = TRUE; + } + + for (int i = 0; i < 16; i++) spad0[i] = SPAD0_SPN_INV_TABLE[8][spad0_encrypted[i]]; + + // Removing the outer layer gives us access to the cipher parameters + int hashLoopCount = ((spad0[15] >> 4) & 0xf) + 7; + int hashTableNo = spad0[15] & 0x7; + + // We're doing this in reverse, so start from the final value + for (int i = 0; i < hashLoopCount - 1; i++) hashTableNo += HASH_ADD; + hashTableNo &= 0x7; + + // Primary decryption loop + for (int i = 0; i < hashLoopCount; i++) { + // Rotate the first 15 bytes right by 5 bits + BYTE prior = spad0[14]; + for (int j = 0; j < 15; j++) { + BYTE new = (spad0[j] >> 5) | ((prior & 0x1f) << 3); + prior = spad0[j]; + spad0[j] = new; + } + + for (int j = 0; j < 15; j++) spad0[j] = SPAD0_SPN_INV_TABLE[hashTableNo][spad0[j]]; + + hashTableNo = ((hashTableNo | 8) - HASH_ADD) & 0x7; + } +} diff --git a/src/micetools/lib/mice/spad.h b/src/micetools/lib/mice/spad.h new file mode 100644 index 0000000..9ffe6bb --- /dev/null +++ b/src/micetools/lib/mice/spad.h @@ -0,0 +1,4 @@ +#include + +void Spad0Encrypt(LPBYTE spad0_encrypted, const BYTE* spad0); +void Spad0Decrypt(LPBYTE spad0, const BYTE* spad0_encrypted); diff --git a/src/micetools/micekeychip/callbacks/billing.c b/src/micetools/micekeychip/callbacks/billing.c index 2270b4d..5cdeb56 100644 --- a/src/micetools/micekeychip/callbacks/billing.c +++ b/src/micetools/micekeychip/callbacks/billing.c @@ -78,28 +78,33 @@ byte CA_CERTIFICATION[CA_CERT_BUF_MAX]; int CA_CERT_LEN = 0; void mxkPcpPbCaCertification(pcpa_t* stream, void* data) { if (CA_CERT_LEN == 0) { - FILE* fCert; - fopen_s(&fCert, Config.billing_cacert, "r"); - if (fCert == NULL) - CA_CERT_LEN = -1; - else { - fseek(fCert, 0, SEEK_END); - CA_CERT_LEN = ftell(fCert); + HANDLE hFile = CreateFileA(Config.billing_cacert, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if (hFile == INVALID_HANDLE_VALUE) { + CA_CERT_LEN = 0; + } else { + CA_CERT_LEN = GetFileSize(hFile, NULL); if (CA_CERT_LEN > CA_CERT_BUF_MAX) CA_CERT_LEN = CA_CERT_BUF_MAX; - rewind(fCert); - fread(CA_CERTIFICATION, CA_CERT_LEN, 1, fCert); - fclose(fCert); + DWORD numberOfBytesRead; + int read_remaining = CA_CERT_LEN; + int read_offset = 0; + while (read_remaining) { + printf("Remaining: %d, offset: %d\n", read_remaining, read_offset); + if (!ReadFile(hFile, CA_CERTIFICATION, CA_CERT_BUF_MAX, &numberOfBytesRead, NULL)) { + printf("Read failed: %d", GetLastError()); + } + // int nread = fread(&CA_CERTIFICATION[read_offset], 1, read_remaining, fCert); + read_remaining -= numberOfBytesRead; + read_offset += numberOfBytesRead; + } + printf("Read done %d\n", CA_CERT_LEN); + + CloseHandle(hFile); } } - if (CA_CERT_LEN == -1) { - // TODO: Fix this maybe? - pcpaSetBinaryMode(stream, binary_mode_none); - pcpaSetSendPacket(stream, BIL_CACERT, "-1"); - return; - } - pcpaSetBinaryMode(stream, binary_mode_send); pcpaSetBeforeBinaryModeCallBackFunc(stream, mxkBinaryCallback, NULL); diff --git a/src/micetools/micekeychip/callbacks/tracedata.c b/src/micetools/micekeychip/callbacks/tracedata.c index a55a38e..f16f437 100644 --- a/src/micetools/micekeychip/callbacks/tracedata.c +++ b/src/micetools/micekeychip/callbacks/tracedata.c @@ -24,8 +24,19 @@ void mxkPcpTdPut(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, TRA_PUT, "0"); } void mxkPcpTdGet(pcpa_t* stream, void* data) { - // TODO: lol - pcpaSetSendPacket(stream, TRA_GET, ""); + char* sPut = pcpaGetCommand(stream, TRA_GET); + pcpaSetSendPacket(stream, TRA_GET, "0"); + if (sPut && strcmp(sPut, "?") == 0) { + pcpaAddSendPacket(stream, "address", "0"); + } else { + pcpaSetBinaryMode(stream, binary_mode_send); + pcpaSetBeforeBinaryModeCallBackFunc(stream, mxkBinaryCallback, NULL); + + BINARY_DATA_LEN = 0; + pcpaSetRecvBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN); + pcpaAddSendPacket(stream, "port", "40107"); + pcpaAddSendPacket(stream, "size", "0"); + } } void mxkPcpTdLogicalErase(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, TRA_LOGICALERASE, ""); diff --git a/src/micetools/segastructs.h b/src/micetools/segastructs.h index 1fde3d1..f6b85ad 100644 --- a/src/micetools/segastructs.h +++ b/src/micetools/segastructs.h @@ -3,7 +3,7 @@ #include #pragma pack(push, 1) -typedef struct _AM_APPBOOT { +typedef struct AM_APPBOOT { uint32_t m_Crc; uint32_t m_Format; char m_GameId[4]; @@ -16,13 +16,13 @@ typedef struct _AM_APPBOOT { uint32_t m_NetworkAddr; } AM_APPBOOT; -typedef struct _AM_APPBOOT_128 { +typedef struct AM_APPBOOT_128 { AM_APPBOOT m_Header; uint8_t Rsv18[88]; uint8_t m_Seed[16]; } AM_APPBOOT_128; -typedef struct _AM_APPBOOT_256 { +typedef struct AM_APPBOOT_256 { AM_APPBOOT m_Header; uint8_t Rsv18[216]; uint8_t m_Seed[16]; diff --git a/src/micetools/util/meson.build b/src/micetools/util/meson.build index 39db54a..9170011 100644 --- a/src/micetools/util/meson.build +++ b/src/micetools/util/meson.build @@ -11,6 +11,7 @@ executable( 'micedump/platform.c', 'micedump/sram.c', # 'micedump/superio.c', + 'micedump/cmos.c', ], link_with: [ mxklib, @@ -21,6 +22,7 @@ executable( amPlatform, amDongle, amSerialId, + amCmos, ], ) @@ -77,3 +79,15 @@ executable( amiDebug, ], ) +executable( + 'micereset', + win_subsystem: subsystem, + sources: [ + 'micereset.c', + ], + link_with: [ + amiTimer, + amEeprom, + amSram, + ], +) diff --git a/src/micetools/util/micedump/cmos.c b/src/micetools/util/micedump/cmos.c new file mode 100644 index 0000000..68b16c4 --- /dev/null +++ b/src/micetools/util/micedump/cmos.c @@ -0,0 +1,57 @@ +#include +#include + +/* + +Cmos: +00-01: 00 21 <- "00 21" = "Boot: USB, HDD", "10 20" = "Boot HDD,USB" +02-0F: 43 65 87 a9 0b 21 43 65 87 a9 3b 93 99 54 +10-19: 35 25 00 00 00 40 4f 40 50 08 +1A-1B: 1a 08 +1C-1D: 1a 08 <- USB flags(?). 08 = normal, 09 = disabled +1E-1F: 1a 0a +20-2F: 03 14 1d 12 28 00 00 00 00 07 00 00 00 00 00 08 +30-3F: 01 80 ce 10 14 00 8a 48 06 01 d4 ff ff 1f 04 00 +40-4B: 60 a0 9f 0b a0 29 47 15 7d 80 90 3f + 4C: 00 <- SEGA flags. 00 = None, 02 = Security freeze, 03 = Freeze + Certified + 4D: 9d + 4E: 00 <- 00 = Boot HDD first, 01 = Boot USB first + 4F: b4 +50-5F: 25 d6 e7 8f 7f 22 72 af b5 1a 00 8f 1c 3c c0 90 + 60: 00 + 61: 00 +62-6F: 06 37 50 8c 66 bd ac 38 7b 52 4a 04 4c dc +70-7F: 82 62 0d 2a 5d 1c 32 6e 05 af 44 c3 45 2e 08 96 + + +*/ + +#include "../lib/am/amCmos.h" + +AM_CMOS_CONFIG config = { + .index = { 0, 0, 0, 0 }, + .m_MbrCount = 0, +}; + +BOOL miceDumpCMOS() { + amCmosDebugLevel = 1; + + fprintf(stderr, "Dumping RTC CMOS using %s\n", amCmosVersion); + + AM_CMOS_STATUS err = amCmosInit(&config); + if (err != AM_CMOS_STATUS_OK) { + fprintf(stderr, "amCmosInit failed: %d\n", err); + amCmosExit(); + return FALSE; + } + + for (BYTE index = 0; index < 0x80; index++) { + BYTE data; + amCmosReadByteInRearpart(index, &data); + printf(" %02x", data); + } + puts(""); + + amCmosExit(); + return TRUE; +} diff --git a/src/micetools/util/micedump/kc_mxkeychip.c b/src/micetools/util/micedump/kc_mxkeychip.c index 90bd997..c551e23 100644 --- a/src/micetools/util/micedump/kc_mxkeychip.c +++ b/src/micetools/util/micedump/kc_mxkeychip.c @@ -53,7 +53,7 @@ AM_DONGLE_STATUS amlib_init_dongle(void) { return AM_DONGLE_STATUS_OK; } -void miceDumpKCMxkeychip(void) { +BOOL miceDumpKCMxkeychip(void) { amDongleDebugLevel = 1; fprintf(stderr, "Dumping dongle using %s\n", amDongleVersion); @@ -61,7 +61,7 @@ void miceDumpKCMxkeychip(void) { WSADATA wsaData; if (WSAStartup(2, &wsaData)) { puts("Failed to WSAStartup"); - return; + return FALSE; } AM_DONGLE_STATUS err; @@ -69,7 +69,7 @@ void miceDumpKCMxkeychip(void) { if (err != AM_DONGLE_STATUS_OK) { printf("Failed to init dongle:%d\n", err); amDongleExit(); - return; + return FALSE; } printf("Keychip ID: %s\n", amlibDongle.keychipId); @@ -108,4 +108,5 @@ void miceDumpKCMxkeychip(void) { puts(""); amDongleExit(); + return TRUE; } diff --git a/src/micetools/util/micedump/kc_pic.c b/src/micetools/util/micedump/kc_pic.c index 6145555..9609da6 100644 --- a/src/micetools/util/micedump/kc_pic.c +++ b/src/micetools/util/micedump/kc_pic.c @@ -5,14 +5,14 @@ #include "../lib/am/amSerialId.h" #include "../lib/mxk/mxk.h" -void miceDumpKCPIC() { +BOOL miceDumpKCPIC() { fprintf(stderr, "Dumping dongle using mxk\n"); MXK_STATUS status; status = mxkInit(); if (status != MXK_STATUS_OK) { amiDebugLog("Failed to mxkInit(): %d", status); - return; + return FALSE; } /** @@ -45,4 +45,6 @@ void miceDumpKCPIC() { char gameId[4]; mxkAbGameId(MXK_CACHE_USE, gameId, &err); printf(" Game ID: %.*s\n", 4, gameId); + + return TRUE; } diff --git a/src/micetools/util/micedump/main.c b/src/micetools/util/micedump/main.c index ba277c8..2f64a26 100644 --- a/src/micetools/util/micedump/main.c +++ b/src/micetools/util/micedump/main.c @@ -17,6 +17,8 @@ int main(int argc, char** argv) { miceDumpKCMxkeychip(); else if (strcmp(argv[i], "kcpic") == 0) miceDumpKCPIC(); + else if (strcmp(argv[i], "cmos") == 0) + miceDumpCMOS(); else printf("Unknown dump type: %s\n", argv[i]); } diff --git a/src/micetools/util/micedump/micedump.h b/src/micetools/util/micedump/micedump.h index dcd5a3d..8997115 100644 --- a/src/micetools/util/micedump/micedump.h +++ b/src/micetools/util/micedump/micedump.h @@ -1,8 +1,11 @@ -void miceDumpDMI(void); -void miceDumpEEPROM(void); -void miceDumpKCMxkeychip(void); -void miceDumpKCN2(void); -void miceDumpKCPIC(void); -void miceDumpPlatform(void); -void miceDumpSRAM(void); -void miceDumpSuperIO(void); +#include + +BOOL miceDumpDMI(void); +BOOL miceDumpEEPROM(void); +BOOL miceDumpKCMxkeychip(void); +BOOL miceDumpKCN2(void); +BOOL miceDumpKCPIC(void); +BOOL miceDumpPlatform(void); +BOOL miceDumpSRAM(void); +BOOL miceDumpSuperIO(void); +BOOL miceDumpCMOS(void); diff --git a/src/micetools/util/micedump/platform.c b/src/micetools/util/micedump/platform.c index a5b1b31..26eed2f 100644 --- a/src/micetools/util/micedump/platform.c +++ b/src/micetools/util/micedump/platform.c @@ -7,7 +7,7 @@ static const char* sBoardType[] = { "RingEdge", "RingWide (Spec 1)", "RingWide (Spec 2)", "RingEdge 2", "Unknown", }; -void miceDumpPlatform(void) { +BOOL miceDumpPlatform(void) { fprintf(stderr, "Dumping platform information using %s\n", amPlatformVersion); AM_PLATFORM_BOARD_TYPE boardType; @@ -17,4 +17,6 @@ void miceDumpPlatform(void) { printf("Board type: %s\n", sBoardType[boardType]); printf("Platform ID: %s\n", platformId.strPlatformId); + + return TRUE; } \ No newline at end of file diff --git a/src/micetools/util/micereset.c b/src/micetools/util/micereset.c new file mode 100644 index 0000000..104099d --- /dev/null +++ b/src/micetools/util/micereset.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "../lib/am/amEeprom.h" +#include "../lib/am/amSram.h" + +BOOL wipe_eeprom() { + if (amEepromInit(NULL) != AM_EEPROM_STATUS_OK) return FALSE; + + BYTE data[0x20]; + memset(data, 0xff, sizeof data); + + // Static = 0 and 32 + // Game data is 1000-1fff = block 128-255 + for (int i = 0; i < 256; i++) { + if (i == 0) continue; + if (i == 32) continue; + printf("Wiping EEPROM block %d\n", i); + amEepromWrite(i * 0x20, data, sizeof data); + } + + amEepromExit(); + return TRUE; +} +BOOL wipe_sram() { + if (amSramInit() != AM_SRAM_STATUS_OK) return FALSE; + + DWORD nbytes = amSram.m_size.LowPart; + + printf("Wiping %d bytes of SRAM\n", nbytes); + BYTE* buffer = malloc(nbytes); + ZeroMemory(buffer, nbytes); + amSramWrite(buffer, 0, nbytes); + free(buffer); + + amSramExit(); + return TRUE; +} + +// void wait_for_dip() { +// puts("Press Test or System to continue"); +// amDipswInit(); +// } + +int main(int argc, char** argv) { + wipe_eeprom(); + wipe_sram(); + return 0; +} diff --git a/src/micetools/util/storagecraft.c b/src/micetools/util/storagecraft.c index c8fb175..a633773 100644 --- a/src/micetools/util/storagecraft.c +++ b/src/micetools/util/storagecraft.c @@ -3,6 +3,53 @@ #include "../dll/hooks/drive/drive.h" +#define SECTOR_SIZE BLOCK_SIZE_HDD + +#define HEADS_PER_CYLINDER 255 +#define SECTORS_PER_TRACK 63 + +#define TRUECRYPT "\"C:\\Program Files (x86)\\TrueCrypt\\TrueCrypt.exe\"" +#define OSR_PASSWORD "nogamenolife" +#define OSR_MOUNTPOINT "R:" +#define OSR_FLAGS "/w /q /m ro" + +BYTE WINDOWS_MBR_BOOTSTRAP[MBR_BOOTSTRAP_SIZE] = { + 0x33, 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0xfb, 0x50, 0x07, 0x50, 0x1f, 0xfc, 0xbe, 0x1b, 0x7c, + 0xbf, 0x1b, 0x06, 0x50, 0x57, 0xb9, 0xe5, 0x01, 0xf3, 0xa4, 0xcb, 0xbd, 0xbe, 0x07, 0xb1, 0x04, + 0x38, 0x6e, 0x00, 0x7c, 0x09, 0x75, 0x13, 0x83, 0xc5, 0x10, 0xe2, 0xf4, 0xcd, 0x18, 0x8b, 0xf5, + 0x83, 0xc6, 0x10, 0x49, 0x74, 0x19, 0x38, 0x2c, 0x74, 0xf6, 0xa0, 0xb5, 0x07, 0xb4, 0x07, 0x8b, + 0xf0, 0xac, 0x3c, 0x00, 0x74, 0xfc, 0xbb, 0x07, 0x00, 0xb4, 0x0e, 0xcd, 0x10, 0xeb, 0xf2, 0x88, + 0x4e, 0x10, 0xe8, 0x46, 0x00, 0x73, 0x2a, 0xfe, 0x46, 0x10, 0x80, 0x7e, 0x04, 0x0b, 0x74, 0x0b, + 0x80, 0x7e, 0x04, 0x0c, 0x74, 0x05, 0xa0, 0xb6, 0x07, 0x75, 0xd2, 0x80, 0x46, 0x02, 0x06, 0x83, + 0x46, 0x08, 0x06, 0x83, 0x56, 0x0a, 0x00, 0xe8, 0x21, 0x00, 0x73, 0x05, 0xa0, 0xb6, 0x07, 0xeb, + 0xbc, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x74, 0x0b, 0x80, 0x7e, 0x10, 0x00, 0x74, 0xc8, 0xa0, + 0xb7, 0x07, 0xeb, 0xa9, 0x8b, 0xfc, 0x1e, 0x57, 0x8b, 0xf5, 0xcb, 0xbf, 0x05, 0x00, 0x8a, 0x56, + 0x00, 0xb4, 0x08, 0xcd, 0x13, 0x72, 0x23, 0x8a, 0xc1, 0x24, 0x3f, 0x98, 0x8a, 0xde, 0x8a, 0xfc, + 0x43, 0xf7, 0xe3, 0x8b, 0xd1, 0x86, 0xd6, 0xb1, 0x06, 0xd2, 0xee, 0x42, 0xf7, 0xe2, 0x39, 0x56, + 0x0a, 0x77, 0x23, 0x72, 0x05, 0x39, 0x46, 0x08, 0x73, 0x1c, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, + 0x8b, 0x4e, 0x02, 0x8b, 0x56, 0x00, 0xcd, 0x13, 0x73, 0x51, 0x4f, 0x74, 0x4e, 0x32, 0xe4, 0x8a, + 0x56, 0x00, 0xcd, 0x13, 0xeb, 0xe4, 0x8a, 0x56, 0x00, 0x60, 0xbb, 0xaa, 0x55, 0xb4, 0x41, 0xcd, + 0x13, 0x72, 0x36, 0x81, 0xfb, 0x55, 0xaa, 0x75, 0x30, 0xf6, 0xc1, 0x01, 0x74, 0x2b, 0x61, 0x60, + 0x6a, 0x00, 0x6a, 0x00, 0xff, 0x76, 0x0a, 0xff, 0x76, 0x08, 0x6a, 0x00, 0x68, 0x00, 0x7c, 0x6a, + 0x01, 0x6a, 0x10, 0xb4, 0x42, 0x8b, 0xf4, 0xcd, 0x13, 0x61, 0x61, 0x73, 0x0e, 0x4f, 0x74, 0x0b, + 0x32, 0xe4, 0x8a, 0x56, 0x00, 0xcd, 0x13, 0xeb, 0xd6, 0x61, 0xf9, 0xc3, 0x49, 0x6e, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x20, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x00, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, + 0x67, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, + 0x65, 0x6d, 0x00, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x44, 0x63, 0x46, 0xa4, 0x2b, 0xd1, 0x00, 0x00, +}; + +// Assumes a SECTOR_SIZE of 512 +#define _KiB(x) (DWORD)(x * 2) +#define _MiB(x) (DWORD)(x * 1024 * 2) +#define _GiB(x) (DWORD)(x * 1024 * 1024 * 2) +#define _GMKiB(g, m, k) (_GiB(g) + _MiB(m) + _KiB(k)) + physical_disk_t newSSD = { .m_SerialNumber = 0x00144DB0, @@ -10,27 +57,27 @@ physical_disk_t newSSD = { .m_BootPartition = 1, .m_HasSegaboot = TRUE, .m_BlockSize = BLOCK_SIZE_HDD, - .m_TotalSize = 64 * 1024 * 1024 * (1024 / BLOCK_SIZE_HDD), + .m_TotalSize = 0, // Force re-calculation .m_DiskType = DiskType_HardDisk, .m_IsFormatted = true, .m_Partitions = { // 1.5GB boot partition - { .m_Size = 0x300B85, .m_Filesystem = MBR_FS_NTFS }, + { .m_Size = _GMKiB(1, 513, 450.5), .m_Filesystem = MBR_FS_NTFS }, // 1.5GB OS recovery - { .m_Size = 0x300BC4, .m_Filesystem = MBR_FS_NTFS }, + { .m_Size = _GMKiB(1, 513, 482), .m_Filesystem = MBR_FS_NTFS }, }, .m_Extended = { - { 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update - { 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0 - { 0x403947, MBR_FS_FAT16, SPD_Patch1 }, // 2GB patch1 - { 0x48ed459, MBR_FS_NTFS, SPD_AppData }, // 40GB appdata - { 0x20014aa, MBR_FS_FAT16, SPD_Original0 }, // 16GB original0 + { _GMKiB(0, 517, 705.5), MBR_FS_FAT16, SPD_OS }, // 512MB OS update + { _GMKiB(0, 2055, 163.5), MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0 + { _GMKiB(0, 2055, 163.5), MBR_FS_FAT16, SPD_Patch1 }, // 2GB patch1 + { _GMKiB(36, 474, 556.5), MBR_FS_NTFS, SPD_AppData }, // 40GB appdata + { _GMKiB(16, 2, 597), MBR_FS_FAT16, SPD_Original0 }, // 16GB original0 { 0 }, // End of table }, }; -sbr_t SegaBootRecord0; -sbr_t SegaBootRecord1; +sbr_t SegaBootRecord0 = { 0 }; +sbr_t SegaBootRecord1 = { 0 }; sbr_slot_t* get_sbr_slot(spd_slot_t slot) { switch (slot) { case SPD_Original0: @@ -132,6 +179,8 @@ void init_pd(physical_disk_t* pConfig) { if (extendedPartNo) { pConfig->m_Partitions[extendedPartNo - 1].m_Size = currentLBA - extendedStart; } + + pConfig->m_TotalSize = currentLBA; } else { // Raw disks have just a single spanning volume pConfig->m_Partitions[0].m_PartitionNumber = 1; @@ -142,21 +191,47 @@ void init_pd(physical_disk_t* pConfig) { } } -BYTE writeBuffer[1024]; -void write_buffer(HANDLE hDisk, LONG nOffset, DWORD nBytes, physical_disk_t* pConfig) { - LARGE_INTEGER offset; - offset.QuadPart = nOffset * pConfig->m_BlockSize; - SetFilePointerEx(hDisk, offset, NULL, FILE_BEGIN); - DWORD nOut; - WriteFile(hDisk, writeBuffer, nBytes, &nOut, NULL); +inline void set_chs(BYTE* chs, WORD cylinder, BYTE head, BYTE sector) { + chs[0] = head; + chs[1] = ((sector & 0x3f) | ((cylinder & 0x300) >> 2)) & 0xff; + chs[2] = cylinder & 0xff; +} +inline void set_chs_from_lba(BYTE* chs, DWORD lba) { + WORD cylinder = (lba / (HEADS_PER_CYLINDER * SECTORS_PER_TRACK)) & 0xffff; + BYTE head = ((lba / SECTORS_PER_TRACK) % HEADS_PER_CYLINDER) & 0xff; + BYTE sector = ((lba % SECTORS_PER_TRACK) + 1) & 0xff; + set_chs(chs, cylinder, head, sector); +} +inline void fix_partition_chs(PMBR_PARTITION partition) { + set_chs_from_lba(partition->start_chs, partition->lba); + set_chs_from_lba(partition->end_chs, partition->lba + partition->sectors - 1); +} + +BYTE writeBuffer[1024]; +void write_buffer(HANDLE hDisk, DWORD nBlock, DWORD nBytes, physical_disk_t* pConfig) { + LARGE_INTEGER offset; + offset.HighPart = 0; + offset.LowPart = nBlock; + offset.QuadPart *= pConfig->m_BlockSize; + SetFilePointerEx(hDisk, offset, NULL, FILE_BEGIN); + printf("Performing write: %d@%08x%08x\n", nBytes, offset.HighPart, offset.LowPart); + DWORD nOut; + WriteFile(hDisk, writeBuffer, nBytes, &nOut, NULL); + if (nOut != nBytes) { + printf("WRITE FAILED!! %d\n", GetLastError()); + CloseHandle(hDisk); + exit(1); + } } -// TODO: Write start_chs lol void write_mbr(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig) { printf("Writing MBR at block %d\n", nOffset); - mbr_t* mbr = (mbr_t*)writeBuffer; + PMBR_HEADER mbr = (PMBR_HEADER)writeBuffer; memset(mbr, 0, sizeof *mbr); + memcpy_s(mbr->bootstrap_code, sizeof mbr->bootstrap_code, WINDOWS_MBR_BOOTSTRAP, + sizeof WINDOWS_MBR_BOOTSTRAP); + mbr->sig[0] = 0x55; mbr->sig[1] = 0xAA; @@ -168,14 +243,17 @@ void write_mbr(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig) { mbr->partitions[i].type = pConfig->m_Partitions[i].m_Filesystem; mbr->partitions[i].lba = pConfig->m_Partitions[i].m_PhysicalLBA; mbr->partitions[i].sectors = pConfig->m_Partitions[i].m_Size; + + fix_partition_chs(&(mbr->partitions[i])); } write_buffer(hDisk, nOffset, sizeof *mbr, pConfig); } void write_ext_header(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig, DWORD nPartition) { printf("Writing extended header at block %d\n", nOffset); + printf(" -> Part %d = %d\n", nPartition + 5, nOffset); - mbr_t* mbr = (mbr_t*)writeBuffer; + PMBR_HEADER mbr = (PMBR_HEADER)writeBuffer; memset(mbr, 0, sizeof *mbr); mbr->sig[0] = 0x55; @@ -183,23 +261,33 @@ void write_ext_header(HANDLE hDisk, LONG nOffset, physical_disk_t* pConfig, DWOR mbr->partitions[0].status = MBR_FLAG_NONE; mbr->partitions[0].type = pConfig->m_Extended[nPartition].m_Filesystem; - mbr->partitions[0].lba = EXT_HEADER_GAP; + mbr->partitions[0].lba = pConfig->m_Extended[nPartition].m_PhysicalLBA; mbr->partitions[0].sectors = pConfig->m_Extended[nPartition].m_Size; + fix_partition_chs(&(mbr->partitions[0])); + // Write the EBR value + mbr->partitions[0].lba = EXT_HEADER_GAP; if (pConfig->m_Extended[nPartition + 1].m_Size) { mbr->partitions[1].status = MBR_FLAG_NONE; - // ! mxinstaller expects to see CHS here, then uses the LBA values mbr->partitions[1].type = MBR_FS_EXT_CHS; + mbr->partitions[1].lba = pConfig->m_Extended[nPartition + 1].m_PhysicalLBA - EXT_HEADER_GAP; + mbr->partitions[1].sectors = pConfig->m_Extended[nPartition + 1].m_Size + EXT_HEADER_GAP; + + fix_partition_chs(&(mbr->partitions[1])); + // Write the EBR values mbr->partitions[1].lba = pConfig->m_Extended[nPartition + 1].m_PhysicalLBA - pConfig->m_Extended[0].m_PhysicalLBA; - mbr->partitions[1].sectors = pConfig->m_Extended[nPartition + 1].m_Size + EXT_HEADER_GAP; + + mbr->partitions[1].end_chs[0] = 0xFE; + mbr->partitions[1].end_chs[1] = 0xFF; + mbr->partitions[1].end_chs[2] = 0xFF; } write_buffer(hDisk, nOffset, sizeof *mbr, pConfig); } void write_pd(HANDLE hDisk, physical_disk_t* pConfig) { - puts("Force-allocating disk space"); + printf("Pre-allocating disk space (0x%x blocks)\n", pConfig->m_TotalSize); write_buffer(hDisk, pConfig->m_TotalSize - 1, pConfig->m_BlockSize, pConfig); // Write MBR headers @@ -209,10 +297,9 @@ void write_pd(HANDLE hDisk, physical_disk_t* pConfig) { write_ext_header(hDisk, headerLBA, pConfig, i); if (i == 0 && pConfig->m_HasSegaboot) { - puts("Writing segaboot"); - // SEGA Partition Description spd_t* spd = (spd_t*)writeBuffer; + ZeroMemory(spd, sizeof *spd); spd->version = SPD_VERSION; for (size_t j = 0; pConfig->m_Extended[j].m_Size; j++) { @@ -225,25 +312,159 @@ void write_pd(HANDLE hDisk, physical_disk_t* pConfig) { spd->crc = amiCrc32RCalc(sizeof *spd - 4, &(spd->version), 0); write_buffer(hDisk, headerLBA + SPD_OFFSET, sizeof *spd, pConfig); + // TODO: Actually populate the SBRs + // SEGA Boot Record 0 and 1. The two are a redundant copy of each other memcpy(writeBuffer, &SegaBootRecord0, sizeof SegaBootRecord0); write_buffer(hDisk, headerLBA + SBR0_OFFSET, sizeof SegaBootRecord0, pConfig); memcpy(writeBuffer, &SegaBootRecord1, sizeof SegaBootRecord1); write_buffer(hDisk, headerLBA + SBR1_OFFSET, sizeof SegaBootRecord1, pConfig); + + printf(" -> SEGA structures = %d+[1/2/3]\n", headerLBA); } } } +void print_bar(LONGLONG nCurrent, LONGLONG nMax) { + printf("["); + DWORD filled = ((float)nCurrent / (float)nMax) * 40; + int i = 0; + for (; i < filled; i++) printf("="); + for (; i < 40; i++) printf(" "); + printf("] %3.2f%%\r", (float)nCurrent / (float)nMax * 100); +} +void end_bar() { printf("[========================================] 100.00%%\n"); } + +BOOL mount_OSR(LPSTR lpOSRPath) { + char szTcCommand[1024]; + sprintf_s(szTcCommand, sizeof szTcCommand, "%s /p %s /v %s /l %s %s", TRUECRYPT, OSR_PASSWORD, + lpOSRPath, OSR_MOUNTPOINT, OSR_FLAGS); + + int dTcRet = system(szTcCommand); + if (dTcRet != 0) { + printf("Failed to mount OSR: %d\n", dTcRet); + printf("Command used was: %s\n", szTcCommand); + return FALSE; + } + return TRUE; +} +BOOL dismount_OSR() { + char szTcCommand[1024]; + sprintf_s(szTcCommand, sizeof szTcCommand, "%s /q /d %s", TRUECRYPT, OSR_MOUNTPOINT, OSR_FLAGS); + + int dTcRet = system(szTcCommand); + if (dTcRet != 0) { + printf("Failed to dismount OSR: %d\n", dTcRet); + printf("Command used was: %s\n", szTcCommand); + return FALSE; + } + return TRUE; +} + +void install_OSR(HANDLE hDisk, LPSTR lpOSRPath) { + if (!mount_OSR(lpOSRPath)) return; + + HANDLE hOSR = CreateFileA("\\\\.\\" OSR_MOUNTPOINT, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hOSR == INVALID_HANDLE_VALUE) { + printf("Failed to open OSR! %d\n", GetLastError()); + return; + } + + DISK_GEOMETRY dg; + DWORD nBytesReturned; + DeviceIoControl(hOSR, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof dg, &nBytesReturned, + NULL); + LONGLONG nBytes = + dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.QuadPart; + + SetFilePointer(hDisk, 63 * 512, NULL, FILE_BEGIN); + + puts("Installing Operating System"); + + BYTE block[4096]; + int print_tick = 0; + for (LONGLONG i = 0; nBytes;) { + DWORD nRead = sizeof block; + if (nRead > nBytes) nRead = (DWORD)nBytes; + + ReadFile(hOSR, block, nRead, &nRead, NULL); + if (nRead == 0) { + if (GetLastError() == ERROR_SUCCESS) break; + + printf("Failed to read OSR. Code: %d\n", GetLastError()); + goto end; + return; + } + + DWORD nWrote = 0; + WriteFile(hDisk, block, nRead, &nWrote, NULL); + if (nWrote != nRead) { + printf("Failed to write OSR to disk. Code: %d\n", GetLastError()); + goto end; + return; + } + + if (print_tick++ == 512) { + print_tick = 0; + print_bar(i, nBytes); + } + + i += nRead; + } + end_bar(); +end: + CloseHandle(hOSR); + dismount_OSR(); +} +void install_OSR_xcopy(LPSTR lpDiskPath, LPSTR lpOSRPath) { + if (!mount_OSR(lpOSRPath)) return; + + printf("Installing OS using xcopy %s -> %s\n", OSR_MOUNTPOINT, lpDiskPath); + + char szXcCommand[1024]; + sprintf_s(szXcCommand, sizeof szXcCommand, "xcopy %s %s /e /c /h /y /q", OSR_MOUNTPOINT, lpDiskPath); + + int dTcRet = system(szXcCommand); + if (dTcRet != 0) { + printf("Failed to xcopy OSR: %d\n", dTcRet); + printf("Command used was: %s\n", szXcCommand); + return FALSE; + } + return TRUE; + + dismount_OSR(); +} + int main(int argc, char* argv[]) { + amiCrc32RInit(); + init_pd(&newSSD); HANDLE hDisk = INVALID_HANDLE_VALUE; + SetLastError(0); - hDisk = CreateFileA("H:\\NewDiskImage.img", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + // hDisk = CreateFileA("H:\\NewDiskImage.img", GENERIC_READ | GENERIC_WRITE, + // FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, + // FILE_ATTRIBUTE_NORMAL, NULL); + hDisk = CreateFileA("\\\\.\\PHYSICALDRIVE4", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + + if (hDisk == INVALID_HANDLE_VALUE) { + printf("Failed to open disk! %d\n", GetLastError()); + return 1; + } write_pd(hDisk, &newSSD); + // install_OSR(hDisk, "H:\\Arcades\\RingOS\\RecoverOS\\0009\\Minint\\system32\\OSR"); + // install_OSR_xcopy(hDisk, "H:\\Arcades\\RingOS\\RecoverOS\\0009\\Minint\\system32\\OSR"); + puts("Please mount OS at W:"); + system("pause"); + install_OSR_xcopy("W:", "H:\\Arcades\\RingOS\\RecoverOS\\0009\\Minint\\system32\\OSR"); + + FlushFileBuffers(hDisk); + CloseHandle(hDisk); return 0; } diff --git a/src/patches/maimai_dump_.patch b/src/patches/maimai_dump_.patch index 5aa4f64..6030e41 100644 --- a/src/patches/maimai_dump_.patch +++ b/src/patches/maimai_dump_.patch @@ -19,3 +19,5 @@ *00c89320 : 00000000 > 01000000 # amBackupDebugLevel *00c88bb4 : 00000000 > 01000000 # amHwResetDebugLevel *00c830e8 : 00000000 > 01000000 # LOG_EN + +*00b93c30 : 680074007400700073003a002f002f006d0079002d00610069006d0065002e006e00650074002f00610069006d0065002f0069002f0072006500670069007300740071002e00680074006d006c003f00610063003d000000 > 680074007400700073003a002f002f006d006900630065006e00650074002e006300610074006700690072006c002e00610072006d0079002f00710072003f00610063003d00000000000000000000000000000000000000 # aime URL \ No newline at end of file