commit
320617e2e5
83 changed files with 5822 additions and 0 deletions
@ -0,0 +1,10 @@
|
||||
dist/ |
||||
build/ |
||||
builddir/ |
||||
srcdir/ |
||||
.vscode/ |
||||
|
||||
# Don't distribute the libpcp sources |
||||
src/micetools/lib/libpcp/ |
||||
# And keep build artifacts out of git! |
||||
src/libpcp.lib |
@ -0,0 +1,45 @@
|
||||
BUILD_DIR := build
|
||||
BUILD_DIR_32 := $(BUILD_DIR)/build32
|
||||
BUILD_DIR_64 := $(BUILD_DIR)/build64
|
||||
DIST_DIR := dist
|
||||
|
||||
MICE_32 = "$(BUILD_DIR_32)/src\mice.exe"
|
||||
MICE_64 = "$(BUILD_DIR_64)/src\mice.exe"
|
||||
|
||||
VCVARS_32 = C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat
|
||||
VCVARS_64 = C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat
|
||||
|
||||
.PHONY: all |
||||
all: mice86 dist |
||||
|
||||
mice86: |
||||
"$(VCVARS_32)" \
|
||||
& meson setup --backend ninja --cross cross-32.ini $(BUILD_DIR_32) \
|
||||
& meson compile -C $(BUILD_DIR_32)
|
||||
|
||||
mice64: |
||||
"$(VCVARS_64)" \
|
||||
& meson setup --cross cross-64.ini $(BUILD_DIR_64) \
|
||||
& meson compile -C $(BUILD_DIR_64)
|
||||
|
||||
.PHONY: clean |
||||
clean: |
||||
@del /S /F /Q $(BUILD_DIR)
|
||||
@rmdir /S /Q $(BUILD_DIR)
|
||||
@del /S /F /Q $(DIST_DIR)
|
||||
@rmdir /S /Q $(DIST_DIR)
|
||||
|
||||
.PHONY: dist |
||||
dist: |
||||
@-mkdir $(DIST_DIR)
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micekeychip\micekeychip.exe" "$(DIST_DIR)/micekeychip.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/micepatch.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/lib/libpcp\libpcp.lib" "$(DIST_DIR)/libpcp.lib"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice86.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/dll\mice.dll" "$(DIST_DIR)/mice86.dll"
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice64.exe"
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/dll\mice.dll" "$(DIST_DIR)/mice64.dll"
|
||||
|
||||
@xcopy /E /H /C /R /Q /Y src\system "$(DIST_DIR)\system/*"
|
||||
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
|
@ -0,0 +1,8 @@
|
||||
# micetools |
||||
|
||||
For a complete build, ensure to download `libpcp.lib` and place it in `src/` |
||||
prior to running `make`. |
||||
|
||||
**Note:** exe hashes will not match the distributed binaries when compiling |
||||
using `libpcp.lib` as the distributed binaries have been compiled directly |
||||
against libpcp's source. |
@ -0,0 +1,11 @@
|
||||
[binaries] |
||||
c = 'cl' |
||||
cpp = 'cl' |
||||
strip = 'cl' |
||||
|
||||
[host_machine] |
||||
system = 'windows' |
||||
cpu_family = 'x86' |
||||
cpu = 'i686' |
||||
endian = 'little' |
||||
|
@ -0,0 +1,10 @@
|
||||
[binaries] |
||||
c = 'cl' |
||||
cpp = 'cl' |
||||
strip = 'cl' |
||||
|
||||
[host_machine] |
||||
system = 'windows' |
||||
cpu_family = 'x86_64' |
||||
cpu = 'x86_64' |
||||
endian = 'little' |
@ -0,0 +1,14 @@
|
||||
project('micetools', 'c') |
||||
|
||||
if (host_machine.cpu_family() == 'x86') |
||||
add_project_arguments('-DMICE_WIN32', language: 'c') |
||||
endif |
||||
|
||||
add_project_arguments( |
||||
'-DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need |
||||
'-D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it |
||||
# '/O1', # Optimise size |
||||
language: 'c', |
||||
) |
||||
|
||||
subdir('src') |
@ -0,0 +1,4 @@
|
||||
inih = subproject('inih_dep') |
||||
|
||||
libs_dir = meson.current_source_dir() |
||||
subdir('micetools') |
@ -0,0 +1,141 @@
|
||||
#include "com.h" |
||||
|
||||
com_hook_t* com_hook_list = NULL; |
||||
com_hook_t* new_com_hook(BYTE port) { |
||||
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook); |
||||
|
||||
swprintf(hook->wName, (sizeof hook->wName) / (sizeof hook->wName[0]), L"COM%d", port); |
||||
hook->com = port; |
||||
|
||||
hook->GetCommState = NULL; |
||||
hook->SetCommState = NULL; |
||||
hook->GetCommTimeouts = NULL; |
||||
hook->SetCommTimeouts = NULL; |
||||
hook->SetupComm = NULL; |
||||
hook->PurgeComm = NULL; |
||||
hook->GetCommModemStatus = NULL; |
||||
hook->WaitCommEvent = NULL; |
||||
hook->ClearCommError = NULL; |
||||
|
||||
return hook; |
||||
}; |
||||
void hook_com(com_hook_t* hook) { |
||||
hook->next = NULL; |
||||
hook->virtual_handle = NULL; |
||||
if (com_hook_list == NULL) { |
||||
com_hook_list = hook; |
||||
return; |
||||
} |
||||
|
||||
com_hook_t* hl = com_hook_list; |
||||
while (hl->next != NULL) hl = hl->next; |
||||
hl->next = hook; |
||||
}; |
||||
|
||||
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) { |
||||
log_misc("comm", "GetCommState(0x%p, 0x%p)", hFile, lpDCB); |
||||
|
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->GetCommState != NULL) { |
||||
return hook->GetCommState(hook->data, lpDCB); |
||||
} |
||||
} |
||||
return TrueGetCommState(hFile, lpDCB); |
||||
} |
||||
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) { |
||||
log_misc("comm", "SetCommState(0x%p, 0x%p)", hFile, lpDCB); |
||||
|
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->SetCommState != NULL) { |
||||
return hook->SetCommState(hook->data, lpDCB); |
||||
} |
||||
} |
||||
return TrueSetCommState(hFile, lpDCB); |
||||
} |
||||
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { |
||||
log_misc("comm", "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts); |
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->GetCommTimeouts != NULL) { |
||||
return hook->GetCommTimeouts(hook->data, lpCommTimeouts); |
||||
} |
||||
} |
||||
return TrueGetCommTimeouts(hFile, lpCommTimeouts); |
||||
} |
||||
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { |
||||
log_misc("comm", "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts); |
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->SetCommTimeouts != NULL) { |
||||
return hook->SetCommTimeouts(hook->data, lpCommTimeouts); |
||||
} |
||||
} |
||||
return TrueSetCommTimeouts(hFile, lpCommTimeouts); |
||||
} |
||||
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) { |
||||
log_misc("comm", "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue); |
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->SetupComm != NULL) { |
||||
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue); |
||||
} |
||||
} |
||||
return TrueSetupComm(hFile, dwInQueue, dwOutQueue); |
||||
} |
||||
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) { |
||||
log_misc("comm", "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags); |
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->PurgeComm != NULL) { |
||||
return hook->PurgeComm(hook->data, dwFlags); |
||||
} |
||||
} |
||||
return TruePurgeComm(hFile, dwFlags); |
||||
} |
||||
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) { |
||||
log_misc("comm", "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat); |
||||
|
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->GetCommModemStatus != NULL) { |
||||
return hook->GetCommModemStatus(hook->data, lpModelStat); |
||||
} |
||||
} |
||||
return TrueGetCommModemStatus(hFile, lpModelStat); |
||||
} |
||||
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) { |
||||
log_misc("comm", "WaitCommEvent"); |
||||
|
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->WaitCommEvent != NULL) { |
||||
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped); |
||||
} |
||||
} |
||||
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped); |
||||
} |
||||
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) { |
||||
log_misc("comm", "ClearCommError"); |
||||
|
||||
com_hook_t* hook = com_hook_list; |
||||
while (hook != NULL) { |
||||
if (hook->virtual_handle == hFile && hook->ClearCommError != NULL) { |
||||
return hook->ClearCommError(hook->data, lpErrors, lpStat); |
||||
} |
||||
} |
||||
return TrueClearCommError(hFile, lpErrors, lpStat); |
||||
} |
||||
|
||||
void hook_commio() { |
||||
hook("Kernel32.dll", "GetCommState", FakeGetCommState, (void**)&TrueGetCommState, 6); |
||||
hook("Kernel32.dll", "SetCommState", FakeSetCommState, (void**)&TrueSetCommState, 6); |
||||
hook("Kernel32.dll", "GetCommTimeouts", FakeGetCommTimeouts, (void**)&TrueGetCommTimeouts, 6); |
||||
hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6); |
||||
hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6); |
||||
hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm, 6); |
||||
hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus, (void**)&TrueGetCommModemStatus, 6); |
||||
hook("Kernel32.dll", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent, 6); |
||||
hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError, 6); |
||||
} |
@ -0,0 +1,47 @@
|
||||
#include <Windows.h> |
||||
#include <stdbool.h> |
||||
#include <stdio.h> |
||||
|
||||
static BOOL(WINAPI* TrueGetCommState)(HANDLE hFile, LPDCB lpDCB); |
||||
static BOOL(WINAPI* TrueSetCommState)(HANDLE hFile, LPDCB lpDCB); |
||||
static BOOL(WINAPI* TrueGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts); |
||||
static BOOL(WINAPI* TrueSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts); |
||||
static BOOL(WINAPI* TrueSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue); |
||||
static BOOL(WINAPI* TruePurgeComm)(HANDLE hFile, DWORD dwFlags); |
||||
static BOOL(WINAPI* TrueGetCommModemStatus)(HANDLE hFile, LPDWORD lpModelStat); |
||||
static BOOL(WINAPI* TrueWaitCommEvent)(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped); |
||||
static BOOL(WINAPI* TrueClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat); |
||||
|
||||
typedef BOOL(FnGetCommState)(void* com, LPDCB lpDCB); |
||||
typedef BOOL(FnSetCommState)(void* com, LPDCB lpDCB); |
||||
typedef BOOL(FnGetCommTimeouts)(void* com, LPCOMMTIMEOUTS lpCommTimeouts); |
||||
typedef BOOL(FnSetCommTimeouts)(void* com, LPCOMMTIMEOUTS lpCommTimeouts); |
||||
typedef BOOL(FnSetupComm)(void* com, DWORD dwInQueue, DWORD dwOutQueue); |
||||
typedef BOOL(FnPurgeComm)(void* com, DWORD dwFlags); |
||||
typedef BOOL(FnGetCommModemStatus)(void* com, LPDWORD lpModelStat); |
||||
typedef BOOL(FnWaitCommEvent)(void* com, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped); |
||||
typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat); |
||||
|
||||
typedef struct com_hook { |
||||
HANDLE virtual_handle; |
||||
WCHAR wName[7]; // max is COM255
|
||||
BYTE com; |
||||
|
||||
FnGetCommState* GetCommState; |
||||
FnSetCommState* SetCommState; |
||||
FnGetCommTimeouts* GetCommTimeouts; |
||||
FnSetCommTimeouts* SetCommTimeouts; |
||||
FnSetupComm* SetupComm; |
||||
FnPurgeComm* PurgeComm; |
||||
FnGetCommModemStatus* GetCommModemStatus; |
||||
FnWaitCommEvent* WaitCommEvent; |
||||
FnClearCommError* ClearCommError; |
||||
|
||||
void* data; |
||||
|
||||
struct com_hook* next; |
||||
} com_hook_t; |
||||
|
||||
com_hook_t* new_com_hook(BYTE port); |
||||
void hook_com(com_hook_t* hook); |
||||
void hook_com(); |
@ -0,0 +1,44 @@
|
||||
#include "comdevice.h" |
||||
|
||||
BOOL DevGetCommState(void* data, LPDCB lpDCB) { return TRUE; } |
||||
BOOL DevSetCommState(void* data, LPDCB lpDCB) { return TRUE; } |
||||
BOOL DevGetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; } |
||||
BOOL DevSetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; } |
||||
BOOL DevSetupComm(void* data, DWORD dwInQueue, DWORD dwOutQueue) { return TRUE; } |
||||
BOOL DevPurgeComm(void* data, DWORD dwFlags) { |
||||
if (dwFlags & PURGE_RXCLEAR) ((com_device_t*)data)->filled = 0; |
||||
return TRUE; |
||||
} |
||||
BOOL DevGetCommModemStatus(void* data, LPDWORD lpModelStat) { |
||||
// TODO: JVS SENSE
|
||||
return TRUE; |
||||
} |
||||
BOOL DevWaitCommEvent(void* data, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) { |
||||
WaitForSingleObject(((com_device_t*)data)->event, INFINITE); |
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent); |
||||
return TRUE; |
||||
} |
||||
BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) { return TRUE; } |
||||
|
||||
com_device_t* new_com_device(BYTE port) { |
||||
com_device_t* hook = (com_device_t*)malloc(sizeof *hook); |
||||
com_hook_t* com = new_com_hook(port); |
||||
file_hook_t* file = new_file_hook(com->wName); |
||||
com->data = hook; |
||||
|
||||
com->GetCommState = DevGetCommState; |
||||
com->SetCommState = DevSetCommState; |
||||
com->GetCommTimeouts = DevGetCommTimeouts; |
||||
com->SetCommTimeouts = DevSetCommTimeouts; |
||||
com->SetupComm = DevSetupComm; |
||||
com->PurgeComm = DevPurgeComm; |
||||
com->GetCommModemStatus = DevGetCommModemStatus; |
||||
com->WaitCommEvent = DevWaitCommEvent; |
||||
com->ClearCommError = DevClearCommError; |
||||
|
||||
hook->filled = 0; |
||||
hook->event = CreateEventW(NULL, TRUE, FALSE, hook->com->wName); |
||||
hook->com = com; |
||||
|
||||
return hook; |
||||
} |
@ -0,0 +1,11 @@
|
||||
#include "com.h" |
||||
#include "files.h" |
||||
|
||||
typedef struct com_device { |
||||
com_hook_t* com; |
||||
file_hook_t* file; |
||||
|
||||
BYTE queue[2048]; |
||||
DWORD filled; |
||||
HANDLE event; |
||||
} com_device_t; |
@ -0,0 +1,147 @@
|
||||
#include <Windows.h> |
||||
#include <shlwapi.h> |
||||
#pragma comment(lib, "Shlwapi.lib") |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "../lib/mice/mice.h" |
||||
#include "drivers/mx.h" |
||||
#include "files.h" |
||||
#include "com.h" |
||||
#include "micesetupapi.h" |
||||
|
||||
WCHAR exePath[MAX_PATH + 1]; |
||||
|
||||
void enable_traces() { |
||||
if (wcscmp(exePath, L"Game.exe") == 0) { |
||||
*(DWORD*)(0x008717a0) = 1; |
||||
*(DWORD*)(0x00871728) = 1; |
||||
*(DWORD*)(0x00871cd8) = 1; |
||||
*(DWORD*)(0x00872660) = 1; |
||||
*(DWORD*)(0x0087297c) = 1; // LOG_EN_EEPROM
|
||||
*(DWORD*)(0x00872980) = 1; |
||||
*(DWORD*)(0x00872988) = 1; |
||||
*(DWORD*)(0x00873540) = 1; |
||||
*(DWORD*)(0x00873538) = 1; |
||||
*(DWORD*)(0x0087f890) = 1; |
||||
*(DWORD*)(0x00882ce4) = 1; |
||||
*(DWORD*)(0x00882cec) = 1; |
||||
*(DWORD*)(0x00883018) = 1; |
||||
*(DWORD*)(0x00886ff8) = 1; |
||||
*(DWORD*)(0x0088b1b8) = 1; |
||||
*(DWORD*)(0x0088b1c0) = 1; |
||||
} else if (wcscmp(exePath, L"ALLNetProc_Win.exe") == 0) { |
||||
*(DWORD*)(0x004f48b0) = 1; // LOG_EN_DONGLE
|
||||
*(DWORD*)(0x004f989c) = 1; // LOG_EN_PCP
|
||||
*(DWORD*)(0x004f7d04) = 1; // LOG_EN_EEPROM
|
||||
*(DWORD*)(0x004f7d08) = 1; // LOG_EN_BACKUP
|
||||
*(DWORD*)(0x004f8118) = 1; // LOG_EN_RTC
|
||||
*(DWORD*)(0x004f96dc) = 1; // LOG_EN_GFETCHER
|
||||
*(DWORD*)(0x004f8338) = 1; // LOG_EN_NETWORK
|
||||
*(DWORD*)(0x004f88c0) = 1; // LOG_EN_MASTER
|
||||
*(DWORD*)(0x004f88b0) = 1; // LOG_EN_HM
|
||||
*(DWORD*)(0x004f8330) = 1; // LOG_EN_SRAM
|
||||
*(DWORD*)(0x004f9728) = 1; // LOG_EN_PLATFORM
|
||||
|
||||
//*(DWORD*)(0x004f9e7c) = 5; // LOG_EN_ASSERTS (handled by the bellow
|
||||
// instead)
|
||||
*(DWORD*)(0x004e884c) = 10; // ALPB_LOG_LEVEL (0=None, 1=Error,
|
||||
// 2=Warning, 3=Most, 4=Debug)
|
||||
} else if (wcscmp(exePath, L"ORIG_mxsegaboot.exe") == 0 || wcscmp(exePath, L"mxsegaboot.exe") == 0) { |
||||
// start of am
|
||||
*(DWORD*)(0x0054fcd8) = 1; // LOG_EN_JVS_DRIVER
|
||||
*(DWORD*)(0x00538810) = 1; // LOG_EN_DIPSW
|
||||
*(DWORD*)(0x0054afc8) = 1; // LOG_EN_ATA
|
||||
*(DWORD*)(0x00544b78) = 1; // LOG_EN_DONGLE
|
||||
*(DWORD*)(0x00536c98) = 1; // LOG_EN_EEPROM
|
||||
*(DWORD*)(0x00537834) = 1; // LOG_EN_GCATCHER
|
||||
*(DWORD*)(0x00537d4c) = 1; // LOG_EN_GDELIVER
|
||||
*(DWORD*)(0x0053828c) = 1; // LOG_EN_GFETCHER
|
||||
*(DWORD*)(0x00547fd0) = 1; // LOG_EN_HWRESET
|
||||
*(DWORD*)(0x00547fd8) = 1; // LOG_EN_PLATFORM
|
||||
*(DWORD*)(0x00548268) = 1; // LOG_EN_HM
|
||||
*(DWORD*)(0x00536f30) = 1; // LOG_EN_BACKUP
|
||||
*(DWORD*)(0x00547fcc) = 1; // LOG_EN_CMOS
|
||||
*(DWORD*)(0x005382d8) = 1; // LOG_EN_INSTALL
|
||||
*(DWORD*)(0x00538818) = 1; // LOG_EN_JVS
|
||||
*(DWORD*)(0x00544b68) = 1; // LOG_EN_JVSP
|
||||
*(DWORD*)(0x0054b3d8) = 1; // LOG_EN_MASTER
|
||||
*(DWORD*)(0x00548280) = 1; // LOG_EN_NETWORK
|
||||
*(DWORD*)(0x00548050) = 1; // LOG_EN_RTC
|
||||
*(DWORD*)(0x00536c94) = 1; // LOG_EN_SRAM
|
||||
*(DWORD*)(0x005487f8) = 1; // LOG_EN_STORAGE
|
||||
*(DWORD*)(0x00536c90) = 1; // LOG_EN_SYS
|
||||
// end of am
|
||||
*(DWORD*)(0x00536c70) = 1; // LOG_EN_PCPT
|
||||
} else if (wcscmp(exePath, L"maimai_dump_.exe") == 0) { |
||||
*(DWORD*)(0x00c8ab7c) = 1; // LOG_EN_SRAM
|
||||
*(DWORD*)(0x00f406f0) = 1; // LOG_EN_CABINET_DL
|
||||
*(DWORD*)(0x00c88680) = 1; // LOG_EN_INSTALL
|
||||
*(DWORD*)(0x00c8ab78) = 1; // LOG_EN_EEPROM
|
||||
*(DWORD*)(0x00c88608) = 1; // LOG_EN_PLATFORM
|
||||
*(DWORD*)(0x00c88dd0) = 1; // LOG_EN_STORAGE
|
||||
*(DWORD*)(0x00ca25ec) = 1; // LOG_EN_PCP
|
||||
*(DWORD*)(0x00c96ed0) = 1; // LOG_EN_HM
|
||||
*(DWORD*)(0x00f406ec) = 1; // LOG_EN_HTTP
|
||||
*(DWORD*)(0x00c89ca8) = 1; // LOG_EN_DIPSW
|
||||
*(DWORD*)(0x00c96ed8) = 1; // LOG_EN_DONGLE
|
||||
*(DWORD*)(0x00c9a83c) = 1; // LOG_EN_JVSP
|
||||
*(DWORD*)(0x00c89730) = 1; // LOG_EN_NETWORK
|
||||
*(DWORD*)(0x00c9a440) = 1; // LOG_EN_JVST_THREAD
|
||||
*(DWORD*)(0x00c8ab80) = 1; // LOG_EN_JVS
|
||||
*(DWORD*)(0x00c89fc8) = 1; // LOG_EN_MASTER
|
||||
*(DWORD*)(0x00c88bb8) = 1; // LOG_EN_RTC
|
||||
*(DWORD*)(0x00c9e420) = 1; // LOG_EN_JVST_DRIVER
|
||||
*(DWORD*)(0x00c89320) = 1; // LOG_EN_BACKUP
|
||||
*(DWORD*)(0x00c88bb4) = 1; // LOG_EN_HWRESET
|
||||
*(DWORD*)(0x00c830e8) = 1; // LOG_EN
|
||||
} else if (wcscmp(exePath, L"mxnetwork.exe") == 0) { |
||||
*(DWORD*)(0x004438e0) = 1; // LOG_EN_PCP
|
||||
*(DWORD*)(0x004433f8) = 1; // LOG_EN_UTL
|
||||
} else { |
||||
log_warning("traces", "No known traces for %ls", exePath); |
||||
} |
||||
} |
||||
|
||||
void prebind_hooks() { |
||||
hook_setupapi(); |
||||
hook_commio(); |
||||
hook_io(); |
||||
} |
||||
|
||||
void init_injection() { |
||||
// We're in a new context now, so need to reconfigure
|
||||
setup_logging(); |
||||
log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath); |
||||
|
||||
dmi_build_default(); |
||||
|
||||
enable_traces(); |
||||
|
||||
setup_columba(); |
||||
setup_mxsram(); |
||||
setup_mxsuperio(); |
||||
setup_mxjvs(); |
||||
setup_mxhwreset(); |
||||
setup_mxsmbus(); |
||||
|
||||
if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) { |
||||
log_error("platform", "failed to install platform device"); |
||||
} |
||||
|
||||
// Must be the last thing called!
|
||||
// register_devices();
|
||||
prebind_hooks(); |
||||
setup_hooks(); |
||||
} |
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { |
||||
if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE; |
||||
|
||||
GetModuleFileNameW(NULL, exePath, MAX_PATH); |
||||
wcscpy_s(exePath, MAX_PATH + 1, PathFindFileNameW(exePath)); |
||||
|
||||
init_injection(); |
||||
|
||||
return TRUE; |
||||
} |
@ -0,0 +1,51 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/dmi/dmi.h" |
||||
#include "../lib/mice/mice.h" |
||||
#include "files.h" |
||||
|
||||
BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { |
||||
switch (dwIoControlCode) { |
||||
case IOCTL_COLUMBA_READ_DMI: |
||||
log_misc("columba", |
||||
"DeviceIoControl(<columba>, <read dmi>, 0x%p, 0x%x, -, " |
||||
"0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
memset(lpOutBuffer, 0, nOutBufferSize); |
||||
|
||||
if (((LPWORD)lpInBuffer)[0] == 0x0000) { |
||||
DMI_HEADER dmi = { |
||||
.Signature = {'_', 'D', 'M', 'I', '_'}, |
||||
.Checksum = 0, |
||||
.StructLength = dmi_size, |
||||
.StructAddr = 0xdeeabeef, |
||||
.NumberOfStructs = 0x20, |
||||
.BCDRevision = 0, |
||||
.Reserved = 0, |
||||
}; |
||||
dmi.Checksum = dmi_calc_checksum((char*)&dmi, 15); |
||||
|
||||
memcpy(lpOutBuffer, &dmi, sizeof(DMI_HEADER)); |
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DMI_HEADER); |
||||
} else { |
||||
memcpy(lpOutBuffer, dmi_table, dmi_size); |
||||
if (lpBytesReturned) *lpBytesReturned = dmi_size; |
||||
} |
||||
|
||||
break; |
||||
default: |
||||
log_warning("columba", "unhandled 0x%08x", dwIoControlCode); |
||||
return FALSE; |
||||
} |
||||
|
||||
return FALSE; |
||||
} |
||||
|
||||
void setup_columba() { |
||||
file_hook_t* columba = new_file_hook(L"\\\\.\\columba"); |
||||
columba->DeviceIoControl = &columba_DeviceIoControl; |
||||
|
||||
hook_file(columba); |
||||
} |
@ -0,0 +1,23 @@
|
||||
#include "../files.h" |
||||
#include <initguid.h> |
||||
|
||||
FnDeviceIoControl mxhwreset_DeviceIoControl; |
||||
void setup_mxhwreset(); |
||||
|
||||
FnDeviceIoControl mxjvs_DeviceIoControl; |
||||
void setup_mxjvs(); |
||||
|
||||
FnDeviceIoControl mxsmbus_DeviceIoControl; |
||||
void setup_mxsmbus(); |
||||
|
||||
FnDeviceIoControl mxsram_DeviceIoControl; |
||||
FnSetFilePointer mxsram_SetFilePointer; |
||||
FnWriteFile mxsram_WriteFile; |
||||
FnReadFile mxsram_ReadFile; |
||||
void setup_mxsram(); |
||||
|
||||
FnDeviceIoControl mxsuperio_DeviceIoControl; |
||||
void setup_mxsuperio(); |
||||
|
||||
DEFINE_GUID(MXSMBUS_GUID, 0x5C49E1FE, 0x3FEC, 0x4B8D, 0xA4, 0xB5, 0x76, 0xBE, 0x70, 0x25, 0xD8, 0x42); |
||||
DEFINE_GUID(PLATFORM_GUID, 0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3e, 0x30, 0x1F, 0x73); |
@ -0,0 +1,24 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/mice/mice.h" |
||||
#include "mx.h" |
||||
|
||||
BOOL mxhwreset_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { |
||||
switch (dwIoControlCode) { |
||||
case IOCTL_MXHWRESET_RESET: |
||||
if (lpBytesReturned) *lpBytesReturned = 0; |
||||
break; |
||||
default: |
||||
log_warning("mxhwreset", "unhandled 0x%08x", dwIoControlCode); |
||||
return FALSE; |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
void setup_mxhwreset() { |
||||
file_hook_t* mxhwreset = new_file_hook(L"\\\\.\\mxhwreset"); |
||||
mxhwreset->DeviceIoControl = &mxhwreset_DeviceIoControl; |
||||
|
||||
hook_file(mxhwreset); |
||||
} |
@ -0,0 +1,37 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/mice/mice.h" |
||||
#include "mx.h" |
||||
|
||||
BOOL mxjvs_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, |
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, |
||||
LPOVERLAPPED lpOverlapped) { |
||||
switch (dwIoControlCode) { |
||||
case IOCTL_MXJVS_EXCHANGE: |
||||
log_misc("mxjvs", |
||||
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, " |
||||
"0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
// mxjvsDevice->exchange(
|
||||
// lpbyte(lpInBuffer), nInBufferSize & 0xFFFF,
|
||||
// lpbyte(lpOutBuffer), lpBytesReturned
|
||||
// );
|
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = 0; |
||||
break; |
||||
default: |
||||
log_warning("mxjvs", "unhandled 0x%08x", dwIoControlCode); |
||||
return FALSE; |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
void setup_mxjvs() { |
||||
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs"); |
||||
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl; |
||||
|
||||
hook_file(mxjvs); |
||||
} |
@ -0,0 +1,363 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/dmi/dmi.h" |
||||
#include "../lib/mice/mice.h" |
||||
#include "mx.h" |
||||
#include "smbus.h" |
||||
|
||||
// PCA9535 (DIPSW)
|
||||
#define PCA9535_WRITE 0x04 |
||||
#define PCA9535_READ 0x05 |
||||
|
||||
#define PCA9535_IN0 0x00 |
||||
#define PCA9535_IN1 0x01 |
||||
#define PCA9535_OUT0 0x02 |
||||
#define PCA9535_OUT1 0x03 |
||||
#define PCA9535_INV0 0x04 |
||||
#define PCA9535_INV1 0x05 |
||||
#define PCA9535_CONF0 0x06 |
||||
#define PCA9535_CONF1 0x07 |
||||
|
||||
#define PCA9535 0x20 |
||||
#define EEPROM 0x57 |
||||
|
||||
#define EEPROM_DUMP L"dev/eeprom.bin" |
||||
typedef struct eeprom_reg { |
||||
BYTE data[32]; |
||||
} eeprom_reg_t; |
||||
typedef struct eeprom_bank { |
||||
eeprom_reg_t reg[0x100]; |
||||
} eeprom_bank_t; |
||||
|
||||
// 256 registers, 32 bytes each
|
||||
eeprom_bank_t EEPROM_DATA; |
||||
/*
|
||||
* Known registers: |
||||
* - Reg 0x00: Stores ??? in [00] |
||||
* - Reg 0x08: Stores LPC address in [00, 01] |
||||
* - Reg 0x16: Stores ??? in [00, 01] |
||||
* - Reg 0x0e: Stores |
||||
*/ |
||||
|
||||
typedef uint_fast32_t crc_t; |
||||
|
||||
static const crc_t crc_table[256] = { |
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, |
||||
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, |
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, |
||||
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, |
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, |
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, |
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, |
||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, |
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, |
||||
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, |
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, |
||||
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, |
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, |
||||
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, |
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, |
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, |
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, |
||||
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, |
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, |
||||
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, |
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, |
||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, |
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, |
||||
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, |
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, |
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, |
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, |
||||
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, |
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; |
||||
#define CRC_ALGO_TABLE_DRIVEN 1 |
||||
static inline crc_t crc_init(void) { return 0xffffffff; } |
||||
crc_t crc_update(crc_t crc, const void* data, size_t data_len) { |
||||
const unsigned char* d = (const unsigned char*)data; |
||||
unsigned int tbl_idx; |
||||
|
||||
while (data_len--) { |
||||
tbl_idx = (crc ^ *d) & 0xff; |
||||
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff; |
||||
d++; |
||||
} |
||||
return crc & 0xffffffff; |
||||
} |
||||
static inline crc_t crc_finalize(crc_t crc) { return crc ^ 0xffffffff; } |
||||
|
||||
void eeprom_dump() { |
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); |
||||
if (dump == INVALID_HANDLE_VALUE) { |
||||
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed"); |
||||
return; |
||||
} |
||||
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL); |
||||
FlushFileBuffers(dump); |
||||
_CloseHandle(dump); |
||||
} |
||||
void eeprom_restore() { |
||||
HANDLE dump = |
||||
_CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
||||
if (dump == INVALID_HANDLE_VALUE) return; |
||||
DWORD read; |
||||
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL)) |
||||
log_error("eeprom", "failed to restore (%d)", GetLastError()); |
||||
_CloseHandle(dump); |
||||
} |
||||
|
||||
DWORD eeprom_crc(BYTE reg) { |
||||
if (reg == 0x80 || reg == 0x280) { |
||||
// Some registers are only treated as 16 byte values
|
||||
return crc_finalize(crc_update(crc_init(), EEPROM_DATA.reg[reg].data + 4, 12)); |
||||
} |
||||
return crc_finalize(crc_update(crc_init(), EEPROM_DATA.reg[reg].data + 4, 28)); |
||||
} |
||||
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { |
||||
eeprom_restore(); |
||||
for (BYTE i = index; i < index + length; i++) { |
||||
if (i > 0x1f) break; |
||||
|
||||
BYTE byte = EEPROM_DATA.reg[reg].data[i]; |
||||
|
||||
// If register has a CRC
|
||||
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
|
||||
// == 0x11 || reg == 0x12 || reg == 0x200) {
|
||||
if (true) { |
||||
// Intercept the read and inject a CRC instead
|
||||
if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) { |
||||
DWORD crc = eeprom_crc(reg); |
||||
byte = crc >> 8 * i & 0xff; |
||||
} |
||||
} |
||||
|
||||
data[i - index] = byte; |
||||
} |
||||
} |
||||
void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) { |
||||
for (BYTE i = index; i < index + length; i++) { |
||||
if (i > 0x1f) break; |
||||
EEPROM_DATA.reg[reg].data[i] = data[i - index]; |
||||
} |
||||
eeprom_dump(); |
||||
} |
||||
|
||||
BYTE eeprom_read_one(BYTE reg, BYTE index) { |
||||
BYTE data; |
||||
eeprom_read(reg, index, &data, 1); |
||||
return data; |
||||
} |
||||
void eeprom_write_one(BYTE reg, BYTE index, BYTE data) { eeprom_write(reg, index, &data, 1); } |
||||
|
||||
BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { |
||||
mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer; |
||||
mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer; |
||||
|
||||
mxsmbus_request_packet* request_packet = (mxsmbus_request_packet*)lpInBuffer; |
||||
mxsmbus_request_packet* request_out = (mxsmbus_request_packet*)lpOutBuffer; |
||||
|
||||
BYTE dlen; |
||||
|
||||
switch (dwIoControlCode) { |
||||
case IOCTL_MXSMBUS_GET_VERSION: |
||||
log_misc("mxsmbus", |
||||
"DeviceIoControl(<mxsmbus>, <get version>, 0x%p, 0x%x, " |
||||
"-, 0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
((LPDWORD)lpOutBuffer)[0] = 0x01020001; |
||||
if (lpBytesReturned) *lpBytesReturned = 4; |
||||
break; |
||||
case IOCTL_MXSMBUS_REQUEST: // dip r/w
|
||||
log_misc("mxsmbus", |
||||
"DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, " |
||||
"0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
// Game trace:
|
||||
// 05 for 20
|
||||
// ^[x3]
|
||||
// 04 for 20
|
||||
// ^[x3]
|
||||
// 05 for 20
|
||||
// 03 for 57
|
||||
// ^[after every eeprom read/write]
|
||||
|
||||
// Address 0x20 = PCA9535 = DIP switches
|
||||
// Address 0x30 = Keychip? "N2"
|
||||
// Address 0x55 = Keychip?
|
||||
// Address 0x57 = EEPROM
|
||||
|
||||
// dyn = 0x57
|
||||
// 03: addr dyn: amEepromWait
|
||||
// 04: addr dyn: amHmI2CWriteByte (via IOCTL_MXSMBUS_I2C instead)
|
||||
// 05: addr dyn: amHmI2CWriteByte (via IOCTL_MXSMBUS_I2C instead)
|
||||
//
|
||||
// dyn2 = 0x20
|
||||
// 04: addr dyn2: amDipswWriteByteInternal
|
||||
// 05: addr dyn2: amDipswReadByteInternal[Ex]
|
||||
|
||||
// 0B: addr 0x20: amHmGetLPCChipId
|
||||
// 0B: addr 0x21: amHmGetLPCChipId
|
||||
// 48: addr 0x00: amHmGetLPCChipId
|
||||
|
||||
switch (i2c_packet->addr) { |
||||
case PCA9535: |
||||
switch (i2c_packet->prt) { |
||||
case PCA9535_WRITE: |
||||
switch (i2c_packet->reg) { |
||||
case PCA9535_OUT1: |
||||
log_error("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0], |
||||
i2c_packet->data[1]); |
||||
break; |
||||
case PCA9535_INV0: |
||||
log_error("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0], |
||||
i2c_packet->data[1]); |
||||
break; |
||||
case PCA9535_INV1: |
||||
log_error("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0], |
||||
i2c_packet->data[1]); |
||||
break; |
||||
default: |
||||
log_error("mxsmbux", |
||||
"(write) Undefined pca9535 " |
||||
"register: 0x%02x", |
||||
i2c_packet->reg); |
||||
exit(1); |
||||
} |
||||
break; |
||||
case PCA9535_READ: |
||||
switch (i2c_packet->reg) { |
||||
case PCA9535_IN0: // DIPSW
|
||||
i2c_packet->data[0] = 0x00; |
||||
break; |
||||
case PCA9535_IN1: // What's this one?
|
||||
i2c_packet->data[0] = 0x00; |
||||
break; |
||||
case PCA9535_INV0: |
||||
case PCA9535_INV1: |
||||
case PCA9535_OUT1: |
||||
i2c_packet->data[0] = 0x00; |
||||
break; |
||||
default: |
||||
log_error("mxsmbux", |
||||
"(read) Undefined pca9535 " |
||||
"register: 0x%02x", |
||||
i2c_packet->reg); |
||||
exit(1); |
||||
} |
||||
i2c_packet->status = 0x00; |
||||
break; |
||||
default: |
||||
log_error("mxsmbux", "Unknown pca9535 command: 0x%02x", i2c_packet->prt); |
||||
exit(1); |
||||
} |
||||
break; |
||||
case EEPROM: |
||||
switch (i2c_packet->prt) { |
||||
case 3: // Wait
|
||||
// 0x18 = wait, 0x00 = done
|
||||
i2c_packet->status = 0; |
||||
break; |
||||
default: |
||||
log_error("mxsmbux", "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; |
||||
} |
||||
|
||||
if (request_packet->addr != EEPROM) { |
||||
log_error("mxsmbus", "Unexpected I2C device: 0x%02x", request_packet->addr); |
||||
exit(1); |
||||
} |
||||
// 04 = Write byte
|
||||
// 05 = Read byte
|
||||
//
|
||||
// 08 = Write block
|
||||
// 09 = Read block
|
||||
|
||||
if (request_packet->prt == 0x08) { |
||||
// Write
|
||||
log_misc("mxsmbus", "eeprom write %02x (0x%04x)", dlen, request_packet->reg); |
||||
// for (int i = 0; i < dlen; i++) printf("%02x ",
|
||||
// request_packet->data[i]); puts("");
|
||||
|
||||
eeprom_write(request_packet->reg >> 5, 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, 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 { |
||||
log_warning("mxsmbus", "UNHANDLED MXSMBUS I2C %02x", request_packet->prt); |
||||
exit(1); |
||||
} |
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(mxsmbus_request_packet); |
||||
break; |
||||
default: |
||||
log_warning("mxsmbus", "unhandled 0x%08x", dwIoControlCode); |
||||
return FALSE; |
||||
} |
||||
return TRUE; |
||||
} |
||||
|
||||
void setup_mxsmbus() { |
||||
file_hook_t* mxsmbus = new_file_hook(L"\\\\.\\mxsmbus"); |
||||
mxsmbus->DeviceIoControl = &mxsmbus_DeviceIoControl; |
||||
|
||||
hook_file(mxsmbus); |
||||
|
||||
if (!add_fake_device(&MXSMBUS_GUID, L"\\\\.\\mxsmbus")) { |
||||
log_error("mxsmbus", "failed to install mxsmbus device"); |
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/mice/mice.h" |
||||
#include "mx.h" |
||||
|
||||
#define SRAM_DUMP L"dev/sram.bin" |
||||
#define SRAM_SIZE 1024 * 2084 |
||||
LPBYTE SRAM; |
||||
DWORD SRAM_POINTER = 0; |
||||
|
||||
void sram_dump() { |
||||
HANDLE dump = _CreateFileW(SRAM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); |
||||
if (dump == INVALID_HANDLE_VALUE) { |
||||
log_error("sram", "CreateFileA(SRAM_DUMP) failed"); |
||||
return; |
||||
} |
||||
_WriteFile(dump, SRAM, SRAM_SIZE, NULL, NULL); |
||||
_CloseHandle(dump); |
||||
} |
||||
|
||||
void sram_restore() { |
||||
HANDLE dump = |
||||
_CreateFileW(SRAM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
||||
if (dump == INVALID_HANDLE_VALUE) return; |
||||
DWORD read; |
||||
if (!_ReadFile(dump, SRAM, SRAM_SIZE, &read, NULL)) log_error("sram", "failed to restore (%d)", GetLastError()); |
||||
_CloseHandle(dump); |
||||
} |
||||
|
||||
BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { |
||||
DWORD SRAM_VERSION = 0x0001; |
||||
DWORD SRAM_SECTOR_SIZE = 0x100; // Max is 0x800
|
||||
|
||||
switch (dwIoControlCode) { |
||||
case IOCTL_MXSRAM_PING: // Get version
|
||||
log_misc("mxsram", |
||||
"DeviceIoControl(<mxsram>, <ping>, 0x%p, 0x%x, -, 0x%x, " |
||||
"-, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
((LPDWORD)lpOutBuffer)[0] = SRAM_VERSION; |
||||
if (lpBytesReturned) *lpBytesReturned = 4; |
||||
break; |
||||
case IOCTL_DISK_GET_DRIVE_GEOMETRY: |
||||
log_misc("mxsram", |
||||
"DeviceIoControl(<mxsram>, <get drive geom>, 0x%p, " |
||||
"0x%x, -, 0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
DISK_GEOMETRY out = *(PDISK_GEOMETRY)lpOutBuffer; |
||||
memset(&out, 0, sizeof(out)); |
||||
out.Cylinders.QuadPart = 1; |
||||
out.MediaType = FixedMedia; |
||||
out.TracksPerCylinder = 224; |
||||
out.SectorsPerTrack = 32; |
||||
out.BytesPerSector = 1; |
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY); |
||||
break; |
||||
case IOCTL_MXSRAM_GET_SECTOR_SIZE: |
||||
log_misc("mxsram", |
||||
"DeviceIoControl(<mxsram>, <get sector size>, 0x%p, " |
||||
"0x%x, -, 0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
((LPDWORD)lpOutBuffer)[0] = SRAM_SECTOR_SIZE; |
||||
if (lpBytesReturned) *lpBytesReturned = 4; |
||||
break; |
||||
default: |
||||
log_warning("mxsram", "unhandled 0x%08x", dwIoControlCode); |
||||
return FALSE; |
||||
} |
||||
|
||||
return TRUE; |
||||
} |
||||
|
||||
DWORD mxsram_SetFilePointer(LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { |
||||
if (dwMoveMethod == FILE_BEGIN) { |
||||
SRAM_POINTER = lDistanceToMove; |
||||
} else if (dwMoveMethod == FILE_CURRENT) { |
||||
SRAM_POINTER += lDistanceToMove; |
||||
} |
||||
return SRAM_POINTER; |
||||
} |
||||
|
||||
BOOL mxsram_WriteFile(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, |
||||
LPOVERLAPPED lpOverlapped) { |
||||
log_misc("mxsram", "sram write 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToWrite); |
||||
if (SRAM_POINTER + nNumberOfBytesToWrite >= SRAM_SIZE) { |
||||
nNumberOfBytesToWrite = SRAM_SIZE - SRAM_POINTER; |
||||
} |
||||
memcpy(SRAM + SRAM_POINTER, lpBuffer, nNumberOfBytesToWrite); |
||||
sram_dump(); |
||||
*lpNumberOfBytesWritten = nNumberOfBytesToWrite; |
||||
return TRUE; |
||||
} |
||||
|
||||
BOOL mxsram_ReadFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, |
||||
LPOVERLAPPED lpOverlapped) { |
||||
log_misc("mxsram", "sram read 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToRead); |
||||
if (SRAM_POINTER + nNumberOfBytesToRead >= SRAM_SIZE) { |
||||
nNumberOfBytesToRead = SRAM_SIZE - SRAM_POINTER; |
||||
} |
||||
sram_restore(); |
||||
memcpy((LPVOID)lpBuffer, SRAM + SRAM_POINTER, nNumberOfBytesToRead); |
||||
*lpNumberOfBytesRead = nNumberOfBytesToRead; |
||||
return TRUE; |
||||
} |
||||
|
||||
void setup_mxsram() { |
||||
// Allocate 2MB of SRAM
|
||||
SRAM = (LPBYTE)malloc(SRAM_SIZE); |
||||
if (!SRAM) { |
||||
log_error(BOOT_LOGGER, "unable to allocate 2MiB for SRAM"); |
||||
exit(1); |
||||
} |
||||
memset(SRAM, 0, SRAM_SIZE); |
||||
sram_restore(); |
||||
|
||||
file_hook_t* mxsram = new_file_hook(L"\\\\.\\mxsram"); |
||||
mxsram->SetFilePointer = &mxsram_SetFilePointer; |
||||
mxsram->ReadFile = &mxsram_ReadFile; |
||||
mxsram->WriteFile = &mxsram_WriteFile; |
||||
|
||||
hook_file(mxsram); |
||||
} |
@ -0,0 +1,289 @@
|
||||
#include <Windows.h> |
||||
|
||||
#include "../lib/mice/mice.h" |
||||
#include "mx.h" |
||||
#include "smbus.h" |
||||
#include "w83791d.h" |
||||
|
||||
BYTE w83791d_bank = 0x00; |
||||
BYTE w83791d_config = W83791D_CONFIG_START; |
||||
BYTE w83791d_noncrit_t1 = 75; // C
|
||||
BYTE w83791d_crit_t1 = 80; // C
|
||||
BYTE w83791d_noncrit_t2 = 75; // C
|
||||
BYTE w83791d_crit_t2 = 80; // C
|
||||
BYTE w83791d_noncrit_t3 = 75; // C
|
||||
BYTE w83791d_crit_t3 = 80; // C
|
||||
BYTE w83791d_vbat_monitor_control = 0x00; |
||||
BOOL w83791d_4f_high = 0; |
||||
|
||||
BOOL mxsuperio_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, |
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { |
||||
mxsuperio_lpc_packet* lpc_packet = (mxsuperio_lpc_packet*)lpInBuffer; |
||||
mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer; |
||||
|
||||
switch (dwIoControlCode) { |
||||
case IOCTL_MXSUPERIO_PING: |
||||
log_misc("mxsuperio", |
||||
"DeviceIoControl(<mxsuperio>, <ping>, 0x%p, 0x%x, -, " |
||||
"0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
((LPDWORD)lpOutBuffer)[0] = 0x01000001; |
||||
if (lpBytesReturned) *lpBytesReturned = 4; |
||||
break; |
||||
case IOCTL_MXSUPERIO_READ: |
||||
log_warning("mxsuperio", |
||||
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, " |
||||
"0x%x, -, -)", |
||||
lpInBuffer, nInBufferSize, nOutBufferSize); |
||||
|
||||
/*
|
||||
BYTE chipId = 0|1 |
||||
BYTE ?? = 0x0b |
||||
BYTE ?? = 0x20|0x21 |
||||
BYTE ret = 0 |
||||
*/ |
||||
|
||||
switch (((LPBYTE)lpInBuffer)[2]) { |
||||
case 0x20: |
||||
((LPBYTE)lpInBuffer)[3] = 0xa0; |
||||
break; |
||||
case 0x21: |
||||
((LPBYTE)lpInBuffer)[3] = 0x20; |
||||
break; |
||||
default: |
||||
((LPBYTE)lpInBuffer)[3] = 0x00; |
||||
break; |
||||
} |
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = 4; |
||||
break; |
||||
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: { |
||||
BYTE index = lpc_packet->index; |
||||
BYTE reg = lpc_packet->reg; |
||||
|
||||
switch (w83791d_bank) { |
||||
case 0x00: { |
||||
switch (reg) { |
||||
case W83791D_REG_WCHIPID: |
||||
lpc_out->data = 0x71; |
||||
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; |
||||
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: |
||||
lpc_out->data = 0xff; // All the beeps! (see main.h)
|
||||
break; |
||||
|
||||
case W83791D_REG_TEMP1_0: |
||||
lpc_out->data = 0x00; // TODO: Figure out the temp val lol
|
||||
break; |
||||
case W83791D_RAM_VCOREA: |
||||
case W83791D_RAM_VNIR0: |
||||
case W83791D_RAM_12VIN: |
||||
lpc_out->data = 0x00; // TODO: Figure out the batt val
|
||||
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), VDD 5 latched
|
||||
// good.
|
||||
lpc_out->data = 0b01011111; // Let's not /0!
|
||||
break; |
||||
|
||||
case W83791D_VBAT_MONITOR_CONTROL: |
||||
lpc_out->data = w83791d_vbat_monitor_control; |
||||
break; |
||||
|
||||
default: |
||||
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg); |
||||
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: |
||||
|