ill advised broken commit

This commit is contained in:
Bottersnike 2022-12-24 03:04:04 +00:00
parent f02db82030
commit 52a66a2623
75 changed files with 4045 additions and 941 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ build/
builddir/
srcdir/
.vscode/
openssl-1.0.1/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,3 +23,6 @@ void setup_mxsuperio();
FnDeviceIoControl columba_DeviceIoControl;
void setup_columba();
FnDeviceIoControl mxparallel_DeviceIoControl;
void setup_mxparallel();

View File

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

View File

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

View File

@ -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(<mxsmbus>, <request>, 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(<mxsmbus>, <i2c>, 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;

View File

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

View File

@ -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(<mxsuperio>, <ping>, 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(<mxsuperio>, <write>, 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:

View File

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

132
src/micetools/dll/gui/gui.c Normal file
View File

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

View File

@ -0,0 +1,3 @@
gui_files = files(
'gui.c',
)

View File

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

View File

@ -10,5 +10,6 @@
#include "time.h"
#include "registry.h"
#include "drive.h"
#include "system.h"
void hook_all();

View File

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

View File

@ -1,5 +1,5 @@
#pragma once
#include "common.h"
#include "../common.h"
void hook_drives();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +1,18 @@
#pragma once
// #include "../common.h"
#include <Windows.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
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();

View File

@ -10,4 +10,5 @@ hooks_files = files(
'time.c',
'registry.c',
'drive.c',
'system.c',
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
#pragma once
#include "../common.h"
void hook_system();

View File

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

View File

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

View File

@ -1,9 +1,10 @@
#include "hook.h"
#include "log.h"
#include <memory.h>
#include <stdlib.h>
#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);
}

View File

@ -5,6 +5,7 @@
#include <stdlib.h>
#include <time.h>
#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);
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,7 @@ subdir('json')
subdir('dmi')
subdir('mice')
subdir('am')
subdir('mxk')
fs = import('fs')
subdir('libpcp')

View File

@ -0,0 +1,113 @@
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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);
}
}

View File

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

View File

@ -0,0 +1,19 @@
#include <stdbool.h>
#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();

View File

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

View File

@ -1,5 +1,7 @@
#include "exe.h"
#include <stdlib.h>
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());

View File

@ -2,7 +2,8 @@
#include <stdbool.h>
#include <stdio.h>
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

View File

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

View File

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

View File

@ -6,3 +6,4 @@
#include "patch.h"
#include "crc.h"
#include "ringbuf.h"
#include "config.h"

View File

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

View File

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

View File

@ -0,0 +1,13 @@
mxklib = static_library(
'mxk',
sources: [
'mxk.c',
'mxkCrypt.c',
'mxkPacket.c',
'mxkTransport.c',
],
include_directories: [
openssl_inc,
],
dependencies: [openssl_lib]
)

133
src/micetools/lib/mxk/mxk.c Normal file
View File

@ -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 <stdio.h>
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;
}

107
src/micetools/lib/mxk/mxk.h Normal file
View File

@ -0,0 +1,107 @@
#pragma once
#include <Windows.h>
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);

View File

@ -0,0 +1,158 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
#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);
}

View File

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

View File

@ -0,0 +1,187 @@
#include "../am/amTimer.h"
#include "../mice/ioctl.h"
#include "mxk.h"
// TODO: Don't use puts!
#include <stdio.h>
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);
}

View File

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

View File

@ -8,4 +8,4 @@
void mxkBinaryCallback(pcpa_t* stream, void* data);
int mxkInit();
e_pcpa_t mxkPcpStreamInit();
e_pcpa_t mxkPcpServer();
e_pcpa_t mxkPcpServer();

View File

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

View File

@ -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',
],
)

View File

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

View File

@ -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 <region>\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());

141
src/micetools/util/proxy.c Normal file
View File

@ -0,0 +1,141 @@
#include <Windows.h>
#include <Ws2tcpip.h>
#include <process.h>
#include <psapi.h>
#include <stdio.h>
#include <string.h>
#include <winbase.h>
#include <winsock2.h>
#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;
}

View File

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

View File

@ -0,0 +1,9 @@
[
{
"name": "LOG_EN_DONGLE",
"at": "00431270",
"from": "00000000",
"to": "01000000",
"count": 4
}
]

View File

@ -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"
}
]

@ -0,0 +1 @@
Subproject commit b0649485e96c3b25e8b691aca489c89f9913e53a