ill advised broken commit
This commit is contained in:
parent
f02db82030
commit
52a66a2623
|
@ -3,3 +3,4 @@ build/
|
||||||
builddir/
|
builddir/
|
||||||
srcdir/
|
srcdir/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
openssl-1.0.1/
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -8,13 +8,12 @@ BUILD_DRIVE := M:
|
||||||
MICE_32 := "$(BUILD_DIR_32)/src\mice.exe"
|
MICE_32 := "$(BUILD_DIR_32)/src\mice.exe"
|
||||||
MICE_64 := "$(BUILD_DIR_64)/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_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_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||||
|
|
||||||
# For windows XP:
|
# For windows XP:
|
||||||
# VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.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
|
VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" -vcvars_ver=14.16
|
||||||
|
|
||||||
|
|
||||||
.ONESHELL:
|
.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\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\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\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"
|
@copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd"
|
||||||
|
|
||||||
|
|
23
meson.build
23
meson.build
|
@ -1,21 +1,40 @@
|
||||||
project('micetools', 'c', default_options: [
|
project('micetools', 'c', default_options: [
|
||||||
'buildtype=minsize',
|
'buildtype=minsize',
|
||||||
# ! Toggle /\ and \/ when building for XP (minsize=normal, static=XP)
|
# ! Toggle /\ and \/ when building for XP (minsize=normal, static=XP)
|
||||||
# 'b_vscrt=static_from_buildtype',
|
'b_vscrt=static_from_buildtype',
|
||||||
'warning_level=3',
|
'warning_level=3',
|
||||||
])
|
])
|
||||||
|
|
||||||
winxp = false
|
winxp = true
|
||||||
subsystem = 'console,5.01'
|
subsystem = 'console,5.01'
|
||||||
|
|
||||||
if (host_machine.cpu_family() == 'x86')
|
if (host_machine.cpu_family() == 'x86')
|
||||||
add_project_arguments('-DMICE_WIN32', language: 'c')
|
add_project_arguments('-DMICE_WIN32', language: 'c')
|
||||||
endif
|
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(
|
add_project_arguments(
|
||||||
'/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
|
'/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
|
||||||
'/D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it
|
'/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
|
'/wd4706', # assignment within conditional expression
|
||||||
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
|
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
|
||||||
'/wd4201', # ewfapi.h: nameless struct/union
|
'/wd4201', # ewfapi.h: nameless struct/union
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
inih = subproject('inih_dep')
|
inih = subproject('inih_dep')
|
||||||
|
cimgui = subproject('cimgui_dep', default_options: ['win32=enabled', 'dx9=enabled'])
|
||||||
|
|
||||||
libs_dir = meson.current_source_dir()
|
libs_dir = meson.current_source_dir()
|
||||||
subdir('micetools')
|
subdir('micetools')
|
||||||
|
|
|
@ -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); }
|
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 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
|
// Read data from a com device, unescaping as we go
|
||||||
void comio_read(com_device_t* com, BYTE* data, BYTE len) {
|
void comio_read(com_device_t* com, BYTE* data, BYTE len) {
|
||||||
|
BYTE one_byte;
|
||||||
for (; len; len--) {
|
for (; len; len--) {
|
||||||
comdev_read_blocking(com, &one_byte, 1);
|
comdev_read_blocking(com, &one_byte, 1);
|
||||||
if (one_byte == COMIO_MARK) {
|
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
|
// Write data to a com device, escaping as we go
|
||||||
void comio_write(com_device_t* com, BYTE* data, BYTE len) {
|
void comio_write(com_device_t* com, BYTE* data, BYTE len) {
|
||||||
|
BYTE one_byte;
|
||||||
for (; len; len--) {
|
for (; len; len--) {
|
||||||
one_byte = *(data++);
|
one_byte = *(data++);
|
||||||
if (one_byte == COMIO_MARK || one_byte == COMIO_SYNC) {
|
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) {
|
void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) {
|
||||||
|
BYTE one_byte;
|
||||||
do {
|
do {
|
||||||
if (comdev_available(com) < (sizeof *head + 1)) {
|
if (comdev_available(com) < (sizeof *head + 1)) {
|
||||||
SwitchToThread();
|
SwitchToThread();
|
||||||
|
@ -126,8 +128,8 @@ void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) {
|
||||||
unsigned char sum;
|
unsigned char sum;
|
||||||
comio_read(com, &sum, 1);
|
comio_read(com, &sum, 1);
|
||||||
}
|
}
|
||||||
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len,
|
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data) {
|
||||||
BYTE* data) {
|
BYTE one_byte;
|
||||||
one_byte = COMIO_SYNC;
|
one_byte = COMIO_SYNC;
|
||||||
comdev_write(com, &one_byte, 1);
|
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);
|
comio_write(com, data, len);
|
||||||
// Checksum
|
// Checksum
|
||||||
one_byte = 0;
|
one_byte = 0;
|
||||||
for (BYTE i = 0; i < sizeof resp; i++)
|
for (BYTE i = 0; i < sizeof resp; i++) one_byte += ((LPBYTE)&resp)[i];
|
||||||
one_byte += ((LPBYTE)&resp)[i];
|
for (BYTE i = 0; i < len; i++) one_byte += data[i];
|
||||||
for (BYTE i = 0; i < len; i++)
|
|
||||||
one_byte += data[i];
|
|
||||||
comio_write(com, &one_byte, 1);
|
comio_write(com, &one_byte, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,168 @@ BYTE extra[0xff];
|
||||||
#define FWVer "TN32MSEC003S F/W Ver1.2"
|
#define FWVer "TN32MSEC003S F/W Ver1.2"
|
||||||
#define HWVer "TN32MSEC003S H/W Ver3.0"
|
#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) {
|
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) {
|
while (1) {
|
||||||
comio_recv_head_t req;
|
comio_recv_head_t req;
|
||||||
comio_next_req(dev, &req, extra);
|
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);
|
log_info("aime_bd", "Bana key: %.*s", req.length, extra);
|
||||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||||
break;
|
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) {
|
} else if (req.dst == 0x08 || req.dst == 0x09) {
|
||||||
// LED sub-boards
|
// 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");
|
comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12");
|
||||||
break;
|
break;
|
||||||
case LedSetColour:
|
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!
|
// No response expected here!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +274,17 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void install_aime_bd() {
|
void install_aime_bd() {
|
||||||
com_device_t* aime = new_com_device(2);
|
char* text = MiceConfig.devices.aime_bd;
|
||||||
com_device_thread(aime, aime_bd_thread);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,8 @@ typedef struct rs232c_recv_head {
|
||||||
|
|
||||||
BYTE extra[0xff];
|
BYTE extra[0xff];
|
||||||
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
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) {
|
while (1) {
|
||||||
rs232c_recv_head_t head;
|
rs232c_recv_head_t head;
|
||||||
if (comdev_available(dev) < sizeof head) {
|
if (comdev_available(dev) < sizeof head) {
|
||||||
|
@ -89,13 +90,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||||
|
|
||||||
switch (head.op) {
|
switch (head.op) {
|
||||||
case 0x01:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
|
@ -105,13 +106,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||||
COLOURS[extra[0]][1] = extra[2];
|
COLOURS[extra[0]][1] = extra[2];
|
||||||
COLOURS[extra[0]][2] = extra[3];
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
case 0x32:
|
case 0x32:
|
||||||
log_warning("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
log_trace("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||||
extra[4], extra[5], extra[6], extra[7]);
|
extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]);
|
||||||
|
|
||||||
for (unsigned char i = extra[2] - 1; i < extra[1]; i++) {
|
for (unsigned char i = extra[2] - 1; i < extra[1]; i++) {
|
||||||
COLOURS[i][0] = extra[3];
|
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
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
case 0x33:
|
case 0x33:
|
||||||
log_warning("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
log_trace("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||||
extra[4], extra[5], extra[6], extra[7]);
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
COLOURS[extra[0]][0] = extra[extra[5]];
|
COLOURS[extra[0]][0] = extra[extra[5]];
|
||||||
|
@ -133,7 +135,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x39:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// 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];
|
COLOURS[9][2] = extra[0];
|
||||||
break;
|
break;
|
||||||
case 0x3b:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
case 0x3c:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
case 0x3f:
|
case 0x3f:
|
||||||
log_warning("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
log_trace("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||||
extra[4], extra[5], extra[6]);
|
extra[2], extra[3], extra[4], extra[5], extra[6]);
|
||||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
|
@ -161,14 +163,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||||
case 0x7c:
|
case 0x7c:
|
||||||
// extra[0] goes from 0 to 7
|
// extra[0] goes from 0 to 7
|
||||||
// Could this be some sort of calibration for the buttons?
|
// 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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||||
// \/ causes 7b to be used
|
// \/ causes 7b to be used
|
||||||
// comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
// comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||||
// syn dst src len sts op. rep --- chk
|
// syn dst src len sts op. rep --- chk
|
||||||
break;
|
break;
|
||||||
case 0x7b:
|
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);
|
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||||
// syn dst src len sts op. rep chk
|
// syn dst src len sts op. rep chk
|
||||||
break;
|
break;
|
||||||
|
@ -211,12 +213,17 @@ void led_overlay(IDirect3DDevice9* dev) {
|
||||||
void install_led_bd() {
|
void install_led_bd() {
|
||||||
register_gui_hook(&led_overlay);
|
register_gui_hook(&led_overlay);
|
||||||
|
|
||||||
com_device_t* com5 = new_com_device(5);
|
char* text = MiceConfig.devices.led_bd;
|
||||||
com_device_thread(com5, led_null_thread);
|
char* copy = (char*)malloc(strlen(text) + 1);
|
||||||
com_device_t* leds_1p = new_com_device(6);
|
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||||
com_device_thread(leds_1p, led_bd_thread);
|
|
||||||
com_device_t* com7 = new_com_device(7);
|
char* next_token;
|
||||||
com_device_thread(com7, led_null_thread);
|
char* token = strtok_s(copy, ",", &next_token);
|
||||||
com_device_t* leds_2p = new_com_device(8);
|
while (token != NULL) {
|
||||||
com_device_thread(leds_2p, led_bd_thread);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ static BYTE get_touch_id(BYTE id) {
|
||||||
BOOL touch_is_enabled = false;
|
BOOL touch_is_enabled = false;
|
||||||
BYTE thresh = 0x00; // Lazy caching of single value
|
BYTE thresh = 0x00; // Lazy caching of single value
|
||||||
DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||||
|
log_info("touch_bd", "%ls woke up", dev->com->wName);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (touch_is_enabled && !comdev_available(dev)) {
|
if (touch_is_enabled && !comdev_available(dev)) {
|
||||||
// Active mode!
|
// Active mode!
|
||||||
|
@ -79,6 +81,17 @@ DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void install_touch_bd() {
|
void install_touch_bd() {
|
||||||
com_device_t* touch = new_com_device(3);
|
char* text = MiceConfig.devices.touch_bd;
|
||||||
com_device_thread(touch, touch_bd_thread);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,42 +5,47 @@
|
||||||
|
|
||||||
WCHAR exePath[MAX_PATH + 1];
|
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;
|
patches_t patches;
|
||||||
char error[256];
|
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);
|
log_error(BOOT_LOGGER, "Failed to load patches file: %s", error);
|
||||||
} else {
|
return;
|
||||||
char exePathC[MAX_PATH + 1];
|
}
|
||||||
WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < patches.nopatchsets; i++) {
|
for (size_t i = 0; i < patches.nopatchsets; i++) {
|
||||||
patchset_t* patchset = patches.patchsets[i];
|
patchset_t* patchset = patches.patchsets[i];
|
||||||
|
|
||||||
// Require the binary explicitly named
|
// Require the binary explicitly named
|
||||||
if (patchset->binary_name == NULL || strcmp(patchset->binary_name, exePathC) != 0) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (!patchset->apply) continue;
|
|
||||||
|
|
||||||
for (size_t j = 0; j < patchset->nopatches; j++) {
|
memcpy((void*)patch.offset, patch.to, patch.count);
|
||||||
patch_t patch = patchset->patches[j];
|
log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset);
|
||||||
|
VirtualProtect((void*)patch.offset, patch.count, oldProt, &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);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((void*)patch.offset, patch.to, patch.count);
|
|
||||||
log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_patches(&patches);
|
free_patches(&patches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void prebind_hooks() {
|
void prebind_hooks() {
|
||||||
hook_all();
|
hook_all();
|
||||||
install_devices();
|
install_devices();
|
||||||
|
@ -54,35 +59,47 @@ void prebind_hooks() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_injection() {
|
void init_injection() {
|
||||||
|
load_mice_config();
|
||||||
|
|
||||||
// We're in a new context now, so need to reconfigure
|
// We're in a new context now, so need to reconfigure
|
||||||
setup_logging();
|
setup_logging();
|
||||||
log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath);
|
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
|
// 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
|
// MX SRAM: SRAM-based nv memory
|
||||||
setup_mxsram();
|
if (MiceConfig.drivers.mxsram) setup_mxsram();
|
||||||
// MX SuperIO: Communicate with the HW monitor chip
|
// MX SuperIO: Communicate with the HW monitor chip
|
||||||
setup_mxsuperio();
|
if (MiceConfig.drivers.mxsuperio) setup_mxsuperio();
|
||||||
// MX JVS: Interacting with JVS-based devices
|
// MX JVS: Interacting with JVS-based devices
|
||||||
setup_mxjvs();
|
if (MiceConfig.drivers.mxjvs) setup_mxjvs();
|
||||||
// MX HW Reset: Forcibly reboot the machine
|
// 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
|
// 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")) {
|
if (MiceConfig.drivers.platform) {
|
||||||
log_error("platform", "failed to install platform device");
|
if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) {
|
||||||
|
log_error("platform", "failed to install platform device");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must be the last thing called!
|
// Must be the last thing called!
|
||||||
// register_devices();
|
|
||||||
prebind_hooks();
|
prebind_hooks();
|
||||||
setup_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) {
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||||
if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE;
|
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();
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,3 +23,6 @@ void setup_mxsuperio();
|
||||||
|
|
||||||
FnDeviceIoControl columba_DeviceIoControl;
|
FnDeviceIoControl columba_DeviceIoControl;
|
||||||
void setup_columba();
|
void setup_columba();
|
||||||
|
|
||||||
|
FnDeviceIoControl mxparallel_DeviceIoControl;
|
||||||
|
void setup_mxparallel();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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)
|
|
@ -13,13 +13,6 @@ typedef struct eeprom_bank {
|
||||||
|
|
||||||
// 256 registers, 32 bytes each
|
// 256 registers, 32 bytes each
|
||||||
eeprom_bank_t EEPROM_DATA;
|
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() {
|
void eeprom_dump() {
|
||||||
HANDLE dump =
|
HANDLE dump =
|
||||||
|
@ -28,7 +21,7 @@ void eeprom_dump() {
|
||||||
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
|
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
|
||||||
return;
|
return;
|
||||||
} else {
|
} 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);
|
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
|
||||||
FlushFileBuffers(dump);
|
FlushFileBuffers(dump);
|
||||||
|
@ -51,16 +44,52 @@ void eeprom_restore() {
|
||||||
DWORD eeprom_crc(BYTE reg) {
|
DWORD eeprom_crc(BYTE reg) {
|
||||||
if (reg == 0x04 || reg == 0x14 || reg == 0x80 || reg == 0x280) {
|
if (reg == 0x04 || reg == 0x14 || reg == 0x80 || reg == 0x280) {
|
||||||
// Some registers are only treated as 16 byte values
|
// Some registers are only treated as 16 byte values
|
||||||
crc32_build_table();
|
|
||||||
return crc32(12, EEPROM_DATA.reg[reg].data + 4, 0);
|
return crc32(12, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
crc32_build_table();
|
|
||||||
return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
|
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();
|
eeprom_restore();
|
||||||
for (BYTE i = index; i < index + length; i++) {
|
for (BYTE i = index; i < index + length; i++) {
|
||||||
if (i > 0x1f) break;
|
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!
|
// 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 register has a CRC
|
||||||
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
|
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
|
||||||
// == 0x11 || reg == 0x12 || reg == 0x200) {
|
// == 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) {
|
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++) {
|
for (BYTE i = index; i < index + length; i++) {
|
||||||
if (i > 0x1f) break;
|
if (i > 0x1f) break;
|
||||||
|
@ -93,12 +174,358 @@ void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||||
eeprom_dump();
|
eeprom_dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE eeprom_read_one(BYTE reg, BYTE index) {
|
typedef enum {
|
||||||
BYTE data;
|
SMB_CMD_QUICK = 0b000,
|
||||||
eeprom_read(reg, index, &data, 1);
|
SMB_CMD_BYTE = 0b001,
|
||||||
return data;
|
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,
|
BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
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_packet = (mxsmbus_i2c_packet*)lpInBuffer;
|
||||||
mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer;
|
mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer;
|
||||||
|
|
||||||
mxsmbus_request_packet* request_packet = (mxsmbus_request_packet*)lpInBuffer;
|
// Default value
|
||||||
mxsmbus_request_packet* request_out = (mxsmbus_request_packet*)lpOutBuffer;
|
if (lpBytesReturned) *lpBytesReturned = nOutBufferSize;
|
||||||
|
|
||||||
BYTE dlen;
|
|
||||||
|
|
||||||
static uint16_t pca9535_config = 0xffff;
|
|
||||||
|
|
||||||
switch (dwIoControlCode) {
|
switch (dwIoControlCode) {
|
||||||
case IOCTL_MXSMBUS_GET_VERSION:
|
case IOCTL_MXSMBUS_GET_VERSION:
|
||||||
|
@ -123,229 +546,34 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||||
((LPDWORD)lpOutBuffer)[0] = 0x01020001;
|
((LPDWORD)lpOutBuffer)[0] = 0x01020001;
|
||||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||||
break;
|
break;
|
||||||
case IOCTL_MXSMBUS_REQUEST: // dip r/w
|
case IOCTL_MXSMBUS_I2C: {
|
||||||
log_trace("mxsmbus",
|
BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||||
"DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, "
|
if (command > 10) {
|
||||||
"0x%x, -, -)",
|
((BYTE*)lpOutBuffer)[0] = 0x19;
|
||||||
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");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (handle_smbus(lpInBuffer)) {
|
||||||
if (request_packet->addr != SMBUS_EEPROM) {
|
((BYTE*)lpOutBuffer)[0] = 0x00;
|
||||||
log_error("mxsmbus", "Unexpected I2C device: 0x%02x", request_packet->addr);
|
return TRUE;
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
log_warning("mxsmbus", "UNHANDLED MXSMBUS I2C %02x", request_packet->prt);
|
((BYTE*)lpOutBuffer)[0] = 0x01;
|
||||||
exit(1);
|
return FALSE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case IOCTL_MXSMBUS_REQUEST: {
|
||||||
|
BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||||
|
if (command > 11) {
|
||||||
|
((BYTE*)lpOutBuffer)[0] = 0x19;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
if (handle_smbus(lpInBuffer)) {
|
||||||
if (lpBytesReturned) *lpBytesReturned = sizeof(mxsmbus_request_packet);
|
((BYTE*)lpOutBuffer)[0] = 0x00;
|
||||||
break;
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
((BYTE*)lpOutBuffer)[0] = 0x01;
|
||||||
|
return FALSE;
|
||||||
|
};
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
log_warning("mxsmbus", "unhandled 0x%08x", dwIoControlCode);
|
log_warning("mxsmbus", "unhandled 0x%08x", dwIoControlCode);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -73,7 +73,6 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||||
printf("MXSRSFP %08x\n", lDistanceToMove);
|
|
||||||
if (dwMoveMethod == FILE_BEGIN) {
|
if (dwMoveMethod == FILE_BEGIN) {
|
||||||
SRAM_POINTER = lDistanceToMove;
|
SRAM_POINTER = lDistanceToMove;
|
||||||
} else if (dwMoveMethod == FILE_CURRENT) {
|
} else if (dwMoveMethod == FILE_CURRENT) {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
#include "mxsuperio.h"
|
||||||
|
|
||||||
#include "mx.h"
|
#include "mx.h"
|
||||||
#include "smbus.h"
|
|
||||||
#include "w83791d.h"
|
|
||||||
#include "w83627uhg.h"
|
#include "w83627uhg.h"
|
||||||
|
#include "w83791d.h"
|
||||||
|
|
||||||
BYTE w83791d_bank = 0x00;
|
BYTE w83791d_bank = 0x00;
|
||||||
BYTE w83791d_config = W83791D_CONFIG_START;
|
BYTE w83791d_config = W83791D_CONFIG_START;
|
||||||
|
@ -22,361 +23,314 @@ BYTE w83627uhg_systin_target = 0x00;
|
||||||
BYTE w83627uhg_cputin_target = 0x00;
|
BYTE w83627uhg_cputin_target = 0x00;
|
||||||
BYTE w83627uhg_target_tolerance = 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,
|
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||||
mxsuperio_lpc_packet* lpc_packet = (mxsuperio_lpc_packet*)lpInBuffer;
|
superio_packet* lpc_packet = (superio_packet*)lpInBuffer;
|
||||||
mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer;
|
superio_packet* lpc_out = (superio_packet*)lpOutBuffer;
|
||||||
|
|
||||||
switch (dwIoControlCode) {
|
switch (dwIoControlCode) {
|
||||||
case IOCTL_MXSUPERIO_PING:
|
case IOCTL_MXSUPERIO_PING: {
|
||||||
log_misc("mxsuperio",
|
|
||||||
"DeviceIoControl(<mxsuperio>, <ping>, 0x%p, 0x%x, -, "
|
|
||||||
"0x%x, -, -)",
|
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
|
||||||
|
|
||||||
((LPDWORD)lpOutBuffer)[0] = 0x01000001;
|
((LPDWORD)lpOutBuffer)[0] = 0x01000001;
|
||||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case IOCTL_MXSUPERIO_READ: {
|
case IOCTL_MXSUPERIO_READ: {
|
||||||
BYTE chip = ((LPBYTE)lpInBuffer)[0];
|
superio_lpc_packet* packet = (superio_lpc_packet*)(lpInBuffer);
|
||||||
BYTE device = ((LPBYTE)lpInBuffer)[1];
|
if (lpBytesReturned) *lpBytesReturned = sizeof *packet;
|
||||||
BYTE index = ((LPBYTE)lpInBuffer)[2];
|
packet->data = 0xff;
|
||||||
BYTE* data = &((LPBYTE)lpInBuffer)[3];
|
|
||||||
|
|
||||||
log_misc("mxsuperio", "read: chip:%d device:%d index:%02x", chip, device, index);
|
if (packet->chip != LPC_CONFIGURATION) goto W83627UHG_processed;
|
||||||
|
|
||||||
/*
|
// TODO: Is just emulating the chip ID enough?
|
||||||
{
|
|
||||||
IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
|
// Global registers
|
||||||
IN BYTE logical device (0 = FDC, 11 = HW mon)
|
switch (packet->reg) {
|
||||||
IN BYTE index
|
case 0x20: // Chip ID MSB
|
||||||
OUT BYTE read value
|
packet->data = 0xa2;
|
||||||
|
goto W83627UHG_processed;
|
||||||
|
case 0x21: // Chip ID LSB
|
||||||
|
packet->data = 0x32;
|
||||||
|
goto W83627UHG_processed;
|
||||||
}
|
}
|
||||||
|
// Device specific registers
|
||||||
The 846-5004D I have here is at base address 0x4e
|
switch (packet->device) {
|
||||||
*/
|
//
|
||||||
|
|
||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
W83627UHG_processed:
|
||||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
log_misc("mxsuperio", "read: chip:%d device:%d reg:%02x data:%02x", packet->chip,
|
||||||
|
packet->device, packet->reg, packet->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IOCTL_MXSUPERIO_WRITE:
|
case IOCTL_MXSUPERIO_WRITE: {
|
||||||
log_misc("mxsuperio",
|
superio_lpc_packet* packet = (superio_lpc_packet*)(lpInBuffer);
|
||||||
"DeviceIoControl(<mxsuperio>, <write>, 0x%p, 0x%x, -, "
|
if (lpBytesReturned) *lpBytesReturned = sizeof *packet;
|
||||||
"0x%x, -, -)",
|
|
||||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
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;
|
break;
|
||||||
|
}
|
||||||
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: {
|
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: {
|
||||||
// TODO: This code is all for W83791D, however W83627UHG is more appropriate in some
|
// 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?
|
// 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
|
// reg 0x48 = LPC Chip ID
|
||||||
// index = 0,1
|
// index = 0,1
|
||||||
// data > 0x0f, data < 0x70
|
// data > 0x0f, data < 0x70
|
||||||
|
|
||||||
// lpc_out->data = eeprom_read_one(reg, index);
|
if (lpc_packet->index == LPC_CONFIGURATION) {
|
||||||
log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg,
|
lpc_out->data = hwmon_read(lpc_packet);
|
||||||
lpc_out->data);
|
} 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;
|
} break;
|
||||||
case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: {
|
case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: {
|
||||||
BYTE index = lpc_packet->index;
|
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b",
|
||||||
BYTE reg = lpc_packet->reg;
|
lpc_packet->index, lpc_packet->reg, lpc_packet->data);
|
||||||
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index,
|
|
||||||
reg, lpc_packet->data);
|
|
||||||
|
|
||||||
switch (w83791d_bank) {
|
if (lpc_packet->index == LPC_CONFIGURATION) {
|
||||||
case 0x00: {
|
hwmon_write(lpc_packet);
|
||||||
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 (lpBytesReturned) *lpBytesReturned = 0;
|
if (lpBytesReturned) *lpBytesReturned = 0;
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -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;
|
|
@ -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); }
|
|
@ -0,0 +1,3 @@
|
||||||
|
gui_files = files(
|
||||||
|
'gui.c',
|
||||||
|
)
|
|
@ -1,14 +1,18 @@
|
||||||
#include "_hooks.h"
|
#include "_hooks.h"
|
||||||
|
|
||||||
void hook_all() {
|
void hook_all() {
|
||||||
hook_logging();
|
if (MiceConfig.hooks.logging) hook_logging();
|
||||||
hook_gui();
|
if (MiceConfig.hooks.gui) {
|
||||||
hook_setupapi();
|
hook_gui();
|
||||||
hook_commio();
|
setup_hud_gui();
|
||||||
hook_io();
|
}
|
||||||
hook_processes();
|
if (MiceConfig.hooks.setupapi) hook_setupapi();
|
||||||
hook_network();
|
if (MiceConfig.hooks.commio) hook_commio();
|
||||||
hook_time();
|
if (MiceConfig.hooks.io) hook_io();
|
||||||
hook_registry();
|
if (MiceConfig.hooks.processes) hook_processes();
|
||||||
hook_drives();
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
void hook_all();
|
void hook_all();
|
||||||
|
|
|
@ -14,14 +14,29 @@ BOOL c_drive_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||||
return TRUE;
|
return TRUE;
|
||||||
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
|
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
|
||||||
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1;
|
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1;
|
||||||
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].StartingOffset.QuadPart = 0;
|
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].DiskNumber = 0;
|
||||||
DWORD a = (sizeof(*((VOLUME_DISK_EXTENTS*)lpOutBuffer)));
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
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;
|
LARGE_INTEGER pd0_file_pointer;
|
||||||
BOOL pd0_SetFilePointerEx(void* file, LARGE_INTEGER liDistanceToMove,
|
BOOL pd0_SetFilePointerEx(void* file, LARGE_INTEGER liDistanceToMove,
|
||||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
||||||
|
@ -225,6 +240,11 @@ typedef struct {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
spd_slot_t content;
|
spd_slot_t content;
|
||||||
} partition_t;
|
} 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[] = {
|
partition_t partitions[] = {
|
||||||
{ 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update
|
{ 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update
|
||||||
{ 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0
|
{ 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0
|
||||||
|
@ -239,23 +259,93 @@ partition_t partitions[] = {
|
||||||
#define BLOCKSIZE 512ll
|
#define BLOCKSIZE 512ll
|
||||||
|
|
||||||
#define SPD_OFFSET ((extended_base * BLOCKSIZE) + sizeof(mbr_t))
|
#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)
|
#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,
|
BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||||
log_info("pd0", "Read %d @ %llx", nNumberOfBytesToRead, pd0_file_pointer.QuadPart);
|
log_info("pd0", "Read %d @ %llx", nNumberOfBytesToRead, pd0_file_pointer.QuadPart);
|
||||||
|
|
||||||
uint32_t ext_offset = 0;
|
uint32_t ext_offset = 0;
|
||||||
uint32_t offsets[NUM_PARITIONS];
|
uint32_t offsets[NUM_PARITIONS];
|
||||||
|
LONGLONG slot_offsets[NUM_PARITIONS];
|
||||||
uint32_t extended_base = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE;
|
uint32_t extended_base = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE;
|
||||||
for (int i = 0; i < NUM_PARITIONS; i++) {
|
for (int i = 0; i < NUM_PARITIONS; i++) {
|
||||||
offsets[i] = ext_offset;
|
offsets[i] = ext_offset;
|
||||||
ext_offset += partitions[i].size + MBR_LBA_GAP;
|
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("Offsets0: %08x\n", offsets[0]);
|
||||||
printf("%08x\n", extended_base);
|
printf("ExtendBase: %08x\n", extended_base);
|
||||||
|
|
||||||
// MBR (C+Recover+Extend)
|
// MBR (C+Recover+Extend)
|
||||||
if (pd0_file_pointer.QuadPart == 0) {
|
if (pd0_file_pointer.QuadPart == 0) {
|
||||||
|
@ -311,7 +401,6 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
crc32_build_table();
|
|
||||||
SegaBootRecord.crc = crc32(sizeof SegaBootRecord - 4, &SegaBootRecord.version, 0);
|
SegaBootRecord.crc = crc32(sizeof SegaBootRecord - 4, &SegaBootRecord.version, 0);
|
||||||
|
|
||||||
// SEGA Partition Description
|
// SEGA Partition Description
|
||||||
|
@ -345,6 +434,11 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||||
} else if (pd0_file_pointer.QuadPart <
|
} else if (pd0_file_pointer.QuadPart <
|
||||||
(MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE) * BLOCKSIZE) {
|
(MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE) * BLOCKSIZE) {
|
||||||
log_warning("pd0", "Game attempting to read recovery partition!");
|
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 {
|
} else {
|
||||||
for (int i = 0; i < NUM_PARITIONS; i++) {
|
for (int i = 0; i < NUM_PARITIONS; i++) {
|
||||||
if (pd0_file_pointer.QuadPart <
|
if (pd0_file_pointer.QuadPart <
|
||||||
|
@ -354,7 +448,22 @@ BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||||
} else if (pd0_file_pointer.QuadPart <
|
} else if (pd0_file_pointer.QuadPart <
|
||||||
(offsets[i] + MBR_LBA_GAP + partitions[i].size + extended_base) *
|
(offsets[i] + MBR_LBA_GAP + partitions[i].size + extended_base) *
|
||||||
BLOCKSIZE) {
|
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;
|
goto warned;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,9 +493,12 @@ BOOL pd0_WriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||||
void hook_drives() {
|
void hook_drives() {
|
||||||
file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:");
|
file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:");
|
||||||
c_drive->DeviceIoControl = &c_drive_DeviceIoControl;
|
c_drive->DeviceIoControl = &c_drive_DeviceIoControl;
|
||||||
|
|
||||||
hook_file(c_drive);
|
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"\\\\.\\PhysicalDrive0");
|
||||||
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive2063598201");
|
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive2063598201");
|
||||||
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive1811939950");
|
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive1811939950");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.h"
|
#include "../common.h"
|
||||||
|
|
||||||
void hook_drives();
|
void hook_drives();
|
||||||
|
|
||||||
|
|
|
@ -85,66 +85,12 @@ void hook_file(file_hook_t* hook) {
|
||||||
};
|
};
|
||||||
|
|
||||||
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
||||||
{ .drive = "Y:\\", .path = ".\\dev\\Y\\" },
|
// Note: Had to create last_shime.log
|
||||||
// Note: Had tp create last_shime.log
|
|
||||||
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
|
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
|
||||||
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
|
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
|
||||||
|
|
||||||
{ .drive = "C:\\\\Windows\\\\System32\\", .path = "Sys32" },
|
|
||||||
{ .drive = "C:\\\\WINDOWS\\\\system32\\", .path = "Sys32" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LPCSTR redirect_path(LPCSTR path) {
|
char _redirected_path[MAX_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) {
|
void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) {
|
||||||
file_hook_t* file_hook = file_hook_list;
|
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,
|
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||||
|
@ -181,11 +198,19 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d
|
||||||
return handle;
|
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;
|
return handle;
|
||||||
}
|
}
|
||||||
HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
|
@ -204,21 +229,35 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
lpFileName = redirect_path(lpFileName);
|
redirect_path(lpFileName, &lpFileName);
|
||||||
|
|
||||||
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||||
log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
||||||
return 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 =
|
BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) {
|
||||||
// FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode,
|
redirect_path(pszPath, &pszPath);
|
||||||
// lpSecurityAttributes,
|
return TrueDeleteFileA(pszPath);
|
||||||
// dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
}
|
||||||
// log_trace(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result);
|
BOOL WINAPI FakeDeleteFileW(LPCSTR pszPath) {
|
||||||
// return result;
|
LPCSTR redirected;
|
||||||
|
if (redirect_path(pszPath, &redirected)) {
|
||||||
|
return TrueDeleteFileA(redirected);
|
||||||
|
}
|
||||||
|
return TrueDeleteFileW(pszPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
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,
|
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
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);
|
log_trace("file", "WriteFile(%08x)", hFile);
|
||||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||||
if (hook != NULL) {
|
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,
|
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||||
lpOverlapped);
|
lpOverlapped);
|
||||||
}
|
}
|
||||||
|
@ -343,7 +387,7 @@ BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) {
|
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);
|
return True_stat64i32(path, buffer);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -361,5 +405,10 @@ void hook_io() {
|
||||||
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
|
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
|
||||||
hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 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);
|
hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,10 @@ static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOf
|
||||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||||
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||||
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
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,
|
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
static HWND window;
|
static HWND window;
|
||||||
BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
|
BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
|
||||||
DWORD wndProcId;
|
DWORD wndProcId;
|
||||||
|
@ -34,8 +36,9 @@ BOOL GetD3D9Device(void** pTable, size_t Size) {
|
||||||
if (dummyDeviceCreated != S_OK) {
|
if (dummyDeviceCreated != S_OK) {
|
||||||
d3dpp.Windowed = !d3dpp.Windowed;
|
d3dpp.Windowed = !d3dpp.Windowed;
|
||||||
|
|
||||||
dummyDeviceCreated = pD3D->lpVtbl->CreateDevice(pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
|
dummyDeviceCreated = pD3D->lpVtbl->CreateDevice(
|
||||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
|
pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
|
||||||
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
|
||||||
if (dummyDeviceCreated != S_OK) {
|
if (dummyDeviceCreated != S_OK) {
|
||||||
pD3D->lpVtbl->Release(pD3D);
|
pD3D->lpVtbl->Release(pD3D);
|
||||||
return false;
|
return false;
|
||||||
|
@ -51,7 +54,8 @@ BOOL GetD3D9Device(void** pTable, size_t Size) {
|
||||||
|
|
||||||
static HRESULT(WINAPI* TrueEndScene)(IDirect3DDevice9*);
|
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);
|
D3DCOLOR rectColor = D3DCOLOR_XRGB(r, g, b);
|
||||||
D3DRECT BarRect = { x, y, x + w, y + h };
|
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,
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
|
||||||
DWORD_PTR dwRefData) {
|
DWORD_PTR dwRefData) {
|
||||||
// ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
||||||
|
|
||||||
return DefSubclassProc(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];
|
void* d3d9Device[119];
|
||||||
|
|
||||||
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device))) {
|
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)) {
|
if (hWnd && !SetWindowSubclass(hWnd, WndProc, (int)&WndProc, (DWORD_PTR)NULL)) {
|
||||||
log_error("gui", "failed to SetWindowSubclass(%d)", GetLastError());
|
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;
|
return hWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hook_gui() {
|
void hook_gui() {
|
||||||
//
|
//
|
||||||
hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7);
|
hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7);
|
||||||
|
hook("User32.dll", "CreateWindowExW", FakeCreateWindowExW, (void**)&TrueCreateWindowExW, 7);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.h"
|
#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,
|
void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g,
|
||||||
int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
|
unsigned char b);
|
||||||
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);
|
|
||||||
|
|
||||||
typedef VOID(FnEndScene)(IDirect3DDevice9* dev);
|
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 register_gui_hook(FnEndScene* end_scene);
|
||||||
void hook_gui();
|
void hook_gui();
|
||||||
|
void setup_hud_gui();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "../util/_util.h"
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
|
||||||
|
#include "../util/_util.h"
|
||||||
|
|
||||||
char* trim_string(char* string) {
|
char* trim_string(char* string) {
|
||||||
size_t len = strlen(string) - 1;
|
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) {
|
int WINAPIV Fakevfprintf_s(FILE* _Stream, const char* _Format, va_list _ArgList) {
|
||||||
return vlog_game("vfprintf_s", _Format, _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,
|
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID,
|
||||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData) {
|
PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings,
|
||||||
|
LPVOID lpRawData) {
|
||||||
switch (wType) {
|
switch (wType) {
|
||||||
case EVENTLOG_SUCCESS:
|
case EVENTLOG_SUCCESS:
|
||||||
case EVENTLOG_AUDIT_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;
|
break;
|
||||||
case EVENTLOG_AUDIT_FAILURE:
|
case EVENTLOG_AUDIT_FAILURE:
|
||||||
case EVENTLOG_ERROR_TYPE:
|
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;
|
break;
|
||||||
case EVENTLOG_WARNING_TYPE:
|
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;
|
break;
|
||||||
case EVENTLOG_INFORMATION_TYPE:
|
case EVENTLOG_INFORMATION_TYPE:
|
||||||
default:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -89,7 +97,8 @@ BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD
|
||||||
BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; }
|
BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; }
|
||||||
|
|
||||||
// static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString);
|
// 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() {
|
void hook_logging() {
|
||||||
hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf, 6);
|
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", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 6);
|
||||||
hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_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", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6);
|
||||||
hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, (void**)&TrueDeregisterEventSource, 6);
|
hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource,
|
||||||
|
(void**)&TrueDeregisterEventSource, 6);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
// #include "../common.h"
|
// #include "../common.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName);
|
static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName);
|
||||||
static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID,
|
||||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData);
|
PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize,
|
||||||
|
LPCSTR* lpStrings, LPVOID lpRawData);
|
||||||
static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
||||||
|
|
||||||
int(WINAPIV* Trueprintf)(const char* _Format, ...);
|
int(WINAPIV* Trueprintf)(const char* _Format, ...);
|
||||||
static int(WINAPIV* Truefprintf)(FILE* _File, const char* _Format, ...);
|
static int(WINAPIV* Truefprintf)(void* _File, const char* _Format, ...);
|
||||||
static int(WINAPIV* Truefprintf_s)(FILE* _Stream, const char* _Format, ...);
|
static int(WINAPIV* Truefprintf_s)(void* _Stream, const char* _Format, ...);
|
||||||
static int(WINAPIV* Truevfprintf_s)(FILE* _Stream, const char* _Format, va_list _ArgList);
|
static int(WINAPIV* Truevfprintf_s)(void* _Stream, const char* _Format, va_list _ArgList);
|
||||||
|
|
||||||
void hook_logging();
|
void hook_logging();
|
||||||
|
|
|
@ -10,4 +10,5 @@ hooks_files = files(
|
||||||
'time.c',
|
'time.c',
|
||||||
'registry.c',
|
'registry.c',
|
||||||
'drive.c',
|
'drive.c',
|
||||||
|
'system.c',
|
||||||
)
|
)
|
|
@ -59,16 +59,16 @@ typedef struct {
|
||||||
} dns;
|
} dns;
|
||||||
dns INTERCEPT_DNS[] = {
|
dns INTERCEPT_DNS[] = {
|
||||||
// Startup
|
// Startup
|
||||||
{ "naominet.jp", { 192, 168, 103, 254 } },
|
{ "naominet.jp", { 10, 79, 140, 238 } },
|
||||||
// Billing
|
// Billing
|
||||||
{ "ib.naominet.jp", { 192, 168, 103, 254 } },
|
{ "ib.naominet.jp", { 10, 79, 140, 238 } },
|
||||||
// Aime
|
// Aime
|
||||||
{ "aime.naominet.jp", { 192, 168, 103, 254 } },
|
{ "aime.naominet.jp", { 10, 79, 140, 238 } },
|
||||||
// Routers (ping targets)
|
// Routers (ping targets)
|
||||||
{ "tenporouter.loc", { 192, 168, 103, 254 } },
|
{ "tenporouter.loc", { 10, 79, 140, 238 } },
|
||||||
{ "bbrouter.loc", { 192, 168, 103, 254 } }, // Must match tenporouter
|
{ "bbrouter.loc", { 10, 79, 140, 238 } }, // Must match tenporouter
|
||||||
{ "mobirouter.loc", { 192, 168, 103, 254 } },
|
{ "mobirouter.loc", { 10, 79, 140, 238 } },
|
||||||
{ "dslrouter.loc", { 192, 168, 103, 254 } },
|
{ "dslrouter.loc", { 10, 79, 140, 238 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
DNS_RECORDA dummy_record;
|
DNS_RECORDA dummy_record;
|
||||||
|
|
|
@ -8,17 +8,35 @@ const wchar_t* HOOK_BINARIES[] = {
|
||||||
|
|
||||||
#define DISABLE_PROC_SPAWNING
|
#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,
|
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
||||||
DWORD dwCreationFlags, LPVOID lpEnvironment,
|
DWORD dwCreationFlags, LPVOID lpEnvironment,
|
||||||
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||||
// #ifdef DISABLE_PROC_SPAWNING
|
// #ifdef DISABLE_PROC_SPAWNING
|
||||||
// log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
// log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||||
// return FALSE;
|
// return FALSE;
|
||||||
// #else
|
// #else
|
||||||
log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
// log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||||
|
log_info("spawn", "CreateProcessW %ls", lpApplicationName);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
CHAR applicationName[MAX_PATH + 1];
|
CHAR applicationName[MAX_PATH + 1];
|
||||||
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName,
|
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];
|
CHAR commandLine[MAX_PATH + 1];
|
||||||
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL,
|
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
child = start_and_inject(applicationName, commandLine, MICELIB, false);
|
child = start_and_inject(applicationName, commandLine, MICELIB, false, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
child = start_and_inject(applicationName, NULL, MICELIB, false);
|
child = start_and_inject(applicationName, NULL, MICELIB, false, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !FAILED(child);
|
return !FAILED(child);
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void hook_processes() {
|
void hook_processes() {
|
||||||
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
|
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
|
||||||
|
hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA, 6);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,17 @@
|
||||||
|
|
||||||
static BOOL(WINAPI* TrueCreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
static BOOL(WINAPI* TrueCreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||||
DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory,
|
BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||||
LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation);
|
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();
|
void hook_processes();
|
||||||
|
|
|
@ -1,5 +1,44 @@
|
||||||
#include "registry.h"
|
#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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common.h"
|
#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();
|
void hook_registry();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../common.h"
|
||||||
|
|
||||||
|
void hook_system();
|
|
@ -1,6 +1,7 @@
|
||||||
subdir('drivers')
|
subdir('drivers')
|
||||||
subdir('devices')
|
subdir('devices')
|
||||||
subdir('hooks')
|
subdir('hooks')
|
||||||
|
subdir('gui')
|
||||||
|
|
||||||
shared_library(
|
shared_library(
|
||||||
'mice',
|
'mice',
|
||||||
|
@ -13,6 +14,7 @@ shared_library(
|
||||||
drivers_files,
|
drivers_files,
|
||||||
devices_files,
|
devices_files,
|
||||||
hooks_files,
|
hooks_files,
|
||||||
|
gui_files,
|
||||||
|
|
||||||
'comdevice.c',
|
'comdevice.c',
|
||||||
|
|
||||||
|
@ -22,5 +24,10 @@ shared_library(
|
||||||
dmi_lib,
|
dmi_lib,
|
||||||
mice_lib,
|
mice_lib,
|
||||||
amlib,
|
amlib,
|
||||||
]
|
mxklib,
|
||||||
|
],
|
||||||
|
include_directories: [
|
||||||
|
openssl_inc,
|
||||||
|
],
|
||||||
|
dependencies: [cimgui.get_variable('cimgui_dep')]
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,9 +2,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
// PCA9535 (DIPSW)
|
// PCA9535 (DIPSW)
|
||||||
#define PCA9535_WRITE 0x04
|
|
||||||
#define PCA9535_READ 0x05
|
|
||||||
|
|
||||||
#define PCA9535_IN0 0x00
|
#define PCA9535_IN0 0x00
|
||||||
#define PCA9535_IN1 0x01
|
#define PCA9535_IN1 0x01
|
||||||
#define PCA9535_OUT0 0x02
|
#define PCA9535_OUT0 0x02
|
||||||
|
@ -14,24 +11,129 @@
|
||||||
#define PCA9535_CONF0 0x06
|
#define PCA9535_CONF0 0x06
|
||||||
#define PCA9535_CONF1 0x07
|
#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?
|
Setup:
|
||||||
#define SMBUS_DDR2_DIMM_B1 0x010 // what does 0xA4 mean?
|
! Select logical device 0 = FDC (in this case, we don't care)
|
||||||
#define SMBUS_EEPROM_ 0x0AE // = AT24C64AN
|
index = 0x07, data = 0x00
|
||||||
#define SMBUS_ICS9LPRS908 0xfff // Unknown
|
index = 0x20, read data (Chip ID MSB)
|
||||||
#define SMBUS_W83627UHG 0xfff // Unknown; hwmon. Possibly 0x2e or 0x4e
|
index = 0x21, read data (Chip ID LSB)
|
||||||
#define SMBUS_UPI_UP6261BM8 0xfff // Unknown; vref
|
[merge two bytes to get chip ID]
|
||||||
#define SMBUS_UPI_ISL6322CR 0xfff // Unknown; vrm
|
|
||||||
// SMBUS is send onto the mezzanine board!
|
! 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)
|
#pragma pack(1)
|
||||||
typedef struct mxsmbus_request_packet_ {
|
typedef struct mxsmbus_request_packet_ {
|
||||||
BYTE status;
|
BYTE status;
|
||||||
BYTE prt;
|
BYTE prt;
|
||||||
WORD addr;
|
BYTE addr;
|
||||||
WORD reg;
|
BYTE reg;
|
||||||
BYTE dlen;
|
BYTE dlen;
|
||||||
BYTE data[32];
|
BYTE data[32];
|
||||||
} mxsmbus_request_packet;
|
} mxsmbus_request_packet;
|
||||||
|
@ -40,16 +142,8 @@ typedef struct mxsmbus_request_packet_ {
|
||||||
typedef struct mxsmbus_i2c_packet_ {
|
typedef struct mxsmbus_i2c_packet_ {
|
||||||
BYTE status;
|
BYTE status;
|
||||||
BYTE prt;
|
BYTE prt;
|
||||||
BYTE addr;
|
WORD addr;
|
||||||
BYTE reg;
|
WORD reg;
|
||||||
BYTE dlen;
|
BYTE dlen;
|
||||||
BYTE data[32];
|
BYTE data[32];
|
||||||
} mxsmbus_i2c_packet;
|
} 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 };
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#include "hook.h"
|
#include "hook.h"
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
function_hook_t* hook_list = NULL;
|
function_hook_t* hook_list = NULL;
|
||||||
|
|
||||||
void append_hook(function_hook_t* hook) {
|
void append_hook(function_hook_t* hook) {
|
||||||
|
@ -81,15 +82,18 @@ void setup_hooks() {
|
||||||
|
|
||||||
HMODULE dll = LoadLibraryA(hook->dll);
|
HMODULE dll = LoadLibraryA(hook->dll);
|
||||||
if (dll == NULL) {
|
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;
|
hook = hook->next;
|
||||||
continue;
|
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);
|
log_warning(HOOKS_LOGGER, "failed to get original %s", hook->name);
|
||||||
} else {
|
} 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);
|
log_misc(HOOKS_LOGGER, "hooked %s", hook->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "../../lib/mice/config.h"
|
||||||
#include "../hooks/logging.h"
|
#include "../hooks/logging.h"
|
||||||
|
|
||||||
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||||
|
@ -24,7 +25,7 @@ char* log_prelude() {
|
||||||
return _log_prelude;
|
return _log_prelude;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE LOG_FILE = NULL;
|
HANDLE log_file = NULL;
|
||||||
VOID trace_hook(char* output);
|
VOID trace_hook(char* output);
|
||||||
CRITICAL_SECTION logger_lock;
|
CRITICAL_SECTION logger_lock;
|
||||||
|
|
||||||
|
@ -39,14 +40,54 @@ char* log_colours[] = {
|
||||||
};
|
};
|
||||||
#define LOG_PREFIXES "!GEWIMT"
|
#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];
|
extern WCHAR exePath[MAX_PATH + 1];
|
||||||
int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) {
|
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) {
|
if (wcscmp(exePath, L"mxnetwork.exe") == 0) {
|
||||||
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
|
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
|
||||||
*((DWORD*)(0x004438e8)) = 0x00000000;
|
*((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];
|
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';
|
buf[len + 1] = '\0';
|
||||||
|
|
||||||
// No +1 here to not get the \n
|
// 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);
|
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
if (HAS_COLOUR)
|
if (HAS_COLOUR)
|
||||||
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, log_colours[log_level],
|
(TrueWriteFile ? *TrueWriteFile : WriteFile)(
|
||||||
strlen(log_colours[log_level]), NULL, NULL);
|
sout, log_colours[log_level], strlen(log_colours[log_level]), NULL, NULL);
|
||||||
if (sout != INVALID_HANDLE_VALUE)
|
if (sout != INVALID_HANDLE_VALUE)
|
||||||
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
|
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
|
||||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
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);
|
free(buf);
|
||||||
|
|
||||||
|
@ -153,21 +196,8 @@ VOID trace_hook(char* output) {
|
||||||
void setup_logging() {
|
void setup_logging() {
|
||||||
// Force stdio even for GUI applications
|
// Force stdio even for GUI applications
|
||||||
// TODO: Is there a more robust way to check if we have a proper stdio?
|
// TODO: Is there a more robust way to check if we have a proper stdio?
|
||||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
if (false) {
|
||||||
if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) {
|
force_console_bind();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable colour in CMD
|
// Enable colour in CMD
|
||||||
|
@ -178,9 +208,9 @@ void setup_logging() {
|
||||||
|
|
||||||
InitializeCriticalSection(&logger_lock);
|
InitializeCriticalSection(&logger_lock);
|
||||||
|
|
||||||
#ifdef LOG_TO_FILE
|
if (MiceConfig.mice.log_to_file) {
|
||||||
if (LOG_FILE == NULL)
|
if (log_file == NULL && MiceConfig.mice.log_file[0] != '\0')
|
||||||
LOG_FILE =
|
log_file = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
||||||
CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
CREATE_ALWAYS, 0, NULL);
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,6 @@
|
||||||
#define LOG_MISC 5
|
#define LOG_MISC 5
|
||||||
#define LOG_TRACE 6
|
#define LOG_TRACE 6
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_TRACE
|
|
||||||
|
|
||||||
// #define LOG_TO_FILE
|
|
||||||
|
|
||||||
#define COMM_LOGGER "comm"
|
#define COMM_LOGGER "comm"
|
||||||
#define HOOKS_LOGGER "hooks"
|
#define HOOKS_LOGGER "hooks"
|
||||||
#define BOOT_LOGGER "boot"
|
#define BOOT_LOGGER "boot"
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "locate.h"
|
#include "locate.h"
|
||||||
|
|
||||||
#include "../lib/mice/mice.h"
|
#include "../lib/mice/mice.h"
|
||||||
|
|
||||||
const char* KNOWN_GAMES[] = {
|
const char* KNOWN_GAMES[] = {
|
||||||
|
@ -43,12 +44,10 @@ bool locate_game(char* path, size_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool locate_library(char* path, size_t len) {
|
bool locate_library(char* path, size_t len) {
|
||||||
if (locate_file(path, len, MICELIB)) {
|
if (locate_file(path, len, MiceConfig.launcher.mice_dll)) return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't call DllMain! We don't want to hook ourself!
|
// 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) {
|
if (mice != NULL) {
|
||||||
GetModuleFileNameA(mice, path, len);
|
GetModuleFileNameA(mice, path, len);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
|
|
||||||
const char* VERSION = "0.0-pre";
|
const char* VERSION = "0.0-pre";
|
||||||
|
|
||||||
bool boot_delay = false;
|
bool debug_wait = false;
|
||||||
|
int boot_delay = 0;
|
||||||
bool gametest = false;
|
bool gametest = false;
|
||||||
bool designviewer = false;
|
bool designviewer = false;
|
||||||
bool spriteviewer = false;
|
bool spriteviewer = false;
|
||||||
|
@ -35,8 +36,8 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||||
char* val = argv[++i];
|
char* val = argv[++i];
|
||||||
memcpy(exe_name, val, strlen(val) + 1);
|
memcpy(exe_name, val, strlen(val) + 1);
|
||||||
} else if (strcmp(argv[i], "--mice-d") == 0) {
|
} else if (strcmp(argv[i], "--mice-d") == 0) {
|
||||||
boot_delay = true;
|
debug_wait = true;
|
||||||
} else if (strcmp(argv[i], "-t") == 0) {
|
} else if (strcmp(argv[i], "-mice-t") == 0) {
|
||||||
gametest = true;
|
gametest = true;
|
||||||
} else if (strcmp(argv[i], "-dv") == 0) {
|
} else if (strcmp(argv[i], "-dv") == 0) {
|
||||||
designviewer = true;
|
designviewer = true;
|
||||||
|
@ -46,7 +47,7 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||||
noisetest = true;
|
noisetest = true;
|
||||||
} else {
|
} else {
|
||||||
if (commandline[0] == 0)
|
if (commandline[0] == 0)
|
||||||
strncpy_s(commandline, strlen(argv[i]), argv[i], sizeof commandline);
|
snprintf(commandline, sizeof commandline, "%s", argv[i]);
|
||||||
else
|
else
|
||||||
snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
|
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[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
load_mice_config();
|
||||||
|
|
||||||
fprintf(stderr, "Micetools version: %s\n", VERSION);
|
fprintf(stderr, "Micetools version: %s\n", VERSION);
|
||||||
|
|
||||||
parse_cmdline(argc, argv);
|
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 (exe_name[0] == '\0') {
|
||||||
if (!locate_game(exe_name, MAX_PATH + 1)) {
|
if (!locate_game(exe_name, MAX_PATH + 1)) {
|
||||||
fprintf(stderr, "Fatal: Failed to locate a game\n");
|
fprintf(stderr, "Fatal: Failed to locate a game\n");
|
||||||
|
@ -85,11 +94,13 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
char micepath[MAX_PATH + 1];
|
char micepath[MAX_PATH + 1];
|
||||||
if (!locate_library(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;
|
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 (!game_proc) return -1;
|
||||||
|
|
||||||
if (FAILED(WaitForSingleObject(game_proc, INFINITE))) {
|
if (FAILED(WaitForSingleObject(game_proc, INFINITE))) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
||||||
mxsmbus_request_packet smbus_req = {
|
mxsmbus_i2c_packet smbus_req = {
|
||||||
.status = 0,
|
.status = 0,
|
||||||
.prt = 0x09,
|
.prt = 0x09,
|
||||||
.addr = SMBUS_EEPROM,
|
.addr = SMBUS_EEPROM,
|
||||||
|
@ -52,7 +52,7 @@ BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
||||||
};
|
};
|
||||||
|
|
||||||
DWORD _dummy;
|
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);
|
&smbus_req, sizeof smbus_req, &_dummy, NULL);
|
||||||
if (!s) return FALSE;
|
if (!s) return FALSE;
|
||||||
if (smbus_req.status) 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) {
|
BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
||||||
mxsmbus_request_packet smbus_req = {
|
mxsmbus_i2c_packet smbus_req = {
|
||||||
.status = 0,
|
.status = 0,
|
||||||
.prt = 0x08,
|
.prt = 0x08,
|
||||||
.addr = SMBUS_EEPROM,
|
.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);
|
memcpy(smbus_req.data, data, sizeof smbus_req.data);
|
||||||
|
|
||||||
DWORD _dummy;
|
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);
|
&smbus_req, sizeof smbus_req, &_dummy, NULL);
|
||||||
if (!s) return FALSE;
|
if (!s) return FALSE;
|
||||||
if (smbus_req.status) 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) {
|
void amEepromRepairChecksum(BYTE *data) {
|
||||||
crc32_build_table();
|
|
||||||
|
|
||||||
DWORD check = crc32(28, data + 4, 0);
|
DWORD check = crc32(28, data + 4, 0);
|
||||||
((DWORD*)data)[0] = check;
|
((DWORD*)data)[0] = check;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,8 @@ typedef struct amtime {
|
||||||
amtime_t* amiTimerGet(amtime_t* time);
|
amtime_t* amiTimerGet(amtime_t* time);
|
||||||
|
|
||||||
#define _amTimeMs(time) (((time).microseconds / 1000 + (time).seconds * 1000))
|
#define _amTimeMs(time) (((time).microseconds / 1000 + (time).seconds * 1000))
|
||||||
#define _amTimeDelta(now, start) \
|
#define _amTimeDelta(now, start) \
|
||||||
(((now).microseconds - (start).microseconds) / 1000 + \
|
(((now).microseconds - (start).microseconds) / 1000 + ((now).seconds - (start).seconds) * 1000)
|
||||||
((now).seconds - (start).seconds) * 1000)
|
|
||||||
|
#define _amTimeDeltaMircos(now, start) \
|
||||||
|
((((now).seconds - (start).seconds) * 1000000 - (start).microseconds) + (now).microseconds)
|
||||||
|
|
|
@ -80,7 +80,7 @@ bool pcppCheckPrompt(pcpp_t* stream) {
|
||||||
return found;
|
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;
|
bool bVar1 = true;
|
||||||
int local_8 = 0;
|
int local_8 = 0;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ subdir('json')
|
||||||
subdir('dmi')
|
subdir('dmi')
|
||||||
subdir('mice')
|
subdir('mice')
|
||||||
subdir('am')
|
subdir('am')
|
||||||
|
subdir('mxk')
|
||||||
|
|
||||||
fs = import('fs')
|
fs = import('fs')
|
||||||
subdir('libpcp')
|
subdir('libpcp')
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
@ -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();
|
|
@ -20,6 +20,8 @@ void crc32_build_table() {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int crc32(int length, unsigned char *data, unsigned int initial) {
|
unsigned int crc32(int length, unsigned char *data, unsigned int initial) {
|
||||||
|
crc32_build_table();
|
||||||
|
|
||||||
unsigned int value = ~initial;
|
unsigned int value = ~initial;
|
||||||
while (length--) {
|
while (length--) {
|
||||||
value = value >> 8 ^ CRC_TABLE[(*data ^ value) & 0xff];
|
value = value >> 8 ^ CRC_TABLE[(*data ^ value) & 0xff];
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "exe.h"
|
#include "exe.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
bool inject_debug_wait(HANDLE process) {
|
bool inject_debug_wait(HANDLE process) {
|
||||||
BOOL present;
|
BOOL present;
|
||||||
|
|
||||||
|
@ -14,10 +16,11 @@ bool inject_debug_wait(HANDLE process) {
|
||||||
fprintf(stderr, "Debugger attached, resuming\n");
|
fprintf(stderr, "Debugger attached, resuming\n");
|
||||||
return true;
|
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);
|
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) {
|
if (arg_addr == NULL) {
|
||||||
fprintf(stderr, "Fatal: VirtualAllocEx failed: %03x\n", GetLastError());
|
fprintf(stderr, "Fatal: VirtualAllocEx failed: %03x\n", GetLastError());
|
||||||
return false;
|
return false;
|
||||||
|
@ -28,7 +31,8 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) {
|
||||||
return false;
|
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) {
|
if (remote_thread == NULL) {
|
||||||
fprintf(stderr, "Fatal: CreateRemoteThread failed: %03x\n", GetLastError());
|
fprintf(stderr, "Fatal: CreateRemoteThread failed: %03x\n", GetLastError());
|
||||||
return false;
|
return false;
|
||||||
|
@ -39,12 +43,11 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD result;
|
if (FAILED(GetExitCodeThread(remote_thread, result))) {
|
||||||
if (FAILED(GetExitCodeThread(remote_thread, &result))) {
|
|
||||||
fprintf(stderr, "Fatal: GetExitCodeThread failed: %03x\n", GetLastError());
|
fprintf(stderr, "Fatal: GetExitCodeThread failed: %03x\n", GetLastError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (*result == 0) {
|
||||||
fprintf(stderr, "Fatal: GetExitCodeThread failed: result == 0\n");
|
fprintf(stderr, "Fatal: GetExitCodeThread failed: result == 0\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -64,10 +67,12 @@ bool inject_dll(HANDLE process, LPCSTR inject) {
|
||||||
return false;
|
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;
|
STARTUPINFOA startupInfo;
|
||||||
PROCESS_INFORMATION processInformation = { 0 };
|
PROCESS_INFORMATION processInformation = { 0 };
|
||||||
|
|
||||||
|
@ -93,17 +98,38 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the binary
|
// Start the binary
|
||||||
if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
|
if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL,
|
||||||
&processInformation)) {
|
&startupInfo, &processInformation)) {
|
||||||
fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError());
|
fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError());
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delay) {
|
if (debug_wait) {
|
||||||
if (!inject_debug_wait(processInformation.hProcess)) goto abort;
|
if (!inject_debug_wait(processInformation.hProcess)) goto abort;
|
||||||
}
|
}
|
||||||
|
// Sleep(5000);
|
||||||
if (!inject_dll(processInformation.hProcess, inject)) goto abort;
|
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
|
// Injection completed, let the program continue execution
|
||||||
if (FAILED(ResumeThread(processInformation.hThread))) {
|
if (FAILED(ResumeThread(processInformation.hThread))) {
|
||||||
fprintf(stderr, "Fatal: ResumeThread failed: %03x\n", GetLastError());
|
fprintf(stderr, "Fatal: ResumeThread failed: %03x\n", GetLastError());
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.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
|
#ifndef MICELIB
|
||||||
#ifdef MICE_WIN32
|
#ifdef MICE_WIN32
|
||||||
|
|
|
@ -3,12 +3,13 @@
|
||||||
#define FILE_DEVICE_SEGA 0x9c40
|
#define FILE_DEVICE_SEGA 0x9c40
|
||||||
|
|
||||||
// amSramInit
|
// 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
|
// amSramInit
|
||||||
#define IOCTL_MXSRAM_GET_SECTOR_SIZE \
|
#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 \
|
#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
|
// EEPROM uses MXSMBUS_GUID device class
|
||||||
// DIPSW uses MXSMBUS_GUID device class
|
// DIPSW uses MXSMBUS_GUID device class
|
||||||
|
@ -24,46 +25,59 @@
|
||||||
|
|
||||||
// Same as IOCTL_MXSRAM_PING
|
// Same as IOCTL_MXSRAM_PING
|
||||||
// amHmProbeSuperIoDevice
|
// 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
|
// amHmGetLPCChipId
|
||||||
#define IOCTL_MXSUPERIO_READ CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
#define IOCTL_MXSUPERIO_READ \
|
||||||
#define IOCTL_MXSUPERIO_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
(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
|
// amHmLpcReadByte
|
||||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ \
|
#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
|
// amHmLpcWriteByte
|
||||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE \
|
#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
|
// Same as IOCTL_MXSUPERIO_READ
|
||||||
// amHmI2CReadByte,amHmI2CWriteByte,amEepromWait
|
// 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
|
// amEepromGetDriverVerision
|
||||||
|
// amDipswGetDriverVersion
|
||||||
#define IOCTL_MXSMBUS_GET_VERSION \
|
#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
|
// amEepromI2CReadBlock,amEepromI2CWriteBlock,amHmGetLPCChipId
|
||||||
#define IOCTL_MXSMBUS_I2C CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
// uses the 0x27 sized request
|
||||||
#define IOCTL_MXSMBUS_IDK CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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 \
|
#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)
|
||||||
|
|
|
@ -5,8 +5,10 @@ mice_lib = static_library(
|
||||||
'patch.c',
|
'patch.c',
|
||||||
'crc.c',
|
'crc.c',
|
||||||
'ringbuf.c',
|
'ringbuf.c',
|
||||||
|
'config.c',
|
||||||
],
|
],
|
||||||
link_with: [
|
link_with: [
|
||||||
|
inih.get_variable('lib_inih'),
|
||||||
json_lib,
|
json_lib,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,3 +6,4 @@
|
||||||
#include "patch.h"
|
#include "patch.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
#include "ringbuf.h"
|
#include "ringbuf.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
|
@ -40,8 +40,10 @@ void free_patches(patches_t* patches) {
|
||||||
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
|
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
|
||||||
if (patches->patchsets[i] != NULL) {
|
if (patches->patchsets[i] != NULL) {
|
||||||
for (size_t j = 0; j < patches->patchsets[i]->nopatches; j++) {
|
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].from != NULL)
|
||||||
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to);
|
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]);
|
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);
|
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->nopatchsets = set_count;
|
||||||
patches->patchsets = (patchset_t**)malloc(set_count * sizeof(patchset_t*));
|
patches->patchsets = (patchset_t**)malloc(set_count * sizeof(patchset_t*));
|
||||||
for (int i = 0; i < set_count; i++) patches->patchsets[i] = NULL;
|
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);
|
snprintf(error, json_error_max, "'apply' missing for patch %d (%s)", i, name);
|
||||||
goto failed;
|
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;
|
json_value* set_patches;
|
||||||
if (!fetch(set_json[i], "patches", &set_patches) || set_patches->type != json_array) {
|
if (!fetch(set_json[i], "patches", &set_patches) || set_patches->type != json_array) {
|
||||||
char* patches_file_path;
|
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];
|
char load_error[json_error_max];
|
||||||
set_patches = load_json_from_file(patches_file_path, load_error);
|
set_patches = load_json_from_file(patches_file_path, load_error);
|
||||||
if (set_patches == NULL) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (set_patches->type != json_array) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
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;
|
patchset->patches[j].offset = at;
|
||||||
size_t size = strlen(from);
|
size_t size = strlen(from);
|
||||||
if (size != strlen(to)) {
|
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;
|
goto failed;
|
||||||
}
|
}
|
||||||
if (size % 2 != 0) {
|
if (size % 2 != 0) {
|
||||||
|
@ -203,7 +222,7 @@ failed:
|
||||||
return false;
|
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;
|
patches->nopatchsets = 0;
|
||||||
|
|
||||||
json_value* parsed = load_json_from_file(path, error);
|
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;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_string(json_value* object, char* name, char** value);
|
||||||
bool fetch_int(json_value* object, char* name, size_t* value);
|
bool fetch_int(json_value* object, char* name, size_t* value);
|
||||||
bool fetch_bool(json_value* object, char* name, bool* 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
|
// Main two exports
|
||||||
void free_patches(patches_t* patches);
|
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);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
mxklib = static_library(
|
||||||
|
'mxk',
|
||||||
|
sources: [
|
||||||
|
'mxk.c',
|
||||||
|
'mxkCrypt.c',
|
||||||
|
'mxkPacket.c',
|
||||||
|
'mxkTransport.c',
|
||||||
|
],
|
||||||
|
include_directories: [
|
||||||
|
openssl_inc,
|
||||||
|
],
|
||||||
|
dependencies: [openssl_lib]
|
||||||
|
)
|
|
@ -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;
|
||||||
|
}
|
|
@ -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);
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -192,7 +192,7 @@ bool GetKeyFile(LPCSTR src, LPCSTR dst) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetSystemKeyFile() { return GetKeyFile(SYSTEM_KEYFILE_ADS, SYSTEM_KEY_FILE); };
|
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() {
|
bool SetDiskAccessPrivilege() {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 100; i++) {
|
for (i = 0; i < 100; i++) {
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
void mxkBinaryCallback(pcpa_t* stream, void* data);
|
void mxkBinaryCallback(pcpa_t* stream, void* data);
|
||||||
int mxkInit();
|
int mxkInit();
|
||||||
e_pcpa_t mxkPcpStreamInit();
|
e_pcpa_t mxkPcpStreamInit();
|
||||||
e_pcpa_t mxkPcpServer();
|
e_pcpa_t mxkPcpServer();
|
||||||
|
|
|
@ -98,7 +98,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
char error[json_error_max];
|
char error[json_error_max];
|
||||||
patches_t all_patches;
|
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);
|
fprintf(stderr, "%s\n", error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,8 @@ executable(
|
||||||
'micedump.c',
|
'micedump.c',
|
||||||
],
|
],
|
||||||
link_with: [
|
link_with: [
|
||||||
amlib
|
amlib,
|
||||||
|
mxklib,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,3 +28,11 @@ executable(
|
||||||
'micemonitor.c',
|
'micemonitor.c',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'kcproxy',
|
||||||
|
win_subsystem: subsystem,
|
||||||
|
sources: [
|
||||||
|
'proxy.c',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#pragma comment(lib, "Setupapi.lib")
|
#pragma comment(lib, "Setupapi.lib")
|
||||||
|
|
||||||
#include "../lib/am/amEeprom.h"
|
#include "../lib/am/amEeprom.h"
|
||||||
|
#include "../lib/mxk/mxk.h"
|
||||||
|
|
||||||
#define OpenDriver(x) \
|
#define OpenDriver(x) \
|
||||||
CreateFileA("\\\\.\\" x, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)
|
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.dType = 1;
|
||||||
request.size = sizeof readBuf;
|
request.size = sizeof readBuf;
|
||||||
|
|
||||||
BOOL succ = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request,
|
BOOL succ = DeviceIoControl(columba, IOCTL_COLUMBA_READ, &request, sizeof request, &readBuf,
|
||||||
sizeof request, &readBuf, sizeof readBuf, &bytesOut, NULL);
|
sizeof readBuf, &bytesOut, NULL);
|
||||||
if (succ && bytesOut == sizeof readBuf) {
|
if (succ && bytesOut == sizeof readBuf) {
|
||||||
for (unsigned int offset = 0; offset < 0x8008; offset++) {
|
for (unsigned int offset = 0; offset < 0x8008; offset++) {
|
||||||
if (readBuf[offset] == '_' && readBuf[offset + 1] == 'D' &&
|
if (readBuf[offset] == '_' && readBuf[offset + 1] == 'D' &&
|
||||||
|
@ -84,8 +85,8 @@ BOOL dump_columba() {
|
||||||
}
|
}
|
||||||
DWORD bytesReturned;
|
DWORD bytesReturned;
|
||||||
|
|
||||||
BOOL s = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request, sizeof request,
|
BOOL s = DeviceIoControl(columba, IOCTL_COLUMBA_READ, &request, sizeof request, readBuf,
|
||||||
readBuf, sizeof readBuf, &bytesReturned, NULL);
|
sizeof readBuf, &bytesReturned, NULL);
|
||||||
if (!s || bytesReturned != sizeof readBuf) {
|
if (!s || bytesReturned != sizeof readBuf) {
|
||||||
CloseHandle(columba);
|
CloseHandle(columba);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -110,8 +111,8 @@ BOOL dump_eeprom() {
|
||||||
|
|
||||||
DWORD _dummy;
|
DWORD _dummy;
|
||||||
DWORD version;
|
DWORD version;
|
||||||
DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &version, sizeof version,
|
DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &version, sizeof version, &_dummy,
|
||||||
&_dummy, NULL);
|
NULL);
|
||||||
printf("mxSMBus version: %08x\n", version);
|
printf("mxSMBus version: %08x\n", version);
|
||||||
|
|
||||||
BYTE data[0x20];
|
BYTE data[0x20];
|
||||||
|
@ -137,8 +138,8 @@ BOOL dump_sram() {
|
||||||
BOOL s;
|
BOOL s;
|
||||||
|
|
||||||
DWORD version;
|
DWORD version;
|
||||||
s = DeviceIoControl(mxsram, (DWORD)IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version,
|
s = DeviceIoControl(mxsram, IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version, &_dummy,
|
||||||
&_dummy, NULL);
|
NULL);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
CloseHandle(mxsram);
|
CloseHandle(mxsram);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -160,7 +161,7 @@ BOOL dump_sram() {
|
||||||
printf(":: BytesPerSector: %d\n", geom.BytesPerSector);
|
printf(":: BytesPerSector: %d\n", geom.BytesPerSector);
|
||||||
|
|
||||||
DWORD ssize;
|
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);
|
&_dummy, NULL);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
CloseHandle(mxsram);
|
CloseHandle(mxsram);
|
||||||
|
@ -188,7 +189,7 @@ BOOL dump_sram() {
|
||||||
BYTE superio_read(HANDLE mxsuperio, BYTE chip, BYTE device, BYTE index) {
|
BYTE superio_read(HANDLE mxsuperio, BYTE chip, BYTE device, BYTE index) {
|
||||||
DWORD _dummy;
|
DWORD _dummy;
|
||||||
BYTE payload[4] = { chip, device, index, 0 };
|
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);
|
sizeof payload, &_dummy, NULL);
|
||||||
return payload[3];
|
return payload[3];
|
||||||
}
|
}
|
||||||
|
@ -218,8 +219,8 @@ BOOL dump_superio() {
|
||||||
DWORD _dummy;
|
DWORD _dummy;
|
||||||
|
|
||||||
DWORD version;
|
DWORD version;
|
||||||
s = DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_PING, NULL, 0, &version, sizeof version,
|
s = DeviceIoControl(mxsuperio, IOCTL_MXSUPERIO_PING, NULL, 0, &version, sizeof version, &_dummy,
|
||||||
&_dummy, NULL);
|
NULL);
|
||||||
if (!s) {
|
if (!s) {
|
||||||
CloseHandle(mxsuperio);
|
CloseHandle(mxsuperio);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -245,8 +246,8 @@ BOOL dump_superio() {
|
||||||
puts(":: Super lazy dump of chip 1, bank 0:");
|
puts(":: Super lazy dump of chip 1, bank 0:");
|
||||||
for (uint8_t reg = 0; reg < 0xff; reg++) {
|
for (uint8_t reg = 0; reg < 0xff; reg++) {
|
||||||
unsigned char packet[3] = { 1, reg, 0 };
|
unsigned char packet[3] = { 1, reg, 0 };
|
||||||
DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_HWMONITOR_LPC_READ, &packet,
|
DeviceIoControl(mxsuperio, IOCTL_MXSUPERIO_HWMONITOR_LPC_READ, &packet, sizeof packet,
|
||||||
sizeof packet, &packet, sizeof packet, &_dummy, NULL);
|
&packet, sizeof packet, &_dummy, NULL);
|
||||||
printf(" -> %02x: %02x\n", reg, packet[2]);
|
printf(" -> %02x: %02x\n", reg, packet[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,13 +255,261 @@ BOOL dump_superio() {
|
||||||
return TRUE;
|
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() {
|
int main() {
|
||||||
// if (!dump_columba()) {
|
// if (!dump_columba()) {
|
||||||
// printf("Failed to dump DMI: %03x\n", GetLastError());
|
// printf("Failed to dump DMI: %03x\n", GetLastError());
|
||||||
// }
|
// }
|
||||||
if (!dump_eeprom()) {
|
if (!dump_keychip()) {
|
||||||
printf("Failed to dump EEPROM: %03x\n", GetLastError());
|
printf("Failed to dump keychip: %03x\n", GetLastError());
|
||||||
}
|
}
|
||||||
|
// if (!dump_eeprom()) {
|
||||||
|
// printf("Failed to dump EEPROM: %03x\n", GetLastError());
|
||||||
|
// }
|
||||||
// if (!dump_sram()) {
|
// if (!dump_sram()) {
|
||||||
// printf("Failed to dump SRAM: %03x\n", GetLastError());
|
// printf("Failed to dump SRAM: %03x\n", GetLastError());
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -9,6 +9,18 @@
|
||||||
|
|
||||||
#include "../lib/am/amEeprom.h"
|
#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) {
|
BOOL change_region(BYTE region) {
|
||||||
HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0);
|
HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0);
|
||||||
if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE;
|
if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE;
|
||||||
|
@ -42,11 +54,27 @@ fail:
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
printf("Usage: %s <region>\n", argv[0]);
|
BYTE region = get_region();
|
||||||
return -1;
|
printf("Current region: %02x\n", region);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
BYTE region = argv[1][0] - '0';
|
BYTE region;
|
||||||
printf("Changing to region: %d\n", 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)) {
|
if (!change_region(region)) {
|
||||||
printf("Failed to change region: %03x", GetLastError());
|
printf("Failed to change region: %03x", GetLastError());
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1,9 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "LOG_EN_DONGLE",
|
||||||
|
"at": "00431270",
|
||||||
|
"from": "00000000",
|
||||||
|
"to": "01000000",
|
||||||
|
"count": 4
|
||||||
|
}
|
||||||
|
]
|
|
@ -54,5 +54,26 @@
|
||||||
"binary_name": "mxgfetcher.exe",
|
"binary_name": "mxgfetcher.exe",
|
||||||
"apply": true,
|
"apply": true,
|
||||||
"patches_file": "mxgfetcher.patch.json"
|
"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
|
Loading…
Reference in New Issue