From 52a66a262317717010c0ba053f2bdfd96652d9b1 Mon Sep 17 00:00:00 2001 From: Bottersnike Date: Sat, 24 Dec 2022 03:04:04 +0000 Subject: [PATCH] ill advised broken commit --- .gitignore | 1 + Makefile | 10 +- meson.build | 23 +- src/meson.build | 1 + src/micetools/dll/comdevice.c | 14 +- src/micetools/dll/devices/aime_bd.c | 206 +++++- src/micetools/dll/devices/led_bd.c | 53 +- src/micetools/dll/devices/touch_bd.c | 17 +- src/micetools/dll/dllmain.c | 88 ++- src/micetools/dll/drivers/mx.h | 3 + src/micetools/dll/drivers/mxparallel.c | 444 ++++++++++++ src/micetools/dll/drivers/mxparallel.h | 61 ++ src/micetools/dll/drivers/mxsmbus.c | 714 ++++++++++++------- src/micetools/dll/drivers/mxsram.c | 1 - src/micetools/dll/drivers/mxsuperio.c | 608 ++++++++-------- src/micetools/dll/drivers/mxsuperio.h | 17 + src/micetools/dll/gui/gui.c | 132 ++++ src/micetools/dll/gui/meson.build | 3 + src/micetools/dll/hooks/_hooks.c | 24 +- src/micetools/dll/hooks/_hooks.h | 1 + src/micetools/dll/hooks/drive.c | 128 +++- src/micetools/dll/hooks/drive.h | 2 +- src/micetools/dll/hooks/files.c | 193 +++-- src/micetools/dll/hooks/files.h | 4 + src/micetools/dll/hooks/gui.c | 34 +- src/micetools/dll/hooks/gui.h | 17 +- src/micetools/dll/hooks/logging.c | 33 +- src/micetools/dll/hooks/logging.h | 13 +- src/micetools/dll/hooks/meson.build | 1 + src/micetools/dll/hooks/network.c | 14 +- src/micetools/dll/hooks/processes.c | 35 +- src/micetools/dll/hooks/processes.h | 15 +- src/micetools/dll/hooks/registry.c | 43 +- src/micetools/dll/hooks/registry.h | 14 + src/micetools/dll/hooks/system.c | 55 ++ src/micetools/dll/hooks/system.h | 5 + src/micetools/dll/meson.build | 9 +- src/micetools/dll/smbus.h | 144 +++- src/micetools/dll/util/hook.c | 12 +- src/micetools/dll/util/log.c | 88 ++- src/micetools/dll/util/log.h | 4 - src/micetools/launcher/locate.c | 7 +- src/micetools/launcher/main.c | 23 +- src/micetools/lib/am/amEeprom.c | 10 +- src/micetools/lib/am/amtimer.h | 8 +- src/micetools/lib/libpcp/pcpp.c | 2 +- src/micetools/lib/meson.build | 1 + src/micetools/lib/mice/config.c | 113 +++ src/micetools/lib/mice/config.def | 65 ++ src/micetools/lib/mice/config.h | 19 + src/micetools/lib/mice/crc.c | 2 + src/micetools/lib/mice/exe.c | 48 +- src/micetools/lib/mice/exe.h | 3 +- src/micetools/lib/mice/ioctl.h | 60 +- src/micetools/lib/mice/meson.build | 2 + src/micetools/lib/mice/mice.h | 1 + src/micetools/lib/mice/patch.c | 38 +- src/micetools/lib/mice/patch.h | 5 +- src/micetools/lib/mxk/meson.build | 13 + src/micetools/lib/mxk/mxk.c | 133 ++++ src/micetools/lib/mxk/mxk.h | 107 +++ src/micetools/lib/mxk/mxkCrypt.c | 158 ++++ src/micetools/lib/mxk/mxkPacket.c | 70 ++ src/micetools/lib/mxk/mxkTransport.c | 187 +++++ src/micetools/miceboot/mxstartup.c | 2 +- src/micetools/micekeychip/mxk.h | 2 +- src/micetools/micepatch/main.c | 2 +- src/micetools/util/meson.build | 11 +- src/micetools/util/micedump.c | 281 +++++++- src/micetools/util/micetinker.c | 36 +- src/micetools/util/proxy.c | 141 ++++ src/patches/InitialD8_GLW_RE_SBZZ.patch.json | 121 ++++ src/patches/mxmaster.patch.json | 9 + src/patches/patches.json | 21 + subprojects/cimgui_dep | 1 + 75 files changed, 4045 insertions(+), 941 deletions(-) create mode 100644 src/micetools/dll/drivers/mxparallel.h create mode 100644 src/micetools/dll/drivers/mxsuperio.h create mode 100644 src/micetools/dll/gui/gui.c create mode 100644 src/micetools/dll/gui/meson.build create mode 100644 src/micetools/dll/hooks/system.c create mode 100644 src/micetools/dll/hooks/system.h create mode 100644 src/micetools/lib/mice/config.c create mode 100644 src/micetools/lib/mice/config.def create mode 100644 src/micetools/lib/mice/config.h create mode 100644 src/micetools/lib/mxk/meson.build create mode 100644 src/micetools/lib/mxk/mxk.c create mode 100644 src/micetools/lib/mxk/mxk.h create mode 100644 src/micetools/lib/mxk/mxkCrypt.c create mode 100644 src/micetools/lib/mxk/mxkPacket.c create mode 100644 src/micetools/lib/mxk/mxkTransport.c create mode 100644 src/micetools/util/proxy.c create mode 100644 src/patches/InitialD8_GLW_RE_SBZZ.patch.json create mode 100644 src/patches/mxmaster.patch.json create mode 160000 subprojects/cimgui_dep diff --git a/.gitignore b/.gitignore index 9927fcc..fdfecc3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ build/ builddir/ srcdir/ .vscode/ +openssl-1.0.1/ diff --git a/Makefile b/Makefile index b8e3faa..20095ec 100644 --- a/Makefile +++ b/Makefile @@ -8,13 +8,12 @@ BUILD_DRIVE := M: MICE_32 := "$(BUILD_DIR_32)/src\mice.exe" MICE_64 := "$(BUILD_DIR_64)/src\mice.exe" -VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" -VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" +# VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" +# VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" # For windows XP: -# VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" -vcvars_ver=14.16 -# VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" -vcvars_ver=14.16 - +VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" -vcvars_ver=14.16 +VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" -vcvars_ver=14.16 .ONESHELL: @@ -71,6 +70,7 @@ dist: @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe" @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe" @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe" + @copy /Y "$(BUILD_DIR_32)/src/micetools/util\kcproxy.exe" "$(DIST_DIR)/util/kcproxy.exe" @copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd" diff --git a/meson.build b/meson.build index cd82b2e..ddf0ec3 100644 --- a/meson.build +++ b/meson.build @@ -1,21 +1,40 @@ project('micetools', 'c', default_options: [ 'buildtype=minsize', # ! Toggle /\ and \/ when building for XP (minsize=normal, static=XP) - # 'b_vscrt=static_from_buildtype', + 'b_vscrt=static_from_buildtype', 'warning_level=3', ]) -winxp = false +winxp = true subsystem = 'console,5.01' if (host_machine.cpu_family() == 'x86') add_project_arguments('-DMICE_WIN32', language: 'c') endif +openssl_inc = include_directories('openssl-1.0.1/include') +openssl_lib = meson.get_compiler('c').find_library('libeay32', dirs: [ + join_paths(meson.source_root(), 'openssl-1.0.1/lib') +], required: true) +assert(openssl_lib.found(), 'Please download openssl!') + +add_project_link_arguments( + '/FIXED:NO', + '/DYNAMICBASE', + '/OPT:REF', + '/LTCG', + + language: 'c' +) add_project_arguments( '/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need '/D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it + '/DCIMGUI_DEFINE_ENUMS_AND_STRUCTS', + + # Strip out as much crud as we can to keep XP builds small + '/Os', '/EHc-', '/EHa-', '/EHs-', '/GL', '/GR-', + '/wd4706', # assignment within conditional expression '/wd4214', # windns.h: nonstandard extension used: bit field types other than int '/wd4201', # ewfapi.h: nameless struct/union diff --git a/src/meson.build b/src/meson.build index 3724ab2..6413e70 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,5 @@ inih = subproject('inih_dep') +cimgui = subproject('cimgui_dep', default_options: ['win32=enabled', 'dx9=enabled']) libs_dir = meson.current_source_dir() subdir('micetools') diff --git a/src/micetools/dll/comdevice.c b/src/micetools/dll/comdevice.c index 7fbe7f1..567f001 100644 --- a/src/micetools/dll/comdevice.c +++ b/src/micetools/dll/comdevice.c @@ -81,9 +81,9 @@ bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes) { 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]; } -BYTE one_byte; // Read data from a com device, unescaping as we go void comio_read(com_device_t* com, BYTE* data, BYTE len) { + BYTE one_byte; for (; len; len--) { comdev_read_blocking(com, &one_byte, 1); if (one_byte == COMIO_MARK) { @@ -95,6 +95,7 @@ void comio_read(com_device_t* com, BYTE* data, BYTE len) { } // Write data to a com device, escaping as we go void comio_write(com_device_t* com, BYTE* data, BYTE len) { + BYTE one_byte; for (; len; len--) { one_byte = *(data++); if (one_byte == COMIO_MARK || one_byte == COMIO_SYNC) { @@ -106,6 +107,7 @@ void comio_write(com_device_t* com, BYTE* data, BYTE len) { } } void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { + BYTE one_byte; do { if (comdev_available(com) < (sizeof *head + 1)) { SwitchToThread(); @@ -126,8 +128,8 @@ void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { unsigned char sum; comio_read(com, &sum, 1); } -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, BYTE* data) { + BYTE one_byte; one_byte = COMIO_SYNC; comdev_write(com, &one_byte, 1); @@ -146,10 +148,8 @@ void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE le comio_write(com, data, len); // 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 < sizeof resp; i++) one_byte += ((LPBYTE)&resp)[i]; + for (BYTE i = 0; i < len; i++) one_byte += data[i]; comio_write(com, &one_byte, 1); } diff --git a/src/micetools/dll/devices/aime_bd.c b/src/micetools/dll/devices/aime_bd.c index b6154e5..ca123a1 100644 --- a/src/micetools/dll/devices/aime_bd.c +++ b/src/micetools/dll/devices/aime_bd.c @@ -34,8 +34,168 @@ BYTE extra[0xff]; #define FWVer "TN32MSEC003S F/W Ver1.2" #define HWVer "TN32MSEC003S H/W Ver3.0" +#define CardType_Mifare 0x10 +#define CardType_FeliCa 0x20 + +#pragma pack(1) +typedef struct NFCMifare { + BYTE type; + BYTE id_len; + DWORD uid; +} NFCMifare_t; + +#pragma pack(1) +typedef struct NFCFelica { + BYTE type; + BYTE id_len; + uint64_t IDm; + uint64_t PMm; +} NFCFelica_t; + +#pragma pack(1) +typedef struct MifareBlock { + BYTE bytes[16]; +} MifareBlock_t; + +#pragma pack(1) +typedef struct MifareSector { + MifareBlock_t blocks[4]; +} MifareSector_t; + +#pragma pack(1) +typedef struct MifareMemory_t { + MifareSector_t sectors[16]; +} MifareMemory_t; + +#pragma pack(1) +typedef struct FelicaBlock { + BYTE bytes[16]; +} FelicaBlock_t; + +#pragma pack(1) +typedef struct FelicaMemory { + FelicaBlock_t dataBlocks[15]; + FelicaBlock_t systemBlocks[9]; +} FelicaMemory_t; + +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); +} +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 + 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; + } +} + +void nfc_poll(com_device_t* dev, comio_recv_head_t* req) { + BYTE data[256]; + 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]++; + } + + comio_reply(dev, req, COMIO_STATUS_OK, nbytes, data); +} + DWORD WINAPI aime_bd_thread(com_device_t* dev) { - log_warning("aime_bd", "%ls woke up", dev->com->wName); + log_info("aime_bd", "%ls woke up", dev->com->wName); + bool radio = false; + while (1) { comio_recv_head_t req; comio_next_req(dev, &req, extra); @@ -62,6 +222,32 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { log_info("aime_bd", "Bana key: %.*s", req.length, extra); comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); break; + case RadioOn: + radio = true; + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + case RadioOff: + radio = false; + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + case Poll: + nfc_poll(dev, &req); + break; + + case 0x44: + case 0x51: + case MifareSelectTag: + case Authenticate: + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + + // TODO: These + case ReadBlock: + comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); + break; + case FelicaEncap: + comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); + break; } } else if (req.dst == 0x08 || req.dst == 0x09) { // LED sub-boards @@ -75,6 +261,9 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12"); break; case LedSetColour: + log_misc("nfc", "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! break; } @@ -85,6 +274,17 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { } void install_aime_bd() { - com_device_t* aime = new_com_device(2); - com_device_thread(aime, aime_bd_thread); + char* text = MiceConfig.devices.aime_bd; + char* copy = (char*)malloc(strlen(text) + 1); + memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1); + + char* next_token; + char* token = strtok_s(copy, ",", &next_token); + while (token != NULL) { + BYTE com_port = atoi(token) & 0xFF; + if (com_port) com_device_thread(new_com_device(com_port), aime_bd_thread); + token = strtok_s(NULL, ",", &next_token); + } + + free(copy); } diff --git a/src/micetools/dll/devices/led_bd.c b/src/micetools/dll/devices/led_bd.c index 5594524..b0de4ba 100644 --- a/src/micetools/dll/devices/led_bd.c +++ b/src/micetools/dll/devices/led_bd.c @@ -75,7 +75,8 @@ typedef struct rs232c_recv_head { BYTE extra[0xff]; static DWORD WINAPI led_bd_thread(com_device_t* dev) { - log_warning("led_bd", "%ls woke up", dev->com->wName); + log_info("led_bd", "%ls woke up", dev->com->wName); + while (1) { rs232c_recv_head_t head; if (comdev_available(dev) < sizeof head) { @@ -89,13 +90,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { switch (head.op) { case 0x01: - log_warning("led_bd", "01"); + log_trace("led_bd", "01"); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x01\x01\x18", 8); // syn dst src len sts op. rep chk break; case 0x10: - log_warning("led_bd", "10"); + log_trace("led_bd", "10"); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8); // syn dst src len sts op. rep chk break; @@ -105,13 +106,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { COLOURS[extra[0]][1] = extra[2]; COLOURS[extra[0]][2] = extra[3]; - log_warning("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2], extra[3]); + log_trace("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2], + extra[3]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8); // syn dst src len sts op. rep chk break; case 0x32: - log_warning("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3], - extra[4], extra[5], extra[6], extra[7]); + log_trace("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], + extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]); for (unsigned char i = extra[2] - 1; i < extra[1]; i++) { COLOURS[i][0] = extra[3]; @@ -123,8 +125,8 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { // syn dst src len sts op. rep chk break; case 0x33: - log_warning("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3], - extra[4], extra[5], extra[6], extra[7]); + log_trace("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], + extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x33\x01\x4a", 8); // syn dst src len sts op. rep chk COLOURS[extra[0]][0] = extra[extra[5]]; @@ -133,7 +135,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { break; case 0x39: - log_warning("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]); + log_trace("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8); // syn dst src len sts op. rep chk @@ -142,18 +144,18 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { COLOURS[9][2] = extra[0]; break; case 0x3b: - log_warning("led_bd", "3b"); + log_trace("led_bd", "3b"); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3b\x01\x52", 8); // syn dst src len sts op. rep chk break; case 0x3c: - log_warning("led_bd", "3c (I am %ls)", dev->com->wName); + log_trace("led_bd", "3c (I am %ls)", dev->com->wName); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3c\x01\x53", 8); // syn dst src len sts op. rep chk break; case 0x3f: - log_warning("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3], - extra[4], extra[5], extra[6]); + log_trace("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], + extra[2], extra[3], extra[4], extra[5], extra[6]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8); // syn dst src len sts op. rep chk break; @@ -161,14 +163,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) { case 0x7c: // extra[0] goes from 0 to 7 // Could this be some sort of calibration for the buttons? - log_warning("led_bd", "7c: %02x", extra[0]); + log_trace("led_bd", "7c: %02x", extra[0]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9); // \/ causes 7b to be used // comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9); // syn dst src len sts op. rep --- chk break; case 0x7b: - log_warning("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]); + log_trace("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]); comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8); // syn dst src len sts op. rep chk break; @@ -211,12 +213,17 @@ void led_overlay(IDirect3DDevice9* dev) { void install_led_bd() { register_gui_hook(&led_overlay); - com_device_t* com5 = new_com_device(5); - com_device_thread(com5, led_null_thread); - com_device_t* leds_1p = new_com_device(6); - com_device_thread(leds_1p, led_bd_thread); - com_device_t* com7 = new_com_device(7); - com_device_thread(com7, led_null_thread); - com_device_t* leds_2p = new_com_device(8); - com_device_thread(leds_2p, led_bd_thread); + char* text = MiceConfig.devices.led_bd; + char* copy = (char*)malloc(strlen(text) + 1); + memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1); + + char* next_token; + char* token = strtok_s(copy, ",", &next_token); + while (token != NULL) { + BYTE com_port = atoi(token) & 0xFF; + if (com_port) com_device_thread(new_com_device(com_port), led_bd_thread); + token = strtok_s(NULL, ",", &next_token); + } + + free(copy); } diff --git a/src/micetools/dll/devices/touch_bd.c b/src/micetools/dll/devices/touch_bd.c index b518973..67b3204 100644 --- a/src/micetools/dll/devices/touch_bd.c +++ b/src/micetools/dll/devices/touch_bd.c @@ -18,6 +18,8 @@ static BYTE get_touch_id(BYTE id) { BOOL touch_is_enabled = false; BYTE thresh = 0x00; // Lazy caching of single value DWORD WINAPI touch_bd_thread(com_device_t* dev) { + log_info("touch_bd", "%ls woke up", dev->com->wName); + while (1) { if (touch_is_enabled && !comdev_available(dev)) { // Active mode! @@ -79,6 +81,17 @@ DWORD WINAPI touch_bd_thread(com_device_t* dev) { } void install_touch_bd() { - com_device_t* touch = new_com_device(3); - com_device_thread(touch, touch_bd_thread); + char* text = MiceConfig.devices.touch_bd; + char* copy = (char*)malloc(strlen(text) + 1); + memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1); + + char* next_token; + char* token = strtok_s(copy, ",", &next_token); + while (token != NULL) { + BYTE com_port = atoi(token) & 0xFF; + if (com_port) com_device_thread(new_com_device(com_port), touch_bd_thread); + token = strtok_s(NULL, ",", &next_token); + } + + free(copy); } diff --git a/src/micetools/dll/dllmain.c b/src/micetools/dll/dllmain.c index 40c61a6..04b2cc5 100644 --- a/src/micetools/dll/dllmain.c +++ b/src/micetools/dll/dllmain.c @@ -5,42 +5,47 @@ WCHAR exePath[MAX_PATH + 1]; -void enable_traces() { +void apply_patches() { + char exePathC[MAX_PATH + 1]; + WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL); + patches_t patches; char error[256]; - if (!load_patches(&patches, "patches.json", error)) { + if (!load_patches(&patches, MiceConfig.mice.patches_file, error, exePathC)) { log_error(BOOT_LOGGER, "Failed to load patches file: %s", error); - } else { - char exePathC[MAX_PATH + 1]; - WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL); + return; + } - for (size_t i = 0; i < patches.nopatchsets; i++) { - patchset_t* patchset = patches.patchsets[i]; + for (size_t i = 0; i < patches.nopatchsets; i++) { + patchset_t* patchset = patches.patchsets[i]; - // Require the binary explicitly named - if (patchset->binary_name == NULL || strcmp(patchset->binary_name, exePathC) != 0) { + // Require the binary explicitly named + if (patchset->binary_name == NULL || strcmp(patchset->binary_name, exePathC) != 0) { + continue; + } + if (!patchset->apply) continue; + + for (size_t j = 0; j < patchset->nopatches; j++) { + patch_t patch = patchset->patches[j]; + + DWORD oldProt; + VirtualProtect((void*)patch.offset, patch.count, PAGE_EXECUTE_READWRITE, &oldProt); + + if (memcmp(patch.from, (void*)patch.offset, patch.count) != 0) { + log_error(BOOT_LOGGER, "Patch %s[%d] failed! from-value missmatch", patchset->name, + j); + VirtualProtect((void*)patch.offset, patch.count, oldProt, &oldProt); continue; } - if (!patchset->apply) continue; - for (size_t j = 0; j < patchset->nopatches; j++) { - patch_t patch = patchset->patches[j]; - - if (memcmp(patch.from, (void*)patch.offset, patch.count) != 0) { - log_error(BOOT_LOGGER, "Patch %s[%d] failed! from-value missmatch", patchset->name, j); - continue; - } - - memcpy((void*)patch.offset, patch.to, patch.count); - log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset); - } + memcpy((void*)patch.offset, patch.to, patch.count); + log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset); + VirtualProtect((void*)patch.offset, patch.count, oldProt, &oldProt); } } free_patches(&patches); } - - void prebind_hooks() { hook_all(); install_devices(); @@ -54,35 +59,47 @@ void prebind_hooks() { } void init_injection() { + load_mice_config(); + // We're in a new context now, so need to reconfigure setup_logging(); log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath); - enable_traces(); + if (MiceConfig.mice.apply_patches) apply_patches(); // Columba: Driver-level memory access, used to read the DMI tables - setup_columba(); + if (MiceConfig.drivers.columba) setup_columba(); // MX SRAM: SRAM-based nv memory - setup_mxsram(); + if (MiceConfig.drivers.mxsram) setup_mxsram(); // MX SuperIO: Communicate with the HW monitor chip - setup_mxsuperio(); + if (MiceConfig.drivers.mxsuperio) setup_mxsuperio(); // MX JVS: Interacting with JVS-based devices - setup_mxjvs(); + if (MiceConfig.drivers.mxjvs) setup_mxjvs(); // MX HW Reset: Forcibly reboot the machine - setup_mxhwreset(); + if (MiceConfig.drivers.mxhwreset) setup_mxhwreset(); // MX SMBus: Communicate over the LPC bus. This contains the EEPROM, and PCA9535 - setup_mxsmbus(); + if (MiceConfig.drivers.mxsmbus) setup_mxsmbus(); + // MX Parallel: The parallel port (i.e. keychip) + if (MiceConfig.drivers.mxparallel) setup_mxparallel(); - if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) { - log_error("platform", "failed to install platform device"); + if (MiceConfig.drivers.platform) { + if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) { + log_error("platform", "failed to install platform device"); + } } // Must be the last thing called! - // register_devices(); prebind_hooks(); setup_hooks(); } +void tea_hook_test(char* fmt, ...) { + va_list argp; + va_start(argp, fmt); + vlog_game("tea", fmt, argp); + va_end(argp); +} + BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE; @@ -91,5 +108,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv init_injection(); + if (wcscmp(exePath, L"InitialD8_GLW_RE_SBZZ_dumped_.exe") == 0) { + CreateHook((void*)(0x00407850), &tea_hook_test, 5); + // *((DWORD*)(0x00407850)) = (DWORD)(&logcb); + } + return TRUE; } diff --git a/src/micetools/dll/drivers/mx.h b/src/micetools/dll/drivers/mx.h index b252b7f..d74798b 100644 --- a/src/micetools/dll/drivers/mx.h +++ b/src/micetools/dll/drivers/mx.h @@ -23,3 +23,6 @@ void setup_mxsuperio(); FnDeviceIoControl columba_DeviceIoControl; void setup_columba(); + +FnDeviceIoControl mxparallel_DeviceIoControl; +void setup_mxparallel(); diff --git a/src/micetools/dll/drivers/mxparallel.c b/src/micetools/dll/drivers/mxparallel.c index e69de29..bc96bdf 100644 --- a/src/micetools/dll/drivers/mxparallel.c +++ b/src/micetools/dll/drivers/mxparallel.c @@ -0,0 +1,444 @@ +#include "mxparallel.h" + +BYTE parallel_flags = 0x00; +BYTE parallel_ctrl = 0x00; +BYTE parallel_status = 0x00; +BYTE parallel_data = 0x00; + +BYTE KEYCHIP_ID[16] = { 'A', '7', '2', 'E', '-', '0', '2', 'D', + '1', '1', '2', '6', '1', '1', '1', '6' }; +BYTE MAIN_ID[16] = { 'A', 'A', 'S', 'E', '-', '0', '1', 'A', '6', '5', '6', '4' }; + +appboot_t APPBOOT = { + .format = 1, + .game_id = { 'S', 'D', 'E', 'Y' }, + .region = 8 | 4 | 2 | 1, + .model_type = 2, + // Bitfield + // 1 = use flash for appboot + .system_flag = 0x24, + ._ = 0, + .platform_id = { 'A', 'A', 'S' }, + .dvd_flag = 1, + .network_addr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), + .__ = 0, + .seed = 1, +}; +billing_t BILLING = { + .playlimit = 21046, + .nearfull = 512, +}; +uint32_t BILLING_PLAYCOUNT = 69420; + +#define overlappedComplete(len) \ + do { \ + if (lpOverlapped) { \ + SetLastError(ERROR_SUCCESS); \ + lpOverlapped->Internal = 0; \ + lpOverlapped->InternalHigh = len; \ + SetEvent(lpOverlapped->hEvent); \ + } \ + } while (0) +#define outLen(len) \ + do { \ + if (lpBytesReturned) *lpBytesReturned = len; \ + overlappedComplete(len); \ + } while (0) + +BOOL mxparallel_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + log_trace("mxparallel", "DeviceIoControl(, 0x%08x, 0x%p, 0x%x, -, 0x%x, -, -)", + dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize); + + switch (dwIoControlCode) { + case IOCTL_MXPARALLEL_READ_FLAGS: + ((LPBYTE)lpOutBuffer)[0] = parallel_flags; + outLen(1); + return TRUE; + case IOCTL_MXPARALLEL_WRITE_FLAGS: + parallel_flags = ((LPBYTE)lpInBuffer)[0]; + outLen(0); + return TRUE; + + case IOCTL_MXPARALLEL_READ_CTRL_PORT: + ((LPBYTE)lpOutBuffer)[0] = parallel_ctrl; + outLen(1); + return TRUE; + case IOCTL_MXPARALLEL_WRITE_CTRL_PORT: + parallel_ctrl = ((LPBYTE)lpInBuffer)[0]; + // log_warning("mxparallel", "Write ctrl %08x", parallel_ctrl); + outLen(0); + return TRUE; + + case IOCTL_MXPARALLEL_READ_STATUS: + ((LPBYTE)lpOutBuffer)[0] = parallel_status; + outLen(1); + return TRUE; + case IOCTL_MXPARALLEL_WRITE_STATUS: + parallel_status = ((LPBYTE)lpInBuffer)[0]; + outLen(0); + return TRUE; + + case IOCTL_MXPARALLEL_READ_DATA: + ((LPBYTE)lpOutBuffer)[0] = parallel_data; + outLen(1); + return TRUE; + case IOCTL_MXPARALLEL_WRITE_DATA: + parallel_data = ((LPBYTE)lpInBuffer)[0]; + outLen(0); + return TRUE; + } + return FALSE; +} + +// * Our implementation needs to use the opposite keys to mxkeychip + +void micexkTransportSend(unsigned char* send_data, int nbytes) { + setAck; + for (int i = 0; i < nbytes; i++) { + while (_Strobe) YieldProcessor(); + setBusy; + parallel_data = send_data[i]; + while (!_Strobe) YieldProcessor(); + clearBusy; + while (_Strobe) YieldProcessor(); + } + clearAck; +} +void micexkSendPacket(unsigned char* send_data) { + BYTE encrypted[16]; + memset(encrypted, 0, sizeof encrypted); + mxkCryptEncryptData(encrypted, send_data); + micexkTransportSend(encrypted, 16); +} + +void micexkTransportRecv(unsigned char* buffer, int nbytes) { + for (int i = 0; i < nbytes; i++) { + clearBusy; + while (!_Strobe) YieldProcessor(); + buffer[i] = parallel_data; + setBusy; + while (_Strobe) YieldProcessor(); + clearBusy; + } +} +void micexkRecvPacket(unsigned char* packet) { + unsigned char buffer[16]; + micexkTransportRecv(buffer, 16); + mxkCryptDecryptData(buffer, packet); +} + +BYTE nvram[0x4000]; +BYTE eeprom[0x1000]; +BYTE flash[0x100000]; +void init_nv_storage() { + memset(nvram, 0xff, sizeof nvram); + memset(eeprom, 0xff, sizeof eeprom); + memset(flash, 0xff, sizeof flash); + + // NVRAM + nvram_data_block_t block; + ZeroMemory(&block, sizeof block); + block.length = sizeof BILLING_PUBKEY; + memcpy(block.data, BILLING_PUBKEY, sizeof BILLING_PUBKEY); + memcpy(&nvram[0x1800], &block, sizeof block); + + block.length = sizeof BILLING_CACERT; + memcpy(block.data, BILLING_CACERT, sizeof BILLING_CACERT); + memcpy(&nvram[0x1c00], &block, sizeof block); + + // Flash + billing_t billing_info; + ZeroMemory(&billing_info, sizeof billing_info); + billing_info.playlimit = 21046; + billing_info.nearfull = 512; + mxkSignValue(billing_info.nearfull, billing_info.nearfull_sig); + mxkSignValue(billing_info.playlimit, billing_info.playlimit_sig); + billing_info.crc = crc32(sizeof billing_info - 4, (unsigned char*)&billing_info + 4, 0); + + memcpy(&flash[0x7a000], &billing_info, sizeof billing_info); + memcpy(&flash[0x7b000], &billing_info, sizeof billing_info); +} + +void dump_nv_storage() { + FILE* fp; + fopen_s(&fp, "dev/kc/nvram.bin", "wb"); + fwrite(nvram, 1, sizeof nvram, fp); + fclose(fp); + fopen_s(&fp, "dev/kc/eeprom.bin", "wb"); + fwrite(eeprom, 1, sizeof eeprom, fp); + fclose(fp); + fopen_s(&fp, "dev/kc/flash.bin", "wb"); + fwrite(flash, 1, sizeof flash, fp); + fclose(fp); +} + +/* +addr = (0x70 + block) * 0x1000 + offset + +Eeprom: + Appears to store entries detailing tracedata metadata + [4:crc32] [12:?] + + one copy at 0x000, one copy at 0x100 + 16 entries + first dword: CRC + second dword: ?? + third dword: ?? + fourth dword: + word 1: ?? + word 2: 0xffff + +Nvram: + 2x 0x400 blocks + [4:length] [length:data] + first block: billing pubkey + second block: cacert + +Flash (25DF041A): + nvram0: reads 070000<->070fff + nvram1: reads 071000<->071fff + nvram2: reads 072000<->072fff + nvram3: reads 073000<->073fff + nvram4: reads 074000<->074fff + nvram5: reads 075000<->075fff + nvram6: reads 076000<->076fff + nvram7: reads 077000<->077fff + nvram8: reads 078000<->078fff + nvram9: reads 079000<->079fff + + billing info a: 0x7a000 + billing info b: 0x7b000 + + - The first 0x80 bytes of each tracedata sector is a bitfield indicating which blocks have been + used + - There are 1022 0x40 blocks per tracedata sector (the last two are always unsed, to account for + the 0x80 of metadata) + - There are 7 tracedata sectors, at 0x00000, 0x10000, 0x20000, ..., 0x60000 + - Each slot is DES ECB encrypted, with key 4D77F1748D6D1094 + +*/ + +BYTE kc_aes_iv[16]; + +void mxparallel_process_packet(BYTE* request) { + BYTE response[16]; + memset(response, 10, sizeof response); + + response[0] = request[0]; + switch (request[0]) { + // We're pretending to be the keychip, so S and R are swapped for us! + case SetKeyS: + log_info("mxparallel", "SetKeyS"); + micexkRecvPacket(request); + mxkSetKeyR(request); + micexkSendPacket(response); + break; + case SetKeyR: + log_info("mxparallel", "SetKeyR"); + micexkRecvPacket(request); + mxkSetKeyS(request); + micexkSendPacket(response); + break; + + case Encrypt: + log_info("mxparallel", "Encrypt"); + micexkRecvPacket(request); + micexkSendPacket(request); + break; + case Decrypt: + log_info("mxparallel", "Decrypt"); + micexkRecvPacket(request); + micexkSendPacket(request); + break; + case SetIV: + log_info("mxparallel", "SetIV"); + ZeroMemory(kc_aes_iv, sizeof kc_aes_iv); + micexkSendPacket(response); + break; + case GetAppBootInfo: + log_info("mxparallel", "GetAppBootInfo"); + if (request[1] != 0x00) { + log_warning("mxparallel", "GetAppBootInfo[%d] unexpected!", request[1]); + } + + APPBOOT.crc = crc32(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0); + for (int i = 0; i < sizeof APPBOOT; i += 16) { + micexkSendPacket((unsigned char*)(&APPBOOT) + i); + } + break; + + case KcGetVersion: + log_info("mxparallel", "GetVersion"); + response[0] = 0x01; + response[1] = 0x04; + micexkSendPacket(response); + break; + + case FlashRead: { + uint32_t addr = request[1] | (request[2] << 8) | (request[3] << 16); + uint32_t nbytes = request[4] | (request[5] << 8) | (request[6] << 16); + log_info("mxparallel", "FlashRead: %06x/%06x", addr, nbytes); + + if (addr + nbytes <= sizeof flash) + micexkTransportSend(&flash[addr], nbytes); + else + log_error("mxparallel", "Flash read would exceed storage!"); + + break; + } + case FlashErase: { + uint32_t addr = request[1] | (request[2] << 8) | (request[3] << 16); + log_info("mxparallel", "FlashErase: %06x", addr); + + micexkSendPacket(response); + break; + } + case FlashWrite: { + uint32_t addr = request[1] | (request[2] << 8) | (request[3] << 16); + uint32_t nbytes = request[4] | (request[5] << 8) | (request[6] << 16); + log_info("mxparallel", "FlashWrite: %06x/%06x", addr, nbytes); + + if (addr + nbytes <= sizeof flash) + micexkTransportRecv(&flash[addr], nbytes); + else + log_error("mxparallel", "Flash write would exceed storage!"); + + micexkSendPacket(response); + dump_nv_storage(); + break; + } + + // EEPROM? + case EepromWrite: { + // TODO: What is this? Appears to be some sort of EEPROM write + uint8_t offset = request[1]; + log_info("mxparallel", "EepromWrite: %02x", offset); + + if (offset * 16 + 16 <= sizeof eeprom) { + micexkRecvPacket(&eeprom[offset * 16]); + } else { + log_error("mxparallel", "EEPROM write would exceed storage!"); + } + micexkSendPacket(response); + dump_nv_storage(); + break; + } + case EepromRead: { + // TODO: What is this? Appears to be some sort of EEPROM read + uint8_t offset = request[1]; + log_info("mxparallel", "EepromRead: %02x", offset); + + if (offset * 16 + 16 <= sizeof eeprom) { + micexkSendPacket(&eeprom[offset * 16]); + } else { + log_error("mxparallel", "EEPROM read would exceed storage!"); + } + break; + } + + // NVRAM? + case NvramWrite: { + // TODO: What is this? Appears to be some sort of memory write + uint16_t addr = request[1] | (request[2] << 8); + uint8_t blocks = request[3]; + log_info("mxparallel", "NvramWrite: %04x (%02x)", addr, blocks); + + if (addr + blocks * 16 <= sizeof nvram) { + for (byte i = 0; i < blocks; i++) { + micexkRecvPacket(&(nvram[addr + (i * 16)])); + } + micexkSendPacket(response); + } else { + log_error("mxparallel", "NVRAM write would exceed storage!"); + } + dump_nv_storage(); + break; + } + case NvramRead: { + // TODO: What is this? Appears to be some sort of memory read + uint16_t addr = request[1] | (request[2] << 8); + uint8_t blocks = request[3]; + log_info("mxparallel", "NvramRead: %04x (%02x)", addr, blocks); + + if (addr + blocks * 16 <= sizeof nvram) { + for (byte i = 0; i < blocks; i++) { + micexkSendPacket(&(nvram[addr + (i * 16)])); + } + } else { + log_error("mxparallel", "NVRAM read would exceed storage!"); + } + break; + } + + case AddPlayCount: + log_info("mxparallel", "AddPlayCount"); + BILLING_PLAYCOUNT++; + micexkSendPacket(response); + break; + + case SetMainId: + log_info("mxparallel", "SetMainId"); + + // micexkRecvPacket(MAIN_ID); + micexkRecvPacket(request); + response[0] = 0xff; + micexkSendPacket(response); + break; + case GetMainId: + log_info("mxparallel", "GetMainId"); + micexkSendPacket(MAIN_ID); + break; + case SetKeyId: + log_info("mxparallel", "SetKeyId"); + micexkRecvPacket(KEYCHIP_ID); + micexkSendPacket(response); + break; + case GetKeyId: + log_info("mxparallel", "GetKeyId"); + micexkSendPacket(KEYCHIP_ID); + break; + + case GetPlayCounter: + log_info("mxparallel", "GetPlayCounter"); + ((uint32_t*)response)[0] = BILLING_PLAYCOUNT; + micexkSendPacket(response); + break; + + default: + log_error("mxparallel", "Unhandled opcode: %d", request[0]); + for (byte i = 0; i < 16; i++) { + printf("%02x ", request[i]); + } + puts(""); + + break; + } +} + +DWORD WINAPI mxparallel_thread(LPVOID _) { + log_info("mxparallel", "Parallel device thread spawned"); + clearBusy; + clearAck; + + BYTE last_strobe = 0x00; + while (1) { + unsigned char packet[16]; + micexkRecvPacket(packet); + mxparallel_process_packet(packet); + } +} + +void setup_mxparallel() { + // We're pretending to be a keychip, so need to swap the keys! + mxkSwapKeys(); + + init_nv_storage(); + + file_hook_t* mxparallel = new_file_hook(L"\\\\.\\mxparallel"); + mxparallel->DeviceIoControl = &mxparallel_DeviceIoControl; + hook_file(mxparallel); + + CreateThread(NULL, 0, mxparallel_thread, NULL, 0, NULL); +} diff --git a/src/micetools/dll/drivers/mxparallel.h b/src/micetools/dll/drivers/mxparallel.h new file mode 100644 index 0000000..0f7783b --- /dev/null +++ b/src/micetools/dll/drivers/mxparallel.h @@ -0,0 +1,61 @@ +#pragma once + +#include "../../lib/mxk/mxk.h" +#include "mx.h" + +#pragma pack(1) +typedef struct { + uint32_t crc; + uint32_t playlimit; + uint8_t playlimit_sig[128]; + uint32_t nearfull; + uint8_t nearfull_sig[128]; +} billing_t; +#pragma pack(1) +typedef struct { + uint32_t length; + uint8_t data[0x400 - 4]; +} nvram_data_block_t; + + +void micexkTransportSend(unsigned char* send_data, int nbytes); +void micexkSendPacket(unsigned char* send_data); +void micexkTransportRecv(unsigned char* buffer, int nbytes); +void micexkRecvPacket(unsigned char* packet); + +static appboot_t APPBOOT; +static billing_t BILLING; +static uint32_t BILLING_PLAYCOUNT; + +// Parallel port emulation +static BYTE parallel_flags; +static BYTE parallel_ctrl; +static BYTE parallel_status; +static BYTE parallel_data; + +#define setStatus(mask) \ + do { \ + parallel_status |= mask; \ + } while (0) +#define clearStatus(mask) \ + do { \ + parallel_status &= ~mask; \ + } while (0) +#define getControl(mask) (parallel_ctrl & mask) + +#define setError setStatus(0x08) +#define clearError clearStatus(0x08) +#define setSelect setStatus(0x10) +#define clearSelect clearStatus(0x10) +#define setPo setStatus(0x20) +#define clearPo clearStatus(0x20) +#define setAck setStatus(0x40) +#define clearAck clearStatus(0x40) +#define setBusy setStatus(0x80) +#define clearBusy clearStatus(0x80) + +#define _Strobe getControl(0x01) +#define _LF getControl(0x02) +#define _Reset getControl(0x04) +#define _SelPrint getControl(0x08) +#define _IsDirWrite getControl(0x20) diff --git a/src/micetools/dll/drivers/mxsmbus.c b/src/micetools/dll/drivers/mxsmbus.c index 2bca7cf..29fcd2f 100644 --- a/src/micetools/dll/drivers/mxsmbus.c +++ b/src/micetools/dll/drivers/mxsmbus.c @@ -13,13 +13,6 @@ typedef struct eeprom_bank { // 256 registers, 32 bytes each eeprom_bank_t EEPROM_DATA; -/* - * Known registers: - * - Reg 0x00: Stores ??? in [00] - * - Reg 0x08: Stores LPC address in [00, 01] - * - Reg 0x16: Stores ??? in [00, 01] - * - Reg 0x0e: Stores - */ void eeprom_dump() { HANDLE dump = @@ -28,7 +21,7 @@ void eeprom_dump() { log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed"); return; } else { - log_info("eeprom", "Wrote eeprom to %s", EEPROM_DUMP); + log_info("eeprom", "Wrote eeprom to %ls", EEPROM_DUMP); } _WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL); FlushFileBuffers(dump); @@ -51,16 +44,52 @@ void eeprom_restore() { DWORD eeprom_crc(BYTE reg) { if (reg == 0x04 || reg == 0x14 || reg == 0x80 || reg == 0x280) { // Some registers are only treated as 16 byte values - crc32_build_table(); return crc32(12, EEPROM_DATA.reg[reg].data + 4, 0); } - crc32_build_table(); return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0); } -void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { - log_game("eeprom", "EEPROM READ %d %d %d", reg, index, length); +#pragma pack(1) +typedef struct { + uint32_t checksum; + uint8_t pad1[8]; + uint8_t region; + uint8_t pad2[2]; + char mainId[17]; +} eeprom_block_1; +#pragma pack(1) +typedef struct { + uint32_t checksum; + uint32_t unk; + uint32_t dhcp_enabled; + uint32_t machine_ip; + uint32_t netmask; + uint32_t gateway; + uint32_t primary_dns; + uint32_t secondary_dns; +} eeprom_block_3; +#pragma pack(1) +typedef struct { + uint32_t checksum; + byte pad[4]; + char game_id[4]; + uint32_t unk; +} eeprom_block_5_1; +#pragma pack(1) +typedef struct { + uint32_t checksum; + uint32_t unk1; + uint32_t unk2; + uint32_t unk3; +} eeprom_block_5_2; + +#define SET_IP(val, a, b, c, d) \ + do { \ + *(uint32_t*)&val = (a << 24) | (b << 16) | (c << 8) | d; \ + } while (0) + +void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { eeprom_restore(); for (BYTE i = index; i < index + length; i++) { if (i > 0x1f) break; @@ -69,6 +98,58 @@ void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { // TODO: Reg 1 and 17 in the EEPROM are system info. We should fake these! + if (reg == 0x00 || reg == 0x10) { + eeprom_block_1 block; + memset(&block, 0, sizeof block); + + block.region = 0b111; + strcpy(block.mainId, "AASE-01A65646203"); + + block.checksum = crc32(28, (BYTE*)(&block) + 4, 0); + + byte = ((BYTE*)(&block))[i]; + } + if (reg == 0x02) { + eeprom_block_3 block; + memset(&block, 0, sizeof block); + + // TODO: Load network config! + SET_IP(block.machine_ip, 192, 168, 103, 101); + SET_IP(block.netmask, 255, 255, 255, 0); + SET_IP(block.gateway, 192, 168, 103, 254); + SET_IP(block.primary_dns, 192, 168, 103, 254); + SET_IP(block.secondary_dns, 0, 0, 0, 0); + block.dhcp_enabled = 0; + + block.unk = 4835744; + + block.checksum = crc32(28, (BYTE*)(&block) + 4, 0); + + byte = ((BYTE*)(&block))[i]; + } + if (reg == 0x04) { + eeprom_block_5_1 block1; + eeprom_block_5_2 block2; + + memset(&block1, 0, sizeof block1); + memset(&block2, 0, sizeof block2); + block1.game_id[0] = 'S'; + block1.game_id[1] = 'D'; + block1.game_id[2] = 'E'; + block1.game_id[3] = 'Y'; + + block2.unk2 = 0xffffffff; + block2.unk3 = 0xffffffff; + + block1.checksum = crc32(12, (BYTE*)(&block1) + 4, 0); + block2.checksum = crc32(12, (BYTE*)(&block2) + 4, 0); + + if (i < 16) + byte = ((BYTE*)(&block1))[i]; + else + byte = ((BYTE*)(&block2))[i - 16]; + } + // If register has a CRC // if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg // == 0x11 || reg == 0x12 || reg == 0x200) { @@ -84,7 +165,7 @@ void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { } } void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) { - log_game("eeprom", "EEPROM WRITE %d %d %d", reg, index, length); + log_misc("eeprom", "write reg=%d idx=%d len=%d", reg, index, length); for (BYTE i = index; i < index + length; i++) { if (i > 0x1f) break; @@ -93,12 +174,358 @@ void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) { eeprom_dump(); } -BYTE eeprom_read_one(BYTE reg, BYTE index) { - BYTE data; - eeprom_read(reg, index, &data, 1); - return data; +typedef enum { + SMB_CMD_QUICK = 0b000, + SMB_CMD_BYTE = 0b001, + SMB_CMD_BYTE_DATA = 0b010, + SMB_CMD_WORD_DATA = 0b011, + SMB_CMD_PROCESS_CALL = 0b100, + SMB_CMD_BLOCK = 0b101, + SMB_CMD_I2C_READ = 0b110, + SMB_CMD_BLOCK_PROCESS = 0b111, +} smb_cmd_t; + +// EEPROM +BOOL smbus_AT24C64AN(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) { + BOOL read = addr & 1 == 1; + if (read) { + switch (cmd) { + case SMB_CMD_BYTE: + data[0] = 0x00; + break; + case SMB_CMD_BLOCK: { + WORD reg = *(WORD*)(&data[-1]); + dlen = data[1]; + log_info("eeprom", "Block read, %d @ %02x", dlen, reg); + + eeprom_read(reg >> 5, reg & 0x1f, &data[2], dlen); + return TRUE; + } + default: + log_error("eeprom", "Unsupported read mode: %01x, %02x", cmd, code); + return FALSE; + } + return TRUE; + } + + switch (cmd) { + case SMB_CMD_BLOCK: { + WORD reg = *(WORD*)(&data[-1]); + dlen = data[1]; + log_info("eeprom", "Block write, %d @ %02x", dlen, reg); + + eeprom_write(reg >> 5, reg & 0x1f, &data[2], dlen); + return TRUE; + } + default: + log_error("eeprom", "Unsupported write mode: %01x, %02x", cmd, code); + return FALSE; + } +} + +// dipsw +BOOL smbus_PCA9535(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) { + static uint16_t pca9535_config = 0xffff; + + BOOL read = addr & 1 == 1; + if (read) { + switch (cmd) { + case SMB_CMD_BYTE_DATA: + switch (code) { + case PCA9535_IN0: // DIPSW + /* + 0: ? + 1: ? + 2: ? + 3: Orientation + 4: / \ + 5: | Resolution | + 6: \ / + 7: game specific + + 0b00001000 = landscape + */ + data[0] = 0b00001000; + return TRUE; + case PCA9535_IN1: // SW1/2 + extras + /* + 0: unk + 1: unk + 2: ¬test + 3: ¬service + 4: unk + 5: unk + 6: unk + 7: unk + */ + byte dip = 0x00; + if (GetAsyncKeyState('T') >= 0) { + dip |= 0x04; + } + if (GetAsyncKeyState('S') >= 0) { + dip |= 0x08; + } + data[0] = dip; + return TRUE; + case PCA9535_OUT0: + log_error("pca9535", "Read PCA9535_OUT0 unimplemented!"); + return FALSE; + case PCA9535_OUT1: + data[0] = 0x00; + return TRUE; + case PCA9535_INV0: + data[0] = 0x00; + return TRUE; + case PCA9535_INV1: + data[0] = 0x00; + return TRUE; + case PCA9535_CONF0: + data[0] = pca9535_config >> 8; + return TRUE; + case PCA9535_CONF1: + data[0] = pca9535_config & 0xff; + return TRUE; + default: + log_error("pca9535", "Unknown read command: %02x", code); + return FALSE; + } + default: + log_error("pca9535", "Unsupported read mode: %01x (%02x)", cmd, code); + return FALSE; + } + } + + switch (cmd) { + case SMB_CMD_BYTE_DATA: + switch (code) { + case PCA9535_IN0: + log_error("pca9535", "Write PCA9535_IN0 unimplemented!"); + return FALSE; + case PCA9535_IN1: + log_error("pca9535", "Write PCA9535_IN1 unimplemented!"); + return FALSE; + case PCA9535_OUT0: + log_info("pca9535", "Out 0: %02x", data[0]); + return TRUE; + case PCA9535_OUT1: + log_info("pca9535", "Out 1: %02x", data[0]); + return TRUE; + case PCA9535_INV0: + log_info("pca9535", "Inv 0: %02x", data[0]); + return TRUE; + case PCA9535_INV1: + log_info("pca9535", "Inv 1: %02x", data[0]); + return TRUE; + case PCA9535_CONF0: + log_info("pca9535", "Conf 0: %02x", data[0]); + pca9535_config = (data[0] << 8) | (pca9535_config & 0xff); + return TRUE; + case PCA9535_CONF1: + log_info("pca9535", "Conf 1: %02x", data[0]); + pca9535_config = data[0] | (pca9535_config & 0xff00); + return TRUE; + default: + log_error("pca9535", "Unknown write command: %02x", code); + return FALSE; + } + default: + log_error("pca9535", "Unsupported write mode: %01x (%02x)", cmd, code); + return FALSE; + } +} + +// Very incomplete keychip +BOOL smbus_N2(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) { + static unsigned char challenge[7]; + static unsigned char n2_eeprom[3][0x20]; + + BOOL read = addr & 1 == 1; + if (read) { + switch (cmd) { + case SMB_CMD_BYTE_DATA: + if (code < 0x80) { + BYTE page = (code >> 5) & 0b11; + BYTE offset = code & 0x1f; + + data[0] = n2_eeprom[page][offset]; + + return TRUE; + } else if (code >= N2_GET_UNIQUE_NUMBER && code < N2_GET_UNIQUE_NUMBER + 0xf) { + data[0] = 0x04; // chosen by fair dice roll. + return TRUE; + } else if (code == N2_GET_STATUS) { + // Polled until N2_STATUS_FLAG_BUSY low + data[0] = 0x00; + return TRUE; + } else { + log_error("smb-keychip", "Unknown read command: %02x", code); + return FALSE; + } + default: + log_error("smb-keychip", "Unsupported read mode: %01x (%02x)", cmd, code); + return FALSE; + } + } + + switch (cmd) { + case SMB_CMD_BLOCK: { + WORD reg = *(WORD*)(&data[-1]); + dlen = data[1]; + + if (dlen != 7) { + log_error("smb-keychip", "Expected challenge length of 7 (saw %d)!", dlen); + return FALSE; + } + + memcpy(challenge, &(data[2]), 7); + + char* challenge_s = malloc(dlen * 3 + 1); + for (int i = 0; i < dlen; i++) { + sprintf(challenge_s + i * 3, "%02x ", data[2 + i]); + } + challenge_s[dlen * 3 + 1] = '\0'; + log_info("smb-keychip", "Challenge: %s", challenge_s); + free(challenge_s); + return TRUE; + } + case SMB_CMD_I2C_READ: { + switch (code) { + case N2_I2C_CHALLENGE_RESPONSE: + // This just has to match EXIO! + for (int i = 0; i < dlen; i++) data[i] = 0x69; + return TRUE; + default: + log_error("smb-keychip", "Unknown I2C command: %02x", code); + } + } + default: + log_error("smb-keychip", "Unsupported write mode: %01x (%02x)", cmd, code); + return FALSE; + } +} +BOOL smbus_EXIO(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) { + BOOL read = addr & 1 == 1; + if (read) { + switch (cmd) { + case SMB_CMD_BYTE_DATA: + if (0x40 <= code < 0x40 + 0x14) { + // mxkDsExioReadMacOutputBuffer + // This just has to match N2_I2C_CHALLENGE_RESPONSE! + data[0] = 0x69; + return TRUE; + } else if (code == EXIO_GET_BUSY) { + data[0] = 0x00; // Anything non-zero = busy + return TRUE; + } else { + log_error("smx-exio", "Unknown read command: %02x", code); + return FALSE; + } + default: + log_error("smb-exio", "Unsupported read mode: %01x (%02x)", cmd, code); + return FALSE; + } + } + + switch (cmd) { + case SMB_CMD_BYTE_DATA: + switch (code) { + case 0x5c: + if (data[0] == 0x94) return TRUE; + default: + log_error("smb-exio", "Unknown write command: %02x", code); + return FALSE; + } + case SMB_CMD_BLOCK: { + WORD reg = *(WORD*)(&data[-1]); + dlen = data[1]; + + char* data_s = malloc(dlen * 3 + 1); + for (int i = 0; i < dlen; i++) { + sprintf(data_s + i * 3, "%02x ", data[2 + i]); + } + data_s[dlen * 3 + 1] = '\0'; + + log_info("smb-exio", "Block write, %d @ %04x: %s", dlen, reg, data_s); + free(data_s); + return TRUE; + } + + default: + log_error("smb-exio", "Unsupported write mode: %01x (%02x)", cmd, code); + return FALSE; + } +} + +BOOL handle_smbus(BYTE* request) { + BYTE command = request[1]; + BYTE v_addr = request[2] & 0x7f; + BYTE command_code = request[3]; + + BYTE p_addr = request[2] << 1; + smb_cmd_t smb_cmd = SMB_CMD_QUICK; + switch (command) { + case 0: + break; + case 1: + p_addr++; + break; + case 2: + smb_cmd = SMB_CMD_BYTE; + break; + case 3: + p_addr++; + smb_cmd = SMB_CMD_BYTE; + break; + case 4: + smb_cmd = SMB_CMD_BYTE_DATA; + break; + case 5: + p_addr++; + smb_cmd = SMB_CMD_BYTE_DATA; + break; + case 6: + smb_cmd = SMB_CMD_WORD_DATA; + break; + case 7: + p_addr++; + smb_cmd = SMB_CMD_WORD_DATA; + break; + case 8: + smb_cmd = SMB_CMD_BLOCK; + break; + case 9: + p_addr++; + smb_cmd = SMB_CMD_BLOCK; + break; + case 10: + smb_cmd = SMB_CMD_PROCESS_CALL; + break; + case 11: + smb_cmd = SMB_CMD_I2C_READ; + break; + } + + log_trace("smbus", "Making request to %02X (virtual: %02X/%02x, cmd: %01X, code: %02X)", p_addr, + v_addr, command, smb_cmd, command_code); + + switch (p_addr) { + case SMBUS_EEPROM: + case SMBUS_EEPROM + 1: + return smbus_AT24C64AN(p_addr, smb_cmd, command_code, request[4], &request[5]); + case SMBUS_PCA9535: + case SMBUS_PCA9535 + 1: + return smbus_PCA9535(p_addr, smb_cmd, command_code, request[4], &request[5]); + case SMBUS_N2: + case SMBUS_N2 + 1: + return smbus_N2(p_addr, smb_cmd, command_code, request[4], &request[5]); + case SMBUS_EXIO: + case SMBUS_EXIO + 1: + return smbus_EXIO(p_addr, smb_cmd, command_code, request[4], &request[5]); + default: + log_error("smbus", "Request to unregistered address: %02x", p_addr); + return FALSE; + } } -void eeprom_write_one(BYTE reg, BYTE index, BYTE data) { eeprom_write(reg, index, &data, 1); } BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, @@ -106,12 +533,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer; mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer; - mxsmbus_request_packet* request_packet = (mxsmbus_request_packet*)lpInBuffer; - mxsmbus_request_packet* request_out = (mxsmbus_request_packet*)lpOutBuffer; - - BYTE dlen; - - static uint16_t pca9535_config = 0xffff; + // Default value + if (lpBytesReturned) *lpBytesReturned = nOutBufferSize; switch (dwIoControlCode) { case IOCTL_MXSMBUS_GET_VERSION: @@ -123,229 +546,34 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe ((LPDWORD)lpOutBuffer)[0] = 0x01020001; if (lpBytesReturned) *lpBytesReturned = 4; break; - case IOCTL_MXSMBUS_REQUEST: // dip r/w - log_trace("mxsmbus", - "DeviceIoControl(, , 0x%p, 0x%x, -, " - "0x%x, -, -)", - lpInBuffer, nInBufferSize, nOutBufferSize); - - // Game trace: - // 05 for 20 - // ^[x3] - // 04 for 20 - // ^[x3] - // 05 for 20 - // 03 for 57 - // ^[after every eeprom read/write] - - // Address 0x20 = PCA9535 = DIP switches - // Address 0x30 = Keychip? "N2" - // Address 0x55 = Keychip? - // Address 0x57 = EEPROM - - // dyn = 0x57 - // 03: addr dyn: amEepromWait - // 04: addr dyn: amHmI2CWriteByte (via IOCTL_MXSMBUS_I2C instead) - // 05: addr dyn: amHmI2CWriteByte (via IOCTL_MXSMBUS_I2C instead) - // - // dyn2 = 0x20 - // 04: addr dyn2: amDipswWriteByteInternal - // 05: addr dyn2: amDipswReadByteInternal[Ex] - - // 0B: addr 0x20: amHmGetLPCChipId - // 0B: addr 0x21: amHmGetLPCChipId - // 48: addr 0x00: amHmGetLPCChipId - - switch (i2c_packet->addr) { - case SMBUS_PCA9535: - switch (i2c_packet->prt) { - case PCA9535_WRITE: - switch (i2c_packet->reg) { - case PCA9535_OUT0: - log_info("mxsmbus", "pca9535 OUT0: %02x", i2c_packet->data[0]); - break; - case PCA9535_OUT1: - log_info("mxsmbus", "pca9535 OUT1: %02x", i2c_packet->data[0]); - break; - case PCA9535_INV0: - log_info("mxsmbus", "pca9535 INV0: %02x", i2c_packet->data[0]); - break; - case PCA9535_INV1: - log_info("mxsmbus", "pca9535 INV1: %02x", i2c_packet->data[0]); - break; - case PCA9535_CONF0: - log_info("mxsmbus", "pca9535 CONF0: %02x", i2c_packet->data[0]); - pca9535_config = - (i2c_packet->data[0] << 8) | (pca9535_config & 0xff); - break; - case PCA9535_CONF1: - log_info("mxsmbus", "pca9535 CONF1: %02x", i2c_packet->data[0]); - pca9535_config = - i2c_packet->data[0] | (pca9535_config & 0xff00); - break; - default: - log_error("mxsmbus", - "(write) Undefined pca9535 register: 0x%02x", - i2c_packet->reg); - exit(1); - } - break; - case PCA9535_READ: - switch (i2c_packet->reg) { - case PCA9535_IN0: // DIPSW - /* - 0: ? - 1: ? - 2: ? - 3: Orientation - 4: / \ - 5: | Resolution | - 6: \ / - 7: game specific - - 0b00001000 = landscape - */ - puts("dipsw"); - i2c_packet->data[0] = 0b00001000; - break; - case PCA9535_IN1: // SW1/2 + extras - /* - 0: unk - 1: unk - 2: ¬test - 3: ¬service - 4: unk - 5: unk - 6: unk - 7: unk - */ - byte dip = 0x00; - if (GetAsyncKeyState('T') >= 0) { - dip |= 0x04; - } - if (GetAsyncKeyState('S') >= 0) { - dip |= 0x08; - } - i2c_packet->data[0] = dip; - break; - case PCA9535_INV0: - case PCA9535_INV1: - case PCA9535_OUT1: // LEDs, probably - i2c_packet->data[0] = 0x00; - break; - case PCA9535_CONF0: - i2c_packet->data[0] = pca9535_config >> 8; - break; - case PCA9535_CONF1: - i2c_packet->data[0] = pca9535_config & 0xff; - break; - default: - log_error("mxsmbus", - "(read) Undefined pca9535 " - "register: 0x%02x", - i2c_packet->reg); - exit(1); - } - i2c_packet->status = 0x00; - break; - default: - log_error("mxsmbus", "Unknown pca9535 command: 0x%02x", - i2c_packet->prt); - exit(1); - } - break; - case SMBUS_EEPROM: - switch (i2c_packet->prt) { - case 3: // Wait - // 0x18 = wait, 0x00 = done - i2c_packet->status = 0; - break; - default: - log_error("mxsmbus", "Unknown eeprom command: 0x%02x", i2c_packet->prt); - exit(1); - } - break; - default: - log_error("mxsmbus", "Unknown smbus device: 0x%02x", i2c_packet->addr); - exit(1); - } - - i2c_out->status = MXSBUS_OKAY; - if (lpBytesReturned) *lpBytesReturned = sizeof(mxsmbus_i2c_packet); - break; - case IOCTL_MXSMBUS_I2C: // i2c r/w - log_misc("mxsmbus", - "DeviceIoControl(, , 0x%p, 0x%x, -, 0x%x, " - "-, -)", - lpInBuffer, nInBufferSize, nOutBufferSize); - - log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)", - request_packet->addr, request_packet->prt, request_packet->dlen, - request_packet->reg); - // log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[0], - // dwordInBuffer[1], dwordInBuffer[2], dwordInBuffer[3]); - // log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[4], - // dwordInBuffer[5], dwordInBuffer[6], dwordInBuffer[7]); - // log_warning("eeprom", "%08x %08x", dwordInBuffer[8], - // dwordInBuffer[9]); - - // for (int i = 0; i < nInBufferSize; i++) { - // printf("%02x ", ((LPBYTE)lpInBuffer)[i]); - // } - // puts(""); - - // prt = byteInBuffer[1]; - // addr = wordInBuffer[1]; - // reg = wordInBuffer[2] & 0xFF; - dlen = request_packet->dlen; - if (dlen > 0x20) dlen = 0x20; - - /* - * Known addresses: - * - 0x57: EEPROM - **/ - - request_packet->status = MXSBUS_OKAY; - - if (request_packet->status != 0) { - log_error("mxsmbus", "invalid i2c packet"); + case IOCTL_MXSMBUS_I2C: { + BYTE command = ((BYTE*)lpInBuffer)[1]; + if (command > 10) { + ((BYTE*)lpOutBuffer)[0] = 0x19; return FALSE; } - - if (request_packet->addr != SMBUS_EEPROM) { - log_error("mxsmbus", "Unexpected I2C device: 0x%02x", request_packet->addr); - exit(1); - } - // 04 = Write byte - // 05 = Read byte - // - // 08 = Write block - // 09 = Read block - - if (request_packet->prt == 0x08) { - // Write - log_misc("mxsmbus", "eeprom write %02x (0x%04x)", dlen, request_packet->reg); - // for (int i = 0; i < dlen; i++) printf("%02x ", - // request_packet->data[i]); puts(""); - - eeprom_write((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f, - request_packet->data, request_packet->dlen); - request_out->status = 0; - } else if (i2c_packet->prt == 0x09) { - // Read - log_misc("mxsmbus", "eeprom read %02x (0x%04x)", dlen, request_packet->reg); - eeprom_read((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f, - request_out->data, dlen); - // for (int i = 0; i < dlen; i++) printf("%02x ", - // request_out->data[i]); puts(""); - request_out->status = 0; + if (handle_smbus(lpInBuffer)) { + ((BYTE*)lpOutBuffer)[0] = 0x00; + return TRUE; } else { - log_warning("mxsmbus", "UNHANDLED MXSMBUS I2C %02x", request_packet->prt); - exit(1); + ((BYTE*)lpOutBuffer)[0] = 0x01; + return FALSE; + }; + } + case IOCTL_MXSMBUS_REQUEST: { + BYTE command = ((BYTE*)lpInBuffer)[1]; + if (command > 11) { + ((BYTE*)lpOutBuffer)[0] = 0x19; + return FALSE; } - - if (lpBytesReturned) *lpBytesReturned = sizeof(mxsmbus_request_packet); - break; + if (handle_smbus(lpInBuffer)) { + ((BYTE*)lpOutBuffer)[0] = 0x00; + return TRUE; + } else { + ((BYTE*)lpOutBuffer)[0] = 0x01; + return FALSE; + }; + } default: log_warning("mxsmbus", "unhandled 0x%08x", dwIoControlCode); return FALSE; diff --git a/src/micetools/dll/drivers/mxsram.c b/src/micetools/dll/drivers/mxsram.c index 6cd8fb6..6bc0386 100644 --- a/src/micetools/dll/drivers/mxsram.c +++ b/src/micetools/dll/drivers/mxsram.c @@ -73,7 +73,6 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer } DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { - printf("MXSRSFP %08x\n", lDistanceToMove); if (dwMoveMethod == FILE_BEGIN) { SRAM_POINTER = lDistanceToMove; } else if (dwMoveMethod == FILE_CURRENT) { diff --git a/src/micetools/dll/drivers/mxsuperio.c b/src/micetools/dll/drivers/mxsuperio.c index c80e5c8..a3b6d7f 100644 --- a/src/micetools/dll/drivers/mxsuperio.c +++ b/src/micetools/dll/drivers/mxsuperio.c @@ -1,7 +1,8 @@ +#include "mxsuperio.h" + #include "mx.h" -#include "smbus.h" -#include "w83791d.h" #include "w83627uhg.h" +#include "w83791d.h" BYTE w83791d_bank = 0x00; BYTE w83791d_config = W83791D_CONFIG_START; @@ -22,361 +23,314 @@ BYTE w83627uhg_systin_target = 0x00; BYTE w83627uhg_cputin_target = 0x00; BYTE w83627uhg_target_tolerance = 0x00; +// Configuration 0: Logical address 2E +// Configuration 1: Logical address 4E +// Neither of these values are needed because we aren't talking to a real chip! +#define LPC_CONFIGURATION 1 + +BYTE hwmon_read(superio_packet* packet) { + BYTE index = packet->index; + BYTE reg = packet->reg; + + switch (w83791d_bank) { + case 0x00: { + switch (reg) { + case W83627UHG_REG_FAN_CONF: + return w83627uhg_fanconf; + case W83627UHG_REG_FAN_CONF_2: + return w83627uhg_fanconf_2; + case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT: + return w83627uhg_cpufanout_src_slct; + case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT: + return w83627uhg_sysfanout_src_slct; + case W83627UHG_REG_SYSTIN_TARGET_TEMP: + return w83627uhg_systin_target; + case W83627UHG_REG_CPUTIN_TARGET_TEMP: + return w83627uhg_cputin_target; + case W83627UHG_REG_TARGET_TEMP_TOLERANCE: + return w83627uhg_target_tolerance; + + case W83791D_REG_WCHIPID: + return 0x71; // Observed: c1 + case W83791D_REG_CHIPMAN: + if (w83791d_4f_high) + return 0x5c; // High byte + else + return 0xa3; // Low byte + case W83791D_REG_I2C_ADDR: + return 0x11; // Observed: 2d + case W83791D_REG_BANK: + return w83791d_bank; + + case W83791D_REG_CONFIG: + return w83791d_config; + + case W83791D_REG_BEEP_CTRL_0: + // No beeping :( + return 0x00; + + // TODO: No idea how to read any of these. Pulled from real system + case W83791D_REG_TEMP1_0: + return 0x1a; + case W83791D_RAM_VCOREA: + return 0x76; + case W83791D_RAM_VNIR0: + return 0x86; + case W83791D_RAM_VDD5: + return 0x94; + case W83791D_RAM_12VIN: + return 0xbe; + case W83791D_RAM_N12VIN: + return 0xd1; + + case W83791D_RAM_FAN1: + case W83791D_RAM_FAN2: + case W83791D_RAM_FAN3: + return 0x00; // Fan no spinny! + + case W83791D_VID_FAN_DIV: + // Boths fans divide by 2 (01) + return 0b00000101; + + case W83791D_VBAT_MONITOR_CONTROL: + return w83791d_vbat_monitor_control; + + default: + log_error("mxsuperio", "Unknown HM b0 register: read 0x%02x", reg); + return 0xff; + } + } break; + case 0x01: { + switch (reg) { + case W83791D_REG_BANK: + return w83791d_bank; + + case W83791D_NONCRIT_TEMP_1: + return w83791d_noncrit_t1; + case W83791D_CRIT_TEMP_1: + return w83791d_crit_t1; + case W83791D_NONCRIT_TEMP_2: + return w83791d_noncrit_t2; + case W83791D_CRIT_TEMP_2: + return w83791d_crit_t2; + case W83791D_NONCRIT_TEMP_3: + return w83791d_noncrit_t3; + case W83791D_CRIT_TEMP_3: + return w83791d_crit_t3; + + case W83791D_VIN0: + return W83791D_ENTITY_CPU; + case W83791D_VIN1: + return W83791D_ENTITY_SYSTEM; + + default: + log_error("mxsuperio", "Unknown HM b1 register: 0x%02x", reg); + exit(1); + } + } break; + case 0x05: { + switch (reg) { + case W83791D_REG_BANK: + return w83791d_bank; + + // Used in amHmReadVoltageInternal + // What are these?? + case 0x51: + case 0x40: + return 0xff; + + default: + log_error("mxsuperio", "Unknown HM b5 register: 0x%02x", reg); + return 0xff; + } + } break; + default: + log_error("mxsuperio", "Unknown HM bank: 0x%02x", w83791d_bank); + exit(1); + } +} + +void hwmon_write(superio_packet* packet) { + switch (w83791d_bank) { + case 0x00: { + switch (packet->reg) { + case W83627UHG_REG_FAN_CONF: + w83627uhg_fanconf = packet->data; + break; + case W83627UHG_REG_FAN_CONF_2: + w83627uhg_fanconf_2 = packet->data; + break; + case W83627UHG_REG_CPUFANOUT_VALUE_SELECT: + // Just no-op this + break; + case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT: + w83627uhg_cpufanout_src_slct = packet->data; + break; + case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT: + w83627uhg_sysfanout_src_slct = packet->data; + break; + case W83627UHG_REG_SYSTIN_TARGET_TEMP: + w83627uhg_systin_target = packet->data; + break; + case W83627UHG_REG_CPUTIN_TARGET_TEMP: + w83627uhg_cputin_target = packet->data; + break; + case W83627UHG_REG_TARGET_TEMP_TOLERANCE: + w83627uhg_target_tolerance = packet->data; + break; + case W83627UHG_REG_SYSFANOUT_STOP_VALUE: + case W83627UHG_REG_SYSFANOUT_START_VALUE: + break; + + case W83791D_REG_BEEP_CTRL_0: + // Ignore for now + break; + + case W83791D_REG_BANK: + w83791d_4f_high = !!(packet->data & 0x80); + w83791d_bank = packet->data & 7; + break; + case W83791D_REG_CONFIG: + w83791d_config = packet->data; + break; + case W83791D_VBAT_MONITOR_CONTROL: + w83791d_vbat_monitor_control = packet->data; + break; + default: + log_error("mxsuperio", "Unknown HM b0 register: write 0x%02x", packet->reg); + // exit(1); + } + break; + } + case 0x01: { + switch (packet->reg) { + case W83791D_REG_BANK: + w83791d_4f_high = !!(packet->data & 0x80); + w83791d_bank = packet->data & 7; + break; + + case W83791D_NONCRIT_TEMP_1: + w83791d_noncrit_t1 = packet->data; + break; + case W83791D_CRIT_TEMP_1: + w83791d_crit_t1 = packet->data; + break; + case W83791D_NONCRIT_TEMP_2: + w83791d_noncrit_t2 = packet->data; + break; + case W83791D_CRIT_TEMP_2: + w83791d_crit_t2 = packet->data; + break; + case W83791D_NONCRIT_TEMP_3: + w83791d_noncrit_t3 = packet->data; + break; + case W83791D_CRIT_TEMP_3: + w83791d_crit_t3 = packet->data; + break; + + default: + log_error("mxsuperio", "Unknown HM b1 register: 0x%02x", packet->reg); + exit(1); + } + } break; + case 0x05: { + switch (packet->reg) { + case W83791D_REG_BANK: + w83791d_4f_high = !!(packet->data & 0x80); + w83791d_bank = packet->data & 7; + break; + + // Used in amHmReadVoltageInternal + // What is this?? + case 0x40: + break; + + default: + log_error("mxsuperio", "Unknown HM b5 register: 0x%02x", packet->reg); + return; + } + } break; + default: + log_error("mxsuperio", "Unknown HM bank: 0x%02x", w83791d_bank); + exit(1); + } +} + BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - mxsuperio_lpc_packet* lpc_packet = (mxsuperio_lpc_packet*)lpInBuffer; - mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer; + superio_packet* lpc_packet = (superio_packet*)lpInBuffer; + superio_packet* lpc_out = (superio_packet*)lpOutBuffer; switch (dwIoControlCode) { - case IOCTL_MXSUPERIO_PING: - log_misc("mxsuperio", - "DeviceIoControl(, , 0x%p, 0x%x, -, " - "0x%x, -, -)", - lpInBuffer, nInBufferSize, nOutBufferSize); - + case IOCTL_MXSUPERIO_PING: { ((LPDWORD)lpOutBuffer)[0] = 0x01000001; if (lpBytesReturned) *lpBytesReturned = 4; break; + } case IOCTL_MXSUPERIO_READ: { - BYTE chip = ((LPBYTE)lpInBuffer)[0]; - BYTE device = ((LPBYTE)lpInBuffer)[1]; - BYTE index = ((LPBYTE)lpInBuffer)[2]; - BYTE* data = &((LPBYTE)lpInBuffer)[3]; + superio_lpc_packet* packet = (superio_lpc_packet*)(lpInBuffer); + if (lpBytesReturned) *lpBytesReturned = sizeof *packet; + packet->data = 0xff; - log_misc("mxsuperio", "read: chip:%d device:%d index:%02x", chip, device, index); + if (packet->chip != LPC_CONFIGURATION) goto W83627UHG_processed; - /* - { - IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e) - IN BYTE logical device (0 = FDC, 11 = HW mon) - IN BYTE index - OUT BYTE read value + // TODO: Is just emulating the chip ID enough? + + // Global registers + switch (packet->reg) { + case 0x20: // Chip ID MSB + packet->data = 0xa2; + goto W83627UHG_processed; + case 0x21: // Chip ID LSB + packet->data = 0x32; + goto W83627UHG_processed; } - - The 846-5004D I have here is at base address 0x4e - */ - - /* - from micedump: - 0.20: 00 0b 20 ff - 0.21: 00 0b 21 ff - 1.20: 01 0b 20 a2 - 1.21: 01 0b 21 32 - */ - - *data = 0xff; - if (chip == 1) { - if (device == 11) { - switch (index) { - case 0x20: - *data = 0xa2; - break; - case 0x21: - *data = 0x32; - break; - } - } + // Device specific registers + switch (packet->device) { + // } - - if (lpBytesReturned) *lpBytesReturned = 4; + W83627UHG_processed: + log_misc("mxsuperio", "read: chip:%d device:%d reg:%02x data:%02x", packet->chip, + packet->device, packet->reg, packet->data); break; } - case IOCTL_MXSUPERIO_WRITE: - log_misc("mxsuperio", - "DeviceIoControl(, , 0x%p, 0x%x, -, " - "0x%x, -, -)", - lpInBuffer, nInBufferSize, nOutBufferSize); + case IOCTL_MXSUPERIO_WRITE: { + superio_lpc_packet* packet = (superio_lpc_packet*)(lpInBuffer); + if (lpBytesReturned) *lpBytesReturned = sizeof *packet; + + log_misc("mxsuperio", "write: chip:%d device:%d reg:%02x data:%02x", packet->chip, + packet->device, packet->reg, packet->data); + + // TODO: Are there any writes we need to process? - /* - { - IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e) - IN BYTE logical device (0 = FPC, 11 = HW mon) - IN BYTE index - IN BYTE write value - } - */ - if (lpBytesReturned) *lpBytesReturned = 4; break; + } case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: { // TODO: This code is all for W83791D, however W83627UHG is more appropriate in some // cases. Is this an AAL vs AAM difference? Where was the W83791D usage derived from? - BYTE index = lpc_packet->index; - BYTE reg = lpc_packet->reg; - - switch (w83791d_bank) { - case 0x00: { - switch (reg) { - case W83627UHG_REG_FAN_CONF: - lpc_out->data = w83627uhg_fanconf; - break; - case W83627UHG_REG_FAN_CONF_2: - lpc_out->data = w83627uhg_fanconf_2; - break; - case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT: - lpc_out->data = w83627uhg_cpufanout_src_slct; - break; - case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT: - lpc_out->data = w83627uhg_sysfanout_src_slct; - break; - case W83627UHG_REG_SYSTIN_TARGET_TEMP: - lpc_out->data = w83627uhg_systin_target; - break; - case W83627UHG_REG_CPUTIN_TARGET_TEMP: - lpc_out->data = w83627uhg_cputin_target; - break; - case W83627UHG_REG_TARGET_TEMP_TOLERANCE: - lpc_out->data = w83627uhg_target_tolerance; - break; - - case W83791D_REG_WCHIPID: - lpc_out->data = 0x71; // Observed: c1 - break; - case W83791D_REG_CHIPMAN: - if (w83791d_4f_high) - lpc_out->data = 0x5c; // High byte - else - lpc_out->data = 0xa3; // Low byte - break; - case W83791D_REG_I2C_ADDR: - lpc_out->data = 0x11; // Observed: 2d - break; - case W83791D_REG_BANK: - lpc_out->data = w83791d_bank; - break; - - case W83791D_REG_CONFIG: - lpc_out->data = w83791d_config; - break; - - case W83791D_REG_BEEP_CTRL_0: - // No beeping :( - lpc_out->data = 0x00; - break; - - // TODO: No idea how to read any of these. Pulled from real system - case W83791D_REG_TEMP1_0: - lpc_out->data = 0x1a; - break; - case W83791D_RAM_VCOREA: - lpc_out->data = 0x76; - break; - case W83791D_RAM_VNIR0: - lpc_out->data = 0x86; - break; - case W83791D_RAM_VDD5: - lpc_out->data = 0x94; - break; - case W83791D_RAM_12VIN: - lpc_out->data = 0xbe; - break; - case W83791D_RAM_N12VIN: - lpc_out->data = 0xd1; - break; - - case W83791D_RAM_FAN1: - case W83791D_RAM_FAN2: - case W83791D_RAM_FAN3: - lpc_out->data = 0x00; // Fan no spinny! - break; - - case W83791D_VID_FAN_DIV: - // Boths fans divide by 2 (01) - lpc_out->data = 0b00000101; - break; - - case W83791D_VBAT_MONITOR_CONTROL: - lpc_out->data = w83791d_vbat_monitor_control; - break; - - default: - log_error("mxsuperio", "Unknown HM b0 register: read 0x%02x", reg); - return FALSE; - // exit(1); - } - } break; - case 0x01: { - switch (reg) { - case W83791D_REG_BANK: - lpc_out->data = w83791d_bank; - break; - - case W83791D_NONCRIT_TEMP_1: - lpc_out->data = w83791d_noncrit_t1; - break; - case W83791D_CRIT_TEMP_1: - lpc_out->data = w83791d_crit_t1; - break; - case W83791D_NONCRIT_TEMP_2: - lpc_out->data = w83791d_noncrit_t2; - break; - case W83791D_CRIT_TEMP_2: - lpc_out->data = w83791d_crit_t2; - break; - case W83791D_NONCRIT_TEMP_3: - lpc_out->data = w83791d_noncrit_t3; - break; - case W83791D_CRIT_TEMP_3: - lpc_out->data = w83791d_crit_t3; - break; - - case W83791D_VIN0: - lpc_out->data = W83791D_ENTITY_CPU; - break; - case W83791D_VIN1: - lpc_out->data = W83791D_ENTITY_SYSTEM; - break; - - default: - log_error("mxsuperio", "Unknown HM b1 register: 0x%02x", reg); - exit(1); - } - } break; - case 0x05: { - switch (reg) { - case W83791D_REG_BANK: - lpc_out->data = w83791d_bank; - break; - - // Used in amHmReadVoltageInternal - // What are these?? - case 0x51: - case 0x40: - lpc_out->data = 0xff; - break; - - default: - log_error("mxsuperio", "Unknown HM b5 register: 0x%02x", reg); - return FALSE; - // exit(1); - } - } break; - default: - log_error("mxsuperio", "Unknown HM bank: 0x%02x", w83791d_bank); - exit(1); - } // reg 0x48 = LPC Chip ID // index = 0,1 // data > 0x0f, data < 0x70 - // lpc_out->data = eeprom_read_one(reg, index); - log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg, - lpc_out->data); + if (lpc_packet->index == LPC_CONFIGURATION) { + lpc_out->data = hwmon_read(lpc_packet); + } else { + lpc_out->data = 0xff; + } + log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", + lpc_packet->index, lpc_packet->reg, lpc_out->data); - if (lpBytesReturned) *lpBytesReturned = sizeof(mxsuperio_lpc_packet); + if (lpBytesReturned) *lpBytesReturned = sizeof *lpc_out; } break; case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: { - BYTE index = lpc_packet->index; - BYTE reg = lpc_packet->reg; - log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index, - reg, lpc_packet->data); + log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", + lpc_packet->index, lpc_packet->reg, lpc_packet->data); - switch (w83791d_bank) { - case 0x00: { - switch (reg) { - case W83627UHG_REG_FAN_CONF: - w83627uhg_fanconf = lpc_packet->data; - break; - case W83627UHG_REG_FAN_CONF_2: - w83627uhg_fanconf_2 = lpc_packet->data; - break; - case W83627UHG_REG_CPUFANOUT_VALUE_SELECT: - // Just no-op this - break; - case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT: - w83627uhg_cpufanout_src_slct = lpc_packet->data; - break; - case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT: - w83627uhg_sysfanout_src_slct = lpc_packet->data; - break; - case W83627UHG_REG_SYSTIN_TARGET_TEMP: - w83627uhg_systin_target = lpc_packet->data; - break; - case W83627UHG_REG_CPUTIN_TARGET_TEMP: - w83627uhg_cputin_target = lpc_packet->data; - break; - case W83627UHG_REG_TARGET_TEMP_TOLERANCE: - w83627uhg_target_tolerance = lpc_packet->data; - break; - case W83627UHG_REG_SYSFANOUT_STOP_VALUE: - case W83627UHG_REG_SYSFANOUT_START_VALUE: - break; - - case W83791D_REG_BEEP_CTRL_0: - // Ignore for now - break; - - case W83791D_REG_BANK: - w83791d_4f_high = !!(lpc_packet->data & 0x80); - w83791d_bank = lpc_packet->data & 7; - break; - case W83791D_REG_CONFIG: - w83791d_config = lpc_packet->data; - break; - case W83791D_VBAT_MONITOR_CONTROL: - w83791d_vbat_monitor_control = lpc_packet->data; - break; - default: - log_error("mxsuperio", "Unknown HM b0 register: write 0x%02x", reg); - // exit(1); - } - break; - } - case 0x01: { - switch (reg) { - case W83791D_REG_BANK: - w83791d_4f_high = !!(lpc_packet->data & 0x80); - w83791d_bank = lpc_packet->data & 7; - break; - - case W83791D_NONCRIT_TEMP_1: - w83791d_noncrit_t1 = lpc_packet->data; - break; - case W83791D_CRIT_TEMP_1: - w83791d_crit_t1 = lpc_packet->data; - break; - case W83791D_NONCRIT_TEMP_2: - w83791d_noncrit_t2 = lpc_packet->data; - break; - case W83791D_CRIT_TEMP_2: - w83791d_crit_t2 = lpc_packet->data; - break; - case W83791D_NONCRIT_TEMP_3: - w83791d_noncrit_t3 = lpc_packet->data; - break; - case W83791D_CRIT_TEMP_3: - w83791d_crit_t3 = lpc_packet->data; - break; - - default: - log_error("mxsuperio", "Unknown HM b1 register: 0x%02x", reg); - exit(1); - } - } break; - case 0x05: { - switch (reg) { - case W83791D_REG_BANK: - w83791d_4f_high = !!(lpc_packet->data & 0x80); - w83791d_bank = lpc_packet->data & 7; - break; - - // Used in amHmReadVoltageInternal - // What is this?? - case 0x40: - break; - - default: - log_error("mxsuperio", "Unknown HM b5 register: 0x%02x", reg); - return FALSE; - // exit(1); - } - } break; - default: - log_error("mxsuperio", "Unknown HM bank: 0x%02x", w83791d_bank); - exit(1); + if (lpc_packet->index == LPC_CONFIGURATION) { + hwmon_write(lpc_packet); } - if (lpBytesReturned) *lpBytesReturned = 0; } break; default: diff --git a/src/micetools/dll/drivers/mxsuperio.h b/src/micetools/dll/drivers/mxsuperio.h new file mode 100644 index 0000000..72addf5 --- /dev/null +++ b/src/micetools/dll/drivers/mxsuperio.h @@ -0,0 +1,17 @@ +#pragma once +#include "common.h" + +#pragma pack(1) +typedef struct { + BYTE index; + BYTE reg; + BYTE data; +} superio_packet; + +#pragma pack(1) +typedef struct { + BYTE chip; + BYTE device; + BYTE reg; + BYTE data; +} superio_lpc_packet; diff --git a/src/micetools/dll/gui/gui.c b/src/micetools/dll/gui/gui.c new file mode 100644 index 0000000..7919940 --- /dev/null +++ b/src/micetools/dll/gui/gui.c @@ -0,0 +1,132 @@ +#include "../hooks/gui.h" + +#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS +#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS +#endif +#include "cimgui.h" + +BOOL initialized = false; +BOOL haveFirstFrame = false; +static HWND window; + +extern bool ImGui_ImplWin32_Init(void* hwnd); +extern void ImGui_ImplWin32_Shutdown(); +extern void ImGui_ImplWin32_NewFrame(); + +extern bool ImGui_ImplDX9_Init(IDirect3DDevice9* device); +extern void ImGui_ImplDX9_Shutdown(); +extern void ImGui_ImplDX9_NewFrame(); +extern void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); +extern bool ImGui_ImplDX9_GetCP(IDirect3DDevice9* pDevice, D3DDEVICE_CREATION_PARAMETERS* CP); + +extern CRITICAL_SECTION logger_lock; + +void InitImGui(IDirect3DDevice9* pDevice) { + D3DDEVICE_CREATION_PARAMETERS CP; + ImGui_ImplDX9_GetCP(pDevice, &CP); + window = CP.hFocusWindow; + + igCreateContext(NULL); + ImGuiIO* io = igGetIO(); + io->IniFilename = NULL; + io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; + ImFontAtlas_AddFontDefault(io->Fonts, NULL); + + ImGui_ImplWin32_Init(window); + ImGui_ImplDX9_Init(pDevice); + initialized = true; + return; +} + +extern int jvs_buttons[2][16]; +extern BOOL JVS_SENSE; +void jvs_tab() { + int coin_count_1 = 0; + int coin_count_2 = 0; + + igText("Player 1 Coins: %d", coin_count_1); + igText("Player 2 Coins: %d", coin_count_2); + igSeparator(); + igText("Sense: %d", JVS_SENSE); + igSeparator(); + ImVec4 white = { 1.0, 1.0, 1.0, 1.0 }; + ImVec4 red = { 1.0, 0.0, 0.0, 1.0 }; + + igColumns(5, NULL, true); + // for (auto s : scancodes) { + // igTextColored((GetKeyState(s.second) < 0) ? red : white, "%s: %x", s.first, s.second); + // igNextColumn(); + // } + igColumns(1, NULL, true); + igColumns(8, NULL, true); + for (int player = 0; player < 2; player++) { + for (int button = 0; button < 16; button++) { + int scan = jvs_buttons[player][button]; + igTextColored((GetKeyState(scan) < 0) ? red : white, "p%d_%02d: %02x", player, button, scan); + igNextColumn(); + } + } + igColumns(1, NULL, true); + + igSeparator(); + igText("JVS Count"); + // for (auto c : jvsCount) { + // igText("%x: %d", c.first, c.second); + // } + igSeparator(); + igText("Comio Count"); + // for (auto c : comioCount) { + // igText("%x: %d", c.first, c.second); + // } +} + + +void hud_gui(IDirect3DDevice9* dev) { + static bool showMenu = false; + + // if (GetAsyncKeyState(scancodes["openMenu"]) & 1) { + // showMenu = !showMenu; + // } + + if (!initialized) { + InitImGui(dev); + return; + } + // if (!showMenu) return; + + ImGui_ImplDX9_NewFrame(); + ImGui_ImplWin32_NewFrame(); + + igNewFrame(); + + igBegin("maimai control", NULL, 0); + if (!haveFirstFrame) { + ImVec2 size = { 600, 700 }; + igSetWindowSize_Vec2(size, 0); + haveFirstFrame = true; + } + + EnterCriticalSection(&logger_lock); + + if (igBeginTabBar("MainTabs", 0)) { + if (igBeginTabItem("Logs", NULL, 0)) { + // log_tab(); + igEndTabItem(); + } + if (igBeginTabItem("JVS", NULL, 0)) { + jvs_tab(); + igEndTabItem(); + } + igEndTabBar(); + } + + LeaveCriticalSection(&logger_lock); + + igEnd(); + + igEndFrame(); + igRender(); + ImGui_ImplDX9_RenderDrawData(igGetDrawData()); +} + +void setup_hud_gui() { register_gui_hook(&hud_gui); } diff --git a/src/micetools/dll/gui/meson.build b/src/micetools/dll/gui/meson.build new file mode 100644 index 0000000..aae5d3b --- /dev/null +++ b/src/micetools/dll/gui/meson.build @@ -0,0 +1,3 @@ +gui_files = files( + 'gui.c', +) diff --git a/src/micetools/dll/hooks/_hooks.c b/src/micetools/dll/hooks/_hooks.c index 2ff66c7..f31f17b 100644 --- a/src/micetools/dll/hooks/_hooks.c +++ b/src/micetools/dll/hooks/_hooks.c @@ -1,14 +1,18 @@ #include "_hooks.h" void hook_all() { - hook_logging(); - hook_gui(); - hook_setupapi(); - hook_commio(); - hook_io(); - hook_processes(); - hook_network(); - hook_time(); - hook_registry(); - hook_drives(); + if (MiceConfig.hooks.logging) hook_logging(); + if (MiceConfig.hooks.gui) { + hook_gui(); + setup_hud_gui(); + } + if (MiceConfig.hooks.setupapi) hook_setupapi(); + if (MiceConfig.hooks.commio) hook_commio(); + if (MiceConfig.hooks.io) hook_io(); + if (MiceConfig.hooks.processes) hook_processes(); + if (MiceConfig.hooks.network) hook_network(); + if (MiceConfig.hooks.time) hook_time(); + if (MiceConfig.hooks.registry) hook_registry(); + if (MiceConfig.hooks.drives) hook_drives(); + hook_system(); } diff --git a/src/micetools/dll/hooks/_hooks.h b/src/micetools/dll/hooks/_hooks.h index 7643c6e..10d30c3 100644 --- a/src/micetools/dll/hooks/_hooks.h +++ b/src/micetools/dll/hooks/_hooks.h @@ -10,5 +10,6 @@ #include "time.h" #include "registry.h" #include "drive.h" +#include "system.h" void hook_all(); diff --git a/src/micetools/dll/hooks/drive.c b/src/micetools/dll/hooks/drive.c index 466a48b..5c4c5d7 100644 --- a/src/micetools/dll/hooks/drive.c +++ b/src/micetools/dll/hooks/drive.c @@ -14,14 +14,29 @@ BOOL c_drive_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe return TRUE; case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1; - ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].StartingOffset.QuadPart = 0; - DWORD a = (sizeof(*((VOLUME_DISK_EXTENTS*)lpOutBuffer))); + ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].DiskNumber = 0; return TRUE; default: return FALSE; } } +BOOL x_drive_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + log_trace("X", "DeviceIOControl %08x", dwIoControlCode); + memset(lpOutBuffer, 0, nInBufferSize); + switch (dwIoControlCode) { + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0; + return TRUE; + default: + log_warning("X", "Unhandled DeviceIOControl %08x", dwIoControlCode); + return FALSE; + } +} + LARGE_INTEGER pd0_file_pointer; BOOL pd0_SetFilePointerEx(void* file, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) { @@ -225,6 +240,11 @@ typedef struct { uint8_t type; spd_slot_t content; } partition_t; +#define PARITION_OS 0 +#define PARITION_PATCH0 1 +#define PARITION_PATCH1 2 +#define PARITION_APP_DATA 3 +#define PARITION_ORIGINAL0 4 partition_t partitions[] = { { 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update { 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0 @@ -239,23 +259,93 @@ partition_t partitions[] = { #define BLOCKSIZE 512ll #define SPD_OFFSET ((extended_base * BLOCKSIZE) + sizeof(mbr_t)) -#define SBR0_OFFSET (SPD_OFFSET + sizeof (spd_t)) +#define SBR0_OFFSET (SPD_OFFSET + sizeof(spd_t)) #define SBR1_OFFSET (SBR0_OFFSET + sizeof SegaBootRecord) +/* + First 512 bytes of SPD_Original0: + LOADER::LoadBootIDHeader +*/ + +BYTE Original0BootIDHeader[512] = { + 0x4B, 0xDF, 0xB4, 0x43, 0x27, 0x3C, 0xFE, 0xD6, 0xA2, 0xA8, 0xF8, 0xFD, 0xB4, 0x55, 0xE6, 0xBA, + 0x5A, 0x0F, 0xBF, 0x14, 0xA4, 0x37, 0xB6, 0x42, 0xB3, 0xAD, 0x11, 0x4A, 0xCA, 0x1A, 0x4C, 0xD9, + 0x11, 0xF1, 0x60, 0x4B, 0x37, 0x58, 0x9C, 0x9A, 0x89, 0x8F, 0x07, 0x9C, 0xE7, 0xF2, 0x64, 0xCC, + 0x6E, 0x84, 0x87, 0xAA, 0x20, 0xA0, 0xB8, 0x55, 0x9B, 0xE7, 0x79, 0x4F, 0x51, 0x25, 0xC3, 0x7E, + 0xEF, 0xD9, 0x25, 0xA9, 0x94, 0xF1, 0x7F, 0xEF, 0xE1, 0xD9, 0xAE, 0x4F, 0xC2, 0xEE, 0xB6, 0xA8, + 0xD9, 0x54, 0x0F, 0x33, 0xA8, 0xA9, 0x22, 0x72, 0x81, 0xD0, 0xA3, 0x04, 0x5C, 0x45, 0x3E, 0xBE, + 0xF7, 0x2A, 0xED, 0x55, 0xAB, 0x16, 0xC1, 0xA8, 0x61, 0x70, 0xEE, 0x55, 0xCB, 0xE6, 0x68, 0xA5, + 0xB4, 0xDC, 0x30, 0x6D, 0x32, 0xD6, 0x69, 0x8D, 0xFC, 0x90, 0x71, 0x7E, 0xDB, 0x6B, 0x17, 0xFA, + 0xAB, 0xE0, 0x11, 0x14, 0xBA, 0xD9, 0x33, 0xB7, 0x7C, 0x54, 0x9E, 0x21, 0xA1, 0x43, 0xFD, 0x8F, + 0x14, 0xF4, 0xBE, 0x5F, 0x0B, 0x02, 0x8E, 0x87, 0xCA, 0x85, 0xE9, 0xC1, 0x60, 0xF7, 0x7E, 0x44, + 0x55, 0x3A, 0x5E, 0x94, 0x65, 0x95, 0xFD, 0x02, 0xF9, 0xFF, 0xBF, 0x07, 0x80, 0xC5, 0x26, 0x58, + 0x6F, 0x37, 0xFA, 0x59, 0x2F, 0x02, 0xF3, 0x9D, 0x24, 0x7D, 0x42, 0x6B, 0xF3, 0x49, 0x63, 0xC9, + 0x2A, 0xCB, 0xFC, 0x71, 0x69, 0x44, 0xB5, 0xAC, 0xD3, 0x37, 0xA0, 0x01, 0x65, 0x3D, 0x49, 0xC4, + 0x7D, 0xE5, 0xF8, 0x6E, 0x09, 0xC7, 0x3E, 0xD1, 0x96, 0x09, 0x23, 0xA4, 0xE8, 0xA5, 0x6A, 0xA2, + 0x5B, 0x5B, 0xA5, 0x9C, 0xF8, 0x8D, 0x84, 0x55, 0x3F, 0x19, 0x8F, 0xDC, 0xFA, 0x7B, 0xF1, 0xC9, + 0xB6, 0xBF, 0xE8, 0x73, 0xB9, 0xC9, 0xC3, 0x17, 0x14, 0xAB, 0xA3, 0x60, 0x13, 0xED, 0x6D, 0xCC, + 0x10, 0x7B, 0x1D, 0xC6, 0xBC, 0xEC, 0x56, 0xFA, 0x52, 0xC5, 0x4E, 0xAC, 0x8F, 0x36, 0x8B, 0x92, + 0x6C, 0xB5, 0x9A, 0x57, 0x7D, 0xFA, 0x97, 0x72, 0xFC, 0xFA, 0xB8, 0xFE, 0x20, 0x71, 0xFB, 0x63, + 0x00, 0x96, 0x29, 0xCE, 0xE2, 0x06, 0xFF, 0x64, 0x48, 0xB5, 0x1F, 0xD6, 0x88, 0x48, 0x7A, 0x62, + 0x2B, 0xBE, 0xE6, 0xC4, 0xFD, 0xF6, 0x85, 0x45, 0x0A, 0x8C, 0x6C, 0x20, 0x64, 0x05, 0x81, 0x13, + 0xB5, 0x59, 0xAE, 0x34, 0x41, 0x0B, 0xB5, 0x65, 0x57, 0x59, 0x9C, 0xE8, 0xD0, 0xAE, 0x81, 0xD8, + 0x6D, 0xC9, 0xFD, 0xF8, 0xC9, 0x15, 0xB6, 0xDC, 0xC9, 0x13, 0xF2, 0x6E, 0xD9, 0xA5, 0x77, 0x62, + 0xB7, 0x15, 0x61, 0x21, 0x73, 0xFE, 0x0A, 0x57, 0x3B, 0x2C, 0x2F, 0x23, 0xC3, 0x33, 0xB8, 0x77, + 0xCE, 0xCE, 0x76, 0x98, 0xDB, 0xE5, 0x9A, 0x00, 0xE1, 0xC3, 0x6F, 0x7D, 0x42, 0xC4, 0xDE, 0xB7, + 0x1D, 0xA0, 0xC1, 0x1C, 0xB9, 0x09, 0x28, 0xD9, 0x59, 0x9D, 0x3F, 0xEA, 0xF1, 0xB6, 0xA0, 0x1C, + 0x5E, 0x4A, 0xE4, 0x1A, 0xE7, 0xA7, 0x1C, 0xAD, 0xF6, 0xF1, 0xCB, 0x9C, 0x06, 0xE6, 0x4C, 0xF4, + 0xD6, 0xEE, 0x5F, 0x18, 0xF5, 0x00, 0x4A, 0x76, 0x5E, 0x7D, 0x96, 0x20, 0x57, 0x68, 0x23, 0x69, + 0x8F, 0x60, 0x91, 0xBF, 0x00, 0x08, 0xFE, 0x4F, 0x36, 0x45, 0x86, 0x14, 0x48, 0xC5, 0x8B, 0xEA, + 0xE3, 0x64, 0x27, 0x1E, 0x49, 0xDF, 0x98, 0xAD, 0xE2, 0x66, 0x09, 0x07, 0xDD, 0x24, 0xB0, 0x4D, + 0x52, 0xA6, 0xD1, 0x3D, 0xB9, 0x52, 0x0B, 0x88, 0x97, 0x97, 0x0F, 0x83, 0x85, 0xD5, 0x3F, 0x0E, + 0x1A, 0xF2, 0x26, 0xBA, 0x14, 0x53, 0xDD, 0xF4, 0x7D, 0xAF, 0xB6, 0xEE, 0x36, 0x3A, 0xB5, 0xDA, + 0x2F, 0x99, 0xC8, 0x54, 0xD2, 0xDB, 0x52, 0x49, 0xD6, 0xB6, 0x07, 0x1A, 0xBA, 0x9A, 0x85, 0xBB, +}; + +sbr_slot_t* get_sbr_slot(spd_slot_t slot) { + switch (slot) { + case SPD_Original0: + return &SegaBootRecord.slot_original0; + case SPD_Original1: + return NULL; + case SPD_Patch0: + return &SegaBootRecord.slot_patch0; + case SPD_Patch1: + return &SegaBootRecord.slot_patch1; + case SPD_OS: + return &SegaBootRecord.slot_os; + case SPD_AppData: + return &SegaBootRecord.slot_appdata; + default: + return NULL; + } +} + BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { log_info("pd0", "Read %d @ %llx", nNumberOfBytesToRead, pd0_file_pointer.QuadPart); uint32_t ext_offset = 0; uint32_t offsets[NUM_PARITIONS]; + LONGLONG slot_offsets[NUM_PARITIONS]; uint32_t extended_base = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE; for (int i = 0; i < NUM_PARITIONS; i++) { offsets[i] = ext_offset; ext_offset += partitions[i].size + MBR_LBA_GAP; + + sbr_slot_t* pslot = get_sbr_slot(partitions[i].content); + if (pslot == NULL) + slot_offsets[i] = offsets[i]; + else { + LONGLONG partition_start = (offsets[i] + extended_base + MBR_LBA_GAP) * BLOCKSIZE; + LONGLONG slot_size = (LONGLONG)pslot->segcount * (LONGLONG)pslot->segsize; + LONGLONG slot_start = partitions[i].size * BLOCKSIZE - slot_size; + slot_offsets[i] = partition_start + slot_start; + } } - printf("%08x\n", offsets[0]); - printf("%08x\n", extended_base); + printf("Offsets0: %08x\n", offsets[0]); + printf("ExtendBase: %08x\n", extended_base); // MBR (C+Recover+Extend) if (pd0_file_pointer.QuadPart == 0) { @@ -311,7 +401,6 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, return TRUE; } - crc32_build_table(); SegaBootRecord.crc = crc32(sizeof SegaBootRecord - 4, &SegaBootRecord.version, 0); // SEGA Partition Description @@ -345,6 +434,11 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } else if (pd0_file_pointer.QuadPart < (MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE) * BLOCKSIZE) { log_warning("pd0", "Game attempting to read recovery partition!"); + } else if (pd0_file_pointer.QuadPart == slot_offsets[PARITION_ORIGINAL0]) { + log_info("pd0", "Original0 BootID Header read"); + memcpy(lpBuffer, Original0BootIDHeader, sizeof Original0BootIDHeader); + *lpNumberOfBytesRead = sizeof Original0BootIDHeader; + return TRUE; } else { for (int i = 0; i < NUM_PARITIONS; i++) { if (pd0_file_pointer.QuadPart < @@ -354,7 +448,22 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, } else if (pd0_file_pointer.QuadPart < (offsets[i] + MBR_LBA_GAP + partitions[i].size + extended_base) * BLOCKSIZE) { - log_warning("pd0", "Read performed within partition %d", i + 5); + LONGLONG partition_start = (offsets[i] + extended_base + MBR_LBA_GAP) * BLOCKSIZE; + LONGLONG delta = pd0_file_pointer.QuadPart - partition_start; + + sbr_slot_t* slot = get_sbr_slot(partitions[i].content); + if (slot == NULL) { + log_warning("pd0", + "Read performed within empty partition %d (partition +%09llx)", + i + 5, delta); + } else { + LONGLONG slot_size = slot->segcount * slot->segsize; + LONGLONG slot_start = partitions[i].size * BLOCKSIZE - slot_size; + log_warning("pd0", + "Read performed within slot %d (partition +%09llx/slot +%09llx)", i, + delta, delta - slot_start); + } + goto warned; } } @@ -384,9 +493,12 @@ BOOL pd0_WriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, void hook_drives() { file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:"); c_drive->DeviceIoControl = &c_drive_DeviceIoControl; - hook_file(c_drive); + file_hook_t* x_drive = new_file_hook(L"X:"); + x_drive->DeviceIoControl = &x_drive_DeviceIoControl; + hook_file(x_drive); + file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive0"); // file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive2063598201"); // file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive1811939950"); diff --git a/src/micetools/dll/hooks/drive.h b/src/micetools/dll/hooks/drive.h index d221dd3..0148746 100644 --- a/src/micetools/dll/hooks/drive.h +++ b/src/micetools/dll/hooks/drive.h @@ -1,5 +1,5 @@ #pragma once -#include "common.h" +#include "../common.h" void hook_drives(); diff --git a/src/micetools/dll/hooks/files.c b/src/micetools/dll/hooks/files.c index 5b4933c..712f3b7 100644 --- a/src/micetools/dll/hooks/files.c +++ b/src/micetools/dll/hooks/files.c @@ -85,66 +85,12 @@ void hook_file(file_hook_t* hook) { }; drive_redirect_t DRIVE_REDIRECT_TABLE[] = { - { .drive = "Y:\\", .path = ".\\dev\\Y\\" }, - // Note: Had tp create last_shime.log + // Note: Had to create last_shime.log { .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" }, // {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"}, - - { .drive = "C:\\\\Windows\\\\System32\\", .path = "Sys32" }, - { .drive = "C:\\\\WINDOWS\\\\system32\\", .path = "Sys32" }, }; -LPCSTR redirect_path(LPCSTR path) { - for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) { - drive_redirect_t row = DRIVE_REDIRECT_TABLE[i]; - if (strstr(path, row.drive)) { - log_misc(HOOKS_LOGGER, "Redirecting '%s' to '%s'", path, row.path); - - size_t new_len = strlen(path) - strlen(row.drive) + strlen(row.path); - // TODO: Make this not leak memory! - char* new_str = (char*)malloc(new_len + 1); - strcpy_s(new_str, new_len + 1, row.path); - - char* dst = new_str + strlen(row.path); - size_t len = strlen(path) - strlen(row.drive); - const char* src = path + strlen(row.drive); - - for (; len > 0; len--) (dst++)[0] = (src++)[0]; - dst[0] = 0; - log_misc(HOOKS_LOGGER, "New filename: '%s'", new_str); - return new_str; - } - } - return path; -} -LPCWSTR redirect_path_w(LPCWSTR path) { - return path; - // TODO: THIS!! - for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) { - drive_redirect_t row = DRIVE_REDIRECT_TABLE[i]; - if (wcsstr(path, row.drive)) { - log_misc(HOOKS_LOGGER, "Redirecting '%ls' to '%ls'", path, row.path); - - size_t new_len = wcslen(path) - wcslen(row.drive) + wcslen(row.path); - // TODO: Make this not leak memory! - wchar_t* new_str = (wchar_t*)malloc((new_len + 1) * 2); - wcscpy_s(new_str, new_len + 1, row.path); - - wchar_t* dst = new_str + wcslen(row.path) * 2; - size_t len = wcslen(path) - wcslen(row.drive); - const wchar_t* src = path + wcslen(row.drive) * 2; - - for (; len > 0; len--) { - (dst++)[0] = (src++)[0]; - (dst++)[0] = (src++)[0]; - } - dst[0] = 0; - log_misc(HOOKS_LOGGER, "New filename: '%ls'", new_str); - return new_str; - } - } - return path; -} +char _redirected_path[MAX_PATH]; void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) { file_hook_t* file_hook = file_hook_list; @@ -168,6 +114,77 @@ void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_c } }; +void make_dirs(char* path) { + int count = 0; + size_t i; + size_t len = strlen(path); + while (1) { + int n = 0; + for (i = 0; i < len; i++) { + if (path[i] == '\\' || path[i] == '/' || path[i] == '\0') { + if (n++ == count) { + path[i] = '\0'; + count++; + break; + } + path[i] = '\\'; + } + } + if (i == len) return; + CreateDirectory(path, NULL); + } +} + +BOOL redirect_path(LPCSTR path, LPCSTR* redirected) { + return FALSE; + for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) { + drive_redirect_t row = DRIVE_REDIRECT_TABLE[i]; + if (strncmp(path, row.drive, strlen(row.drive)) == 0) { + log_trace(HOOKS_LOGGER, "Redirecting '%s' to '%s'", path, row.path); + + size_t new_len = strlen(path) - strlen(row.drive) + strlen(row.path); + strcpy_s(_redirected_path, new_len + 1, row.path); + + char* dst = _redirected_path + strlen(row.path); + size_t len = strlen(path) - strlen(row.drive); + const char* src = path + strlen(row.drive); + + for (; len > 0; len--) (dst++)[0] = (src++)[0]; + dst[0] = 0; + log_trace(HOOKS_LOGGER, "New filename: '%s'", _redirected_path); + + make_dirs(_redirected_path); + *redirected = _redirected_path; + return TRUE; + } + } + + if ((('a' <= path[0] && path[0] <= 'z') || ('A' <= path[0] && path[0] <= 'Z')) && + path[1] == ':' && (path[2] == '/' || path[2] == '\\')) { + char drive; + if ('A' <= path[0] && path[0] <= 'Z') { + drive = path[0] - 'A' + 'a'; + } else { + drive = path[0]; + } + ZeroMemory(_redirected_path, sizeof _redirected_path); + snprintf(_redirected_path, sizeof _redirected_path, "dev\\%c\\%s", drive, path + 3); + + make_dirs(_redirected_path); + *redirected = _redirected_path; + return TRUE; + } + + return FALSE; +} + +BOOL redirect_path_w(LPCWSTR lpFileName, LPCSTR* redirected) { + char cFileName[MAX_PATH] = { 0 }; + WideCharToMultiByte(CP_ACP, 0, lpFileName, wcslen(lpFileName), cFileName, sizeof cFileName, + NULL, NULL); + return redirect_path(cFileName, redirected); +} + HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, @@ -181,11 +198,19 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d return handle; } - lpFileName = redirect_path_w(lpFileName); + HANDLE handle; + + LPCSTR redirected; + if (redirect_path_w(lpFileName, &redirected)) { + handle = TrueCreateFileA(redirected, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + log_misc(HOOKS_LOGGER, "CreateFileW(%s) -> 0x%p", redirected, handle); + } else { + handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, + dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + log_misc(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle); + } - HANDLE handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, - dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - log_misc(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle); return handle; } HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, @@ -204,21 +229,35 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw return handle; } - lpFileName = redirect_path(lpFileName); - + redirect_path(lpFileName, &lpFileName); HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle); return handle; +} - // lpFileName = redirect_path(lpFileName); +BOOL WINAPI FakePathFileExistsA(LPCSTR pszPath) { + redirect_path(pszPath, &pszPath); + return TruePathFileExistsA(pszPath); +} +BOOL WINAPI FakePathFileExistsW(LPCSTR pszPath) { + LPCSTR redirected; + if (redirect_path(pszPath, &redirected)) { + return TruePathFileExistsA(redirected); + } + return TruePathFileExistsW(pszPath); +} - // HANDLE result = - // FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode, - // lpSecurityAttributes, - // dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); - // log_trace(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result); - // return result; +BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) { + redirect_path(pszPath, &pszPath); + return TrueDeleteFileA(pszPath); +} +BOOL WINAPI FakeDeleteFileW(LPCSTR pszPath) { + LPCSTR redirected; + if (redirect_path(pszPath, &redirected)) { + return TrueDeleteFileA(redirected); + } + return TrueDeleteFileW(pszPath); } BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, @@ -298,6 +337,12 @@ DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { + if (hFile == GetStdHandle(STD_INPUT_HANDLE) || hFile == GetStdHandle(STD_OUTPUT_HANDLE) || + hFile == GetStdHandle(STD_ERROR_HANDLE)) { + return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, + lpOverlapped); + } + log_trace("file", "WriteFile(%08x)", hFile); file_hook_t* hook = get_handle_file_hook(hFile); if (hook != NULL) { @@ -310,8 +355,7 @@ DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesT } } - return FALSE; - + // return FALSE; return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); } @@ -343,7 +387,7 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) { } int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) { - path = redirect_path((char*)path); + redirect_path((char*)path, &path); return True_stat64i32(path, buffer); }; @@ -361,5 +405,10 @@ void hook_io() { hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6); hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 6); + hook("Shlwapi.dll", "PathFileExistsA", FakePathFileExistsA, (void**)&TruePathFileExistsA, 5); + hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW, 5); + hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA, 5); + hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW, 5); + hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5); } diff --git a/src/micetools/dll/hooks/files.h b/src/micetools/dll/hooks/files.h index 38234d7..c746e1a 100644 --- a/src/micetools/dll/hooks/files.h +++ b/src/micetools/dll/hooks/files.h @@ -28,6 +28,10 @@ static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOf LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize); static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject); +static BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath); +static BOOL(WINAPI* TruePathFileExistsW)(LPCWSTR pszPath); +static BOOL(WINAPI* TrueDeleteFileA)(LPCSTR lpFileName); +static BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName); typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, diff --git a/src/micetools/dll/hooks/gui.c b/src/micetools/dll/hooks/gui.c index d8c3227..011158d 100644 --- a/src/micetools/dll/hooks/gui.c +++ b/src/micetools/dll/hooks/gui.c @@ -1,5 +1,7 @@ #include "gui.h" +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + static HWND window; BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) { DWORD wndProcId; @@ -34,8 +36,9 @@ BOOL GetD3D9Device(void** pTable, size_t Size) { if (dummyDeviceCreated != S_OK) { d3dpp.Windowed = !d3dpp.Windowed; - dummyDeviceCreated = pD3D->lpVtbl->CreateDevice(pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, - D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice); + dummyDeviceCreated = pD3D->lpVtbl->CreateDevice( + pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice); if (dummyDeviceCreated != S_OK) { pD3D->lpVtbl->Release(pD3D); return false; @@ -51,7 +54,8 @@ BOOL GetD3D9Device(void** pTable, size_t Size) { static HRESULT(WINAPI* TrueEndScene)(IDirect3DDevice9*); -void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b) { +void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, + unsigned char b) { D3DCOLOR rectColor = D3DCOLOR_XRGB(r, g, b); D3DRECT BarRect = { x, y, x + w, y + h }; @@ -82,16 +86,12 @@ void register_gui_hook(FnEndScene* end_scene) { LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { - // ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); + ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam); return DefSubclassProc(hWnd, uMsg, wParam, lParam); } -HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, - int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, - LPVOID lpParam) { - HWND hWnd = TrueCreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, - hMenu, hInstance, lpParam); +void post_win_create(HWND hWnd) { void* d3d9Device[119]; if (GetD3D9Device(d3d9Device, sizeof(d3d9Device))) { @@ -101,11 +101,27 @@ HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWi if (hWnd && !SetWindowSubclass(hWnd, WndProc, (int)&WndProc, (DWORD_PTR)NULL)) { log_error("gui", "failed to SetWindowSubclass(%d)", GetLastError()); } +} +HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, + DWORD dwStyle, int X, int Y, int nWidth, int nHeight, + HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { + HWND hWnd = TrueCreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, + nHeight, hWndParent, hMenu, hInstance, lpParam); + post_win_create(hWnd); + return hWnd; +} +HWND WINAPI FakeCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, + DWORD dwStyle, int X, int Y, int nWidth, int nHeight, + HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) { + HWND hWnd = TrueCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, + nHeight, hWndParent, hMenu, hInstance, lpParam); + post_win_create(hWnd); return hWnd; } void hook_gui() { // hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7); + hook("User32.dll", "CreateWindowExW", FakeCreateWindowExW, (void**)&TrueCreateWindowExW, 7); } diff --git a/src/micetools/dll/hooks/gui.h b/src/micetools/dll/hooks/gui.h index 018bc18..dbec24e 100644 --- a/src/micetools/dll/hooks/gui.h +++ b/src/micetools/dll/hooks/gui.h @@ -1,12 +1,18 @@ #pragma once #include "common.h" +static HWND(WINAPI* TrueCreateWindowExA)(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, + DWORD dwStyle, int X, int Y, int nWidth, int nHeight, + HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, + LPVOID lpParam); +static HWND(WINAPI* TrueCreateWindowExW)(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, + DWORD dwStyle, int X, int Y, int nWidth, int nHeight, + HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, + LPVOID lpParam); +static BOOL(WINAPI* TrueSetSystemCursor)(HCURSOR hcur, DWORD id); -static HWND(WINAPI* TrueCreateWindowExA)(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, - int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, - HINSTANCE hInstance, LPVOID lpParam); - -void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b); +void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, + unsigned char b); typedef VOID(FnEndScene)(IDirect3DDevice9* dev); @@ -18,3 +24,4 @@ end_scene_hook_t* end_scene_hook_list; void register_gui_hook(FnEndScene* end_scene); void hook_gui(); +void setup_hud_gui(); diff --git a/src/micetools/dll/hooks/logging.c b/src/micetools/dll/hooks/logging.c index dc20f66..dea79cd 100644 --- a/src/micetools/dll/hooks/logging.c +++ b/src/micetools/dll/hooks/logging.c @@ -1,6 +1,7 @@ -#include "../util/_util.h" #include "logging.h" +#include "../util/_util.h" + char* trim_string(char* string) { size_t len = strlen(string) - 1; @@ -62,25 +63,32 @@ int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) { int WINAPIV Fakevfprintf_s(FILE* _Stream, const char* _Format, va_list _ArgList) { return vlog_game("vfprintf_s", _Format, _ArgList); } -HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; } +HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { + return (HANDLE)0xDEADBEEF; +} -BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, - WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData) { +BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, + PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, + LPVOID lpRawData) { switch (wType) { case EVENTLOG_SUCCESS: case EVENTLOG_AUDIT_SUCCESS: - for (int i = 0; i < wNumStrings; i++) log_misc("evtlog", trim_string((char*)lpStrings[i])); + for (int i = 0; i < wNumStrings; i++) + log_misc("evtlog", trim_string((char*)lpStrings[i])); break; case EVENTLOG_AUDIT_FAILURE: case EVENTLOG_ERROR_TYPE: - for (int i = 0; i < wNumStrings; i++) log_error("evtlog", trim_string((char*)lpStrings[i])); + for (int i = 0; i < wNumStrings; i++) + log_error("evtlog", trim_string((char*)lpStrings[i])); break; case EVENTLOG_WARNING_TYPE: - for (int i = 0; i < wNumStrings; i++) log_warning("evtlog", trim_string((char*)lpStrings[i])); + for (int i = 0; i < wNumStrings; i++) + log_warning("evtlog", trim_string((char*)lpStrings[i])); break; case EVENTLOG_INFORMATION_TYPE: default: - for (int i = 0; i < wNumStrings; i++) log_info("evtlog", trim_string((char*)lpStrings[i])); + for (int i = 0; i < wNumStrings; i++) + log_info("evtlog", trim_string((char*)lpStrings[i])); break; } return TRUE; @@ -89,7 +97,8 @@ BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; } // static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString); -// VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", lpOutputString); } +// VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", +// lpOutputString); } void hook_logging() { hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf, 6); @@ -97,7 +106,9 @@ void hook_logging() { hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 6); hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_s, 6); - hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, (void**)&TrueRegisterEventSourceA, 6); + hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, + (void**)&TrueRegisterEventSourceA, 6); hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6); - hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, (void**)&TrueDeregisterEventSource, 6); + hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, + (void**)&TrueDeregisterEventSource, 6); } diff --git a/src/micetools/dll/hooks/logging.h b/src/micetools/dll/hooks/logging.h index 11efa66..458e1fd 100644 --- a/src/micetools/dll/hooks/logging.h +++ b/src/micetools/dll/hooks/logging.h @@ -1,17 +1,18 @@ #pragma once // #include "../common.h" #include -#include #include +#include static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName); -static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, - WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData); +static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, + PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, + LPCSTR* lpStrings, LPVOID lpRawData); static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog); int(WINAPIV* Trueprintf)(const char* _Format, ...); -static int(WINAPIV* Truefprintf)(FILE* _File, const char* _Format, ...); -static int(WINAPIV* Truefprintf_s)(FILE* _Stream, const char* _Format, ...); -static int(WINAPIV* Truevfprintf_s)(FILE* _Stream, const char* _Format, va_list _ArgList); +static int(WINAPIV* Truefprintf)(void* _File, const char* _Format, ...); +static int(WINAPIV* Truefprintf_s)(void* _Stream, const char* _Format, ...); +static int(WINAPIV* Truevfprintf_s)(void* _Stream, const char* _Format, va_list _ArgList); void hook_logging(); diff --git a/src/micetools/dll/hooks/meson.build b/src/micetools/dll/hooks/meson.build index 9a9b526..7afce36 100644 --- a/src/micetools/dll/hooks/meson.build +++ b/src/micetools/dll/hooks/meson.build @@ -10,4 +10,5 @@ hooks_files = files( 'time.c', 'registry.c', 'drive.c', + 'system.c', ) \ No newline at end of file diff --git a/src/micetools/dll/hooks/network.c b/src/micetools/dll/hooks/network.c index f145bc4..b2c32b2 100644 --- a/src/micetools/dll/hooks/network.c +++ b/src/micetools/dll/hooks/network.c @@ -59,16 +59,16 @@ typedef struct { } dns; dns INTERCEPT_DNS[] = { // Startup - { "naominet.jp", { 192, 168, 103, 254 } }, + { "naominet.jp", { 10, 79, 140, 238 } }, // Billing - { "ib.naominet.jp", { 192, 168, 103, 254 } }, + { "ib.naominet.jp", { 10, 79, 140, 238 } }, // Aime - { "aime.naominet.jp", { 192, 168, 103, 254 } }, + { "aime.naominet.jp", { 10, 79, 140, 238 } }, // Routers (ping targets) - { "tenporouter.loc", { 192, 168, 103, 254 } }, - { "bbrouter.loc", { 192, 168, 103, 254 } }, // Must match tenporouter - { "mobirouter.loc", { 192, 168, 103, 254 } }, - { "dslrouter.loc", { 192, 168, 103, 254 } }, + { "tenporouter.loc", { 10, 79, 140, 238 } }, + { "bbrouter.loc", { 10, 79, 140, 238 } }, // Must match tenporouter + { "mobirouter.loc", { 10, 79, 140, 238 } }, + { "dslrouter.loc", { 10, 79, 140, 238 } }, }; DNS_RECORDA dummy_record; diff --git a/src/micetools/dll/hooks/processes.c b/src/micetools/dll/hooks/processes.c index 31700eb..6ac2372 100644 --- a/src/micetools/dll/hooks/processes.c +++ b/src/micetools/dll/hooks/processes.c @@ -8,17 +8,35 @@ const wchar_t* HOOK_BINARIES[] = { #define DISABLE_PROC_SPAWNING +BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, + DWORD dwCreationFlags, LPVOID lpEnvironment, + LPCSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation) { + log_info("spawn", "CreateProcessA %s %s", lpApplicationName, lpCommandLine); + + HANDLE fake_evt = CreateEvent(NULL, TRUE, FALSE, NULL); + SetEvent(fake_evt); + + if (lpProcessInformation) { + lpProcessInformation->hProcess = fake_evt; + } + return TRUE; +} BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { -// #ifdef DISABLE_PROC_SPAWNING -// log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); -// return FALSE; -// #else - log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); + // #ifdef DISABLE_PROC_SPAWNING + // log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); + // return FALSE; + // #else + // log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); + log_info("spawn", "CreateProcessW %ls", lpApplicationName); + return TRUE; CHAR applicationName[MAX_PATH + 1]; WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, @@ -29,15 +47,16 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, CHAR commandLine[MAX_PATH + 1]; WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL, NULL); - child = start_and_inject(applicationName, commandLine, MICELIB, false); + child = start_and_inject(applicationName, commandLine, MICELIB, false, 0, NULL); } else { - child = start_and_inject(applicationName, NULL, MICELIB, false); + child = start_and_inject(applicationName, NULL, MICELIB, false, 0, NULL); } return !FAILED(child); -// #endif + // #endif } void hook_processes() { hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6); + hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA, 6); } diff --git a/src/micetools/dll/hooks/processes.h b/src/micetools/dll/hooks/processes.h index 898dfd2..7f6659b 100644 --- a/src/micetools/dll/hooks/processes.h +++ b/src/micetools/dll/hooks/processes.h @@ -3,8 +3,17 @@ static BOOL(WINAPI* TrueCreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, - LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, - DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, - LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation); + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, DWORD dwCreationFlags, + LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); +static BOOL(WINAPI* TrueCreateProcessA)(LPCSTR lpApplicationName, LPSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, DWORD dwCreationFlags, + LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation); void hook_processes(); diff --git a/src/micetools/dll/hooks/registry.c b/src/micetools/dll/hooks/registry.c index 75964d7..1e453ce 100644 --- a/src/micetools/dll/hooks/registry.c +++ b/src/micetools/dll/hooks/registry.c @@ -1,5 +1,44 @@ #include "registry.h" -void hook_registry() { - +LSTATUS WINAPI FakeRegCloseKey(HKEY hKey) { + log_trace("registry", "RegCloseKey %08x", hKey); + return ERROR_SUCCESS; +} +LSTATUS WINAPI FakeRegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, + DWORD dwOptions, REGSAM samDesired, + const LPSECURITY_ATTRIBUTES lpSecurityAttributes, + PHKEY phkResult, LPDWORD lpdwDisposition) { + log_trace("registry", "RegCreateKeyExA %08x %s", hKey, lpSubKey); + return ERROR_SUCCESS; +} +LSTATUS WINAPI FakeRegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey) { + log_trace("registry", "RegDeleteKeyA %08x %s", hKey, lpSubKey); + return ERROR_SUCCESS; +} +LSTATUS WINAPI FakeRegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName) { + log_trace("registry", "RegDeleteKeyValueA %08x %s %s", hKey, lpSubKey, lpValueName); + return ERROR_SUCCESS; +} +LSTATUS WINAPI FakeRegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, + LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass, + PFILETIME lpftLastWriteTime) { + log_trace("registry", "RegEnumKeyExA %08x %s", hKey, lpName); + return ERROR_NO_MORE_ITEMS; +} +LSTATUS WINAPI FakeRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, + LPDWORD lpcchValueName, LPDWORD lpReserved, LPDWORD lpType, + LPBYTE lpData, LPDWORD lpcbData) { + log_trace("registry", "RegEnumValueA %08x %s", hKey, lpValueName); + return ERROR_NO_MORE_ITEMS; +} + +void hook_registry() { + hook("Advapi32.dll", "RegCloseKey", FakeRegCloseKey, (void**)&TrueRegCloseKey, 4); + hook("Advapi32.dll", "RegCreateKeyExA", FakeRegCreateKeyExA, (void**)&TrueRegCreateKeyExA, 6); + hook("Advapi32.dll", "RegDeleteKeyA", FakeRegDeleteKeyA, (void**)&TrueRegDeleteKeyA, 4); + hook("Advapi32.dll", "RegDeleteKeyValueA", FakeRegDeleteKeyValueA, + (void**)&TrueRegDeleteKeyValueA, 5); + hook("Advapi32.dll", "RegEnumKeyExA", FakeRegEnumKeyExA, (void**)&TrueRegEnumKeyExA, 5); + // TODO: Passthrough + // hook("Advapi32.dll", "RegEnumValueA", FakeRegEnumValueA, (void**)&TrueRegEnumValueA, 5); } diff --git a/src/micetools/dll/hooks/registry.h b/src/micetools/dll/hooks/registry.h index 5f812de..9fae511 100644 --- a/src/micetools/dll/hooks/registry.h +++ b/src/micetools/dll/hooks/registry.h @@ -1,4 +1,18 @@ #pragma once #include "common.h" +static LSTATUS (WINAPI *TrueRegCloseKey)(HKEY hKey); +static LSTATUS (WINAPI *TrueRegCreateKeyExA)(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, + DWORD dwOptions, REGSAM samDesired, + const LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, + LPDWORD lpdwDisposition); +static LSTATUS (WINAPI *TrueRegDeleteKeyA)(HKEY hKey, LPCSTR lpSubKey); +static LSTATUS (WINAPI *TrueRegDeleteKeyValueA)(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName); +static LSTATUS (WINAPI *TrueRegEnumKeyExA)(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcchName, + LPDWORD lpReserved, LPSTR lpClass, LPDWORD lpcchClass, + PFILETIME lpftLastWriteTime); +static LSTATUS (WINAPI *TrueRegEnumValueA)(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpcchValueName, + LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, + LPDWORD lpcbData); + void hook_registry(); diff --git a/src/micetools/dll/hooks/system.c b/src/micetools/dll/hooks/system.c new file mode 100644 index 0000000..1e88188 --- /dev/null +++ b/src/micetools/dll/hooks/system.c @@ -0,0 +1,55 @@ +#include "system.h" + +// const char OS_VERSION[] = "Service Pack 3"; + +OSVERSIONINFOA OS_VERSION = { + .dwOSVersionInfoSize = 148, + .dwMajorVersion = 5, + .dwMinorVersion = 1, + .dwBuildNumber = 2600, + .dwPlatformId = VER_PLATFORM_WIN32_NT, + .szCSDVersion = "Service Pack 3", +}; +WCHAR TEMP_PATH[] = L"C:\\DOCUME~1\\SYSTEM~1\\LOCALS~1\\Temp\\"; + +BOOL WINAPI FakeGetVersionExA(LPOSVERSIONINFOA lpVersionInformation) { + log_trace("system", "GetVersionExA"); + memcpy(lpVersionInformation, &OS_VERSION, sizeof OS_VERSION); + return TRUE; +} +BOOL WINAPI FakeGetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, + LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { + log_trace("system", "GetVolumeInformationW"); + *lpVolumeSerialNumber = 0x1c0fd22b; + return TRUE; +}; + +DWORD WINAPI FakeGetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) { + memcpy(lpBuffer, TEMP_PATH, sizeof TEMP_PATH); + return wcslen(TEMP_PATH); +}; + +HCURSOR WINAPI FakeLoadCursorFromFileA(LPCSTR lpFileName) { return (HANDLE)1; } +BOOL FakeSetSystemCursor(HCURSOR hcur, DWORD id) { return TRUE; } +BOOL FakeDeleteObject(HGDIOBJ ho) { return TRUE; } + +LONG WINAPI FakeChangeDisplaySettingsA(DEVMODEA* lpDevMode, DWORD dwFlags) { return 0; } +LONG WINAPI FakeChangeDisplaySettingsExA(LPCSTR lpszDeviceName, DEVMODEA* lpDevMode, HWND hwnd, + DWORD dwflags, LPVOID lParam) { + return 0; +} + +void hook_system() { + hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL, 5); + hook("Kernel32.dll", "GetTempPathW", FakeGetTempPathW, NULL, 5); + hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL, 5); + + hook("User32.dll", "ChangeDisplaySettingsA", FakeChangeDisplaySettingsA, NULL, 4); + hook("User32.dll", "ChangeDisplaySettingsExA", FakeChangeDisplaySettingsExA, NULL, 6); + + // hook("User32.dll", "LoadCursorFromFileA", FakeLoadCursorFromFileA, NULL, 5); + // hook("User32.dll", "SetSystemCursor", FakeSetSystemCursor, NULL, 5); + // hook("User32.dll", "DeleteObject", FakeDeleteObject, NULL, 5); +} diff --git a/src/micetools/dll/hooks/system.h b/src/micetools/dll/hooks/system.h new file mode 100644 index 0000000..bed2465 --- /dev/null +++ b/src/micetools/dll/hooks/system.h @@ -0,0 +1,5 @@ +#pragma once + +#include "../common.h" + +void hook_system(); diff --git a/src/micetools/dll/meson.build b/src/micetools/dll/meson.build index 7d5110a..9d1e05b 100644 --- a/src/micetools/dll/meson.build +++ b/src/micetools/dll/meson.build @@ -1,6 +1,7 @@ subdir('drivers') subdir('devices') subdir('hooks') +subdir('gui') shared_library( 'mice', @@ -13,6 +14,7 @@ shared_library( drivers_files, devices_files, hooks_files, + gui_files, 'comdevice.c', @@ -22,5 +24,10 @@ shared_library( dmi_lib, mice_lib, amlib, - ] + mxklib, + ], + include_directories: [ + openssl_inc, + ], + dependencies: [cimgui.get_variable('cimgui_dep')] ) diff --git a/src/micetools/dll/smbus.h b/src/micetools/dll/smbus.h index 7552244..9a02f42 100644 --- a/src/micetools/dll/smbus.h +++ b/src/micetools/dll/smbus.h @@ -2,9 +2,6 @@ #include "common.h" // PCA9535 (DIPSW) -#define PCA9535_WRITE 0x04 -#define PCA9535_READ 0x05 - #define PCA9535_IN0 0x00 #define PCA9535_IN1 0x01 #define PCA9535_OUT0 0x02 @@ -14,24 +11,129 @@ #define PCA9535_CONF0 0x06 #define PCA9535_CONF1 0x07 -#define SMBUS_PCA9535 0x20 -#define SMBUS_EEPROM 0x57 // Doesn't line up with manual! +/* +W83627UHG: + Configuration is based on HEFRAS + Configuration 0: + [Logical index port] 0x2e + [Logical data port] 0x2f + Configuration 1: + [Logical index port] 0x4e + [Logical data port] 0x4f -#define SMBUS_DDR2_DIMM_A1 0x000 // what does 0xA0 mean? -#define SMBUS_DDR2_DIMM_B1 0x010 // what does 0xA4 mean? -#define SMBUS_EEPROM_ 0x0AE // = AT24C64AN -#define SMBUS_ICS9LPRS908 0xfff // Unknown -#define SMBUS_W83627UHG 0xfff // Unknown; hwmon. Possibly 0x2e or 0x4e -#define SMBUS_UPI_UP6261BM8 0xfff // Unknown; vref -#define SMBUS_UPI_ISL6322CR 0xfff // Unknown; vrm -// SMBUS is send onto the mezzanine board! + Setup: + ! Select logical device 0 = FDC (in this case, we don't care) + index = 0x07, data = 0x00 + index = 0x20, read data (Chip ID MSB) + index = 0x21, read data (Chip ID LSB) + [merge two bytes to get chip ID] + + ! Select logical device B = HM + * Read base address of address and data ports + * Address = xxxh + 5h, Data = xxxh + 6h + index = 0x07, data = 0x0b + index = 0x60, read data (Base MSB) + index = 0x61, read data (Base LSB) + [merge two bytes to get address] + +ICH9 Smbus Controller: + mxsmbus.sys -> io-controller-hub-9-datasheet.pdf, page 759 + PEC is disabled + + Requests are made using a virtual address. + The physical address is *2 of the virtual, +1 for read. + + Commands: + 0: paddr = vaddr * 2 ; smb_cmd = quick + 1: paddr = vaddr * 2 + 1; smb_cmd = quick + 2: paddr = vaddr * 2 ; smb_cmd = byte + 3: paddr = vaddr * 2 + 1; smb_cmd = byte + 4: paddr = vaddr * 2 ; smb_cmd = byte data + 5: paddr = vaddr * 2 + 1; smb_cmd = byte data + 6: paddr = vaddr * 2 ; smb_cmd = word data + 7: paddr = vaddr * 2 + 1; smb_cmd = word data + 8: paddr = vaddr * 2 ; smb_cmd = block + 9: paddr = vaddr * 2 + 1; smb_cmd = block + 10: paddr = vaddr * 2 ; smb_cmd = process call + 11: paddr = vaddr * 2 ; smb_cmd = i2c read + + IOCTL_MXSMBUS_REQUEST: + assert command <= 11 + 0x25 bytes + IOCTL_MXSMBUS_I2C: + assert command <= 10 + 0x27 bytes + + +LPC device 0x00 = FPC +LPC device 0x07 = W83627UHG + + + +smbus: + 0x801: + PCA9535: 0000 100[Wr] | 8 bit addr/reg | [... + amHmI2C: 0000 100[Wr] | 8 bit addr/reg | [... + +superio: + 0x803: + amHmLPC: + + +IOCTL_MXSUPERIO_READ: + read 1: -> .. 0B 20 00 + <- .. .. .. XX + read 2: -> .. 0B 21 00 + <- .. .. .. YY + assert XXYY == 0xA020 (case 1) or 0xA230 (case 2) + +! SMBUS is I2C +- ICH9: **host** (schematics, sheet 11) + +- EEPROM AT24C64AN: 0AE (schematics, sheet 10) +- DDR2 DIMM A1: 0A0 (schematics, sheet 13) +- DDR2 DIMM B1: 0A4 (schematics, sheet 14) + +- ICS9LPRS908: 0x?? (schematics, sheet 15) +- W83627UHG LPC I/O: 0x?? (schematics, sheet 16) ((2E / 4E on a toggle?)) +- Mystery chips on the mezanine and keychip (schematics, sheet 17) +- VRMs: 0x?? (schematics, sheet 27) + +! ??? is SPI + +! System SPI +- SPI Flash ROM: ??? (schematics, sheet 11) +- + +! LPC (superio) is its own thing? +- ICH9: **host** (schematics, sheet 11) +- TPM (schematics, sheet 10) +- W83627UHC (schematics, sheet 16) +*/ + +// SMBUS Devices (+1 is implied for read addresses) +#define SMBUS_PCA9535 0x40 +#define SMBUS_DIMM_A1 0xA0 +#define SMBUS_DIMM_B1 0xA4 +#define SMBUS_EXIO 0xA8 +#define SMBUS_N2 0xAA +#define SMBUS_EEPROM 0xAE + +// Keychip +#define N2_GET_EEPROM 0x40 +#define N2_GET_UNIQUE_NUMBER 0xA0 +#define N2_GET_STATUS 0xA8 +#define N2_STATUS_FLAG_BUSY 2 +#define N2_I2C_CHALLENGE_RESPONSE 0xB0 + +#define EXIO_GET_BUSY 0x00 #pragma pack(1) typedef struct mxsmbus_request_packet_ { BYTE status; BYTE prt; - WORD addr; - WORD reg; + BYTE addr; + BYTE reg; BYTE dlen; BYTE data[32]; } mxsmbus_request_packet; @@ -40,16 +142,8 @@ typedef struct mxsmbus_request_packet_ { typedef struct mxsmbus_i2c_packet_ { BYTE status; BYTE prt; - BYTE addr; - BYTE reg; + WORD addr; + WORD reg; BYTE dlen; BYTE data[32]; } mxsmbus_i2c_packet; - -#pragma pack(1) -typedef struct mxsuperio_lpc_packet_ { - BYTE index; - BYTE reg; - BYTE data; -} mxsuperio_lpc_packet; -enum mxsbus_status { MXSBUS_OKAY = 0 }; diff --git a/src/micetools/dll/util/hook.c b/src/micetools/dll/util/hook.c index b7812cf..4918920 100644 --- a/src/micetools/dll/util/hook.c +++ b/src/micetools/dll/util/hook.c @@ -1,9 +1,10 @@ #include "hook.h" -#include "log.h" #include #include +#include "log.h" + function_hook_t* hook_list = NULL; void append_hook(function_hook_t* hook) { @@ -81,15 +82,18 @@ void setup_hooks() { HMODULE dll = LoadLibraryA(hook->dll); if (dll == NULL) { - log_error(HOOKS_LOGGER, "failed to load dll %s. %s skipped", hook->dll, hook->name); + log_error(HOOKS_LOGGER, "failed to load dll %s (%03x). %s skipped", hook->dll, + GetLastError(), hook->name); hook = hook->next; continue; } - if ((*(hook->store) = GetProcAddress(dll, hook->name)) == NULL) { + void* original = GetProcAddress(dll, hook->name); + if (original == NULL) { log_warning(HOOKS_LOGGER, "failed to get original %s", hook->name); } else { - *((void**)hook->store) = CreateHook(*hook->store, hook->patch, hook->length); + void* gateway = CreateHook(original, hook->patch, hook->length); + if (hook->store != NULL) *hook->store = gateway; log_misc(HOOKS_LOGGER, "hooked %s", hook->name); } diff --git a/src/micetools/dll/util/log.c b/src/micetools/dll/util/log.c index 6837315..3e1931f 100644 --- a/src/micetools/dll/util/log.c +++ b/src/micetools/dll/util/log.c @@ -5,6 +5,7 @@ #include #include +#include "../../lib/mice/config.h" #include "../hooks/logging.h" extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, @@ -24,7 +25,7 @@ char* log_prelude() { return _log_prelude; } -HANDLE LOG_FILE = NULL; +HANDLE log_file = NULL; VOID trace_hook(char* output); CRITICAL_SECTION logger_lock; @@ -39,14 +40,54 @@ char* log_colours[] = { }; #define LOG_PREFIXES "!GEWIMT" -void logcb(LPCSTR param_1) { log_error("logcb", param_1); } +void force_console_bind() { + // AttachConsole(ATTACH_PARENT_PROCESS); + if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) { + FILE* newstream; + if (GetStdHandle(STD_INPUT_HANDLE)) { + freopen_s(&newstream, "CONIN$", "r", stdin); + setvbuf(stdin, NULL, _IONBF, 0); + } + if (GetStdHandle(STD_OUTPUT_HANDLE)) { + freopen_s(&newstream, "CONOUT$", "w", stdout); + setvbuf(stdout, NULL, _IONBF, 0); + } + if (GetStdHandle(STD_ERROR_HANDLE)) { + freopen_s(&newstream, "CONOUT$", "w", stderr); + setvbuf(stderr, NULL, _IONBF, 0); + } + } +} + +void logcb(LPCSTR param_1) { log_game("amLog", param_1); } +void __stdcall amLogCallback(DWORD level, char* format) { + if (level == 0) + log_game("amLog:E", format); + else if (level == 0) + log_game("amLog:W", format); + else + log_game("amLog:I", format); +} + +DWORD pLogcb; +DWORD* ppLogcb; extern WCHAR exePath[MAX_PATH + 1]; int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) { + // TODO: These are all horrible bodges if (wcscmp(exePath, L"mxnetwork.exe") == 0) { // *((DWORD*)(0x004438e8)) = (DWORD)(&logcb); *((DWORD*)(0x004438e8)) = 0x00000000; } + if (wcscmp(exePath, L"maimai_dump_.exe") == 0) { + *((DWORD*)(0x00c820ec)) = 0x00000001; + pLogcb = (DWORD)(&amLogCallback); + ppLogcb = &pLogcb; + *((DWORD***)(0x00c820F4)) = &ppLogcb; + // *((DWORD*)(0x004438e8)) = (DWORD)(&logcb); + } + + force_console_bind(); char prefix = LOG_PREFIXES[log_level]; @@ -65,19 +106,21 @@ int _do_log(BYTE log_level, const char* caller, const char* format, va_list args buf[len + 1] = '\0'; // No +1 here to not get the \n - if (LOG_LEVEL >= log_level) { + if (MiceConfig.mice.log_level >= log_level) { HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE); if (HAS_COLOUR) - (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, log_colours[log_level], - strlen(log_colours[log_level]), NULL, NULL); + (TrueWriteFile ? *TrueWriteFile : WriteFile)( + sout, log_colours[log_level], strlen(log_colours[log_level]), NULL, NULL); if (sout != INVALID_HANDLE_VALUE) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL); puts(HAS_COLOUR ? "\033[0m" : ""); + FlushFileBuffers(sout); + } + + if (MiceConfig.mice.log_to_file) { + if (log_file && log_file != INVALID_HANDLE_VALUE) + (TrueWriteFile ? TrueWriteFile : WriteFile)(log_file, buf, len + 1, NULL, NULL); } -#ifdef LOG_TO_FILE - if (LOG_FILE && LOG_FILE != INVALID_HANDLE_VALUE) - (TrueWriteFile ? TrueWriteFile : WriteFile)(LOG_FILE, buf, len + 1, NULL, NULL); -#endif free(buf); @@ -153,21 +196,8 @@ VOID trace_hook(char* output) { void setup_logging() { // Force stdio even for GUI applications // TODO: Is there a more robust way to check if we have a proper stdio? - AttachConsole(ATTACH_PARENT_PROCESS); - if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) { - FILE* newstream; - if (GetStdHandle(STD_INPUT_HANDLE)) { - freopen_s(&newstream, "CONIN$", "r", stdin); - setvbuf(stdin, NULL, _IONBF, 0); - } - if (GetStdHandle(STD_OUTPUT_HANDLE)) { - freopen_s(&newstream, "CONOUT$", "w", stdout); - setvbuf(stdout, NULL, _IONBF, 0); - } - if (GetStdHandle(STD_ERROR_HANDLE)) { - freopen_s(&newstream, "CONOUT$", "w", stderr); - setvbuf(stderr, NULL, _IONBF, 0); - } + if (false) { + force_console_bind(); } // Enable colour in CMD @@ -178,9 +208,9 @@ void setup_logging() { InitializeCriticalSection(&logger_lock); -#ifdef LOG_TO_FILE - if (LOG_FILE == NULL) - LOG_FILE = - CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); -#endif + if (MiceConfig.mice.log_to_file) { + if (log_file == NULL && MiceConfig.mice.log_file[0] != '\0') + log_file = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, 0, NULL); + } } diff --git a/src/micetools/dll/util/log.h b/src/micetools/dll/util/log.h index 406a4b6..0ebd8f2 100644 --- a/src/micetools/dll/util/log.h +++ b/src/micetools/dll/util/log.h @@ -10,10 +10,6 @@ #define LOG_MISC 5 #define LOG_TRACE 6 -#define LOG_LEVEL LOG_TRACE - -// #define LOG_TO_FILE - #define COMM_LOGGER "comm" #define HOOKS_LOGGER "hooks" #define BOOT_LOGGER "boot" diff --git a/src/micetools/launcher/locate.c b/src/micetools/launcher/locate.c index 947aeff..92db8eb 100644 --- a/src/micetools/launcher/locate.c +++ b/src/micetools/launcher/locate.c @@ -1,4 +1,5 @@ #include "locate.h" + #include "../lib/mice/mice.h" const char* KNOWN_GAMES[] = { @@ -43,12 +44,10 @@ bool locate_game(char* path, size_t len) { } bool locate_library(char* path, size_t len) { - if (locate_file(path, len, MICELIB)) { - return true; - } + if (locate_file(path, len, MiceConfig.launcher.mice_dll)) return true; // Don't call DllMain! We don't want to hook ourself! - HANDLE mice = LoadLibraryExA(MICELIB, NULL, DONT_RESOLVE_DLL_REFERENCES); + HANDLE mice = LoadLibraryExA(MiceConfig.launcher.mice_dll, NULL, DONT_RESOLVE_DLL_REFERENCES); if (mice != NULL) { GetModuleFileNameA(mice, path, len); return true; diff --git a/src/micetools/launcher/main.c b/src/micetools/launcher/main.c index 2557582..b43c0f9 100644 --- a/src/micetools/launcher/main.c +++ b/src/micetools/launcher/main.c @@ -6,7 +6,8 @@ const char* VERSION = "0.0-pre"; -bool boot_delay = false; +bool debug_wait = false; +int boot_delay = 0; bool gametest = false; bool designviewer = false; bool spriteviewer = false; @@ -35,8 +36,8 @@ void parse_cmdline(int argc, char* argv[]) { char* val = argv[++i]; memcpy(exe_name, val, strlen(val) + 1); } else if (strcmp(argv[i], "--mice-d") == 0) { - boot_delay = true; - } else if (strcmp(argv[i], "-t") == 0) { + debug_wait = true; + } else if (strcmp(argv[i], "-mice-t") == 0) { gametest = true; } else if (strcmp(argv[i], "-dv") == 0) { designviewer = true; @@ -46,7 +47,7 @@ void parse_cmdline(int argc, char* argv[]) { noisetest = true; } else { if (commandline[0] == 0) - strncpy_s(commandline, strlen(argv[i]), argv[i], sizeof commandline); + snprintf(commandline, sizeof commandline, "%s", argv[i]); else snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]); } @@ -54,10 +55,18 @@ void parse_cmdline(int argc, char* argv[]) { } int main(int argc, char* argv[]) { + load_mice_config(); + fprintf(stderr, "Micetools version: %s\n", VERSION); parse_cmdline(argc, argv); + if (exe_name[0] == '\0' && MiceConfig.launcher.game_binary[0] != '\0') { + snprintf(exe_name, sizeof exe_name, "%s", MiceConfig.launcher.game_binary); + } + if (MiceConfig.launcher.wait_for_debugger) debug_wait = true; + boot_delay = MiceConfig.launcher.startup_delay; + if (exe_name[0] == '\0') { if (!locate_game(exe_name, MAX_PATH + 1)) { fprintf(stderr, "Fatal: Failed to locate a game\n"); @@ -85,11 +94,13 @@ int main(int argc, char* argv[]) { char micepath[MAX_PATH + 1]; if (!locate_library(micepath, MAX_PATH + 1)) { - fprintf(stderr, "Fatal: Failed to locate micelib\n"); + fprintf(stderr, "Fatal: Failed to locate micelib. Check your mice_dll setting!\n"); return 0; } - HANDLE game_proc = start_and_inject(exe_name, cmdline, micepath, boot_delay); + char* extra_injections = MiceConfig.launcher.inject; + HANDLE game_proc = + start_and_inject(exe_name, cmdline, micepath, debug_wait, boot_delay, extra_injections); if (!game_proc) return -1; if (FAILED(WaitForSingleObject(game_proc, INFINITE))) { diff --git a/src/micetools/lib/am/amEeprom.c b/src/micetools/lib/am/amEeprom.c index eadd8fe..2ff85f8 100644 --- a/src/micetools/lib/am/amEeprom.c +++ b/src/micetools/lib/am/amEeprom.c @@ -42,7 +42,7 @@ fail: } BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { - mxsmbus_request_packet smbus_req = { + mxsmbus_i2c_packet smbus_req = { .status = 0, .prt = 0x09, .addr = SMBUS_EEPROM, @@ -52,7 +52,7 @@ BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { }; DWORD _dummy; - BOOL s = DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req, + BOOL s = DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req, &smbus_req, sizeof smbus_req, &_dummy, NULL); if (!s) return FALSE; if (smbus_req.status) return FALSE; @@ -61,7 +61,7 @@ BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { } BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { - mxsmbus_request_packet smbus_req = { + mxsmbus_i2c_packet smbus_req = { .status = 0, .prt = 0x08, .addr = SMBUS_EEPROM, @@ -72,7 +72,7 @@ BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { memcpy(smbus_req.data, data, sizeof smbus_req.data); DWORD _dummy; - BOOL s = DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req, + BOOL s = DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req, &smbus_req, sizeof smbus_req, &_dummy, NULL); if (!s) return FALSE; if (smbus_req.status) return FALSE; @@ -81,8 +81,6 @@ BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) { } void amEepromRepairChecksum(BYTE *data) { - crc32_build_table(); - DWORD check = crc32(28, data + 4, 0); ((DWORD*)data)[0] = check; } diff --git a/src/micetools/lib/am/amtimer.h b/src/micetools/lib/am/amtimer.h index f8cfb62..8ffd5ee 100644 --- a/src/micetools/lib/am/amtimer.h +++ b/src/micetools/lib/am/amtimer.h @@ -10,6 +10,8 @@ typedef struct amtime { amtime_t* amiTimerGet(amtime_t* time); #define _amTimeMs(time) (((time).microseconds / 1000 + (time).seconds * 1000)) -#define _amTimeDelta(now, start) \ - (((now).microseconds - (start).microseconds) / 1000 + \ - ((now).seconds - (start).seconds) * 1000) +#define _amTimeDelta(now, start) \ + (((now).microseconds - (start).microseconds) / 1000 + ((now).seconds - (start).seconds) * 1000) + +#define _amTimeDeltaMircos(now, start) \ + ((((now).seconds - (start).seconds) * 1000000 - (start).microseconds) + (now).microseconds) diff --git a/src/micetools/lib/libpcp/pcpp.c b/src/micetools/lib/libpcp/pcpp.c index fb6d418..4ee7b3e 100644 --- a/src/micetools/lib/libpcp/pcpp.c +++ b/src/micetools/lib/libpcp/pcpp.c @@ -80,7 +80,7 @@ bool pcppCheckPrompt(pcpp_t* stream) { return found; } -e_pcpt_t pcppCheckRecvMsg(unsigned char* recv_data, size_t buf_len, int param_3) { +e_pcpp_t pcppCheckRecvMsg(unsigned char* recv_data, size_t buf_len, int param_3) { bool bVar1 = true; int local_8 = 0; diff --git a/src/micetools/lib/meson.build b/src/micetools/lib/meson.build index da60a15..00b2686 100644 --- a/src/micetools/lib/meson.build +++ b/src/micetools/lib/meson.build @@ -3,6 +3,7 @@ subdir('json') subdir('dmi') subdir('mice') subdir('am') +subdir('mxk') fs = import('fs') subdir('libpcp') diff --git a/src/micetools/lib/mice/config.c b/src/micetools/lib/mice/config.c new file mode 100644 index 0000000..8839355 --- /dev/null +++ b/src/micetools/lib/mice/config.c @@ -0,0 +1,113 @@ +#include "config.h" + +#include +#include +#include + +#include "../../../../subprojects/inih_dep/ini.h" + +config_t MiceConfig = { +#define SECTION(s, comment) .s = { +#define CFG_str(s, n, default, comment) .n = default, +#define CFG_bool(s, n, default, comment) .n = default, +#define CFG_int(s, n, default, comment) .n = default, +#define CFG_hex(s, n, precision, default, comment) .n = 0x##default, +#define ENDSECTION(s) \ + } \ + , +#include "config.def" + ._keep_linter_happy = true +}; + +void fprintf_prefix(FILE *file, const char *prefix, const char *text) { + char* copy = (char*)malloc(strlen(text) + 1); + memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1); + + char* next_token; + char* token = strtok_s(copy, "\n", &next_token); + while (token != NULL) { + fprintf(file, "%s%s\n", prefix, token); + token = strtok_s(NULL, "\n", &next_token); + } + + free(copy); +} + +void make_default_config() { + FILE *config_file; + fopen_s(&config_file, CONFIG_PATH, "w"); + if (config_file == NULL) { + puts("Failed to create config file!"); + return; + }; + int first_section = true; + +#define CFG_str(s, n, default, comment) \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + fprintf(config_file, "; (string) default = %s\n", default); \ + fprintf(config_file, "%s = %s\n", #n, default); + +#define CFG_bool(s, n, default, comment) \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + fprintf(config_file, "; (bool) default = %s\n", default ? "true" : "false"); \ + fprintf(config_file, "%s = %s\n", #n, default ? "true" : "false"); + +#define CFG_int(s, n, default, comment) \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + fprintf(config_file, "; (int) default = %d\n", default); \ + fprintf(config_file, "%s = %d\n", #n, default); + +#define CFG_hex(s, n, precision, default, comment) \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + fprintf(config_file, "; (hex) default = %.*X\n", precision, 0x##default); \ + fprintf(config_file, "%s = %.*X\n", #n, precision, 0x##default); + +#define SECTION(s, comment) \ + if (!first_section) fprintf(config_file, "\n"); \ + first_section = false; \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + fprintf(config_file, "[%s]\n", #s); + +#define HEADER(comment) \ + if (strlen(comment) != 0) fprintf_prefix(config_file, "; ", comment); \ + first_section = false; + +#include "config.def" + + fclose(config_file); +} + +int handler(void *user, const char *section, const char *name, const char *value) { + config_t *cfg = (config_t *)user; + + char *end; + + if (false) + ; +#define CFG_str(s, n, default, comment) \ + else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) cfg->s.n = _strdup(value); +#define CFG_bool(s, n, default, comment) \ + else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) cfg->s.n = \ + strcmp(value, "true") == 0; +#define CFG_int(s, n, default, comment) \ + else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) { \ + cfg->s.n = strtol(value, &end, 10); \ + if (end == value || *end != '\0' || errno == ERANGE) cfg->s.n = default; \ + } +#define CFG_hex(s, n, precision, default, comment) \ + else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) { \ + cfg->s.n = strtol(value, &end, 16); \ + if (end == value || *end != '\0' || errno == ERANGE) cfg->s.n = 0x##default; \ + } + +#include "config.def" + + return 1; +} + +void load_mice_config() { + if (ini_parse(CONFIG_PATH, handler, &MiceConfig) < 0) { + make_default_config(); + printf("Can't load '%s', using defaults\n", CONFIG_PATH); + } +} diff --git a/src/micetools/lib/mice/config.def b/src/micetools/lib/mice/config.def new file mode 100644 index 0000000..d6ddb52 --- /dev/null +++ b/src/micetools/lib/mice/config.def @@ -0,0 +1,65 @@ +#ifndef SECTION +#define SECTION(s, comment) +#endif +#ifndef HEADER +#define HEADER(comment) +#endif +#ifndef ENDSECTION +#define ENDSECTION(s) +#endif + +HEADER("The main config file for micetools") + +SECTION(mice, "General mice settings") +CFG_int(mice, log_level, 4, "1 = Game\n2 = Error\n3 = Warning\n4 = Info\n5 = Misc\n6 = Trace") +CFG_bool(mice, log_to_file, false, "Also log out to log_file") +CFG_str(mice, log_file, "log.txt", "The file to log to if log_to_file is enabled") +CFG_bool(mice, apply_patches, true, "Load and apply patches from patches_file at runtime") +CFG_str(mice, patches_file, "patches.json", "The file to read patches from") +ENDSECTION(mice) + +SECTION(launcher, "These options are only used during initial bootstrapping") +CFG_str(launcher, game_binary, "", "Override binary detection") +CFG_bool(launcher, wait_for_debugger, false, "Wait for a debugger to attach when starting") +CFG_int(launcher, startup_delay, 0, "Pause during startup") +CFG_str(launcher, mice_dll, "mice86.dll", "The path to mice's DLL") +CFG_str(launcher, inject, "", "Extra DLLs to inject during boot") +ENDSECTION(launcher) + +SECTION(devices, "Specify COM ports for devices to attach, comma seperated") +CFG_str(devices, aime_bd, "2", "AIME reader board") +CFG_str(devices, touch_bd, "3", "maimai touch screen") +CFG_str(devices, led_bd, "5,6,7,8", "maimai led boards") +ENDSECTION(devices) + +SECTION(drivers, "Enable or disable drivers. Disabling any is not recommended.") +CFG_bool(drivers, columba, true, "Columba memory driver") +CFG_bool(drivers, mxsram, true, "SRAM driver") +CFG_bool(drivers, mxsuperio, true, "SuperIO driver") +CFG_bool(drivers, mxjvs, true, "JVS driver") +CFG_bool(drivers, mxhwreset, true, "System reboot driver") +CFG_bool(drivers, mxsmbus, true, "SMBus driver") +CFG_bool(drivers, mxparallel, true, "Parallel port driver") +CFG_bool(drivers, platform, true, "amPlatform driver") +ENDSECTION(drivers) + +SECTION(hooks, "Enable or disable hooks. Disabling any is not recommended.") +CFG_bool(hooks, logging, true, "Hooks logging functions and the eventlog to capture game logs") +CFG_bool(hooks, gui, true, "Required for overlays to work") +CFG_bool(hooks, setupapi, true, "Required for SRAM") +CFG_bool(hooks, commio, true, "Emulates COM devices") +CFG_bool(hooks, io, true, "Hooks all file IO operations, including driver communication") +CFG_bool(hooks, processes, true, "Controls process spawning to re-hook children") +CFG_bool(hooks, network, true, "Provides a virtual network environment for the game") +CFG_bool(hooks, time, true, "Some binaries try to change the system time; this handles that") +CFG_bool(hooks, registry, true, "") +CFG_bool(hooks, drives, true, "Provides an emulation layer for the physical game SSD") +ENDSECTION(hooks) + +#undef CFG_str +#undef CFG_int +#undef CFG_bool +#undef CFG_hex +#undef SECTION +#undef ENDSECTION +#undef HEADER diff --git a/src/micetools/lib/mice/config.h b/src/micetools/lib/mice/config.h new file mode 100644 index 0000000..79e2217 --- /dev/null +++ b/src/micetools/lib/mice/config.h @@ -0,0 +1,19 @@ +#include + +#define CONFIG_PATH "mice.ini" + +typedef struct config { +#define SECTION(s, comment) struct { +#define CFG_str(s, n, default, comment) char* n; +#define CFG_bool(s, n, default, comment) bool n; +#define CFG_int(s, n, default, comment) int n; +#define CFG_hex(s, n, precision, default, comment) int n; +#define ENDSECTION(s) } s; +#include "config.def" + bool _keep_linter_happy; +} config_t; + +extern config_t MiceConfig; + +void make_default_config(); +void load_mice_config(); diff --git a/src/micetools/lib/mice/crc.c b/src/micetools/lib/mice/crc.c index 3a401a6..bdef3a6 100644 --- a/src/micetools/lib/mice/crc.c +++ b/src/micetools/lib/mice/crc.c @@ -20,6 +20,8 @@ void crc32_build_table() { } unsigned int crc32(int length, unsigned char *data, unsigned int initial) { + crc32_build_table(); + unsigned int value = ~initial; while (length--) { value = value >> 8 ^ CRC_TABLE[(*data ^ value) & 0xff]; diff --git a/src/micetools/lib/mice/exe.c b/src/micetools/lib/mice/exe.c index 71f1cef..cdda1d6 100644 --- a/src/micetools/lib/mice/exe.c +++ b/src/micetools/lib/mice/exe.c @@ -1,5 +1,7 @@ #include "exe.h" +#include + bool inject_debug_wait(HANDLE process) { BOOL present; @@ -14,10 +16,11 @@ bool inject_debug_wait(HANDLE process) { fprintf(stderr, "Debugger attached, resuming\n"); return true; } -bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) { +bool remote_call(HANDLE process, LPVOID function, LPCSTR argument, DWORD* result) { int nchars = strlen(argument); - LPVOID arg_addr = VirtualAllocEx(process, NULL, nchars + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + LPVOID arg_addr = + VirtualAllocEx(process, NULL, nchars + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (arg_addr == NULL) { fprintf(stderr, "Fatal: VirtualAllocEx failed: %03x\n", GetLastError()); return false; @@ -28,7 +31,8 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) { return false; } - HANDLE remote_thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)function, arg_addr, 0, NULL); + HANDLE remote_thread = + CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)function, arg_addr, 0, NULL); if (remote_thread == NULL) { fprintf(stderr, "Fatal: CreateRemoteThread failed: %03x\n", GetLastError()); return false; @@ -39,12 +43,11 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) { return false; } - DWORD result; - if (FAILED(GetExitCodeThread(remote_thread, &result))) { + if (FAILED(GetExitCodeThread(remote_thread, result))) { fprintf(stderr, "Fatal: GetExitCodeThread failed: %03x\n", GetLastError()); return false; } - if (result == 0) { + if (*result == 0) { fprintf(stderr, "Fatal: GetExitCodeThread failed: result == 0\n"); return false; } @@ -64,10 +67,12 @@ bool inject_dll(HANDLE process, LPCSTR inject) { return false; } - return remote_call(process, addr_LoadLibraryA, inject); + DWORD result; + return remote_call(process, addr_LoadLibraryA, inject, &result); } -HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) { +HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait, DWORD delay, + LPCSTR extra_injections) { STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation = { 0 }; @@ -93,17 +98,38 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) { } // Start the binary - if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo, - &processInformation)) { + if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, + &startupInfo, &processInformation)) { fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError()); goto abort; } - if (delay) { + if (debug_wait) { if (!inject_debug_wait(processInformation.hProcess)) goto abort; } + // Sleep(5000); if (!inject_dll(processInformation.hProcess, inject)) goto abort; + if (extra_injections != NULL && extra_injections[0] != '\0') { + char* copy = (char*)malloc(strlen(extra_injections) + 1); + memcpy_s(copy, strlen(extra_injections) + 1, extra_injections, + strlen(extra_injections) + 1); + + char* next_token; + char* token = strtok_s(copy, "\n", &next_token); + while (token != NULL) { + if (!inject_dll(processInformation.hProcess, token)) goto abort; + token = strtok_s(NULL, "\n", &next_token); + } + + free(copy); + } + + if (delay) { + fprintf(stderr, "Delaying for %dms\n", delay); + Sleep(delay); + } + // Injection completed, let the program continue execution if (FAILED(ResumeThread(processInformation.hThread))) { fprintf(stderr, "Fatal: ResumeThread failed: %03x\n", GetLastError()); diff --git a/src/micetools/lib/mice/exe.h b/src/micetools/lib/mice/exe.h index d17664b..07650b1 100644 --- a/src/micetools/lib/mice/exe.h +++ b/src/micetools/lib/mice/exe.h @@ -2,7 +2,8 @@ #include #include -HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay); +HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait, DWORD delay, + LPCSTR extra_injections); #ifndef MICELIB #ifdef MICE_WIN32 diff --git a/src/micetools/lib/mice/ioctl.h b/src/micetools/lib/mice/ioctl.h index 4be9dc7..021c746 100644 --- a/src/micetools/lib/mice/ioctl.h +++ b/src/micetools/lib/mice/ioctl.h @@ -3,12 +3,13 @@ #define FILE_DEVICE_SEGA 0x9c40 // amSramInit -#define IOCTL_MXSRAM_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_MXSRAM_PING \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) // amSramInit #define IOCTL_MXSRAM_GET_SECTOR_SIZE \ - CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXSRAM_GET_VERSION \ - CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) // EEPROM uses MXSMBUS_GUID device class // DIPSW uses MXSMBUS_GUID device class @@ -24,46 +25,59 @@ // Same as IOCTL_MXSRAM_PING // amHmProbeSuperIoDevice -#define IOCTL_MXSUPERIO_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_MXSUPERIO_PING \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) // amHmGetLPCChipId -#define IOCTL_MXSUPERIO_READ CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_MXSUPERIO_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_MXSUPERIO_READ \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MXSUPERIO_WRITE \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) // amHmLpcReadByte #define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ \ - CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) // amHmLpcWriteByte #define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE \ - CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS) -#define IOCTL_MXJVS_EXCHANGE CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MXJVS_EXCHANGE \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) // Same as IOCTL_MXSUPERIO_READ // amHmI2CReadByte,amHmI2CWriteByte,amEepromWait -#define IOCTL_MXSMBUS_REQUEST CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) +// amDipswReadByteInternal,amDipswWriteByteInternal +// uses the 0x25 sized request +#define IOCTL_MXSMBUS_REQUEST \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) // amEepromGetDriverVerision +// amDipswGetDriverVersion #define IOCTL_MXSMBUS_GET_VERSION \ - CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) // amEepromI2CReadBlock,amEepromI2CWriteBlock,amHmGetLPCChipId -#define IOCTL_MXSMBUS_I2C CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_MXSMBUS_IDK CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) +// uses the 0x27 sized request +#define IOCTL_MXSMBUS_I2C \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MXSMBUS_IDK \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_COLUMBA_READ CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS) +#define IOCTL_COLUMBA_READ \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS) -#define IOCTL_MXHWRESET_RESET CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MXHWRESET_RESET \ + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_MXPARALLEL_WRITE_DATA \ - CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_DATA \ - CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXPARALLEL_WRITE_STATUS \ - CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_STATUS \ - CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXPARALLEL_WRITE_CTRL_PORT \ - CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_CTRL_PORT \ - CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXPARALLEL_WRITE_FLAGS \ - CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_FLAGS \ - CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) + (DWORD) CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) diff --git a/src/micetools/lib/mice/meson.build b/src/micetools/lib/mice/meson.build index 9aedba1..89c556c 100644 --- a/src/micetools/lib/mice/meson.build +++ b/src/micetools/lib/mice/meson.build @@ -5,8 +5,10 @@ mice_lib = static_library( 'patch.c', 'crc.c', 'ringbuf.c', + 'config.c', ], link_with: [ + inih.get_variable('lib_inih'), json_lib, ] ) diff --git a/src/micetools/lib/mice/mice.h b/src/micetools/lib/mice/mice.h index e387ada..87830ff 100644 --- a/src/micetools/lib/mice/mice.h +++ b/src/micetools/lib/mice/mice.h @@ -6,3 +6,4 @@ #include "patch.h" #include "crc.h" #include "ringbuf.h" +#include "config.h" diff --git a/src/micetools/lib/mice/patch.c b/src/micetools/lib/mice/patch.c index 22d03d5..73982bd 100644 --- a/src/micetools/lib/mice/patch.c +++ b/src/micetools/lib/mice/patch.c @@ -40,8 +40,10 @@ void free_patches(patches_t* patches) { for (int i = patches->nopatchsets - 1; i >= 0; i--) { if (patches->patchsets[i] != NULL) { for (size_t j = 0; j < patches->patchsets[i]->nopatches; j++) { - if (patches->patchsets[i]->patches[j].from != NULL) free(patches->patchsets[i]->patches[j].from); - if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to); + if (patches->patchsets[i]->patches[j].from != NULL) + free(patches->patchsets[i]->patches[j].from); + if (patches->patchsets[i]->patches[j].to != NULL) + free(patches->patchsets[i]->patches[j].to); } free(patches->patchsets[i]); } @@ -78,7 +80,8 @@ json_value* load_json_from_file(char* path, char* error) { return json_parse_ex(&settings, json_buf, sz, error); } -bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error) { +bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error, + const char* test_binary_name) { patches->nopatchsets = set_count; patches->patchsets = (patchset_t**)malloc(set_count * sizeof(patchset_t*)); for (int i = 0; i < set_count; i++) patches->patchsets[i] = NULL; @@ -109,6 +112,18 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha snprintf(error, json_error_max, "'apply' missing for patch %d (%s)", i, name); goto failed; } + + if (binary_name && test_binary_name) { + if (strcmp(binary_name, test_binary_name) != 0) { + patchset->name = name; + patchset->description = description; + patchset->binary_name = binary_name; + patchset->apply = apply; + patchset->nopatches = 0; + continue; + } + } + json_value* set_patches; if (!fetch(set_json[i], "patches", &set_patches) || set_patches->type != json_array) { char* patches_file_path; @@ -116,15 +131,18 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha char load_error[json_error_max]; set_patches = load_json_from_file(patches_file_path, load_error); if (set_patches == NULL) { - fprintf(stderr, "W: patcher: Failed to load '%s': %s\n", patches_file_path, load_error); + fprintf(stderr, "W: patcher: Failed to load '%s': %s\n", patches_file_path, + load_error); continue; } if (set_patches->type != json_array) { - fprintf(stderr, "W: patcher: Failed to load '%s': not an array\n", patches_file_path); + fprintf(stderr, "W: patcher: Failed to load '%s': not an array\n", + patches_file_path); continue; } } else { - snprintf(error, json_error_max, "Neither 'patches' nor 'patchs_file' in patch %d (%s)", i, name); + snprintf(error, json_error_max, + "Neither 'patches' nor 'patchs_file' in patch %d (%s)", i, name); goto failed; } } @@ -174,7 +192,8 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha patchset->patches[j].offset = at; size_t size = strlen(from); if (size != strlen(to)) { - snprintf(error, json_error_max, "'from' and 'to' lengths differ in patch %s[%d]", name, j); + snprintf(error, json_error_max, "'from' and 'to' lengths differ in patch %s[%d]", + name, j); goto failed; } if (size % 2 != 0) { @@ -203,7 +222,7 @@ failed: return false; } -bool load_patches(patches_t* patches, char* path, char* error) { +bool load_patches(patches_t* patches, char* path, char* error, const char* test_binary_name) { patches->nopatchsets = 0; json_value* parsed = load_json_from_file(path, error); @@ -223,6 +242,7 @@ bool load_patches(patches_t* patches, char* path, char* error) { return false; } - if (!parse_patches(patches, patches_json, loaded_patches, error)) return false; + if (!parse_patches(patches, patches_json, loaded_patches, error, test_binary_name)) + return false; return true; } diff --git a/src/micetools/lib/mice/patch.h b/src/micetools/lib/mice/patch.h index c2741d0..61b456f 100644 --- a/src/micetools/lib/mice/patch.h +++ b/src/micetools/lib/mice/patch.h @@ -32,8 +32,9 @@ bool fetch(json_value* object, char* name, json_value** value); bool fetch_string(json_value* object, char* name, char** value); bool fetch_int(json_value* object, char* name, size_t* value); bool fetch_bool(json_value* object, char* name, bool* value); -bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error); +bool parse_patches(patches_t* patches, json_value** set_json, int set_count, char* error, + const char* test_binary_name); // Main two exports void free_patches(patches_t* patches); -bool load_patches(patches_t* patches, char* path, char* error); +bool load_patches(patches_t* patches, char* path, char* error, const char* test_binary_name); diff --git a/src/micetools/lib/mxk/meson.build b/src/micetools/lib/mxk/meson.build new file mode 100644 index 0000000..eacb031 --- /dev/null +++ b/src/micetools/lib/mxk/meson.build @@ -0,0 +1,13 @@ +mxklib = static_library( + 'mxk', + sources: [ + 'mxk.c', + 'mxkCrypt.c', + 'mxkPacket.c', + 'mxkTransport.c', + ], + include_directories: [ + openssl_inc, + ], + dependencies: [openssl_lib] +) diff --git a/src/micetools/lib/mxk/mxk.c b/src/micetools/lib/mxk/mxk.c new file mode 100644 index 0000000..8816bea --- /dev/null +++ b/src/micetools/lib/mxk/mxk.c @@ -0,0 +1,133 @@ +#include "mxk.h" + +#include "../am/amTimer.h" + +BOOL mxkExchengeAesKey(HANDLE mxparallel) { + FILETIME filetime; + amtime_t now; + + unsigned char key_s[16]; + unsigned char key_r[16]; + + size_t i; + for (i = 0; i < 16; i++) { + amiTimerGet(&now); + GetSystemTimeAsFileTime(&filetime); + key_s[i] = (filetime.dwHighDateTime & 0xff) ^ (filetime.dwLowDateTime & 0xff) ^ + (now.microseconds & 0xff); + } + + for (i = 0; i < 16; i++) { + amiTimerGet(&now); + GetSystemTimeAsFileTime(&filetime); + key_r[i] = (filetime.dwHighDateTime & 0xff) ^ (filetime.dwLowDateTime & 0xff) ^ + (now.microseconds & 0xff); + } + + unsigned char packet[16]; + + mxkPacketReqSetKeyS(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkSendPacket(mxparallel, key_s)) return FALSE; + if (!mxkRecvPacket(mxparallel, packet)) return FALSE; + if (packet[0] != SetKeyS) return FALSE; + mxkSetKeyS(key_s); + + mxkPacketReqSetKeyR(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkSendPacket(mxparallel, key_r)) return FALSE; + mxkSetKeyR(key_r); + if (!mxkRecvPacket(mxparallel, packet)) return FALSE; + + return TRUE; +} + +BOOL mxkVersion(HANDLE mxparallel, unsigned short* version) { + unsigned char packet[16]; + + mxkPacketReqGetVersion(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkRecvPacket(mxparallel, packet)) return FALSE; + + *version = ((unsigned short*)packet)[0]; + return TRUE; +} +#include +BOOL mxkSetMainId(HANDLE mxparallel, const unsigned char* main_id) { + unsigned char packet[16]; + + mxkPacketReqSetMainId(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkSendPacket(mxparallel, main_id)) return FALSE; + + mxkRecvPacket(mxparallel, packet); + + return packet[0] != 0xff; +} +BOOL mxkGetMainId(HANDLE mxparallel, unsigned char* main_id) { + unsigned char packet[16]; + + mxkPacketReqGetMainId(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkRecvPacket(mxparallel, main_id)) return FALSE; + + return TRUE; +} +BOOL mxkGetKeyId(HANDLE mxparallel, unsigned char* key_id) { + unsigned char packet[16]; + + mxkPacketReqGetKeyId(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkRecvPacket(mxparallel, key_id)) return FALSE; + + return TRUE; +} +BOOL mxkGetAppBootInfo(HANDLE mxparallel, appboot_t* appboot) { + unsigned char packet[16]; + + mxkPacketReqGetAppBootInfo(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + for (int i = 0; i < sizeof *appboot; i += 16) { + if (!mxkRecvPacket(mxparallel, (unsigned char*)appboot + i)) return FALSE; + } + return TRUE; +} +BOOL mxkGetPlayCounter(HANDLE mxparallel, DWORD* play_counter) { + unsigned char packet[16]; + + mxkPacketReqGetPlayCounter(packet); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkRecvPacket(mxparallel, packet)) return FALSE; + + *play_counter = ((DWORD*)packet)[0]; + return TRUE; +} +BOOL mxkFlashRead(HANDLE mxparallel, unsigned int address, unsigned int nbytes, + unsigned char* buffer) { + unsigned char packet[16]; + mxkPacketReqFlashRead(packet, address, nbytes); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + + for (size_t i = 0; i < nbytes; i += 0x100) { + unsigned int rest = (nbytes - i) > 0x100 ? 0x100 : (nbytes - i); + if (!mxkTransportRecv(mxparallel, buffer + i, rest)) return FALSE; + } + return TRUE; +} +BOOL mxkEepromRead(HANDLE mxparallel, unsigned char page, unsigned char* data) { + unsigned char packet[16]; + mxkPacketReqEepromRead(packet, page); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + if (!mxkRecvPacket(mxparallel, data)) return FALSE; + return TRUE; +} +BOOL mxkNvramRead(HANDLE mxparallel, unsigned short addr, unsigned char blocks, unsigned char* data) { + unsigned char packet[16]; + mxkPacketReqNvramRead(packet, addr, blocks); + if (!mxkSendPacket(mxparallel, packet)) return FALSE; + + for (size_t i = 0; i < blocks; i++) { + if (!mxkRecvPacket(mxparallel, data + (i * 16))) return FALSE; + } + return TRUE; +} diff --git a/src/micetools/lib/mxk/mxk.h b/src/micetools/lib/mxk/mxk.h new file mode 100644 index 0000000..540b649 --- /dev/null +++ b/src/micetools/lib/mxk/mxk.h @@ -0,0 +1,107 @@ +#pragma once +#include + +extern unsigned char KEY_R[16]; +extern unsigned char KEY_S[16]; +extern unsigned char BILLING_PRIVKEY[917]; +extern unsigned char BILLING_PUBKEY[162]; +extern unsigned char BILLING_CACERT[817]; +extern unsigned char KEYCHIP_ID[16]; +extern unsigned char MAIN_ID[16]; + +enum { + SetKeyS = 0, // mxkPacketReqSetKeyS [0] [... + SetKeyR = 1, // mxkPacketReqSetKeyR [1] [... + SetIV = 2, // mxkPacketReqSetIv [2] [... + Decrypt = 3, // mxkPacketReqDecrypt [3] [... + Encrypt = 4, // mxkPacketReqEncrypt [4] [... + GetAppBootInfo = 5, // mxkPacketReqGetAppBootInfo [5] [0] [... + EepromWrite = 6, // mxkPacketReqEepromWrite [6] [x] [... + EepromRead = 7, // mxkPacketReqEepromRead [7] [x] [... + NvramWrite = 8, // mxkPacketReqNvramWrite [8] [x] [x] [y] [... + NvramRead = 9, // mxkPacketReqNvramRead [9] [x] [x] [y] [... + AddPlayCount = 10, // mxkPacketReqAddPlayCount [10] [... + FlashRead = 11, // mxkPacketReqFlashRead [11] [x] [x] [x] [y] [y] [y] [... + FlashErase = 12, // mxkPacketReqFlashErase [12] [x] [x] [x] [... + KcCmd13 = 13, // mxkPacketReq-13 [13] [x] [x] [x] [... + FlashWrite = 14, // mxkPacketReqFlashWrite [14] [x] [x] [x] [y] [y] [y] [... + KcCmd15 = 15, // + KcCmd16 = 16, // + KcCmd17 = 17, // + KcCmd18 = 18, // + KcCmd19 = 19, // + KcGetVersion = 20, // mxkPacketReqGetVersion [20] [... + SetMainId = 21, // mxkPacketReqSetMainId [21] [... + GetMainId = 22, // mxkPacketReqGetMainId [22] [... + SetKeyId = 23, // mxkPacketReqSetKeyId [23] [... + GetKeyId = 24, // mxkPacketReqGetKeyId [24] [... + GetPlayCounter = 25, // mxkPacketReqGetPlayCounter [25] [... +}; + +// Structs +#pragma pack(1) +typedef struct { + DWORD crc; + DWORD format; + char game_id[4]; + BYTE region; + BYTE model_type; + BYTE system_flag; + BYTE _; + char platform_id[3]; + BYTE dvd_flag; + DWORD network_addr; + BYTE __[216]; + BYTE seed[16]; +} appboot_t; + +// Crypt +void mxkSetKeyS(unsigned char* key_s); +void mxkSetKeyR(unsigned char* key_r); +void mxkSwapKeys(); + +void mxkCryptEncryptData(unsigned char* ct, unsigned char* pt); +void mxkCryptDecryptData(unsigned char* ct, unsigned char* pt); + +void mxkSign(void* buffer, size_t nbytes, unsigned char* signature); +void mxkSignValue(unsigned int value, unsigned char* signature); + +// Transport +static BOOL mxkTransportWaitStrobeReady(HANDLE mxparallel); +static BOOL mxkTransportWaitStrobeRelease(HANDLE mxparallel); +static void mxkTransportCtrlPortInAndOut(HANDLE mxparallel, BYTE flag); +static void mxkTransportCtrlPortInOrOut(HANDLE mxparallel, BYTE flag); + +BOOL mxkTransportSend(HANDLE mxparallel, unsigned char* data, DWORD nbytes); +HRESULT mxkTransportRecv(HANDLE mxparallel, unsigned char* data, DWORD nbytes); + +BOOL mxkSendPacket(HANDLE mxparallel, unsigned char* packet); +BOOL mxkRecvPacket(HANDLE mxparallel, unsigned char* packet); +void mxkTransportInitPic(HANDLE mxparallel); + +// MXK Packet +void mxkPacketReqSetKeyS(unsigned char* packet); +void mxkPacketReqSetKeyR(unsigned char* packet); +void mxkPacketReqGetAppBootInfo(unsigned char* packet); +void mxkPacketReqEepromRead(unsigned char* packet, unsigned char page); +void mxkPacketReqGetVersion(unsigned char* packet); +void mxkPacketReqSetMainId(unsigned char* packet); +void mxkPacketReqGetMainId(unsigned char* packet); +void mxkPacketReqGetKeyId(unsigned char* packet); +void mxkPacketReqGetPlayCounter(unsigned char* packet); +void mxkPacketReqFlashRead(unsigned char* packet, unsigned int address, unsigned int nbytes); +void mxkPacketReqNvramRead(unsigned char* packet, unsigned short addr, unsigned char blocks); + +// MXK +BOOL mxkExchengeAesKey(HANDLE mxparallel); +BOOL mxkVersion(HANDLE mxparallel, unsigned short* version); +BOOL mxkSetMainId(HANDLE mxparallel, unsigned char* main_id); +BOOL mxkGetMainId(HANDLE mxparallel, const unsigned char* main_id); +BOOL mxkGetKeyId(HANDLE mxparallel, unsigned char* main_id); +BOOL mxkGetAppBootInfo(HANDLE mxparallel, appboot_t* appboot); +BOOL mxkGetPlayCounter(HANDLE mxparallel, DWORD* play_counter); +BOOL mxkFlashRead(HANDLE mxparallel, unsigned int address, unsigned int nbytes, + unsigned char* buffer); +BOOL mxkEepromRead(HANDLE mxparallel, unsigned char page, unsigned char* data); +BOOL mxkNvramRead(HANDLE mxparallel, unsigned short addr, unsigned char blocks, + unsigned char* data); diff --git a/src/micetools/lib/mxk/mxkCrypt.c b/src/micetools/lib/mxk/mxkCrypt.c new file mode 100644 index 0000000..36eab8b --- /dev/null +++ b/src/micetools/lib/mxk/mxkCrypt.c @@ -0,0 +1,158 @@ +#include +#include + +#include "mxk.h" + +unsigned char KEY_R[16] = { + 0x75, 0x6f, 0x72, 0x61, 0x74, 0x6e, 0x65, 0x6b, 0x61, 0x6d, 0x69, 0x68, 0x73, 0x75, 0x6b, 0x75, +}; +unsigned char KEY_S[16] = { + 0x66, 0x6E, 0x65, 0x6B, 0x65, 0x72, 0x61, 0x77, 0x64, 0x72, 0x61, 0x68, 0x61, 0x67, 0x65, 0x73, +}; + +unsigned char BILLING_PRIVKEY[] = + ("-----BEGIN PRIVATE KEY-----\n" + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAML2GPUuzv2N4bYC\n" + "xtc5bZSzolHFWdCUbP+whjr3K98FOLnYeoi7mtUSUUYOW8wIqy6WM3c4c0Bp7FcQ\n" + "LnZ0zWMm1TfLGHZzZmk5n7Iv6HDPr3ehDgbWLnOpRrVqZDxpAGD2vQb4p2DW4I2x\n" + "GUqnqDa++C8dH/0lXqE6cqwGXNGtAgMBAAECgYEAizgPhG4Dk55QkpeTBDfXH3vT\n" + "Ko9B3qdO2ptkjxDX/C8PXe7POXq2SvcEoIE6Xg3Gp8LMR5NBAbth8J32f9JSov3P\n" + "SiGCGno4k2i2s3jRuVg76FGLDsZH/N1dt4h78VnW0VlInwaM6bQv3zp0u8rXVk/P\n" + "wpYh9AGmquBJS3VYUcECQQD0PDRe28SrhollygGZSO321rYbYhoTIstDXZWyQ/y/\n" + "PWKNwNHcYTHIVGmTrJx2AJUyr1tJhwjiOwlsI5Y1Q4/9AkEAzFpFPcs1r/xgSFxB\n" + "eYrcNseWYbVajtVxG9t57sayaEQbH2UMNA2vqSYK/nU6oJhj5eLRIsPHlA5ZbIiZ\n" + "rvc/cQJAKS0RQ0DX+ncXKQMSm+4wuGHgl+NFNB60mCnp+AEAVpmZyP5OI1J7myOo\n" + "HQ6H3lkgzkfEIzRR6ho773BcfaRjXQJAfS4nEE11G9ML4AezjBLGB0CIHF6NlMWn\n" + "PhtaPCy3iSt/OeIacaCYpJNLVMjXGx1+xIoG9rbbgRSxLs0W55lJ4QJBALOUVcNw\n" + "GKEJdxhIkA8iuUlEyGpKluAgHUNOOKvC3ogRoB0OyH+If/9o8wWDfxgexgM0zGBc\n" + "u178W9XDW+IijDA=\n" + "-----END PRIVATE KEY-----\n"); +unsigned char BILLING_PUBKEY[] = { + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xc2, + 0xf6, 0x18, 0xf5, 0x2e, 0xce, 0xfd, 0x8d, 0xe1, 0xb6, 0x02, 0xc6, 0xd7, 0x39, 0x6d, 0x94, + 0xb3, 0xa2, 0x51, 0xc5, 0x59, 0xd0, 0x94, 0x6c, 0xff, 0xb0, 0x86, 0x3a, 0xf7, 0x2b, 0xdf, + 0x05, 0x38, 0xb9, 0xd8, 0x7a, 0x88, 0xbb, 0x9a, 0xd5, 0x12, 0x51, 0x46, 0x0e, 0x5b, 0xcc, + 0x08, 0xab, 0x2e, 0x96, 0x33, 0x77, 0x38, 0x73, 0x40, 0x69, 0xec, 0x57, 0x10, 0x2e, 0x76, + 0x74, 0xcd, 0x63, 0x26, 0xd5, 0x37, 0xcb, 0x18, 0x76, 0x73, 0x66, 0x69, 0x39, 0x9f, 0xb2, + 0x2f, 0xe8, 0x70, 0xcf, 0xaf, 0x77, 0xa1, 0x0e, 0x06, 0xd6, 0x2e, 0x73, 0xa9, 0x46, 0xb5, + 0x6a, 0x64, 0x3c, 0x69, 0x00, 0x60, 0xf6, 0xbd, 0x06, 0xf8, 0xa7, 0x60, 0xd6, 0xe0, 0x8d, + 0xb1, 0x19, 0x4a, 0xa7, 0xa8, 0x36, 0xbe, 0xf8, 0x2f, 0x1d, 0x1f, 0xfd, 0x25, 0x5e, 0xa1, + 0x3a, 0x72, 0xac, 0x06, 0x5c, 0xd1, 0xad, 0x02, 0x03, 0x01, 0x00, 0x01, +}; + +unsigned char BILLING_CACERT[] = { + 0x30, 0x82, 0x03, 0x2d, 0x30, 0x82, 0x02, 0x15, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x43, + 0xae, 0xdc, 0x17, 0xc6, 0xea, 0xde, 0x6f, 0x69, 0x71, 0x6a, 0xba, 0xcc, 0x97, 0x99, 0x45, 0xcf, + 0x0d, 0xeb, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x25, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x44, + 0x75, 0x6d, 0x6d, 0x79, 0x43, 0x41, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x08, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x50, 0x4b, 0x49, 0x30, 0x20, 0x17, 0x0d, 0x31, 0x38, 0x31, + 0x30, 0x31, 0x35, 0x31, 0x39, 0x33, 0x30, 0x35, 0x31, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x31, 0x38, + 0x31, 0x30, 0x31, 0x35, 0x31, 0x39, 0x33, 0x30, 0x35, 0x31, 0x5a, 0x30, 0x25, 0x31, 0x10, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x43, 0x41, 0x31, + 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x44, 0x75, 0x6d, 0x6d, 0x79, 0x50, + 0x4b, 0x49, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xde, 0x1c, 0x42, 0x76, 0x2f, 0xe1, 0x57, 0xad, 0xc7, 0x56, 0x1b, 0xc2, 0xcd, + 0x67, 0xf5, 0xa4, 0x9d, 0x3c, 0xc4, 0xf6, 0x5b, 0x01, 0xe0, 0x8d, 0x46, 0x6f, 0xb2, 0xdc, 0xad, + 0x78, 0xbf, 0x62, 0xaf, 0xab, 0x12, 0x71, 0x7c, 0x8a, 0xbb, 0xb6, 0x87, 0x88, 0xf5, 0x89, 0xc9, + 0x83, 0x4a, 0xec, 0x0b, 0x05, 0x2f, 0xff, 0xa8, 0x43, 0x4e, 0xd8, 0xb7, 0xc4, 0xfa, 0x25, 0x35, + 0xce, 0x6b, 0x65, 0x86, 0x30, 0x1f, 0x1a, 0xff, 0x12, 0x61, 0x25, 0xe0, 0xd6, 0xcb, 0x00, 0x6c, + 0x1e, 0x92, 0xbf, 0x8b, 0xef, 0xcf, 0x45, 0x34, 0xa4, 0xd0, 0x80, 0xbe, 0x72, 0x7f, 0x2b, 0xc5, + 0x0d, 0xee, 0x40, 0x17, 0x1c, 0x1d, 0x6b, 0xc3, 0x97, 0x51, 0xbc, 0xee, 0x3b, 0x03, 0xe3, 0x35, + 0x34, 0xef, 0x12, 0xea, 0x96, 0x13, 0x2f, 0x98, 0xc9, 0x84, 0xaf, 0x81, 0x68, 0xd5, 0x66, 0x3f, + 0xac, 0x3d, 0x78, 0xe4, 0x38, 0x73, 0xed, 0x19, 0xbc, 0xa1, 0x4e, 0x11, 0x7d, 0x04, 0xfe, 0xec, + 0xb5, 0xa9, 0xc5, 0x2e, 0x4b, 0x7f, 0x3a, 0x65, 0xc3, 0xc5, 0x47, 0x14, 0x45, 0xbc, 0x4a, 0xd4, + 0xa3, 0xc5, 0xa3, 0xc8, 0xc0, 0x30, 0x57, 0xd1, 0xd9, 0xa1, 0x56, 0xb7, 0x87, 0x7b, 0x40, 0xcb, + 0x02, 0x9f, 0x0e, 0xb6, 0x23, 0x17, 0xc0, 0xed, 0x74, 0xd1, 0xbd, 0xdc, 0x6d, 0xe2, 0x83, 0x3a, + 0x6f, 0xe0, 0x8a, 0xe8, 0xe0, 0x0b, 0x84, 0x4a, 0xb3, 0xc4, 0xde, 0xde, 0x31, 0xe6, 0xe8, 0x8e, + 0xe1, 0x4c, 0x70, 0x50, 0xe6, 0xe8, 0x96, 0x45, 0x6c, 0x98, 0xe0, 0x33, 0xa3, 0xb8, 0x35, 0x42, + 0x21, 0x22, 0xd3, 0x09, 0x47, 0x4d, 0x05, 0xf5, 0x64, 0x7d, 0xdd, 0x5e, 0x06, 0x91, 0x00, 0x5e, + 0x6f, 0xbf, 0xf5, 0x74, 0xd9, 0x90, 0x27, 0x98, 0x8e, 0x64, 0x79, 0x77, 0xcf, 0x0c, 0x32, 0x2a, + 0x51, 0x17, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, + 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc4, 0x77, 0x5b, 0x5d, 0x0e, 0xdd, 0xa8, 0x5a, 0xb0, + 0x8f, 0x3c, 0xe5, 0xd3, 0x62, 0xfe, 0x51, 0xe7, 0xc4, 0xc0, 0xd8, 0x30, 0x1f, 0x06, 0x03, 0x55, + 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xc4, 0x77, 0x5b, 0x5d, 0x0e, 0xdd, 0xa8, 0x5a, + 0xb0, 0x8f, 0x3c, 0xe5, 0xd3, 0x62, 0xfe, 0x51, 0xe7, 0xc4, 0xc0, 0xd8, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, + 0x00, 0xa5, 0xc5, 0x86, 0xb3, 0xe0, 0x34, 0xe8, 0x06, 0xaa, 0xaf, 0xd5, 0x40, 0xc6, 0x10, 0xe9, + 0x8b, 0x8b, 0xd2, 0x57, 0x42, 0xbe, 0xfb, 0xdd, 0x76, 0x20, 0x95, 0x91, 0xbf, 0xaa, 0xd1, 0x47, + 0x2e, 0xc7, 0xcf, 0x86, 0xfb, 0x3a, 0xfe, 0x54, 0x39, 0x9e, 0xc0, 0x1e, 0xc8, 0x67, 0x40, 0xd5, + 0x90, 0xbd, 0xdf, 0x50, 0xa7, 0xe7, 0xa1, 0x84, 0xda, 0x0b, 0x8c, 0xbe, 0x63, 0xa1, 0x69, 0x3d, + 0x06, 0x6c, 0x0c, 0x3c, 0x60, 0x0f, 0x84, 0x10, 0x2f, 0x89, 0xd0, 0xe1, 0xf1, 0x05, 0x0b, 0x50, + 0x02, 0x03, 0x25, 0x60, 0xc6, 0x17, 0xc0, 0xad, 0x0c, 0x36, 0x96, 0xf2, 0x81, 0xd8, 0x8e, 0xc0, + 0x53, 0x05, 0x25, 0x63, 0x2a, 0xed, 0x4c, 0x6b, 0xf3, 0x95, 0x31, 0xcf, 0x6f, 0x17, 0x41, 0x23, + 0x31, 0x46, 0xf7, 0x2e, 0xd9, 0x4a, 0x66, 0x43, 0x54, 0xaa, 0x65, 0x02, 0x8e, 0x51, 0x3f, 0x57, + 0x66, 0xd8, 0x62, 0x3a, 0x95, 0x2c, 0xd4, 0xe8, 0x82, 0xb5, 0xce, 0xe0, 0xac, 0x57, 0xca, 0xa7, + 0xc1, 0x15, 0xd5, 0x33, 0x4c, 0x20, 0x7f, 0xa9, 0x7e, 0xd5, 0xf8, 0x73, 0x67, 0xb3, 0x30, 0xea, + 0x20, 0x51, 0xc5, 0xfb, 0x0c, 0x93, 0x92, 0x53, 0x12, 0x3b, 0x04, 0xd4, 0x22, 0xbb, 0xd6, 0xe1, + 0x1e, 0xb3, 0xa2, 0x35, 0xcb, 0xd3, 0x08, 0xd1, 0x76, 0xfb, 0x41, 0xa9, 0x74, 0xaf, 0x3c, 0x5a, + 0xb9, 0x1d, 0x62, 0x4f, 0x76, 0x0d, 0x1d, 0x7d, 0x5c, 0xb2, 0x54, 0x36, 0x6e, 0xef, 0x23, 0xce, + 0xde, 0x03, 0x09, 0x2e, 0xa9, 0x03, 0x90, 0x7b, 0x1a, 0x60, 0xbb, 0x36, 0x20, 0xa1, 0xd4, 0x5e, + 0xa2, 0x42, 0x6c, 0x70, 0x89, 0xff, 0x08, 0x69, 0x31, 0x63, 0x58, 0x62, 0x8c, 0xc3, 0x14, 0x6a, + 0xe1, 0x7a, 0xd3, 0x52, 0xbe, 0x8d, 0xec, 0x2a, 0x1b, 0x7d, 0xc2, 0xf4, 0x0a, 0xd3, 0xc9, 0x9c, + 0xca, +}; + +void mxkSetKeyS(unsigned char* key_s) { memcpy(KEY_S, key_s, 16); } +void mxkSetKeyR(unsigned char* key_r) { memcpy(KEY_R, key_r, 16); } +void mxkSwapKeys() { + unsigned char temp[16]; + memcpy(temp, KEY_R, 16); + memcpy(KEY_R, KEY_S, 16); + memcpy(KEY_S, temp, 16); +} + +void mxkCryptEncryptData(unsigned char* ct, unsigned char* pt) { + EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + EVP_CipherInit_ex(ctx, EVP_aes_128_ecb(), NULL, KEY_S, NULL, 1); + + int outl; + EVP_EncryptUpdate(ctx, ct, &outl, pt, 16); + unsigned char dump[16]; + EVP_EncryptFinal_ex(ctx, dump, &outl); + EVP_CIPHER_CTX_free(ctx); +} + +void mxkCryptDecryptData(unsigned char* ct, unsigned char* pt) { + EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + EVP_CipherInit_ex(ctx, EVP_aes_128_ecb(), NULL, KEY_R, NULL, 0); + + int outl; + EVP_DecryptUpdate(ctx, pt, &outl, ct, 16); + unsigned char dump[16]; + EVP_DecryptFinal_ex(ctx, dump, &outl); + EVP_CIPHER_CTX_free(ctx); +} + +void mxkSign(void* buffer, size_t nbytes, unsigned char* signature) { + BIO* bio = BIO_new_mem_buf(BILLING_PRIVKEY, sizeof BILLING_PRIVKEY); + EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL); + BIO_free(bio); + + EVP_MD_CTX* ctx = EVP_MD_CTX_create(); + EVP_DigestSignInit(ctx, NULL, EVP_sha1(), NULL, pkey); + EVP_DigestSignUpdate(ctx, buffer, nbytes); + EVP_DigestSignFinal(ctx, NULL, &nbytes); + EVP_DigestSignFinal(ctx, signature, &nbytes); + + EVP_PKEY_free(pkey); + EVP_MD_CTX_destroy(ctx); +} + +#pragma pack(1) +typedef struct { + unsigned int value; + unsigned char key_low[4]; + unsigned char key_high[7]; +} sign_payload_t; + +void mxkSignValue(unsigned int value, unsigned char* signature) { + sign_payload_t hash_data; + hash_data.value = value; + memcpy(hash_data.key_low, KEYCHIP_ID, 4); + memcpy(hash_data.key_high, &KEYCHIP_ID[5], 7); + mxkSign(&hash_data, sizeof hash_data, signature); +} diff --git a/src/micetools/lib/mxk/mxkPacket.c b/src/micetools/lib/mxk/mxkPacket.c new file mode 100644 index 0000000..5028d84 --- /dev/null +++ b/src/micetools/lib/mxk/mxkPacket.c @@ -0,0 +1,70 @@ +#include "../am/amTimer.h" +#include "mxk.h" + +void inline _mxkPacketInjectJunk(unsigned char* packet, size_t i) { + FILETIME filetime; + amtime_t now; + + for (; i < 16; i++) { + amiTimerGet(&now); + GetSystemTimeAsFileTime(&filetime); + packet[i] = (filetime.dwHighDateTime & 0xff) ^ (filetime.dwLowDateTime & 0xff) ^ + (now.microseconds & 0xff); + } +} + +void mxkPacketReqSetKeyS(unsigned char* packet) { + packet[0] = SetKeyS; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqSetKeyR(unsigned char* packet) { + packet[0] = SetKeyR; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqGetAppBootInfo(unsigned char* packet) { + packet[0] = GetAppBootInfo; + packet[1] = 0; + _mxkPacketInjectJunk(packet, 2); +} +void mxkPacketReqEepromRead(unsigned char* packet, unsigned char page) { + packet[0] = EepromRead; + packet[1] = page; + _mxkPacketInjectJunk(packet, 2); +} +void mxkPacketReqGetVersion(unsigned char* packet) { + packet[0] = KcGetVersion; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqSetMainId(unsigned char* packet) { + packet[0] = SetMainId; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqGetMainId(unsigned char* packet) { + packet[0] = GetMainId; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqGetKeyId(unsigned char* packet) { + packet[0] = GetKeyId; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqGetPlayCounter(unsigned char* packet) { + packet[0] = GetPlayCounter; + _mxkPacketInjectJunk(packet, 1); +} +void mxkPacketReqFlashRead(unsigned char* packet, unsigned int address, unsigned int nbytes) { + packet[0] = FlashRead; + packet[1] = address & 0xff; + packet[2] = (address >> 8) & 0xff; + packet[3] = (address >> 16) & 0xff; + packet[4] = nbytes & 0xff; + packet[5] = (nbytes >> 8) & 0xff; + packet[6] = (nbytes >> 16) & 0xff; + _mxkPacketInjectJunk(packet, 7); +} +void mxkPacketReqNvramRead(unsigned char* packet, unsigned short addr, unsigned char blocks) { + packet[0] = NvramRead; + packet[1] = addr & 0xff; + packet[2] = (addr >> 8) & 0xff; + packet[3] = blocks; + _mxkPacketInjectJunk(packet, 4); +} diff --git a/src/micetools/lib/mxk/mxkTransport.c b/src/micetools/lib/mxk/mxkTransport.c new file mode 100644 index 0000000..bfcc684 --- /dev/null +++ b/src/micetools/lib/mxk/mxkTransport.c @@ -0,0 +1,187 @@ +#include "../am/amTimer.h" +#include "../mice/ioctl.h" +#include "mxk.h" + +// TODO: Don't use puts! +#include + +BOOL DO_SLEEP_0 = TRUE; + + +#define ReadStatus(mxparallel, status, nret) \ + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_READ_STATUS, NULL, 0, &status, 1, &nret, NULL); + +BOOL mxkTransportWaitStrobeReady(HANDLE mxparallel) { + BYTE status; + DWORD nbytes = 0; + + ReadStatus(mxparallel, status, nbytes); + status &= 0x80; + if (status != 0) { + ReadStatus(mxparallel, status, nbytes); + if ((status & 0x80) != 0) return FALSE; + } + return TRUE; +} + +BOOL mxkTransportWaitStrobeRelease(HANDLE mxparallel) { + BYTE status; + DWORD nbytes = 0; + + ReadStatus(mxparallel, status, nbytes); + status &= 0x80; + if (status == 0) { + ReadStatus(mxparallel, status, nbytes); + if ((status & 0x80) == 0) return FALSE; + } + return TRUE; +} + +void mxkTransportCtrlPortInAndOut(HANDLE mxparallel, BYTE flag) { + BYTE ctrl; + DWORD nbytes = 0; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_READ_CTRL_PORT, NULL, 0, &ctrl, 1, &nbytes, NULL); + ctrl &= flag; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_WRITE_CTRL_PORT, &ctrl, 1, NULL, 0, &nbytes, NULL); +} + +void mxkTransportCtrlPortInOrOut(HANDLE mxparallel, BYTE flag) { + BYTE ctrl; + DWORD nbytes = 0; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_READ_CTRL_PORT, NULL, 0, &ctrl, 1, &nbytes, NULL); + ctrl |= flag; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_WRITE_CTRL_PORT, &ctrl, 1, NULL, 0, &nbytes, NULL); +} + +BOOL mxkTransportSend(HANDLE mxparallel, unsigned char *data, DWORD nbytes) { + DWORD nret; + BYTE status; + + amtime_t start; + amtime_t now; + + for (size_t i = 0; i < nbytes; i++) { + amiTimerGet(&start); + do { + ReadStatus(mxparallel, status, nret); + status &= 0x40; + if (status == 0) break; + amiTimerGet(&now); + if (DO_SLEEP_0) Sleep(0); + } while (_amTimeDeltaMircos(now, start) < 1000000); + + if (status != 0) { + puts("SEND busy error"); + return FALSE; + } + + while (mxkTransportWaitStrobeRelease(mxparallel)) { + amiTimerGet(&now); + if (DO_SLEEP_0) Sleep(0); + if (_amTimeDeltaMircos(now, start) > 999999) { + puts("SEND busy error"); + return FALSE; + } + } + + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_WRITE_DATA, &data[i], 1, NULL, 0, &nret, NULL); + + mxkTransportCtrlPortInAndOut(mxparallel, 0xdf); + mxkTransportCtrlPortInOrOut(mxparallel, 0x01); + + while (mxkTransportWaitStrobeReady(mxparallel)) { + amiTimerGet(&now); + if (DO_SLEEP_0) Sleep(0); + if (_amTimeDeltaMircos(now, start) > 999999'000) { + puts("SEND end error"); + return FALSE; + } + } + + mxkTransportCtrlPortInOrOut(mxparallel, 0x20); + mxkTransportCtrlPortInAndOut(mxparallel, 0xfe); + } + return TRUE; +} + +HRESULT mxkTransportRecv(HANDLE mxparallel, unsigned char *data, DWORD nbytes) { + BYTE status; + DWORD nret; + + amtime_t now; + amtime_t start; + + for (size_t i = 0; i < nbytes; i++) { + amiTimerGet(&start); + do { + ReadStatus(mxparallel, status, nret); + status &= 0x40; + if (status != 0) break; + amiTimerGet(&now); + if (DO_SLEEP_0 != 0) Sleep(0); + } while (_amTimeDeltaMircos(now, start) < 1000000'000); + + if (status == 0) { + puts("RECV busy error 1"); + return FALSE; + } + + while (mxkTransportWaitStrobeReady(mxparallel)) { + amiTimerGet(&now); + if (DO_SLEEP_0 != 0) Sleep(0); + + if (_amTimeDeltaMircos(now, start) > 999999'000) { + puts("RECV busy error 2"); + return FALSE; + } + } + + mxkTransportCtrlPortInOrOut(mxparallel, 0x20); + mxkTransportCtrlPortInOrOut(mxparallel, 0x01); + + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_READ_DATA, NULL, 0, &data[i], 1, &nret, NULL); + + while (mxkTransportWaitStrobeRelease(mxparallel)) { + amiTimerGet(&now); + if (DO_SLEEP_0) Sleep(0); + if (_amTimeDeltaMircos(now, start) > 999999) { + puts("RECV end error"); + return FALSE; + } + } + mxkTransportCtrlPortInAndOut(mxparallel, 0xfe); + } + return TRUE; +} + +BOOL mxkSendPacket(HANDLE mxparallel, unsigned char *packet) { + unsigned char encrypted[16]; + ZeroMemory(encrypted, 16); + mxkCryptEncryptData(encrypted, packet); + return mxkTransportSend(mxparallel, encrypted, 0x10); +} + +BOOL mxkRecvPacket(HANDLE mxparallel, unsigned char *packet) { + unsigned char encrypted[16]; + if (!mxkTransportRecv(mxparallel, encrypted, 0x10)) return FALSE; + mxkCryptDecryptData(encrypted, packet); + return TRUE; +} + +void mxkTransportInitPic(HANDLE mxparallel) { + BYTE flags = 0; + DWORD nbytes = 0; + Sleep(10); + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_READ_FLAGS, NULL, 0, &flags, 1, &nbytes, NULL); + flags = flags & 0x1f | 0x20; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_WRITE_FLAGS, &flags, 1, NULL, 0, &nbytes, NULL); + Sleep(10); + flags = 0x24; + DeviceIoControl(mxparallel, IOCTL_MXPARALLEL_WRITE_CTRL_PORT, &flags, 1, NULL, 0, &nbytes, + NULL); + Sleep(10); + mxkTransportCtrlPortInAndOut(mxparallel, 0xfb); + Sleep(10); + mxkTransportCtrlPortInOrOut(mxparallel, 0x24); + Sleep(10); +} diff --git a/src/micetools/miceboot/mxstartup.c b/src/micetools/miceboot/mxstartup.c index 4877256..e8e89d7 100644 --- a/src/micetools/miceboot/mxstartup.c +++ b/src/micetools/miceboot/mxstartup.c @@ -192,7 +192,7 @@ bool GetKeyFile(LPCSTR src, LPCSTR dst) { } bool GetSystemKeyFile() { return GetKeyFile(SYSTEM_KEYFILE_ADS, SYSTEM_KEY_FILE); }; -bool GetOOUpdateKeyFile() { return GetKeyFile(OS_UPDATE_KEYFILE_ADS, OS_UPDATE_KEY_FILE); }; +bool GetOSUpdateKeyFile() { return GetKeyFile(OS_UPDATE_KEYFILE_ADS, OS_UPDATE_KEY_FILE); }; bool SetDiskAccessPrivilege() { int i; for (i = 0; i < 100; i++) { diff --git a/src/micetools/micekeychip/mxk.h b/src/micetools/micekeychip/mxk.h index e133d2e..fd8de74 100644 --- a/src/micetools/micekeychip/mxk.h +++ b/src/micetools/micekeychip/mxk.h @@ -8,4 +8,4 @@ void mxkBinaryCallback(pcpa_t* stream, void* data); int mxkInit(); e_pcpa_t mxkPcpStreamInit(); -e_pcpa_t mxkPcpServer(); \ No newline at end of file +e_pcpa_t mxkPcpServer(); diff --git a/src/micetools/micepatch/main.c b/src/micetools/micepatch/main.c index 5204b86..26fdd18 100644 --- a/src/micetools/micepatch/main.c +++ b/src/micetools/micepatch/main.c @@ -98,7 +98,7 @@ int main(int argc, char** argv) { char error[json_error_max]; patches_t all_patches; - if (!load_patches(&all_patches, argv[1], error)) { + if (!load_patches(&all_patches, argv[1], error, NULL)) { fprintf(stderr, "%s\n", error); return -1; } diff --git a/src/micetools/util/meson.build b/src/micetools/util/meson.build index 1fc139a..d3cb510 100644 --- a/src/micetools/util/meson.build +++ b/src/micetools/util/meson.build @@ -5,7 +5,8 @@ executable( 'micedump.c', ], link_with: [ - amlib + amlib, + mxklib, ], ) @@ -27,3 +28,11 @@ executable( 'micemonitor.c', ], ) + +executable( + 'kcproxy', + win_subsystem: subsystem, + sources: [ + 'proxy.c', + ], +) diff --git a/src/micetools/util/micedump.c b/src/micetools/util/micedump.c index 3fe88f7..0d9afd6 100644 --- a/src/micetools/util/micedump.c +++ b/src/micetools/util/micedump.c @@ -8,6 +8,7 @@ #pragma comment(lib, "Setupapi.lib") #include "../lib/am/amEeprom.h" +#include "../lib/mxk/mxk.h" #define OpenDriver(x) \ CreateFileA("\\\\.\\" x, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL) @@ -38,8 +39,8 @@ void scan_for_dmi(HANDLE columba, DWORD *stable_addr) { request.dType = 1; request.size = sizeof readBuf; - BOOL succ = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request, - sizeof request, &readBuf, sizeof readBuf, &bytesOut, NULL); + BOOL succ = DeviceIoControl(columba, IOCTL_COLUMBA_READ, &request, sizeof request, &readBuf, + sizeof readBuf, &bytesOut, NULL); if (succ && bytesOut == sizeof readBuf) { for (unsigned int offset = 0; offset < 0x8008; offset++) { if (readBuf[offset] == '_' && readBuf[offset + 1] == 'D' && @@ -84,8 +85,8 @@ BOOL dump_columba() { } DWORD bytesReturned; - BOOL s = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request, sizeof request, - readBuf, sizeof readBuf, &bytesReturned, NULL); + BOOL s = DeviceIoControl(columba, IOCTL_COLUMBA_READ, &request, sizeof request, readBuf, + sizeof readBuf, &bytesReturned, NULL); if (!s || bytesReturned != sizeof readBuf) { CloseHandle(columba); return FALSE; @@ -110,8 +111,8 @@ BOOL dump_eeprom() { DWORD _dummy; DWORD version; - DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &version, sizeof version, - &_dummy, NULL); + DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &version, sizeof version, &_dummy, + NULL); printf("mxSMBus version: %08x\n", version); BYTE data[0x20]; @@ -137,8 +138,8 @@ BOOL dump_sram() { BOOL s; DWORD version; - s = DeviceIoControl(mxsram, (DWORD)IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version, - &_dummy, NULL); + s = DeviceIoControl(mxsram, IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version, &_dummy, + NULL); if (!s) { CloseHandle(mxsram); return FALSE; @@ -160,7 +161,7 @@ BOOL dump_sram() { printf(":: BytesPerSector: %d\n", geom.BytesPerSector); DWORD ssize; - s = DeviceIoControl(mxsram, (DWORD)IOCTL_MXSRAM_GET_SECTOR_SIZE, NULL, 0, &ssize, sizeof ssize, + s = DeviceIoControl(mxsram, IOCTL_MXSRAM_GET_SECTOR_SIZE, NULL, 0, &ssize, sizeof ssize, &_dummy, NULL); if (!s) { CloseHandle(mxsram); @@ -188,7 +189,7 @@ BOOL dump_sram() { BYTE superio_read(HANDLE mxsuperio, BYTE chip, BYTE device, BYTE index) { DWORD _dummy; BYTE payload[4] = { chip, device, index, 0 }; - DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_READ, payload, sizeof payload, payload, + DeviceIoControl(mxsuperio, IOCTL_MXSUPERIO_READ, payload, sizeof payload, payload, sizeof payload, &_dummy, NULL); return payload[3]; } @@ -218,8 +219,8 @@ BOOL dump_superio() { DWORD _dummy; DWORD version; - s = DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_PING, NULL, 0, &version, sizeof version, - &_dummy, NULL); + s = DeviceIoControl(mxsuperio, IOCTL_MXSUPERIO_PING, NULL, 0, &version, sizeof version, &_dummy, + NULL); if (!s) { CloseHandle(mxsuperio); return FALSE; @@ -245,8 +246,8 @@ BOOL dump_superio() { puts(":: Super lazy dump of chip 1, bank 0:"); for (uint8_t reg = 0; reg < 0xff; reg++) { unsigned char packet[3] = { 1, reg, 0 }; - DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_HWMONITOR_LPC_READ, &packet, - sizeof packet, &packet, sizeof packet, &_dummy, NULL); + DeviceIoControl(mxsuperio, IOCTL_MXSUPERIO_HWMONITOR_LPC_READ, &packet, sizeof packet, + &packet, sizeof packet, &_dummy, NULL); printf(" -> %02x: %02x\n", reg, packet[2]); } @@ -254,13 +255,261 @@ BOOL dump_superio() { return TRUE; } +void kc_experiments(HANDLE mxparallel) { + BYTE packet[16]; + BYTE test; + + // Returns FF all the time! + // puts("Attempting to rekey key!!"); + // // OLD ID: A72E-02D11266103 + // ZeroMemory(packet, 16); + // packet[0] = 23; + // mxkSendPacket(mxparallel, packet); + // memcpy(packet, "A72E-69696969696", 16); + // mxkSendPacket(mxparallel, packet); + // mxkRecvPacket(mxparallel, packet); + // puts("Response:"); + // for (int i = 0; i < 16; i++) { + // printf("%02x ", packet[i]); + // } + // puts(""); + + /* + 15: seems to send random bytes back? rng? + 16: echo, but byte 0 == 0 + 17: echo, but byte 0 == 0 + 18: hangs. need to send some more payload? + 19: as 18 + + 26: + */ + // puts("KEY_R:"); + // for (int i = 0; i < 16; i++) { + // printf("%02x ", KEY_R[i]); + // } + // puts(""); + // puts("KEY_S:"); + // for (int i = 0; i < 16; i++) { + // printf("%02x ", KEY_S[i]); + // } + // puts(""); + + // for (int i = 0; i < 10; i++) { + // for (int j = 0; j < 2; j++) { + // for (test = 15; test < 16; test++) { + // ZeroMemory(packet, 16); + // packet[0] = test; + // printf("Sending %d\n", test); + // mxkSendPacket(mxparallel, packet); + // mxkRecvPacket(mxparallel, packet); + // puts("Response:"); + // for (int i = 0; i < 16; i++) { + // printf("%02x ", packet[i]); + // } + // puts(""); + // } + // } + // Sleep(250); + // } + + ZeroMemory(packet, 16); + for (int i = 0; i < 16; i++) packet[i] = i; + packet[0] = 17; + printf("Sending %d\n", 17); + mxkSendPacket(mxparallel, packet); + + /** + * 18: + * Returns the same stuff for all keychips + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * returns: 21 D8 A8 21 2A CD A9 4A 5C D9 7A 35 43 ED 83 7A + * 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * returns: 65 FA F5 BE 9F 93 8D 02 6E C4 D5 60 6E C1 74 D6 + * 19: + * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + * returns: 57 45 43 37 D0 80 48 B1 86 26 A7 81 70 1D 1F 4F + * */ + BYTE response[16]; + mxkRecvPacket(mxparallel, response); + puts("Response:"); + for (int i = 0; i < 16; i++) { + printf("%02x ", response[i]); + } + puts(""); + + puts("Sending DoAs"); + packet[0] = EepromWrite; + packet[1] = 0x20; + mxkSendPacket(mxparallel, packet); + ZeroMemory(packet, 16); + packet[0] = 'D'; + packet[1] = 'o'; + packet[2] = 'A'; + packet[3] = 's'; + mxkSendPacket(mxparallel, packet); + mxkRecvPacket(mxparallel, packet); + if (packet[0] == 0xff) puts("Failed to DoAs"); + else puts("DoAs'd"); + +} + +BYTE KEYCHIP_ID[16]; +BYTE MAIN_ID[16]; +BOOL dump_keychip() { + SECTION_HEAD("keychip"); + FILE *fd; + + HANDLE mxparallel = OpenDriver("mxparallel"); + if (mxparallel == INVALID_HANDLE_VALUE) return FALSE; + + mxkTransportInitPic(mxparallel); + if (!mxkExchengeAesKey(mxparallel)) { + puts("Failed to exchange keys!"); + return FALSE; + } + + unsigned short version; + if (!mxkVersion(mxparallel, &version)) { + puts("Failed to request version!"); + } else { + printf("Version:\t%02x%02x\n", version & 0xff, version >> 8); + } + + ZeroMemory(MAIN_ID, 16); + if (!mxkGetMainId(mxparallel, MAIN_ID)) { + puts("Failed to request main ID!"); + } else { + printf("Main ID:\t%.16s\n", MAIN_ID); + } + + ZeroMemory(MAIN_ID, 16); + if (!mxkSetMainId(mxparallel, MAIN_ID)) { + puts("Failed to zero main ID!"); + } + + ZeroMemory(KEYCHIP_ID, 16); + if (!mxkGetKeyId(mxparallel, KEYCHIP_ID)) { + puts("Failed to request key ID!"); + } else { + printf("Keychip ID:\t%.16s\n", KEYCHIP_ID); + } + + appboot_t appboot; + if (!mxkGetAppBootInfo(mxparallel, &appboot)) { + puts("Failed to request appboot info!"); + } else { + printf("Game ID:\t%.4s\n", appboot.game_id); + printf("Region:\t\t%02x\n", appboot.region); + printf("Model Type:\t%02x\n", appboot.model_type); + printf("Sys Flag:\t%02x\n", appboot.system_flag); + printf("Platform ID:\t%.3s\n", appboot.platform_id); + printf("DVD Flag:\t%02x\n", appboot.dvd_flag); + printf("Network addr:\t%d.%d.%d.%d\n", appboot.network_addr & 0xff, + (appboot.network_addr >> 8) & 0xff, (appboot.network_addr >> 16) & 0xff, + (appboot.network_addr >> 24) & 0xff); + puts("Appboot seed:"); + for (int i = 0; i < 16; i++) { + printf(" %02x", appboot.seed[i]); + } + puts(""); + } + + DWORD playcount; + if (!mxkGetPlayCounter(mxparallel, &playcount)) { + puts("Failed to request playcount!"); + } else { + printf("Playcount:\t%d\n", playcount); + } + + kc_experiments(mxparallel); + + goto skip_kc_dump; + + unsigned char eeprom_block[0x10]; + puts("Dumping EEPROM..."); + fopen_s(&fd, "eeprom.bin", "wb"); + for (int page = 0; page < 0x80; page++) { + if (!mxkEepromRead(mxparallel, page, eeprom_block)) { + printf("\nFailed to read EEPROM:%02x\n", page); + } else { + fseek(fd, page * 16, SEEK_SET); + fwrite(eeprom_block, sizeof eeprom_block, 1, fd); + printf("Wrote EEPROM:%02x to eeprom.bin\r", page); + } + } + puts("\nEEPROM dump complete"); + fclose(fd); + + unsigned char nvram_block[0x100]; + puts("Dumping NVRAM..."); + fopen_s(&fd, "nvram.bin", "wb"); + for (int addr = 0; addr < 0x800; addr += 16 * 16) { + if (!mxkNvramRead(mxparallel, addr, 16, nvram_block)) { + printf("\nFailed to read NVRAM:%03x\n", addr); + } else { + fseek(fd, addr, SEEK_SET); + fwrite(nvram_block, sizeof nvram_block, 1, fd); + printf("Wrote NVRAM:%03x to nvram.bin\r", addr); + } + } + puts("\nNVRAM dump complete"); + fclose(fd); + + unsigned char billing[0x10c]; + if (!mxkFlashRead(mxparallel, 0x7a000, 0x10c, billing)) { + puts("Failed to request billing information"); + } else { + fopen_s(&fd, "billing.bin", "wb"); + fwrite(billing, sizeof billing, 1, fd); + fclose(fd); + puts("Wrote billing information to billing.bin"); + } + + unsigned char billing_copy[0x10c]; + if (!mxkFlashRead(mxparallel, 0x7b000, 0x10c, billing_copy)) { + puts("Failed to request backup billing information"); + } else { + if (memcmp(billing, billing_copy, 0x10c) == 0) { + puts("Billing backup [OK]"); + } else { + puts("Billing backup miss-match!"); + fopen_s(&fd, "billing-backup.bin", "wb"); + fwrite(billing_copy, sizeof billing_copy, 1, fd); + fclose(fd); + puts("Wrote billing backup information to billing-backup.bin"); + } + } + + unsigned char flash[0x1000]; + puts("Attempting to dump flash..."); + fopen_s(&fd, "flash.bin", "wb"); + for (int addr = 0; addr < 0x80000; addr += sizeof flash) { + if (!mxkFlashRead(mxparallel, addr, sizeof flash, flash)) { + printf("\nFailed to read flash:%05x\n", addr); + } else { + fseek(fd, addr, SEEK_SET); + fwrite(flash, sizeof flash, 1, fd); + printf("Wrote flash:%05x to flash.bin\r", addr); + } + } + puts("\nFlash dump complete"); + fclose(fd); + +skip_kc_dump: + CloseHandle(mxparallel); + return TRUE; +} + int main() { // if (!dump_columba()) { // printf("Failed to dump DMI: %03x\n", GetLastError()); // } - if (!dump_eeprom()) { - printf("Failed to dump EEPROM: %03x\n", GetLastError()); + if (!dump_keychip()) { + printf("Failed to dump keychip: %03x\n", GetLastError()); } + // if (!dump_eeprom()) { + // printf("Failed to dump EEPROM: %03x\n", GetLastError()); + // } // if (!dump_sram()) { // printf("Failed to dump SRAM: %03x\n", GetLastError()); // } diff --git a/src/micetools/util/micetinker.c b/src/micetools/util/micetinker.c index 7a739c5..2fbb5f5 100644 --- a/src/micetools/util/micetinker.c +++ b/src/micetools/util/micetinker.c @@ -9,6 +9,18 @@ #include "../lib/am/amEeprom.h" +BYTE get_region() { + HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0); + if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE; + + BYTE data[0x20]; + amEepromReadBlock(mxsmbus, 0, sizeof data, data); + + CloseHandle(mxsmbus); + + return data[12]; +} + BOOL change_region(BYTE region) { HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0); if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE; @@ -42,11 +54,27 @@ fail: int main(int argc, char** argv) { if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return -1; + BYTE region = get_region(); + printf("Current region: %02x\n", region); + return 0; } - BYTE region = argv[1][0] - '0'; - printf("Changing to region: %d\n", region); + BYTE region; + + if (argv[1][0] <= '9') + region |= (argv[1][0] - '0') << 4; + else if (argv[1][0] <= 'A') + region |= (argv[1][0] - 'A' + 10) << 4; + else + region |= (argv[1][0] - 'a' + 10) << 4; + + if (argv[1][1] <= '9') + region |= argv[1][1] - '0'; + else if (argv[1][1] <= 'F') + region |= argv[1][1] - 'A' + 10; + else + region |= argv[1][1] - 'a' + 10; + + printf("Changing to region: %02x\n", region); if (!change_region(region)) { printf("Failed to change region: %03x", GetLastError()); diff --git a/src/micetools/util/proxy.c b/src/micetools/util/proxy.c new file mode 100644 index 0000000..ed77bd3 --- /dev/null +++ b/src/micetools/util/proxy.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#pragma comment(lib, "Ws2_32.lib") +#pragma comment(lib, "Psapi.lib") + +#define UPSTREAM_HOST "127.0.0.1" +#define UPSTREAM_PORT 6969 + +FILE *log_file; +SOCKET upstream; + +void client_worker(SOCKET sock) { + char recv_buf[512]; + while (1) { + // Prompt + int nout = recv(upstream, recv_buf, sizeof recv_buf, 0); + send(sock, recv_buf, nout, 0); + + int nin = recv(sock, recv_buf, sizeof recv_buf, 0); + if (nin == -1) break; + + fprintf(log_file, "sys->kc %d:", nin); + for (int i = 0; i < nin; i++) { + fprintf(log_file, " %02x", recv_buf[i]); + } + fprintf(log_file, ": %.*s", nin, recv_buf); + fprintf(log_file, "\n"); + + send(upstream, recv_buf, nin, 0); + // Response + nout = recv(upstream, recv_buf, sizeof recv_buf, 0); + + fprintf(log_file, "kc->sys %d:", nout); + for (int i = 0; i < nout; i++) { + fprintf(log_file, " %02x", recv_buf[i]); + } + fprintf(log_file, ": %.*s", nout, recv_buf); + fprintf(log_file, "\n"); + + send(sock, recv_buf, nout, 0); + } +} + +void killProcessByName(const char *exeName) { + DWORD procList[0xffff]; + DWORD procCount; + char processName[MAX_PATH]; + + if (!EnumProcesses(procList, sizeof(procList), &procCount)) return; + + procCount = procCount / sizeof(DWORD); + + for (DWORD procIdx = 0; procIdx < procCount; procIdx++) { + HANDLE procHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procList[procIdx]); + GetProcessImageFileName(procHandle, processName, sizeof(processName)); + if (strstr(processName, exeName)) TerminateProcess(procHandle, 0); + CloseHandle(procHandle); + } +} +int main() { + STARTUPINFO si = { sizeof si }; + PROCESS_INFORMATION pi; + killProcessByName("mxkeychip-port-patched.exe"); + if (!CreateProcessA(NULL, "S:/mxkeychip-port-patched.exe", NULL, NULL, FALSE, 0, NULL, NULL, + &si, &pi)) { + printf("Failed to spawn mxkc: %03x\n", GetLastError()); + } + struct sockaddr_in name; + + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + + name.sin_family = AF_INET; + name.sin_addr.s_addr = inet_addr(UPSTREAM_HOST); + name.sin_port = htons(UPSTREAM_PORT); + while (1) { + SOCKET upstream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (connect(upstream, &name, sizeof name) < 0) { + closesocket(upstream); + printf("Still waiting %d\n", GetLastError()); + continue; + } + puts("Connected!"); + closesocket(upstream); + break; + } + + SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + name.sin_family = AF_INET; + name.sin_addr.s_addr = inet_addr("127.0.0.1"); + name.sin_port = htons(40106); + bind(s, &name, sizeof name); + + listen(s, 1); + + while (1) { + if (fopen_s(&log_file, "E:\\kc.log", "a")) + if (fopen_s(&log_file, "D:\\kc.log", "a")) + if (fopen_s(&log_file, "kc.log", "a")) printf("Failed to open log %d\n", errno); + + struct sockaddr_in addr; + int addr_len; + SOCKET sock = accept(s, &addr, &addr_len); + fprintf(log_file, "Connection open %s:%d\n", inet_ntoa(addr.sin_addr), addr.sin_port); + printf("Connection open %s:%d\n", inet_ntoa(addr.sin_addr), addr.sin_port); + + if (addr.sin_addr.s_addr == inet_addr("127.0.0.1")) { + upstream = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + name.sin_family = AF_INET; + name.sin_addr.s_addr = inet_addr(UPSTREAM_HOST); + name.sin_port = htons(UPSTREAM_PORT); + if (connect(upstream, &name, sizeof name) < 0) + puts("mxkc connect failed!"); + else + client_worker(sock); + + closesocket(upstream); + } + + fprintf(log_file, "Connection close %s:%d\n", inet_ntoa(addr.sin_addr), addr.sin_port); + printf("Connection close %s:%d\n", inet_ntoa(addr.sin_addr), addr.sin_port); + + closesocket(sock); + fclose(log_file); + } + + closesocket(s); + WSACleanup(); + + HANDLE mxkeychip = OpenProcess(PROCESS_TERMINATE, FALSE, pi.dwProcessId); + TerminateProcess(mxkeychip, 1); + CloseHandle(mxkeychip); + return 0; +} diff --git a/src/patches/InitialD8_GLW_RE_SBZZ.patch.json b/src/patches/InitialD8_GLW_RE_SBZZ.patch.json new file mode 100644 index 0000000..3f66e3a --- /dev/null +++ b/src/patches/InitialD8_GLW_RE_SBZZ.patch.json @@ -0,0 +1,121 @@ +[ + { + "name": "LOG_EN_ATA", + "at": "01b20630", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_BACKUP", + "at": "01b0e638", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_DIPSW", + "at": "01b0ef68", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_DONGLE", + "at": "01b0ef70", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_EEPROM", + "at": "01b1415c", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_GDELIVER", + "at": "01b1333c", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_GFETCHER", + "at": "01b12dfc", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_HM", + "at": "01b123c4", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_INSTALL", + "at": "01b123d0", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_JVSP", + "at": "01b20524", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_JVST", + "at": "01b24618", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_MASTER", + "at": "01b13390", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_NETWORK", + "at": "01b0e0c0", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_PCP", + "at": "01b28bfc", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_PLATFORM", + "at": "01b204b0", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_RTC", + "at": "01b13f40", + "from": "00000000", + "to": "01000000", + "count": 4 + }, + { + "name": "LOG_EN_SRAM", + "at": "01b14158", + "from": "00000000", + "to": "01000000", + "count": 4 + } +] \ No newline at end of file diff --git a/src/patches/mxmaster.patch.json b/src/patches/mxmaster.patch.json new file mode 100644 index 0000000..71defd4 --- /dev/null +++ b/src/patches/mxmaster.patch.json @@ -0,0 +1,9 @@ +[ + { + "name": "LOG_EN_DONGLE", + "at": "00431270", + "from": "00000000", + "to": "01000000", + "count": 4 + } +] \ No newline at end of file diff --git a/src/patches/patches.json b/src/patches/patches.json index 498bc02..3d2079d 100644 --- a/src/patches/patches.json +++ b/src/patches/patches.json @@ -54,5 +54,26 @@ "binary_name": "mxgfetcher.exe", "apply": true, "patches_file": "mxgfetcher.patch.json" + }, + { + "name": "mxmaster logs", + "description": "Enable logging facilities", + "binary_name": "mxmaster.exe", + "apply": true, + "patches_file": "mxmaster.patch.json" + }, + { + "name": "InitialD8_GLW_RE_SBZZ logs", + "description": "Enable logging facilities", + "binary_name": "InitialD8_GLW_RE_SBZZ.exe", + "apply": true, + "patches_file": "InitialD8_GLW_RE_SBZZ.patch.json" + }, + { + "name": "InitialD8_GLW_RE_SBZZ logs", + "description": "Enable logging facilities", + "binary_name": "InitialD8_GLW_RE_SBZZ_dumped.exe", + "apply": true, + "patches_file": "InitialD8_GLW_RE_SBZZ.patch.json" } ] \ No newline at end of file diff --git a/subprojects/cimgui_dep b/subprojects/cimgui_dep new file mode 160000 index 0000000..b064948 --- /dev/null +++ b/subprojects/cimgui_dep @@ -0,0 +1 @@ +Subproject commit b0649485e96c3b25e8b691aca489c89f9913e53a