More intense service dummies

This commit is contained in:
Bottersnike 2023-03-28 21:08:02 +01:00
parent 585e6ba4b2
commit 8a3d1e80bb
Signed by: Bottersnike
SSH Key Fingerprint: SHA256:3g0ghwd4dNX1k1RX8qazbiT+3RIYn/daeBevHZVCiU0
55 changed files with 1671 additions and 912 deletions

View File

@ -61,9 +61,11 @@ dist:
@copy /Y "$(BUILD_DIR)/src/micetools/util\exio_test.exe" "$(DIST_DIR)/util/exio_test.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\dongleDecrypt.exe" "$(DIST_DIR)/util/dongleDecrypt.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\testBin.exe" "$(DIST_DIR)/util/testBin.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/util\micegbdisk.exe" "$(DIST_DIR)/util/micegbdisk.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummymaster\dummymaster.exe" "$(DIST_DIR)/system_dummy/dummymaster.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummyinstaller\dummyinstaller.exe" "$(DIST_DIR)/system_dummy/dummyinstaller.exe"
@copy /Y "$(BUILD_DIR)/src/micetools/system_dummy\dummykeychip\dummykeychip.exe" "$(DIST_DIR)/system_dummy/dummykeychip.exe"
@copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd"

View File

@ -63,6 +63,7 @@ void install_devices() {
install_led_bd();
install_touch_bd();
install_aime_bd();
install_servo_15069();
start_devices();

View File

@ -6,6 +6,7 @@
void install_led_bd();
void install_touch_bd();
void install_aime_bd();
void install_servo_15069();
smbus_callback_t smbus_N2_write;
smbus_callback_t smbus_N2_read;

View File

@ -5,6 +5,7 @@ devices_files = files(
'ser_led_bd.c',
'ser_maitouch.c',
'ser_tn32msec.c',
'ser_servo_838-15069.c',
# SMBus devices
'smb_pca9535.c',
'smb_ds2460.c',

View File

@ -0,0 +1,82 @@
#include "../hooks/gui.h"
#include "_devices.h"
#define SERVO_OK 0
#define SERVO_NG 8
static DWORD WINAPI ser_servo_15069_thread(com_device_t* dev) {
log_game(plfServo15069, "%ls woke up", dev->com->wName);
unsigned char data[4];
unsigned char response;
while (1) {
comdev_read_blocking(dev, data, 4);
// Validate checksums!
if (!(data[0] & 0x80) || (data[3] & 0x80) ||
(data[0] & 0x7f) != (data[1] ^ data[2] ^ data[3])) {
log_error(plfServo15069, "checksums failed: %02x %02x %02x %02x", data[0], data[1],
data[2], data[3]);
continue;
}
log_game(plfServo15069, "read:%02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
/**
* Read 4 bytes:
*
* [0]=v1 | 0x80
* [1]=v2
* [2]=v3
* [3]=(v1^v2^v3) & 0x7f
*
* v1&0x7f=[3]^v2^v3
* v2=[1]
* v3=[2]
*
* High byte v1 unrecoverable!
*/
/**
* Wake sequence in test mode:
*
* 0x7f: 0, 0
* 0x01, 64, 16
* 0x02, 4, 84
*
*/
switch (data[0] & 0x7f) {
case 0x7f:
response = SERVO_OK;
comdev_write(dev, &response, 1);
break;
case 1:
case 2:
log_warning(plfServo15069, "Not sure what %d is!", data[0] & 0x7f);
response = (data[0] & 7) | SERVO_OK;
comdev_write(dev, &response, 1);
break;
default:
log_error(plfServo15069, "Unknown opcode: %02x", data[0] & 0x7f);
response = SERVO_NG;
comdev_write(dev, &response, 1);
break;
}
/**
* Respond one byte, 8=high:
* [0] \
* [1] => data
* [2] /
* [3] = status
* [4] \
* [5] => data again
* [6] /
* [7] = X
*/
}
}
void install_servo_15069() { register_device("servo_15069", ser_servo_15069_thread); }

View File

@ -152,27 +152,6 @@ void tea_hook_test(char* fmt, ...) {
va_end(argp);
}
int mxkMain();
int miceDummyMaster(unsigned short textPort, unsigned short binaryPort, bool global);
int miceDummyInstaller(unsigned short textPort, unsigned short binaryPort, bool global);
DWORD WINAPI MxkThreadProc(LPVOID lpParameter) {
mxkMain();
return 0;
};
DWORD WINAPI MdMasterThreadProc(LPVOID lpParameter) {
miceDummyMaster(40100, 40101, false);
return 0;
};
DWORD WINAPI MdInstallerThreadProc(LPVOID lpParameter) {
miceDummyInstaller(40102, 40103, false);
return 0;
};
void spawn_pcp_processes(void) {
// CreateThread(NULL, 0, MxkThreadProc, NULL, 0, NULL);
// CreateThread(NULL, 0, MdMasterThreadProc, NULL, 0, NULL);
// CreateThread(NULL, 0, MdInstallerThreadProc, NULL, 0, NULL);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE;
@ -187,8 +166,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
// *((DWORD*)(0x00407850)) = (DWORD)(&logcb);
}
spawn_pcp_processes();
// if (wcscmp(exeName, L"RingGame.exe") == 0) {
// log_warning(plfBoot, "Bodge hook goo!");
// CreateHook32((void*)(0x005f2580), &tea_hook_test);

View File

@ -10,10 +10,10 @@ BOOL WINAPI columba_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
switch (dwIoControlCode) {
case IOCTL_COLUMBA_READ:
log_misc(plfColumba, "DeviceIoControl(<columba>, <read>, 0x%p, 0x%x, -, 0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
log_trace(plfColumba, "DeviceIoControl(<columba>, <read>, 0x%p, 0x%x, -, 0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
AM_COLUMBA_REQUEST* request = (AM_COLUMBA_REQUEST*)lpInBuffer;
log_info(plfColumba, "Physical read: 0x%04x %ss at %08X", request->m_elementCount,
log_misc(plfColumba, "Physical read: 0x%04x %ss at %08X", request->m_elementCount,
request->m_elementSize == 1 ? "byte"
: request->m_elementSize == 2 ? "short"
: request->m_elementSize == 4 ? "long"

View File

@ -407,251 +407,11 @@ BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
char PARITY[] = { 'N', 'O', 'E', 'M', 'S' };
char* STOP[] = { "1", "1.5", "2" };
log_info(plfMxJvs, "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize,
log_misc(plfMxJvs, "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize,
PARITY[lpDCB->Parity], STOP[lpDCB->StopBits]);
return TRUE;
}
// jvs_board_t maimai_jvs_config[1] = { {
// .test_keybind = VK_OEM_4, // [{
// .coin_keybinds = {'1', '2'},
// .keybinds = {
// {
// 0,
// 0,
// 0,
// 'W', // *1P8
// 'Q', // *1P7
// 'A', // *1P6
// 'Z', // *1P5
// 'X', // *1P4
// 'C', // *1P3
// 0,
// 'E', // *1P1
// 'D', // *1P2
// 0,
// 0,
// '1', // *1P Service
// 0,
// },
// {
// 0,
// 0,
// 0,
// 'I', // *2P8
// 'U', // *2P7
// 'J', // *2P6
// 'M', // *2P5
// VK_OEM_COMMA, // *2P4
// VK_OEM_PERIOD, // *2P3
// 0,
// 'O', // *2P1
// 'L', // *2P2
// 0,
// 0,
// '2', // *2P Service
// 0,
// },
// },
// .flags = {
// {
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_NC,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NONE,
// JVS_FLAG_NC,
// },
// {
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_NC,
// JVS_FLAG_INVERT,
// JVS_FLAG_INVERT,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NONE,
// JVS_FLAG_NC,
// },
// },
// .coin_counts = {0, 0},
// .handler = &jvs_exchange,
// .id = JVS_837_14572_ID,
// } };
// jvs_board_t under_night_jvs_config[1] = {
// {
// .test_keybind = VK_OEM_4, // [{
// .coin_keybinds = {'1', '2'},
// .keybinds = {
// {
// 0, 0, 0, 0, 0, 0,
// 'A', // D (EXCs)
// 'R', // C (Heavy)
// 'E', // B (Middle)
// 'W', // A (Light)
// VK_RIGHT, // Right
// VK_LEFT, // Left
// VK_DOWN, // Down
// VK_UP, // Up
// VK_BACK, // Service
// VK_RETURN, // Start
// },
// {
// 0, 0, 0, 0, 0, 0,
// 'J', // D (EXCs)
// 'P', // C (Heavy)
// 'O', // B (Middle)
// 'I', // A (Light)
// VK_NUMPAD6, // Right
// VK_NUMPAD4, // Left
// VK_NUMPAD2, // Down
// VK_NUMPAD8, // Up
// VK_BACK, // Service
// VK_RETURN, // Start
// },
// },
// .flags = {
// {
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// },
// {
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NC,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// JVS_FLAG_NONE,
// },
// },
// .coin_counts = {0, 0},
// .handler = &jvs_exchange,
// .id = JVS_837_14572_ID,
// },
// // {
// // .test_keybind = VK_OEM_4, // [{
// // .coin_keybinds = {0, 0},
// // .keybinds = {
// // {
// // 0, 0, 0, 0, 0, 0,
// // 'J', // D (EXCs)
// // 'P', // C (Heavy)
// // 'O', // B (Middle)
// // 'I', // A (Light)
// // VK_NUMPAD6, // Right
// // VK_NUMPAD4, // Left
// // VK_NUMPAD2, // Down
// // VK_NUMPAD8, // Up
// // VK_BACK, // Service
// // VK_RETURN, // Start
// // },
// // {0},
// // },
// // .flags = {
// // {
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // JVS_FLAG_NONE,
// // },
// // {
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // JVS_FLAG_NC,
// // },
// // },
// // .coin_counts = {0, 0},
// // .handler = &jvs_exchange,
// // .id = JVS_837_14572_ID,
// // },
// };
void init_jvs_boards() {
for (int i = 0; i < _countof(jvs_boards); i++) {
jvs_boards[i].num = i;

View File

@ -70,7 +70,7 @@ BOOL WINAPI mxsram_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, L
switch (dwIoControlCode) {
case IOCTL_MXSRAM_PING: // Get version
log_info(plfMxSram,
log_misc(plfMxSram,
"DeviceIoControl(<mxsram>, <ping>, 0x%p, 0x%x, -, 0x%x, "
"-, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
@ -79,7 +79,7 @@ BOOL WINAPI mxsram_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, L
if (lpBytesReturned) *lpBytesReturned = 4;
break;
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
log_info(plfMxSram,
log_misc(plfMxSram,
"DeviceIoControl(<mxsram>, <get drive geom>, 0x%p, "
"0x%x, -, 0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
@ -97,7 +97,7 @@ BOOL WINAPI mxsram_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, L
log_error(plfMxSram, "Unhandled IOCTL_DISK_GET_LENGTH_INFO");
return FALSE;
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
log_info(plfMxSram,
log_misc(plfMxSram,
"DeviceIoControl(<mxsram>, <get sector size>, 0x%p, "
"0x%x, -, 0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);

View File

@ -91,8 +91,18 @@ void mice_got_game_id(char game_id[4]) {
// 2P is unbound by default, as a (nice) keymap with both
// will probably also involve changing 1P too.
}
} else if (IS_GAME(SBVH /* Sega & Sonic All-Stars Racing Arcade */)) {
log_info(plfBoot, "Detect game Sega & Sonic All-Stars Racing Arcade");
MiceConfig.devices.com1 = "servo_15069";
MiceConfig.devices.com2 = "";
MiceConfig.devices.com3 = "";
MiceConfig.devices.com5 = "";
MiceConfig.devices.com6 = "";
MiceConfig.devices.com7 = "";
MiceConfig.devices.com8 = "";
} else {
log_warning(plfBoot, "Unknown game ID: %.4s", game_id);
if (game_id[0] != '\0') return log_warning(plfBoot, "Unknown game ID: %.4s", game_id);
return;
}

View File

@ -248,9 +248,13 @@ DWORD WINAPI FakeQueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWOR
swprintf_s(lpTargetPath, ucchMax, L"\\Device\\%ls", volume->m_DeviceName);
return ucchMax;
} else {
// ! We cannot do this, because some programs lie in ucchMax!!
// ZeroMemory(lpTargetPath, ucchMax);
// TODO: This, properly!!
ZeroMemory(lpTargetPath, ucchMax);
swprintf_s(lpTargetPath, ucchMax, DUMMY_USB_RM);
size_t nbytes = swprintf_s(lpTargetPath, ucchMax, DUMMY_USB_RM);
lpTargetPath[nbytes] = '\0';
lpTargetPath[nbytes + 1] = '\0';
}
return 0;
}
@ -292,14 +296,14 @@ UINT WINAPI FakeGetDriveTypeA(LPCSTR lpRootPathName) {
disk_volume_t* volume = getVolumeByPath(lpRootPathName, VOL_MATCH_PATH | VOL_MATCH_DOS_DEVICE);
if (volume == NULL) {
// If we aren't faking this drive, check if we're allowing fall-through
// char gameDrive = char_lower(GetGamedataDrive());
// if (strlen(lpRootPathName) >= 2 && char_lower(lpRootPathName[0]) == gameDrive &&
// lpRootPathName[1] == ':') {
// return DRIVE_FIXED;
// }
char gameDrive = char_lower(GetGamedataDrive());
if (strlen(lpRootPathName) >= 2 && char_lower(lpRootPathName[0]) == gameDrive &&
lpRootPathName[1] == ':') {
return DRIVE_FIXED;
}
// SetLastError(ERROR_FILE_NOT_FOUND);
// return DRIVE_NO_ROOT_DIR;
// We could do the above, but for now, we're just going to pass through to the real API.
return TrueGetDriveTypeA(lpRootPathName);
}

View File

@ -2,6 +2,7 @@
#include <Windows.h>
// Lifted from Irb.h
#pragma pack(push, 1)
typedef struct _IDENTIFY_DEVICE_DATA {
struct {
USHORT Reserved1 : 1;
@ -373,3 +374,4 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT Signature : 8;
USHORT CheckSum : 8;
} IDENTIFY_DEVICE_DATA, *PIDENTIFY_DEVICE_DATA;
#pragma pack(pop)

View File

@ -36,8 +36,8 @@ BOOL WINAPI pd_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOI
}
/**
* C1: Seen by mxkeychip
* C2: Seen by factorytest
* C1: ssd.hostproof; Used by mxkeychip
* C2: ssh.proof; Used by mxkeychip and factorytest
*/
if (command != 0xC1 && command != 0xC2) {

View File

@ -1,5 +1,6 @@
#include "logging.h"
#include "../../lib/mice/mice.h"
#include "../util/_util.h"
char* trim_string(char* string) {

View File

@ -3,8 +3,9 @@
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr);
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
// Poorly exclude nxauth. TODO: better
if (port != 40190) {
// Poorly exclude nxauth and mxgcatcher.
// TODO: better
if (port != 40190 && port != 40110) {
log_info(plfNetwork, "connect(%hhu.%hhu.%hhu.%hhu:%hu)", (addr >> 24) & 0xff,
(addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff, port);
}

View File

@ -43,7 +43,7 @@ BOOL WINAPI FakeSetupDiEnumDeviceInterfaces(HDEVINFO DeviceInfoSet, PSP_DEVINFO_
if (DeviceInterfaceData) {
while (device != NULL) {
if (device->handle == DeviceInfoSet) {
log_info(plfSetupAPI, "hooking fake device: %ls", device->path);
log_misc(plfSetupAPI, "hooking fake device: %ls", device->path);
memcpy(&DeviceInterfaceData->InterfaceClassGuid, device->guid, sizeof *device->guid);
DeviceInterfaceData->Flags = SPINT_ACTIVE;
DeviceInterfaceData->Reserved = (ULONG_PTR)device->path;
@ -68,7 +68,7 @@ BOOL WINAPI FakeSetupDiGetDeviceInterfaceDetailA(HDEVINFO DeviceInfoSet, PSP_DEV
FAKE_DEVICE* device = fake_devices;
while (device != NULL) {
if (device->handle == DeviceInfoSet && (ULONG_PTR)device->path == DeviceInterfaceData->Reserved) {
log_info(plfSetupAPI, "Intercepted SetupDiGetDeviceInterfaceDetailA");
log_misc(plfSetupAPI, "Intercepted SetupDiGetDeviceInterfaceDetailA");
const WCHAR* res = (WCHAR*)DeviceInterfaceData->Reserved;
int new_len = (wcslen(res) + 1) * (sizeof *res);

View File

@ -9,7 +9,6 @@ shared_library(
vs_module_defs: 'mice.def',
sources: [
'util/misc.c',
'util/log.c',
'util/hook.c',
'util/path.c',
@ -29,11 +28,7 @@ shared_library(
amiTimer,
amiMd5,
mxk,
# Madoka service emulation
mxklib,
dummymaster,
dummyinstaller,
],
include_directories: [
openssl_inc,

View File

@ -1,7 +1,6 @@
#pragma once
#include "hook.h"
#include "log.h"
#define HDATA_FILE 0
#define HDATA_FIND_VOLUME 1

View File

@ -4,7 +4,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include "log.h"
#include "../../lib/mice/mice.h"
function_hook_t* hook_list = NULL;
@ -104,19 +104,19 @@ void* CreateHook32(PVOID src, PVOID dst) {
// push 0x... (dword)
len = 5;
} else if (bSrc[0] == 0x55 && bSrc[1] == 0x8B && bSrc[2] == 0xEC && bSrc[3] == 0x83 &&
bSrc[4] == 0xE4) {
bSrc[4] == 0xE4) {
// pusb ebp
// mov ebp,esp
// and esp,ffffff**
len = 6;
} else if (bSrc[0] == 0x55 && bSrc[1] == 0x8B && bSrc[2] == 0xEC && bSrc[3] == 0x8b &&
bSrc[4] == 0x45) {
bSrc[4] == 0x45) {
// pusb ebp
// mov ebp,esp
// mov eax,DWORD PTR [...]
len = 6;
} else if (bSrc[0] == 0x55 && bSrc[1] == 0x8B && bSrc[2] == 0xEC && bSrc[3] == 0x80 &&
bSrc[4] == 0x3D) {
bSrc[4] == 0x3D) {
// pusb ebp
// mov ebp,esp
// cmd BYTE PTR ds:0x...,0x...
@ -169,8 +169,7 @@ void setup_hooks() {
// (TrueGetProcAddress ? TrueGetProcAddress : GetProcAddress)(dll, hook->name);
void* original = GetProcAddress(dll, hook->name);
if (original == NULL) {
log_warning(plfHooks, "failed to get original %s (%03x)", hook->name,
GetLastError());
log_warning(plfHooks, "failed to get original %s (%03x)", hook->name, GetLastError());
} else {
void* gateway = CreateHook32(original, hook->patch);
if (hook->store != NULL) *hook->store = gateway;

View File

@ -3,29 +3,23 @@
#include "../lib/mice/mice.h"
#include "locate.h"
#include "spawn.h"
bool debug_wait = false;
int boot_delay = 0;
bool gametest = false;
bool designviewer = false;
bool spriteviewer = false;
bool noisetest = false;
char exe_name[MAX_PATH + 1] = "";
char commandline[MAX_PATH + 1] = "";
void print_help(char* exe) {
fprintf(stderr, "Usage: %s [-h] [-t] [-b executable.exe] [-d]\n", exe);
fprintf(stderr, " -h: Print this help message and exit\n");
fprintf(stderr, " -b: Specify the game binary to use\n");
fprintf(stderr, " -d: Wait for a debugger to attach when starting\n");
fprintf(stderr, " -t: Start the game in test mode\n");
fprintf(stderr, " -dv: Start the game in design viewer mode\n");
fprintf(stderr, " -sv: Start the game in sprite viewer mode\n");
fprintf(stderr, " -nt: Start the game in noisetest mode\n");
log_info(plfBoot, "Usage: %s [-h] [-t] [-b executable.exe] [-d]", exe);
log_info(plfBoot, " -h: Print this help message and exit");
log_info(plfBoot, " -b: Specify the game binary to use");
log_info(plfBoot, " --mice-d: Wait for a debugger to attach when starting");
log_info(plfBoot, " --mice.<config>=<setting>: Set launcher options");
exit(0);
}
void parse_cmdline(int argc, char* argv[]) {
bool parse_cmdline(int argc, char* argv[]) {
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0) {
print_help(argv[0]);
@ -35,14 +29,44 @@ void parse_cmdline(int argc, char* argv[]) {
memcpy(exe_name, val, strlen(val) + 1);
} else if (strcmp(argv[i], "--mice-d") == 0) {
debug_wait = true;
} else if (strcmp(argv[i], "-mice-t") == 0) {
gametest = true;
} else if (strcmp(argv[i], "-dv") == 0) {
designviewer = true;
} else if (strcmp(argv[i], "-sv") == 0) {
spriteviewer = true;
} else if (strcmp(argv[i], "-nt") == 0) {
noisetest = true;
} else if (strncmp(argv[i], "--mice.", strlen("--mice.")) == 0) {
char key[256];
char value[256];
key[0] = value[0] = '\0';
char* arg = argv[i] + strlen("--mice.");
int j = 0;
for (; j < _countof(key) - 2; j++) {
if (arg[j] == '\0') break;
if (arg[j] == '=') {
strcpy_s(value, _countof(value), arg + j + 1);
break;
}
key[j] = arg[j];
}
key[j] = '\0';
bool handled = false;
for (j = 0; j < _countof(mxspawns); j++) {
if (strcmp(key, mxspawns[j].name) != 0) continue;
handled = true;
if (strcmp(value, "no") == 0)
mxspawns[j].mode = SPAWN_NONE;
else if (strcmp(value, "mx") == 0)
mxspawns[j].mode |= SPAWN_REAL;
else if (strcmp(value, "md") == 0)
mxspawns[j].mode |= SPAWN_DUMMY;
else {
log_error(plfBoot, "Unknown spawn mode: %s=%s", key, value);
return false;
}
}
if (!handled) {
log_error(plfBoot, "Unknown launcher config: %s=%s", key, value);
return false;
}
} else {
if (commandline[0] == 0)
snprintf(commandline, sizeof commandline, "%s", argv[i]);
@ -50,18 +74,20 @@ void parse_cmdline(int argc, char* argv[]) {
snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
}
}
return true;
}
int main(int argc, char* argv[]) {
load_mice_config();
setup_logging();
log_info(plfBoot, "Micetools version: %s", MICE_VERSION);
CHAR workDir[MAX_PATH + 1];
GetCurrentDirectory(MAX_PATH, workDir);
fprintf(stderr, "Work dir: %s\n", workDir);
log_info(plfBoot, "Current directory: %s", workDir);
fprintf(stderr, "Micetools version: %s\n", MICE_VERSION);
parse_cmdline(argc, argv);
if (!parse_cmdline(argc, argv)) return 0;
if (exe_name[0] == '\0' && MiceConfig.launcher.game_binary[0] != '\0') {
snprintf(exe_name, sizeof exe_name, "%s", MiceConfig.launcher.game_binary);
@ -71,44 +97,36 @@ int main(int argc, char* argv[]) {
if (exe_name[0] == '\0') {
if (!locate_game(exe_name, MAX_PATH + 1)) {
fprintf(stderr, "Fatal: Failed to locate a game\n");
log_error(plfBoot, "Fatal: Failed to locate a game");
return 0;
}
} else {
DWORD dwAttrib = GetFileAttributes(exe_name);
if (dwAttrib == INVALID_FILE_ATTRIBUTES || dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
fprintf(stderr, "Fatal: %s: no such file found\n", exe_name);
log_error(plfBoot, "Fatal: %s: no such file found", exe_name);
return 0;
}
}
char* cmdline_mode = gametest ? ". gametest"
: designviewer ? ". designviewer"
: spriteviewer ? ". spriteviewer"
: noisetest ? ". noisetest"
: "";
char cmdline[MAX_PATH + 1];
if (commandline[0] == 0)
snprintf(cmdline, sizeof cmdline, "%s", cmdline_mode);
else
snprintf(cmdline, sizeof cmdline, "%s %s", cmdline_mode, commandline);
fprintf(stderr, "exec: %s %s\n", exe_name, cmdline);
spawn_pcp_processes();
log_info(plfBoot, "exec: %s %s", exe_name, commandline);
char micepath[MAX_PATH + 1];
if (!locate_library(micepath, MAX_PATH + 1)) {
fprintf(stderr, "Fatal: Failed to locate micelib. Check your mice_dll setting!\n");
log_error(plfBoot, "Fatal: Failed to locate micelib. Check your mice_dll setting!");
return 0;
}
char* extra_injections = MiceConfig.launcher.inject;
HANDLE game_proc =
start_and_inject(exe_name, cmdline, micepath, debug_wait, boot_delay, extra_injections, 0);
start_and_inject(exe_name, commandline, micepath, debug_wait, boot_delay, extra_injections, 0);
if (!game_proc) return -1;
if (FAILED(WaitForSingleObject(game_proc, INFINITE))) {
fprintf(stderr, "Fatal: WaitForSingleObject failed: %03x\n", GetLastError());
log_error(plfBoot, "Fatal: WaitForSingleObject failed: %03x", GetLastError());
} else {
fprintf(stderr, "Shutting down\n");
log_info(plfBoot, "Shutting down");
CloseHandle(game_proc);
}
return 0;

View File

@ -4,10 +4,18 @@ executable(
win_subsystem: subsystem,
sources: [
'locate.c',
'spawn.c',
'main.c',
rc,
],
link_with: [
mice_lib,
mxklib,
# Madoka service emulation
mxk,
dummykeychip,
dummymaster,
dummyinstaller,
],
)

View File

@ -0,0 +1,63 @@
#include "spawn.h"
#include "../lib/mice/mice.h"
spawn_t mxspawns[3] = {
{ "keychip", SPAWN_DUMMY, MdkThreadProc, MxkThreadProc },
{ "master", SPAWN_DUMMY, MdmThreadProc, NULL },
{ "installer", SPAWN_DUMMY, MdiThreadProc, NULL },
};
int mxkMain();
int miceDummyKeychip(unsigned short textPort, unsigned short binaryPort, bool global);
int miceDummyMaster(unsigned short textPort, unsigned short binaryPort, bool global);
int miceDummyInstaller(unsigned short textPort, unsigned short binaryPort, bool global);
DWORD WINAPI MdkThreadProc(LPVOID lpParameter) {
miceDummyKeychip(40106, 40107, false);
return 0;
};
DWORD WINAPI MxkThreadProc(LPVOID lpParameter) {
mxkMain();
return 0;
};
DWORD WINAPI MdmThreadProc(LPVOID lpParameter) {
miceDummyMaster(40100, 40101, false);
return 0;
};
DWORD WINAPI MdiThreadProc(LPVOID lpParameter) {
miceDummyInstaller(40102, 40103, false);
return 0;
};
static inline void spawn_one(spawn_t* spawn) {
if (spawn->mode == SPAWN_NONE) {
log_warning(plfBoot, "Not spawning %s", spawn->name);
return;
}
if (spawn->mode == SPAWN_BOTH) {
log_error(plfBoot, "Invalid spawn mode for %s! Only one of md or mx may be selected",
spawn->name);
return;
}
if (spawn->mode == SPAWN_REAL) {
if (spawn->real == NULL) {
log_error(plfBoot, "mx mode for %s is not supported yet", spawn->name);
return;
}
CreateThread(NULL, 0, spawn->real, NULL, 0, NULL);
} else if (spawn->mode == SPAWN_DUMMY) {
if (spawn->dummy == NULL) {
log_error(plfBoot, "md mode for %s is not supported yet", spawn->name);
return;
}
CreateThread(NULL, 0, spawn->dummy, NULL, 0, NULL);
} else {
log_error(plfBoot, "Unknown spawn mode %d for %s", spawn->mode, spawn->name);
return;
}
}
void spawn_pcp_processes(void) {
for (int i = 0; i < _countof(mxspawns); i++) spawn_one(&(mxspawns[i]));
}

View File

@ -0,0 +1,22 @@
#include <Windows.h>
typedef struct {
char* name;
int mode;
LPTHREAD_START_ROUTINE dummy;
LPTHREAD_START_ROUTINE real;
} spawn_t;
#define SPAWN_NONE 0
#define SPAWN_DUMMY 1
#define SPAWN_REAL 2
#define SPAWN_BOTH (SPAWN_DUMMY | SPAWN_REAL)
extern spawn_t mxspawns[3];
DWORD WINAPI MxkThreadProc(LPVOID lpParameter);
DWORD WINAPI MdkThreadProc(LPVOID lpParameter);
DWORD WINAPI MdmThreadProc(LPVOID lpParameter);
DWORD WINAPI MdiThreadProc(LPVOID lpParameter);
void spawn_pcp_processes(void);

View File

@ -19,5 +19,6 @@ libpcp = static_library(
],
link_with: [
amiTimer,
amiDebug,
],
)

View File

@ -1,6 +1,5 @@
#pragma once
#define PCP_LOG(fmt, ...) printf("%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__)
#define ZERO(x) memset(&(x), 0, sizeof(x))
#define ZERO_BUF(x) memset((x), 0, sizeof(*x))

View File

@ -49,7 +49,7 @@ e_pcpa_t _pcpaGetErrorFromPcpp(e_pcpp_t err) {
void pcpaCloseBinary(pcpa_t *stream) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn't set\n");
amiDebugLog("error PCPA stream isn't set");
return;
}
stream->binary_mode = binary_mode_none;
@ -59,7 +59,7 @@ void pcpaCloseBinary(pcpa_t *stream) {
void pcpaClose(pcpa_t *stream) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return;
}
pcppClose(&stream->pcpp);
@ -83,11 +83,11 @@ void pcpaClose(pcpa_t *stream) {
e_pcpa_t pcpaInitStream(pcpa_t *stream) {
if (LIBPCP_VERSION == NULL) {
PCP_LOG("error PCPA version isn\'t set\n");
amiDebugLog("error PCPA version isn't set");
return e_pcpa_generic;
}
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -119,11 +119,11 @@ e_pcpa_t pcpaInitStream(pcpa_t *stream) {
e_pcpa_t pcpaOpenClient(pcpa_t *stream, char *ipAddr, ushort port, uint param_4,
timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (ipAddr == 0) {
PCP_LOG("error PCPA IpAddr isn\'t set\n");
amiDebugLog("error PCPA IpAddr isn't set");
return e_pcpa_param_invalid;
}
@ -141,7 +141,7 @@ e_pcpa_t pcpaOpenServerWithBinary(pcpa_t *stream, int open_mode, u_short port, u
e_pcpa_t err;
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -149,29 +149,29 @@ e_pcpa_t pcpaOpenServerWithBinary(pcpa_t *stream, int open_mode, u_short port, u
case 0:
stream->err = err = _errP2A(pcppOpenServer(&stream->pcpp, 0, port, param_5));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenServer\n");
amiDebugLog("error pcppOpenServer");
return err;
}
stream->err = err = _errP2A(pcppOpenBinaryServer(&stream->pcpp, 0, binary_port));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenBinaryServer\n");
amiDebugLog("error pcppOpenBinaryServer");
return err;
}
break;
case 1:
stream->err = err = _errP2A(pcppOpenServer(&stream->pcpp, 1, port, param_5));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenServer\n");
amiDebugLog("error pcppOpenServer");
return err;
}
stream->err = err = _errP2A(pcppOpenBinaryServer(&stream->pcpp, 1, binary_port));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenBinaryServer\n");
amiDebugLog("error pcppOpenBinaryServer");
return err;
}
break;
default:
PCP_LOG("error Open Mode isn\'t set\n");
amiDebugLog("error Open Mode isn't set");
return stream->err = e_pcpa_generic;
}
@ -181,27 +181,27 @@ e_pcpa_t pcpaOpenServerWithBinary(pcpa_t *stream, int open_mode, u_short port, u
e_pcpa_t pcpaSetCallbackFunc(pcpa_t *stream, char *keyword, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (keyword == NULL) {
PCP_LOG("error keyword isn\'t set\n");
amiDebugLog("error keyword isn't set");
return e_pcpa_generic;
}
if (callback == NULL) {
PCP_LOG("error Callback func isn\'t set\n");
amiDebugLog("error Callback func isn't set");
return e_pcpa_generic;
}
if (stream->callback_table == NULL) {
PCP_LOG("error Callback_table buffer isn\'t set\n");
amiDebugLog("error Callback_table buffer isn't set");
return e_pcpa_cb_table_unset;
}
if (strnlen(keyword, PCP_KEYWORD_MAX + 1) > PCP_KEYWORD_MAX) {
PCP_LOG("error a keyword is too long\n");
amiDebugLog("error a keyword is too long");
return e_pcpa_generic;
}
@ -219,7 +219,7 @@ e_pcpa_t pcpaSetCallbackFunc(pcpa_t *stream, char *keyword, pcpa_callback *callb
e_pcpa_t pcpaSetCallbackFuncBuffer(pcpa_t *stream, pcpa_cb_table_t *callback_table,
uint callbacks_max) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -234,7 +234,7 @@ e_pcpa_t pcpaSetCallbackFuncBuffer(pcpa_t *stream, pcpa_cb_table_t *callback_tab
pcp_send_data_t *pcpaSetSendPacket(pcpa_t *stream, char *keyword, char *value) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return NULL;
}
return pcppSetSendPacket(&stream->send_data, keyword, value);
@ -242,7 +242,7 @@ pcp_send_data_t *pcpaSetSendPacket(pcpa_t *stream, char *keyword, char *value) {
char *pcpaGetCommand(pcpa_t *pcpa, char *command) {
if (pcpa == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return NULL;
}
@ -266,7 +266,7 @@ e_pcpa_t pcpaServer(pcpa_t *stream, timeout_t timeout_ms) {
local_14 = timeout_ms;
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
amiTimerGet(&time_start);
@ -408,7 +408,7 @@ e_pcpa_t pcpaServer(pcpa_t *stream, timeout_t timeout_ms) {
return stream->err;
}
} else {
PCP_LOG("error pcpaSendBinary\n");
amiDebugLog("error pcpaSendBinary");
}
}
break;
@ -443,7 +443,7 @@ e_pcpa_t pcpaServer(pcpa_t *stream, timeout_t timeout_ms) {
stream->binary_mode = binary_mode_none;
stream->state = pcpa_state_none;
if (stream->err == e_pcpa_ok) goto LAB_00454a1a;
PCP_LOG("error pcpaRecvBinary\n");
amiDebugLog("error pcpaRecvBinary");
}
break;
case 10:
@ -452,7 +452,7 @@ e_pcpa_t pcpaServer(pcpa_t *stream, timeout_t timeout_ms) {
stream->before_cb(stream, stream->pcpp.sock.recv_buf);
if (stream->callback_table == NULL) {
PCP_LOG("error Callback_table buffer isn\'t set\n");
amiDebugLog("error Callback_table buffer isn't set");
stream->err = e_pcpa_cb_table_unset;
return stream->err;
@ -526,11 +526,11 @@ LAB_00454d84:
e_pcpa_t pcpaRecvBinary(pcpa_t *stream, uint something) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (stream->recv_buffer == NULL) {
PCP_LOG("error Recv buffer isn\'t set\n");
amiDebugLog("error Recv buffer isn't set");
pcpaCloseBinary(stream);
pcpaClose(stream);
return stream->err = e_pcpa_cb_table_full;
@ -547,11 +547,11 @@ e_pcpa_t pcpaRecvBinary(pcpa_t *stream, uint something) {
e_pcpa_t pcpaSendBinary(pcpa_t *stream, uint param_2) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (stream->send_buffer == NULL) {
PCP_LOG("error Send buffer isn\'t set\n");
amiDebugLog("error Send buffer isn't set");
stream->err = e_pcpa_cb_table_full;
pcpaCloseBinary(stream);
pcpaClose(stream);
@ -567,13 +567,13 @@ e_pcpa_t pcpaSendBinary(pcpa_t *stream, uint param_2) {
return err;
}
e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t *stream, unsigned char *send_buffer, size_t len) {
e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t *stream, const unsigned char *send_buffer, size_t len) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (send_buffer == NULL) {
PCP_LOG("error Send Buffer isn\'t set\n");
amiDebugLog("error Send Buffer isn't set");
return e_pcpa_timeout_closed;
}
stream->send_buffer = send_buffer;
@ -584,11 +584,11 @@ e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t *stream, unsigned char *send_buffer, siz
e_pcpa_t pcpaSetBeforeBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
amiDebugLog("error don't set stream");
return e_pcpa_stream_unset;
}
if (callback == NULL) {
PCP_LOG("error Binary mode callback func isn\'t set\n");
amiDebugLog("error Binary mode callback func isn't set");
return e_pcpa_generic;
}
stream->binary_mode_before_cb = callback;
@ -599,11 +599,11 @@ e_pcpa_t pcpaSetBeforeBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *call
e_pcpa_t pcpaSetAfterBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
amiDebugLog("error don't set stream");
return e_pcpa_stream_unset;
}
if (callback == NULL) {
PCP_LOG("error Binary mode callback func isn\'t set\n");
amiDebugLog("error Binary mode callback func isn't set");
return e_pcpa_generic;
}
stream->binary_mode_after_cb = callback;
@ -614,7 +614,7 @@ e_pcpa_t pcpaSetAfterBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *callb
e_pcpa_t pcpaSetBinaryMode(pcpa_t *stream, binary_mode_t binary_mode) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (pcppGetServerSocket(&stream->pcpp, 1) == HANDLE_INVAL) {
@ -627,11 +627,11 @@ e_pcpa_t pcpaSetBinaryMode(pcpa_t *stream, binary_mode_t binary_mode) {
e_pcpa_t pcpaSetRecvBinaryBuffer(pcpa_t *stream, unsigned char *recv_buffer, size_t len) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
if (recv_buffer == NULL) {
PCP_LOG("error Recv Buffer isn\'t set\n");
amiDebugLog("error Recv Buffer isn't set");
return e_pcpa_timeout_closed;
}
stream->recv_buffer = recv_buffer;
@ -642,7 +642,7 @@ e_pcpa_t pcpaSetRecvBinaryBuffer(pcpa_t *stream, unsigned char *recv_buffer, siz
pcp_send_data_t *pcpaAddSendPacket(pcpa_t *stream, char *keyword, char *value) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return NULL;
}
return pcppAddSendPacket(&stream->send_data, keyword, value);
@ -650,7 +650,7 @@ pcp_send_data_t *pcpaAddSendPacket(pcpa_t *stream, char *keyword, char *value) {
char *pcpaGetKeyword(pcpa_t *stream, uint keyword_num) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return NULL;
}
return pcppGetKeyword(&stream->recv_data, keyword_num);
@ -661,7 +661,7 @@ e_pcpa_t pcpaIsBusy(pcpa_t *pcpa, timeout_t timeout) {
amtime_t start;
if (pcpa == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -723,7 +723,7 @@ e_pcpa_t pcpaIsBusy(pcpa_t *pcpa, timeout_t timeout) {
e_pcpa_t pcpaSendRequest(pcpa_t *stream, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -732,7 +732,7 @@ e_pcpa_t pcpaSendRequest(pcpa_t *stream, timeout_t timeout) {
_pcpaGetErrorFromPcpp(pcppSendRequestTable(&stream->pcpp, &stream->send_data, timeout));
stream->err = err;
if (err != e_pcpa_to) {
if (err != e_pcpa_ok) PCP_LOG("Error : pcppSendRequestTable(%d)\n", err);
if (err != e_pcpa_ok) amiDebugLog("Error : pcppSendRequestTable(%d)", err);
memset(&stream->send_data, 0, sizeof stream->send_data);
stream->state = pcpa_state_none;
}
@ -741,7 +741,7 @@ e_pcpa_t pcpaSendRequest(pcpa_t *stream, timeout_t timeout) {
e_pcpa_t pcpaRecvResponse(pcpa_t *stream, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -750,7 +750,7 @@ e_pcpa_t pcpaRecvResponse(pcpa_t *stream, timeout_t timeout) {
_pcpaGetErrorFromPcpp(pcppRecvResponse(&stream->pcpp, &stream->recv_data, timeout));
stream->err = err;
if (err != e_pcpa_to) {
if (err != e_pcpa_ok) PCP_LOG("Error : pcppRecvResponse(%d)\n", err);
if (err != e_pcpa_ok) amiDebugLog("Error : pcppRecvResponse(%d)", err);
stream->state = pcpa_state_none;
}
return err;
@ -758,7 +758,7 @@ e_pcpa_t pcpaRecvResponse(pcpa_t *stream, timeout_t timeout) {
e_pcpa_t pcpaOpenBinaryClient(pcpa_t *stream, ushort port, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}
@ -777,7 +777,7 @@ e_pcpa_t pcpaOpenBinaryClient(pcpa_t *stream, ushort port, timeout_t timeout) {
e_pcpa_t pcpaAccessClient(pcpa_t *stream, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
amiDebugLog("error PCPA stream isn't set");
return e_pcpa_stream_unset;
}

View File

@ -91,7 +91,7 @@ e_pcpa_t pcpaSetBinaryMode(pcpa_t* stream, binary_mode_t binary_mode);
e_pcpa_t pcpaSetCallbackFunc(pcpa_t* stream, char* keyword, pcpa_callback* callback, void* data);
e_pcpa_t pcpaSetCallbackFuncBuffer(pcpa_t* stream, pcpa_cb_table_t* callback_table, uint callbacks_max);
e_pcpa_t pcpaSetRecvBinaryBuffer(pcpa_t* stream, unsigned char* recv_buffer, size_t len);
e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t* stream, unsigned char* send_buffer, size_t len);
e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t* stream, const unsigned char* send_buffer, size_t len);
pcp_send_data_t* pcpaSetSendPacket(pcpa_t* stream, char* keyword, char* value);
pcp_send_data_t *pcpaAddSendPacket(pcpa_t *stream, char *keyword, char *value);
char* pcpaGetCommand(pcpa_t* pcpa, char* command);

View File

@ -55,7 +55,7 @@ e_pcpp_t _pcppGetErrorFromPcpt(int err) {
bool pcppCheckPrompt(pcpp_t* stream) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return false;
}
@ -85,7 +85,7 @@ e_pcpp_t pcppCheckRecvMsg(char* recv_data, size_t buf_len, int param_3) {
bool bVar1 = true;
if (recv_data == NULL) {
PCP_LOG("pointer error\n");
amiDebugLog("pointer error");
return e_pcpp_param_invalid;
}
@ -118,13 +118,13 @@ pcpp_char_type_t pcppCheckStr(char* recv_data, uint* found_at, int* is_qmark) {
uint idx = 0;
if (recv_data == NULL || is_qmark == NULL || found_at == NULL) {
PCP_LOG("pointer error\n");
amiDebugLog("pointer error");
return pcpp_char_error;
}
*is_qmark = 0;
if (*found_at == 0) {
PCP_LOG("stream exhausted\n");
amiDebugLog("stream exhausted");
return pcpp_char_error;
}
@ -170,7 +170,7 @@ pcpp_char_type_t pcppCheckStr(char* recv_data, uint* found_at, int* is_qmark) {
void pcppClose(pcpp_t* stream) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return;
}
@ -201,7 +201,7 @@ void pcppClose(pcpp_t* stream) {
void pcppCloseBinary(pcpp_t* stream) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return;
}
@ -225,7 +225,7 @@ e_pcpp_t pcppGetBlockingTime(uint param_1, timeout_t timeout, pcpp_t* stream, in
amtime_t local_8;
if (stream == NULL || blocking_time == NULL) {
PCP_LOG("pointer error\n");
amiDebugLog("pointer error");
return 0;
}
@ -261,7 +261,7 @@ e_pcpp_t pcppGetBlockingTime(uint param_1, timeout_t timeout, pcpp_t* stream, in
char* pcppGetCommand(pcp_parse_data_t* recv_data, char* command) {
if (recv_data == NULL || command == NULL) {
PCP_LOG("error Recv Data isn\'t set\n");
amiDebugLog("error Recv Data isn't set");
return NULL;
}
@ -276,12 +276,12 @@ char* pcppGetCommand(pcp_parse_data_t* recv_data, char* command) {
char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keywordNum) {
if (recvData == NULL) {
PCP_LOG("error Recv Data isn\'t set\n");
amiDebugLog("error Recv Data isn't set");
return NULL;
}
if ((keywordNum >= PCP_CMDS_MAX) && (keywordNum > recvData->cmd_count)) {
PCP_LOG("error keywordNum over\n");
amiDebugLog("error keywordNum over");
return NULL;
}
return recvData->strings + recvData->keywords[keywordNum];
@ -289,7 +289,7 @@ char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keywordNum) {
SOCKET pcppGetServerSocket(pcpp_t* stream, int which) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return SOCKET_INVAL;
}
@ -305,7 +305,7 @@ SOCKET pcppGetServerSocket(pcpp_t* stream, int which) {
e_pcpp_t pcppInitStream(pcpp_t* stream) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
amiDebugLog("error don't set stream");
return e_pcpp_param_invalid;
}
@ -353,11 +353,11 @@ e_pcpp_t pcppOpenClient(pcpp_t* stream, char* ipAddr, ushort port, uint param_4,
amtime_t now;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (ipAddr == NULL) {
PCP_LOG("error IpAddr isn\'t set\n");
amiDebugLog("error IpAddr isn't set");
return e_pcpp_param_invalid;
}
@ -375,7 +375,7 @@ e_pcpp_t pcppOpenClient(pcpp_t* stream, char* ipAddr, ushort port, uint param_4,
return e_pcpp_to;
}
stream->err = e_pcpp_no_server;
PCP_LOG("error Time out error\n");
amiDebugLog("error Time out error");
}
if (stream->err == 0) {
amiTimerGet(&now);
@ -398,13 +398,13 @@ e_pcpp_t pcppOpenClient(pcpp_t* stream, char* ipAddr, ushort port, uint param_4,
pcptCloseDataSock(&stream->sock);
pcppResetRead(stream);
err = stream->err;
PCP_LOG("error pcppRecvPrompt error = %d\n", err);
amiDebugLog("error pcppRecvPrompt error = %d", err);
} else {
pcptCloseDataSock(&stream->sock);
pcppResetRead(stream);
stream->state = pcpp_state_none;
err = stream->err;
PCP_LOG("error pcptOpenClient error = %d\n", err);
amiDebugLog("error pcptOpenClient error = %d", err);
}
LAB_00a16a90:
return stream->err;
@ -412,7 +412,7 @@ LAB_00a16a90:
e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
@ -421,7 +421,7 @@ e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port) {
stream->last_active = _amTimeMs(time);
stream->state = pcpp_state_none;
if (open_mode != 0 && open_mode != 1) {
PCP_LOG("error Open Mode isn\'t set\n");
amiDebugLog("error Open Mode isn't set");
stream->state = pcpp_state_none;
return stream->err = e_pcpp_param_invalid;
}
@ -429,7 +429,7 @@ e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port) {
e_pcpp_t err = _errT2P(pcptOpenServer(&stream->data_sock, open_mode, port));
stream->err = err;
if (err != e_pcpp_ok) {
PCP_LOG("error pcptOpenBinaryServer\n");
amiDebugLog("error pcptOpenBinaryServer");
return err;
}
@ -440,11 +440,11 @@ e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port) {
e_pcpp_t pcppOpenBinaryClient(pcpp_t* stream, char* ipAddr, ushort port, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (ipAddr == NULL) {
PCP_LOG("error IpAddr isn\'t set\n");
amiDebugLog("error IpAddr isn't set");
return e_pcpp_param_invalid;
}
stream->state = pcpp_state_open_binary;
@ -478,12 +478,12 @@ e_pcpp_t pcppOpenBinaryClient(pcpp_t* stream, char* ipAddr, ushort port, timeout
e_pcpp_t pcppOpenServer(pcpp_t* stream, int open_mode, u_short port, undefined4 param_4) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
stream->field_0xb8 = param_4;
if (open_mode != 0 && open_mode != 1) {
PCP_LOG("error Open Mode isn\'t set\n");
amiDebugLog("error Open Mode isn't set");
stream->err = e_pcpp_param_invalid;
stream->state = pcpp_state_none;
@ -493,7 +493,7 @@ e_pcpp_t pcppOpenServer(pcpp_t* stream, int open_mode, u_short port, undefined4
e_pcpp_t err = _errT2P(pcptOpenServer(&stream->sock, open_mode, port));
stream->err = err;
if (err != e_pcpp_ok) {
PCP_LOG("error pcppOpenServer error = %d\n", err);
amiDebugLog("error pcppOpenServer error = %d", err);
return err;
}
stream->open = 1;
@ -506,7 +506,7 @@ e_pcpp_t pcppOpenServer(pcpp_t* stream, int open_mode, u_short port, undefined4
pcp_send_data_t* pcppSetSendPacket(pcp_send_data_t* send_data, char* keyword, char* value) {
if (send_data == NULL || keyword == NULL) {
PCP_LOG("error Send Data isn\'t set\n");
amiDebugLog("error Send Data isn't set");
return NULL;
}
@ -533,7 +533,7 @@ pcp_send_data_t* pcppSetSendPacket(pcp_send_data_t* send_data, char* keyword, ch
uint pcppRecvCheck(char* buf, int* offset) {
if (buf == NULL || offset == NULL) {
PCP_LOG("pointer error\n");
amiDebugLog("pointer error");
return 1;
}
@ -591,11 +591,11 @@ uint pcppRecvCheck(char* buf, int* offset) {
e_pcpp_t pcppSendResponseTable(pcpp_t* stream, pcp_send_data_t* data, timeout_t timeout_ms) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (data == NULL) {
PCP_LOG("error Response buffer isn\'t set\n");
amiDebugLog("error Response buffer isn't set");
return e_pcpp_param_invalid;
}
@ -610,16 +610,16 @@ e_pcpp_t pcppSendResponse(pcpp_t* stream, pcp_send_data_t* resp_buffer, size_t b
amtime_t time;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (resp_buffer == NULL) {
PCP_LOG("error Response buffer isn\'t set\n");
amiDebugLog("error Response buffer isn't set");
return e_pcpp_param_invalid;
}
if (buf_len > PCP_BUF_MAX - 1) {
PCP_LOG("error Response buffer over\n");
amiDebugLog("error Response buffer over");
return stream->err = e_pcpp_param_invalid;
}
@ -629,7 +629,7 @@ e_pcpp_t pcppSendResponse(pcpp_t* stream, pcp_send_data_t* resp_buffer, size_t b
if (err != e_pcpp_ok) {
stream->state = pcpp_state_none;
pcppResetRead(stream);
PCP_LOG("error Send message format error\n");
amiDebugLog("error Send message format error");
printf("'%s'\n", resp_buffer->data);
return stream->err;
}
@ -668,11 +668,11 @@ e_pcpp_t pcppRecvRequest(pcpp_t* stream, pcp_parse_data_t* recv_data, timeout_t
amtime_t now2;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (recv_data == NULL) {
PCP_LOG("error Request buffer isn\'t set\n");
amiDebugLog("error Request buffer isn't set");
return stream->err = e_pcpp_param_invalid;
}
@ -727,7 +727,7 @@ e_pcpp_t pcppRecvRequestMain(pcpp_t* stream, bool* bReRecv, undefined4 timeout)
char* recv_data;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
@ -759,7 +759,7 @@ e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, timeout_t timeout_ms) {
bool has_timeout = false;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
@ -785,7 +785,7 @@ LAB_00456133:
err = stream->open ? -12 : -6;
pcptCloseDataSock(&stream->sock);
pcppResetRead(stream);
if (stream->open == 0) PCP_LOG("Error : Time out error\n");
if (stream->open == 0) amiDebugLog("Error : Time out error");
}
amiTimerGet(&now);
stream->last_active = _amTimeMs(now);
@ -804,12 +804,12 @@ e_pcpp_t pcppRecvAllMsg(pcpp_t* stream, uint param_1, bool* bReRecv) {
local_14 = param_1;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (bReRecv == NULL) {
PCP_LOG("error bReRecv isn\'t set\n");
amiDebugLog("error bReRecv isn't set");
return e_pcpp_param_invalid;
}
*bReRecv = false;
@ -864,17 +864,17 @@ e_pcpp_t pcppRecvAllMsg(pcpp_t* stream, uint param_1, bool* bReRecv) {
pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, uint* lenout) {
if (stream == NULL || lenout == NULL) {
PCP_LOG("pointer error\n");
amiDebugLog("pointer error");
return NULL;
}
if (stream->recv_data_buffer == NULL) {
PCP_LOG("don\'t set recvData buffer\n");
amiDebugLog("don't set recvData buffer");
return NULL;
}
if (stream->read_bytes_num > PCP_BUF_MAX) {
PCP_LOG("Buffer size error\n");
amiDebugLog("Buffer size error");
return NULL;
}
@ -917,7 +917,7 @@ pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, uint* lenout) {
break;
case PCP_CHAR_SEP:
if (stream->recv_data_buffer->cmd_count > PCP_CMDS_MAX) {
PCP_LOG("Buffer size error\n");
amiDebugLog("Buffer size error");
return NULL;
}
stream->recv_data_buffer->strings[string_idx] = PCP_CHAR_EOF;
@ -927,7 +927,7 @@ pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, uint* lenout) {
break;
case PCP_CHAR_EQU:
if (stream->recv_data_buffer->cmd_count > PCP_CMDS_MAX) {
PCP_LOG("Buffer size error\n");
amiDebugLog("Buffer size error");
return NULL;
}
stream->recv_data_buffer->strings[string_idx] = PCP_CHAR_EOF;
@ -953,7 +953,7 @@ int pcppRecvPrompt(pcpp_t* stream, undefined4 param_2, int param_3) {
uint local_c = param_3;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
@ -995,12 +995,12 @@ int pcppRecvPrompt(pcpp_t* stream, undefined4 param_2, int param_3) {
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, timeout_t timeout_ms) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (stream->resp_buffer == NULL) {
PCP_LOG("error Request buffer isn\'t set\n");
amiDebugLog("error Request buffer isn't set");
return e_pcpp_param_invalid;
}
@ -1037,11 +1037,11 @@ e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len,
recvb_local = param_4;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (recv_buf == NULL) {
PCP_LOG("error Recv Bninary Buffer isn\'t set\n");
amiDebugLog("error Recv Bninary Buffer isn't set");
return e_pcpp_param_invalid;
}
stream->field_0x214 = 0;
@ -1160,11 +1160,11 @@ e_pcpp_t pcppSendBinary(pcpp_t* stream, unsigned char* send_binary_buffer, size_
local_14 = param_4;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (send_binary_buffer == NULL) {
PCP_LOG("error Send Bninary Buffer isn\'t set\n");
amiDebugLog("error Send Bninary Buffer isn't set");
return stream->err = e_pcpp_param_invalid;
}
amiTimerGet(&local_8);
@ -1266,7 +1266,7 @@ e_pcpp_t pcppIsBusy(pcpp_t* stream, timeout_t timeout) {
local_1c = 0;
local_24 = 0;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
amiTimerGet(&local_18);
@ -1511,7 +1511,7 @@ e_pcpp_t pcppIsBusy(pcpp_t* stream, timeout_t timeout) {
}
stream->state = pcpp_state_none;
pcppResetRead(stream);
PCP_LOG("error Response format error\n");
amiDebugLog("error Response format error");
return stream->err;
}
if (iVar3 == 0) break;
@ -1824,7 +1824,7 @@ e_pcpp_t pcppIsBusy(pcpp_t* stream, timeout_t timeout) {
if (eVar7 != e_pcpp_ok) {
stream->state = pcpp_state_none;
pcppResetRead(stream);
PCP_LOG("error Response format error\n");
amiDebugLog("error Response format error");
return stream->err;
}
pcppChangeRequest(stream, &timeout);
@ -1884,7 +1884,7 @@ int pcpp_something(amtime_t* time, timeout_t timeout, pcpp_t* stream, pcpt_t* so
pcp_send_data_t* pcppAddSendPacket(pcp_send_data_t* send_data, char* keyword, char* value) {
if (send_data == NULL || keyword == NULL) {
PCP_LOG("error Send Data isn\'t set\n");
amiDebugLog("error Send Data isn't set");
return NULL;
}
@ -1913,12 +1913,12 @@ pcp_send_data_t* pcppAddSendPacket(pcp_send_data_t* send_data, char* keyword, ch
e_pcpp_t pcppSendRequestTable(pcpp_t* stream, pcp_send_data_t* request_buffer, timeout_t timeout) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (request_buffer == NULL) {
PCP_LOG("error Request buffer isn\'t set\n");
amiDebugLog("error Request buffer isn't set");
return e_pcpp_param_invalid;
}
@ -1932,16 +1932,16 @@ e_pcpp_t pcppSendRequest(pcpp_t* stream, pcp_send_data_t* request_buffer, uint n
amtime_t local_8;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return e_pcpp_param_invalid;
}
if (request_buffer == NULL) {
PCP_LOG("error Request buffer isn\'t set\n");
amiDebugLog("error Request buffer isn't set");
return e_pcpp_param_invalid;
}
if (0x100 < nbytes) {
PCP_LOG("error Request buffer over\n");
amiDebugLog("error Request buffer over");
return (stream->err = e_pcpp_param_invalid);
}
@ -1951,7 +1951,7 @@ e_pcpp_t pcppSendRequest(pcpp_t* stream, pcp_send_data_t* request_buffer, uint n
if (pcpp_err != e_pcpp_ok) {
stream->state = pcpp_state_none;
pcppResetRead(stream);
PCP_LOG("error Message format error\n");
amiDebugLog("error Message format error");
return stream->err;
}
@ -1990,12 +1990,12 @@ e_pcpp_t pcppRecvResponse(pcpp_t* stream, pcp_parse_data_t* buffer, timeout_t ti
amtime_t local_8;
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return -5;
}
if (buffer == NULL) {
PCP_LOG("error Response buffer isn\'t set\n");
amiDebugLog("error Response buffer isn't set");
return -5;
}
@ -2038,7 +2038,7 @@ e_pcpp_t pcppRecvResponse(pcpp_t* stream, pcp_parse_data_t* buffer, timeout_t ti
} else {
stream->state = pcpp_state_none;
pcppResetRead(stream);
PCP_LOG("error Response format error\n");
amiDebugLog("error Response format error");
return stream->err;
}
@ -2047,7 +2047,7 @@ e_pcpp_t pcppRecvResponse(pcpp_t* stream, pcp_parse_data_t* buffer, timeout_t ti
SOCKADDR* pcppGetSockAddr(pcpp_t* stream, bool is_data) {
if (stream == NULL) {
PCP_LOG("error PCPP stream isn\'t set\n");
amiDebugLog("error PCPP stream isn't set");
return NULL;
}

View File

@ -30,7 +30,7 @@ e_pcpt_t pcptInitStream(pcpt_t *sock) {
SOCKET s;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
@ -61,7 +61,7 @@ e_pcpt_t pcptInitStream(pcpt_t *sock) {
void pcptClose(pcpt_t *sock) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return;
}
@ -100,7 +100,7 @@ void pcptClose(pcpt_t *sock) {
void pcptCloseDataSock(pcpt_t *sock) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return;
}
if (sock->field_0x58 != 0) {
@ -118,7 +118,7 @@ void pcptCloseDataSock(pcpt_t *sock) {
e_pcpt_t pcptAcceptServer(pcpt_t *stream, timeout_t timeout_ms) {
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
@ -158,7 +158,7 @@ e_pcpt_t pcptCheckConnectAble(pcpt_t *stream, timeout_t timeout_ms) {
amtime_t start;
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
amiTimerGet(&start);
@ -228,7 +228,7 @@ e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint
if (timeout_ms == TIMEOUT_NONE) wait_timeout = TIMEOUT_NONE;
if (event == NULL) {
PCP_LOG("Error : EVENT HANDLE error\n");
amiDebugLog("Error : EVENT HANDLE error");
return e_pcpt_pointer_unset;
}
@ -261,7 +261,7 @@ e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint
e_pcpt_t pcptOpenDataSockServer(pcpt_t *sock, timeout_t timeout_ms) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CONNECTED) return e_pcpt_already_open;
@ -280,7 +280,7 @@ e_pcpt_t pcptOpenServer(pcpt_t *stream, int open_mode, ushort port) {
e_pcpt_t err;
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
@ -296,8 +296,10 @@ e_pcpt_t pcptOpenServer(pcpt_t *stream, int open_mode, ushort port) {
if (s == SOCKET_INVAL) return stream->err = _errW2T(GetLastError());
uint reuseaddr = 1;
if (FAILED(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&reuseaddr, 4))) {
uint exclusiveAddr = 1;
// ! Note: The real libpcp uses SO_REUSEADDR here.
// ! We deviate from this, and instead use SO_EXCLUSIVEADDRUSE, as this is the correct flag.
if (FAILED(setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (void *)&exclusiveAddr, 4))) {
err = _errW2T(GetLastError());
closesocket(stream->server_sock);
stream->server_sock = SOCKET_INVAL;
@ -349,7 +351,7 @@ e_pcpt_t pcptOpenClient(pcpt_t *stream, char *ipAddr, ushort port, timeout_t tim
pcpt = stream;
if ((stream == NULL) || (ipAddr == NULL)) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
if (stream->client_sock != 0xffffffff) {
@ -471,17 +473,17 @@ e_pcpt_t pcptRecv(pcpt_t *sock, unsigned char *recv_buf, size_t *recv_buf_len,
amtime_t start;
if (sock == NULL || recv_buf == NULL || recv_buf_len == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CLOSED) {
PCP_LOG("error PCP not open\n");
amiDebugLog("error PCP not open");
return sock->err = e_pcpt_not_open;
}
// TODO: URGENT: Something in the FSM causes this condition to error out!
if (sock->client_open != 0) {
PCP_LOG("error PCP already connected\n");
amiDebugLog("error PCP already connected");
return sock->err = e_pcpt_already_connected;
}
@ -540,16 +542,16 @@ e_pcpt_t pcptSend(pcpt_t *sock, unsigned char *send_buf, size_t *send_len, uint
amtime_t start_time;
if (sock == NULL || send_buf == NULL || send_len == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CLOSED) {
PCP_LOG("error PCP not open\n");
amiDebugLog("error PCP not open");
return sock->err = e_pcpt_not_open;
}
if (sock->client_open != 0) {
PCP_LOG("error PCP already connected\n");
amiDebugLog("error PCP already connected");
return sock->err = e_pcpt_already_connected;
}
@ -600,12 +602,12 @@ e_pcpt_t pcptSendAllMsg(pcpt_t *sock, timeout_t timeout_ms) {
amtime_t start;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
if (sock->send_buf == NULL || sock->send_buf_count == NULL) {
PCP_LOG("error send buffer isn\'t set\n");
amiDebugLog("error send buffer isn't set");
return e_pcpt_pointer_unset;
}
@ -662,7 +664,7 @@ e_pcpt_t pcptSendAllMsg(pcpt_t *sock, timeout_t timeout_ms) {
void pcptSetConfig(pcpt_t *stream, uint config, uint value) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
amiDebugLog("error don't set stream");
return;
}
@ -701,7 +703,7 @@ e_pcpt_t pcptIsBusy(pcpt_t *sock, timeout_t timeout_ms) {
timeout_ms_00 = timeout_ms;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
amiDebugLog("error PCP stream isn't set");
return e_pcpt_pointer_unset;
}
switch (sock->client_open) {
@ -872,7 +874,7 @@ e_pcpt_t pcptIsBusy(pcpt_t *sock, timeout_t timeout_ms) {
sock->client_open = 0;
if (eVar8 != e_pcpt_ok) goto LAB_0045997d;
if (sock->recv_buf == NULL || sock->recv_buf_count == NULL) {
PCP_LOG("error Recv buffer isn\'t set\n");
amiDebugLog("error Recv buffer isn't set");
return sock->err = e_pcpt_recv_unset;
}
size_t received =

View File

@ -12,8 +12,10 @@ COMMENT("The main config file for micetools")
COMMENT("")
SECTION(mice, "General mice settings")
COMMENT("Trace logging (6) is intensive, and should only be used when debugging")
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_int(mice, file_log_level, 5, "1 = Game\n2 = Error\n3 = Warning\n4 = Info\n5 = Misc\n6 = Trace")
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.index", "The file to read patches from")

View File

@ -1,234 +1,239 @@
#include "log.h"
#include <dbghelp.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(lib, "DbgHelp.lib")
#include "../../lib/mice/config.h"
#include "../hooks/files.h"
#include "../hooks/logging.h"
#define _LF(category, name, display) \
LOG_FACILITY lf##name = { \
.m_name = display, \
}; \
PLOG_FACILITY plf##name = &lf##name;
#include "log_facilities.def"
#undef _LF
extern WCHAR exeName[MAX_PATH + 1];
extern DWORD imageOffset;
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
BOOL HAS_COLOUR = FALSE;
char _log_prelude[64];
char* log_prelude() {
time_t rawtime;
struct tm timeinfo;
time(&rawtime);
localtime_s(&timeinfo, &rawtime);
strftime(_log_prelude, sizeof _log_prelude, "[%Y/%m/%d %H:%M:%S] ", &timeinfo);
return _log_prelude;
}
static HANDLE log_file = NULL;
CRITICAL_SECTION logger_lock;
static char* log_colours[] = {
"", // Always
"\033[96m", // Game
"\033[91m", // Error
"\033[33m", // Warning
"\033[97m", // Info
"\033[90m", // Misc
"\033[90m", // Trace
};
static const char* COLOR_RESET = "\033[0m";
#define LOG_PREFIXES "!GEWIMT"
void logcb(LPCSTR param_1) { log_game(plfAmLog, "%s", param_1); }
void __stdcall amLogCallback(DWORD level, char* format) {
if (level == 0)
log_game(plfAmLog, "E:%s", format);
else if (level == 0)
log_game(plfAmLog, "W:%s", format);
else
log_game(plfAmLog, "I:%s", format);
}
DWORD pLogcb;
DWORD* ppLogcb;
static char log_buf[1024];
int _do_log(BYTE log_level, PLOG_FACILITY facility, const char* format, va_list args) {
// TODO: These are all horrible bodges
if (wcscmp(exeName, L"mxnetwork.exe") == 0) {
// *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
*((DWORD*)(imageOffset + 0x004438e8)) = 0x00000000;
}
if (wcscmp(exeName, L"maimai_dump_.exe") == 0) {
*((DWORD*)(imageOffset + 0x00c820ec)) = 0x00000001;
pLogcb = (DWORD)(&amLogCallback);
ppLogcb = &pLogcb;
*((DWORD***)(imageOffset + 0x00c820F4)) = &ppLogcb;
// *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
}
char prefix = LOG_PREFIXES[log_level];
EnterCriticalSection(&logger_lock);
int col_len = strlen(log_colours[log_level]);
int log_len = snprintf(log_buf, _countof(log_buf), "%s%s%c:%s:", log_colours[log_level],
log_prelude(), prefix, facility->m_name);
log_len += vsnprintf(log_buf + log_len, _countof(log_buf) - log_len, format, args);
log_len += snprintf(log_buf + log_len, _countof(log_buf) - log_len, "%s\n", COLOR_RESET);
log_buf[_countof(log_buf) - 1] = '\0';
if (MiceConfig.mice.log_level >= log_level) {
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
_WriteFile(sout, log_buf, log_len, NULL, NULL);
// FlushFileBuffers(sout);
}
if (MiceConfig.mice.log_to_file) {
if (log_file && log_file != INVALID_HANDLE_VALUE) {
// Replace the colour reset with a newline, then skip the prefix when writing
log_buf[log_len - col_len] = '\n';
log_buf[log_len - col_len + 1] = '\0';
_WriteFile(log_file, log_buf + col_len, log_len - col_len - sizeof(COLOR_RESET), NULL, NULL);
}
}
LeaveCriticalSection(&logger_lock);
return log_len;
}
int vlog_trace(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_TRACE, facility, format, args);
}
int _log_trace(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_trace(facility, format, args);
va_end(args);
return ret;
}
int vlog_misc(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_MISC, facility, format, args);
}
int _log_misc(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_misc(facility, format, args);
va_end(args);
return ret;
}
int vlog_info(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_INFO, facility, format, args);
}
int _log_info(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_info(facility, format, args);
va_end(args);
return ret;
}
int vlog_warning(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_WARNING, facility, format, args);
}
int _log_warning(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_warning(facility, format, args);
va_end(args);
return ret;
}
int vlog_error(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_ERROR, facility, format, args);
}
int _log_error(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_error(facility, format, args);
va_end(args);
return ret;
}
int vlog_game(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_GAME, facility, format, args);
}
int _log_game(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_game(facility, format, args);
va_end(args);
return ret;
}
void setup_logging() {
// Force stdio even for GUI applications
// AttachConsole(ATTACH_PARENT_PROCESS);
// Enable colour in CMD
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
if (GetConsoleMode(hConsole, &dwMode))
HAS_COLOUR = SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
InitializeCriticalSection(&logger_lock);
if (MiceConfig.mice.log_to_file) {
if (log_file == NULL && MiceConfig.mice.log_file[0] != '\0')
log_file = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, 0, NULL);
}
}
void log_stack(PLOG_FACILITY facility) {
char name[MAX_PATH * sizeof(TCHAR)];
char Storage[sizeof(IMAGEHLP_SYMBOL64) + sizeof(name)];
IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)Storage;
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 stack = { 0 };
stack.AddrPC.Offset = context.Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
BOOL initres = SymInitialize(process, NULL, true);
for (ULONG frame = 0;; frame++) {
BOOL result = StackWalk64(IMAGE_FILE_MACHINE_I386, process, thread, &stack, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL);
symbol->SizeOfStruct = sizeof(Storage);
symbol->MaxNameLength = sizeof(name);
DWORD64 displacement;
SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
UnDecorateSymbolName(symbol->Name, (PSTR)name, sizeof(name), UNDNAME_COMPLETE);
log_error(facility, "%02u called from 0x%08X STACK=0x%08X FRAME=0x%08X %s", frame,
(ULONG64)stack.AddrPC.Offset, (ULONG64)stack.AddrStack.Offset,
(ULONG64)stack.AddrFrame.Offset, symbol->Name);
if (result == FALSE) {
DWORD frameError = GetLastError();
break;
}
}
}
#include "log.h"
#include <dbghelp.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(lib, "DbgHelp.lib")
#include "config.h"
#define _LF(category, name, display) \
LOG_FACILITY lf##name = { \
.m_name = display, \
}; \
PLOG_FACILITY plf##name = &lf##name;
#include "log_facilities.def"
#undef _LF
extern WCHAR exeName[MAX_PATH + 1];
extern DWORD imageOffset;
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
BOOL HAS_COLOUR = FALSE;
char _log_prelude[64];
char* log_prelude() {
time_t rawtime;
struct tm timeinfo;
time(&rawtime);
localtime_s(&timeinfo, &rawtime);
strftime(_log_prelude, sizeof _log_prelude, "[%Y/%m/%d %H:%M:%S] ", &timeinfo);
return _log_prelude;
}
static HANDLE log_file = INVALID_HANDLE_VALUE;
CRITICAL_SECTION logger_lock;
static char* log_colours[] = {
"", // Always
"\033[96m", // Game
"\033[91m", // Error
"\033[33m", // Warning
"\033[97m", // Info
"\033[90m", // Misc
"\033[90m", // Trace
};
static const char* COLOR_RESET = "\033[0m";
#define LOG_PREFIXES "!GEWIMT"
void logcb(LPCSTR param_1) { log_game(plfAmLog, "%s", param_1); }
void __stdcall amLogCallback(DWORD level, char* format) {
if (level == 0)
log_game(plfAmLog, "E:%s", format);
else if (level == 0)
log_game(plfAmLog, "W:%s", format);
else
log_game(plfAmLog, "I:%s", format);
}
DWORD pLogcb;
DWORD* ppLogcb;
static char log_buf[1024];
int _do_log(BYTE log_level, PLOG_FACILITY facility, const char* format, va_list args) {
// Early-return if we have nothing to do
if (MiceConfig.mice.log_level < log_level &&
(!MiceConfig.mice.log_to_file || MiceConfig.mice.file_log_level < log_level)) {
return 0;
}
// TODO: These are all horrible bodges
// if (wcscmp(exeName, L"mxnetwork.exe") == 0) {
// // *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
// *((DWORD*)(imageOffset + 0x004438e8)) = 0x00000000;
// }
// if (wcscmp(exeName, L"maimai_dump_.exe") == 0) {
// *((DWORD*)(imageOffset + 0x00c820ec)) = 0x00000001;
// pLogcb = (DWORD)(&amLogCallback);
// ppLogcb = &pLogcb;
// *((DWORD***)(imageOffset + 0x00c820F4)) = &ppLogcb;
// // *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
// }
char prefix = LOG_PREFIXES[log_level];
EnterCriticalSection(&logger_lock);
int col_len = strlen(log_colours[log_level]);
int log_len = snprintf(log_buf, _countof(log_buf), "%s%s%c:%s:", log_colours[log_level],
log_prelude(), prefix, facility->m_name);
log_len += vsnprintf(log_buf + log_len, _countof(log_buf) - log_len, format, args);
log_len += snprintf(log_buf + log_len, _countof(log_buf) - log_len, "%s\n", COLOR_RESET);
log_buf[_countof(log_buf) - 1] = '\0';
if (MiceConfig.mice.log_level >= log_level) {
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(sout, log_buf, log_len, NULL, NULL);
// FlushFileBuffers(sout);
}
if (MiceConfig.mice.log_to_file && MiceConfig.mice.file_log_level >= log_level) {
if (log_file && log_file != INVALID_HANDLE_VALUE) {
// Replace the colour reset with a newline, then skip the prefix when writing
log_buf[log_len - col_len] = '\n';
log_buf[log_len - col_len + 1] = '\0';
WriteFile(log_file, log_buf + col_len, log_len - col_len - sizeof(COLOR_RESET), NULL,
NULL);
}
}
LeaveCriticalSection(&logger_lock);
return log_len;
}
int vlog_trace(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_TRACE, facility, format, args);
}
int _log_trace(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_trace(facility, format, args);
va_end(args);
return ret;
}
int vlog_misc(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_MISC, facility, format, args);
}
int _log_misc(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_misc(facility, format, args);
va_end(args);
return ret;
}
int vlog_info(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_INFO, facility, format, args);
}
int _log_info(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_info(facility, format, args);
va_end(args);
return ret;
}
int vlog_warning(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_WARNING, facility, format, args);
}
int _log_warning(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_warning(facility, format, args);
va_end(args);
return ret;
}
int vlog_error(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_ERROR, facility, format, args);
}
int _log_error(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_error(facility, format, args);
va_end(args);
return ret;
}
int vlog_game(PLOG_FACILITY facility, const char* format, va_list args) {
return _do_log(LOG_GAME, facility, format, args);
}
int _log_game(PLOG_FACILITY facility, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_game(facility, format, args);
va_end(args);
return ret;
}
void setup_logging() {
// Force stdio even for GUI applications
// AttachConsole(ATTACH_PARENT_PROCESS);
// Enable colour in CMD
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
if (GetConsoleMode(hConsole, &dwMode))
HAS_COLOUR = SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
InitializeCriticalSection(&logger_lock);
if (MiceConfig.mice.log_to_file) {
if (log_file == INVALID_HANDLE_VALUE && MiceConfig.mice.log_file[0] != '\0')
log_file = CreateFileA(MiceConfig.mice.log_file, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_ALWAYS, 0, NULL);
}
}
void log_stack(PLOG_FACILITY facility) {
char name[MAX_PATH * sizeof(TCHAR)];
char Storage[sizeof(IMAGEHLP_SYMBOL64) + sizeof(name)];
IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)Storage;
CONTEXT context;
RtlCaptureContext(&context);
STACKFRAME64 stack = { 0 };
stack.AddrPC.Offset = context.Eip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Esp;
stack.AddrStack.Mode = AddrModeFlat;
stack.AddrFrame.Offset = context.Ebp;
stack.AddrFrame.Mode = AddrModeFlat;
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
BOOL initres = SymInitialize(process, NULL, true);
for (ULONG frame = 0;; frame++) {
BOOL result = StackWalk64(IMAGE_FILE_MACHINE_I386, process, thread, &stack, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL);
symbol->SizeOfStruct = sizeof(Storage);
symbol->MaxNameLength = sizeof(name);
DWORD64 displacement;
SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
UnDecorateSymbolName(symbol->Name, (PSTR)name, sizeof(name), UNDNAME_COMPLETE);
log_error(facility, "%02u called from 0x%08X STACK=0x%08X FRAME=0x%08X %s", frame,
(ULONG64)stack.AddrPC.Offset, (ULONG64)stack.AddrStack.Offset,
(ULONG64)stack.AddrFrame.Offset, symbol->Name);
if (result == FALSE) {
DWORD frameError = GetLastError();
break;
}
}
}

View File

@ -1,80 +1,80 @@
#pragma once
#include <Windows.h>
#include <stdio.h>
#define LOG_GAME 1
#define LOG_ERROR 2
#define LOG_WARNING 3
#define LOG_INFO 4
#define LOG_MISC 5
#define LOG_TRACE 6
typedef struct {
char* m_name;
} LOG_FACILITY, *PLOG_FACILITY;
#define _LF(category, name, display) extern PLOG_FACILITY plf##name;
#include "log_facilities.def"
#undef _LF
extern PLOG_FACILITY plfNetwork;
extern CRITICAL_SECTION logger_lock;
int _log_trace(PLOG_FACILITY facility, const char* format, ...);
int _log_misc(PLOG_FACILITY facility, const char* format, ...);
int _log_info(PLOG_FACILITY facility, const char* format, ...);
int _log_warning(PLOG_FACILITY facility, const char* format, ...);
int _log_error(PLOG_FACILITY facility, const char* format, ...);
int _log_game(PLOG_FACILITY facility, const char* format, ...);
int vlog_trace(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_misc(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_info(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_warning(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_error(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_game(PLOG_FACILITY facility, const char* format, va_list args);
void log_stack(PLOG_FACILITY facility);
void setup_logging();
// Disable some logging entirely at build time for speed
#define COMPILE_LOG_LEVEL 6
#if COMPILE_LOG_LEVEL >= 6
#define log_trace _log_trace
#else
#define log_trace(...)
#endif
#if COMPILE_LOG_LEVEL >= 5
#define log_misc _log_misc
#else
#define log_misc(...)
#endif
#if COMPILE_LOG_LEVEL >= 4
#define log_info _log_info
#else
#define log_info(...)
#endif
#if COMPILE_LOG_LEVEL >= 3
#define log_warning _log_warning
#else
#define log_warning(...)
#endif
#if COMPILE_LOG_LEVEL >= 2
#define log_error _log_error
#else
#define log_error(...)
#endif
#if COMPILE_LOG_LEVEL >= 1
#define log_game _log_game
#else
#define log_game(...)
#endif
#pragma once
#include <Windows.h>
#include <stdio.h>
#define LOG_GAME 1
#define LOG_ERROR 2
#define LOG_WARNING 3
#define LOG_INFO 4
#define LOG_MISC 5
#define LOG_TRACE 6
typedef struct {
char* m_name;
} LOG_FACILITY, *PLOG_FACILITY;
#define _LF(category, name, display) extern PLOG_FACILITY plf##name;
#include "log_facilities.def"
#undef _LF
extern PLOG_FACILITY plfNetwork;
extern CRITICAL_SECTION logger_lock;
int _log_trace(PLOG_FACILITY facility, const char* format, ...);
int _log_misc(PLOG_FACILITY facility, const char* format, ...);
int _log_info(PLOG_FACILITY facility, const char* format, ...);
int _log_warning(PLOG_FACILITY facility, const char* format, ...);
int _log_error(PLOG_FACILITY facility, const char* format, ...);
int _log_game(PLOG_FACILITY facility, const char* format, ...);
int vlog_trace(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_misc(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_info(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_warning(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_error(PLOG_FACILITY facility, const char* format, va_list args);
int vlog_game(PLOG_FACILITY facility, const char* format, va_list args);
void log_stack(PLOG_FACILITY facility);
void setup_logging();
// Disable some logging entirely at build time for speed
#define COMPILE_LOG_LEVEL 6
#if COMPILE_LOG_LEVEL >= 6
#define log_trace _log_trace
#else
#define log_trace(...)
#endif
#if COMPILE_LOG_LEVEL >= 5
#define log_misc _log_misc
#else
#define log_misc(...)
#endif
#if COMPILE_LOG_LEVEL >= 4
#define log_info _log_info
#else
#define log_info(...)
#endif
#if COMPILE_LOG_LEVEL >= 3
#define log_warning _log_warning
#else
#define log_warning(...)
#endif
#if COMPILE_LOG_LEVEL >= 2
#define log_error _log_error
#else
#define log_error(...)
#endif
#if COMPILE_LOG_LEVEL >= 1
#define log_game _log_game
#else
#define log_game(...)
#endif

View File

@ -29,6 +29,7 @@ _LF(Devices, PCA9535, "pca9535")
_LF(Devices, Eeprom, "eeprom")
_LF(Devices, MaiTouch, "maitouch")
_LF(Devices, MaiLED, "mailed")
_LF(Devices, Servo15069, "servo15069")
_LF(Drivers, Columba, "columba")
_LF(Drivers, MxJvs, "mxjvs")

View File

@ -2,6 +2,7 @@ mice_lib = static_library(
'mice',
sources: [
'exe.c',
'log.c',
'patch.c',
'ringbuf.c',
'config.c',

View File

@ -3,11 +3,12 @@
#include <Windows.h>
#include <stdlib.h>
#include "config.h"
#include "../am/am.h"
#include "../ami/ami.h"
#include "config.h"
#include "exe.h"
#include "ioctl.h"
#include "log.h"
#include "patch.h"
#include "ringbuf.h"
#include "version_fallback.h"

View File

@ -103,7 +103,7 @@ MXK_STATUS mxkAbGameId(MXK_CACHE cache, char* gameId, unsigned char* err) {
AppBoot.m_cacheDirty = true;
}
MXK_STATUS status;
MXK_STATUS status = MXK_STATUS_ERROR;
if (!AppBoot.m_useFlash) {
// if (HAS_N2 == true) {
// status = mxkGetKeychipIdFromN2();

View File

@ -25,7 +25,7 @@ pcpa_callback mxkPcpStatus;
pcpa_callback mxkPcpDsCompute;
pcpa_callback mxkPcpSsdProof;
pcpa_callback mxkPcpSsdHostProof;
pcpa_callback mkxPcpEncrypt;
pcpa_callback mxkPcpEncrypt;
pcpa_callback mxkPcpDecrypt;
pcpa_callback mxkPcpSetIv;

View File

@ -3,7 +3,7 @@
void mxkPcpDsCompute(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
void mxkPcpSsdProof(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
void mxkPcpSsdHostProof(pcpa_t* stream, void* data) {}
void mkxPcpEncrypt(pcpa_t* stream, void* data) {
void mxkPcpEncrypt(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, KC_ENCRYPT, "B6787E941C3956EAC70095D6A91E635C");
}
void mxkPcpDecrypt(pcpa_t* stream, void* data) {

View File

@ -0,0 +1,87 @@
#include "mxk.h"
config_t Config = {
#define CFG_str(s, n, default, comment) .s##_##n = default,
#define CFG_bool(s, n, default, comment) .s##_##n = default,
#define CFG_int(s, n, default, comment) .s##_##n = default,
#define CFG_hex(s, n, precision, default, comment) .s##_##n = 0x##default,
#include "config.def"
._keep_linter_happy = true
};
void mxkMakeDefaultConfig() {
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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", comment); \
fprintf(config_file, "[%s]\n", #s);
#define HEADER(comment) \
fprintf(config_file, "; %s\n", comment); \
first_section = false;
#include "config.def"
fclose(config_file);
}
static 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 mxkLoadConfig() {
if (ini_parse(CONFIG_PATH, handler, &Config) < 0)
printf("Can't load '%s', using defaults\n", CONFIG_PATH);
}

View File

@ -21,7 +21,7 @@ SECTION(appboot, "")
CFG_str(appboot, gameid, "SDEY", "4-letter game ID this keychip is for")
CFG_hex(appboot, systemflag, 2, 6C, "System flags")
CFG_int(appboot, modeltype, 2, "System model this keychip is for")
CFG_int(appboot, formattype, 1, "Not totally sure about this")
CFG_int(appboot, formattype, 1, "")
CFG_int(appboot, region, 1, "Region bitmask\n; 8 4 2 1\n; CN EX US JP")
CFG_str(appboot, platformid, "AAS", "The platform this keychip is for. AAM=AMD, AAS=Nvidia")
CFG_str(appboot, network, "192.168.103.0", "The subnet this keychip allows for networking. Must be 192.168.103.0 for network checks to pass")

View File

@ -12,3 +12,6 @@ typedef struct config {
} config_t;
extern config_t Config;
void mxkMakeDefaultConfig();
void mxkLoadConfig();

View File

@ -1,106 +1,5 @@
#include "mxk.h"
config_t Config = {
#define CFG_str(s, n, default, comment) .s##_##n = default,
#define CFG_bool(s, n, default, comment) .s##_##n = default,
#define CFG_int(s, n, default, comment) .s##_##n = default,
#define CFG_hex(s, n, precision, default, comment) .s##_##n = 0x##default,
#include "config.def"
._keep_linter_happy = true};
static 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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", 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(config_file, "; %s\n", comment); \
fprintf(config_file, "[%s]\n", #s);
#define HEADER(comment) \
fprintf(config_file, "; %s\n", comment); \
first_section = false;
#include "config.def"
fclose(config_file);
}
static 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_config() {
if (ini_parse(CONFIG_PATH, handler, &Config) < 0) printf("Can't load '%s', using defaults\n", CONFIG_PATH);
}
int mxkMain() {
DWORD dwAttrib = GetFileAttributes(CONFIG_PATH);
if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) make_default_config();
load_config();
int err = mxkInit();
if (err != 0) {
PCP_LOG("Error mxkInit. Code %d\n", err);
return -1;
}
while (1) {
err = mxkPcpServer();
if (err != e_pcpp_ok) PCP_LOG("Server tick: %d\n", err);
}
}
int main() {
return mxkMain();
}

View File

@ -4,8 +4,8 @@ link_with = [inih.get_variable('lib_inih'), libpcp]
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
sources = [
'main.c',
'mxk.c',
'config.c',
'callbacks/appboot.c',
'callbacks/billing.c',
'callbacks/crypto.c',
@ -22,7 +22,7 @@ mxk = static_library(
executable(
'micekeychip',
win_subsystem: subsystem,
sources: sources,
sources: sources + ['main.c'],
link_with: link_with,
dependencies: dependencies,
)

View File

@ -7,7 +7,7 @@ pcpa_cb_table_t CALLBACK_FUNCTION_BUFFER[40];
byte BINARY_DATA[4096];
size_t BINARY_DATA_LEN;
void mxkBinaryCallback(pcpa_t* stream, void* data) {
void mxkBinaryCallback(pcpa_t *stream, void *data) {
pcpaSetSendBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN);
}
@ -24,11 +24,11 @@ int mxkInit() {
return err;
}
void log_callback(struct pcpa* stream, void* data) {
FILE* log_file;
void log_callback(struct pcpa *stream, void *data) {
FILE *log_file;
fopen_s(&log_file, "pcp.log", "a");
if (log_file != NULL) {
fprintf(log_file, "%s\n", (char*)data);
fprintf(log_file, "%s\n", (char *)data);
fclose(log_file);
}
}
@ -38,7 +38,7 @@ e_pcpa_t mxkPcpStreamInit() {
err = pcpaInitStream(&PCP);
if (err != e_pcpa_ok) {
printf("pcpaInitStream Error. Code:%d\n", err);
amiDebugLog("pcpaInitStream Error. Code:%d", err);
return err;
}
PCP.before_cb = log_callback;
@ -47,7 +47,7 @@ e_pcpa_t mxkPcpStreamInit() {
&PCP, CALLBACK_FUNCTION_BUFFER,
(sizeof CALLBACK_FUNCTION_BUFFER) / (sizeof CALLBACK_FUNCTION_BUFFER[0]));
if (err != e_pcpa_ok) {
printf("pcpaSetCallBackFuncBuffer Error. Code:%d\n", err);
amiDebugLog("pcpaSetCallBackFuncBuffer Error. Code:%d", err);
return err;
}
@ -58,7 +58,7 @@ e_pcpa_t mxkPcpStreamInit() {
pcpaSetCallbackFunc(&PCP, DS_COMPUTE, mxkPcpDsCompute, NULL);
pcpaSetCallbackFunc(&PCP, SSD_PROOF, mxkPcpSsdProof, NULL);
pcpaSetCallbackFunc(&PCP, SSD_HOSTPROOF, mxkPcpSsdHostProof, NULL);
pcpaSetCallbackFunc(&PCP, KC_ENCRYPT, mkxPcpEncrypt, NULL);
pcpaSetCallbackFunc(&PCP, KC_ENCRYPT, mxkPcpEncrypt, NULL);
pcpaSetCallbackFunc(&PCP, KC_DECRYPT, mxkPcpDecrypt, NULL);
pcpaSetCallbackFunc(&PCP, KC_SETIV, mxkPcpSetIv, NULL);
// Appboot
@ -100,12 +100,12 @@ e_pcpa_t mxkPcpStreamInit() {
long text_port = Config.pcp_control_port;
if (text_port > 0xffff) {
puts("PCP control port invalid");
amiDebugLog("PCP control port invalid");
exit(-1);
}
long binary_port = Config.pcp_binary_port;
if (binary_port > 0xffff) {
puts("PCP binary port invalid");
amiDebugLog("PCP binary port invalid");
exit(-1);
}
int open_mode = Config.pcp_bind_global ? OPEN_MODE_GLOBAL : OPEN_MODE_LOCAL;
@ -113,13 +113,13 @@ e_pcpa_t mxkPcpStreamInit() {
err =
pcpaOpenServerWithBinary(&PCP, open_mode, text_port & 0xffff, binary_port & 0xffff, 300000);
if (err != e_pcpa_ok && err != e_pcpa_to) {
printf("pcpaOpenServerWithBinary Error. Code %d\n", err);
amiDebugLog("pcpaOpenServerWithBinary Error. Code %d", err);
return e_pcpa_not_open;
}
if (open_mode == OPEN_MODE_GLOBAL)
printf("Listening on 0.0.0.0:%d (:%d)\n", text_port & 0xffff, binary_port & 0xffff);
amiDebugLog("Listening on 0.0.0.0:%d (:%d)", text_port & 0xffff, binary_port & 0xffff);
else
printf("Listening on 127.0.0.1:%d (:%d)\n", text_port & 0xffff, binary_port & 0xffff);
amiDebugLog("Listening on 127.0.0.1:%d (:%d)", text_port & 0xffff, binary_port & 0xffff);
return e_pcpa_ok;
}
@ -147,7 +147,7 @@ e_pcpa_t mxkPcpServer() {
if (err == e_pcpa_to || err == e_pcpa_closed) err = e_pcpa_ok;
if (err) {
printf("Error pcpaServer. Code %d\n", err);
amiDebugLog("Error pcpaServer. Code %d", err);
pcpaClose(&PCP);
SERVER_STATE = 1;
}
@ -160,4 +160,23 @@ e_pcpa_t mxkPcpServer() {
#endif
return err;
}
}
int mxkMain(void) {
DWORD dwAttrib = GetFileAttributes(CONFIG_PATH);
if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
mxkMakeDefaultConfig();
mxkLoadConfig();
int err = mxkInit();
if (err != 0) {
amiDebugLog("Error mxkInit. Code %d", err);
return -1;
}
while (1) {
err = mxkPcpServer();
if (err != e_pcpp_ok) amiDebugLog("Server tick: %d", err);
}
}

View File

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

View File

@ -0,0 +1,100 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
#include "../../lib/util/hex.h"
#include "callbacks.h"
// dummykeychip is not intended to be used in a production system. Therefore, we need only pick
// values here that will allow us to run game data. The only game I have observed requiring specific
// encryption and decryption results is Border Break, and as such those are the keys loaded here. If
// other games end up doing this, a more thorough alternative will be implemented.
static const unsigned char seed[16] = { 0xdb, 0x86, 0x37, 0x3a, 0x5a, 0x2e, 0x05, 0xb9,
0x63, 0xc2, 0x82, 0xd7, 0x89, 0x12, 0x8d, 0x0d };
static const unsigned char key[16] = { 0x6a, 0xcb, 0x8d, 0xc9, 0x00, 0x49, 0x92, 0x7a,
0xea, 0xcf, 0x71, 0xc9, 0x74, 0x0b, 0x6f, 0xf9 };
static const unsigned char iv[16] = { 0xa4, 0x7a, 0x66, 0x8e, 0xc0, 0xda, 0x67, 0x5e,
0x10, 0xe3, 0xa3, 0xeb, 0xe5, 0x32, 0x8c, 0xf0 };
EVP_CIPHER_CTX* ctxEnc = NULL;
EVP_CIPHER_CTX* ctxDec = NULL;
void mdkPcpAbSeed(pcpa_t* stream, void* data) {
pcpaSetBinaryMode(stream, binary_mode_send);
pcpaSetSendBinaryBuffer(stream, seed, 16);
pcpaSetSendPacket(stream, AB_SEED, "0");
pcpaAddSendPacket(stream, "port", "40107");
pcpaAddSendPacket(stream, "size", "16");
}
void mdkPcpDsCompute(pcpa_t* stream, void* data) {
// TODO: We could, and maybe should, scan for %s_Table.dat files, and use one if we find it
pcpaSetSendPacket(stream, DS_COMPUTE, "");
pcpaAddSendPacket(stream, "code", "54");
}
void mdkPcpSsdProof(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, SSD_PROOF, "0");
pcpaAddSendPacket(stream, "code", "54");
}
void mdkPcpSsdHostProof(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, SSD_HOSTPROOF, "0");
pcpaAddSendPacket(stream, "code", "54");
}
void mdkPcpEncrypt(pcpa_t* stream, void* data) {
char* ptHex = pcpaGetCommand(stream, KC_ENCRYPT);
unsigned char pt[16];
memset(pt, 0, sizeof(pt));
hex_to_bin(ptHex, pt, strlen(ptHex) > 32 ? 32 : strlen(ptHex));
if (ctxEnc == NULL) {
ctxEnc = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(ctxEnc, EVP_aes_128_cbc(), NULL, key, iv, 1);
}
int outl;
unsigned char ct[16];
memset(ct, 0, sizeof(ct));
EVP_EncryptUpdate(ctxEnc, ct, &outl, pt, 16);
char ctHex[33];
bin_to_hex(ctHex, ct, 16);
pcpaSetSendPacket(stream, KC_ENCRYPT, ctHex);
}
unsigned char workingIv[16];
void mdkPcpDecrypt(pcpa_t* stream, void* data) {
char* ctHex = pcpaGetCommand(stream, KC_DECRYPT);
unsigned char ct[16];
memset(ct, 0, sizeof(ct));
hex_to_bin(ctHex, ct, strlen(ctHex) > 32 ? 32 : strlen(ctHex));
if (ctxDec == NULL) {
ctxDec = EVP_CIPHER_CTX_new();
memcpy(workingIv, iv, 16);
} else {
EVP_CIPHER_CTX_cleanup(ctxDec);
}
EVP_CipherInit_ex(ctxDec, EVP_aes_128_cbc(), NULL, key, workingIv, 0);
memcpy(workingIv, ct, 16);
int outl = 0;
unsigned char pt[16];
memset(pt, 0, sizeof(pt));
EVP_DecryptUpdate(ctxDec, pt, &outl, ct, 16);
char ptHex[33];
bin_to_hex(ptHex, pt, 16);
pcpaSetSendPacket(stream, KC_DECRYPT, ptHex);
}
void mdkPcpSetIv(pcpa_t* stream, void* data) {
if (ctxEnc != NULL) {
EVP_CIPHER_CTX_cleanup(ctxEnc);
} else {
ctxEnc = EVP_CIPHER_CTX_new();
}
EVP_CipherInit_ex(ctxEnc, EVP_aes_128_cbc(), NULL, key, iv, 1);
memcpy(workingIv, iv, 16);
pcpaSetSendPacket(stream, KC_SETIV, "1");
}

View File

@ -0,0 +1,53 @@
#include "callbacks.h"
void mdkPcpVersion(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, KC_VERSION, "0104"); }
void mdkPcpStatus(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, KC_STATUS, "available"); }
void mdkPcpAbGameId(pcpa_t* stream, void* data) {
// TODO: Can we do better?
pcpaSetSendPacket(stream, AB_GAMEID, "----");
}
void mdkPcpAbSystemFlag(pcpa_t* stream, void* data) {
// systemflag 24 = billing + allnet, which should suffice for everything
pcpaSetSendPacket(stream, AB_SYSTEMFLAG, "24");
}
void mdkPcpAbModelType(pcpa_t* stream, void* data) {
// ST
pcpaSetSendPacket(stream, AB_MODELTYPE, "2");
}
void mdkPcpAbFormatType(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, AB_FORMATTYPE, "1");
}
void mdkPcpAbRegion(pcpa_t* stream, void* data) {
// All regions
pcpaSetSendPacket(stream, AB_REGION, "FF");
}
void mdkPcpAbPlatformId(pcpa_t* stream, void* data) {
// TODO: We _can_ do better here
pcpaSetSendPacket(stream, AB_PLATFORMID, "AAS");
}
void mdkPcpAbNetworkAddress(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, AB_NETWORKADDRESS, "192.168.103.0");
}
void mdkPcpAbDvd(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, AB_DVD, "01");
}
void mdkPcpPbKeyId(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, BIL_KEYID, "A72E-01A00000000");
}
void mdkPcpPbMainId(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, BIL_MAINID, "");
}
void mdkPcpPbPlayCount(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, BIL_PLAYCOUNT, "00000000");
}
void mdkPcpPbPlayLimit(pcpa_t* stream, void* data) {
// 8192 plays before checkin
pcpaSetSendPacket(stream, BIL_PLAYLIMIT, "00002000");
}
void mdkPcpPbNearfull(pcpa_t* stream, void* data) {
// Accounting mode = 1, nearfull = 512
pcpaSetSendPacket(stream, BIL_NEARFULL, "00010200");
}

View File

@ -0,0 +1,94 @@
#include "../../lib/libpcp/libpcp.h"
pcpa_callback mdkBinaryCallback;
extern byte BINARY_DATA[4096];
extern size_t BINARY_DATA_LEN;
#define KEYCHIP "keychip."
#define APPBOOT KEYCHIP##"appboot."
#define BILLING KEYCHIP##"billing."
#define TRACEDATA KEYCHIP##"tracedata."
// Misc
#define KC_VERSION KEYCHIP##"version"
#define KC_STATUS KEYCHIP##"status"
pcpa_callback mdkPcpVersion;
pcpa_callback mdkPcpStatus;
// Crypto
#define DS_COMPUTE KEYCHIP##"ds.compute"
#define SSD_PROOF KEYCHIP##"ssd.proof"
#define SSD_HOSTPROOF KEYCHIP##"ssd.hostproof"
#define KC_ENCRYPT KEYCHIP##"encrypt"
#define KC_DECRYPT KEYCHIP##"decrypt"
#define KC_SETIV KEYCHIP##"setiv"
pcpa_callback mdkPcpDsCompute;
pcpa_callback mdkPcpSsdProof;
pcpa_callback mdkPcpSsdHostProof;
pcpa_callback mdkPcpEncrypt;
pcpa_callback mdkPcpDecrypt;
pcpa_callback mdkPcpSetIv;
// Appboot
#define AB_GAMEID APPBOOT##"gameid"
#define AB_SYSTEMFLAG APPBOOT##"systemflag"
#define AB_MODELTYPE APPBOOT##"modeltype"
#define AB_FORMATTYPE APPBOOT##"formattype"
#define AB_REGION APPBOOT##"region"
#define AB_PLATFORMID APPBOOT##"platformid"
#define AB_NETWORKADDRESS APPBOOT##"networkaddr"
#define AB_DVD APPBOOT##"dvdflag"
#define AB_SEED APPBOOT##"seed"
pcpa_callback mdkPcpAbGameId;
pcpa_callback mdkPcpAbSystemFlag;
pcpa_callback mdkPcpAbModelType;
pcpa_callback mdkPcpAbFormatType;
pcpa_callback mdkPcpAbRegion;
pcpa_callback mdkPcpAbPlatformId;
pcpa_callback mdkPcpAbNetworkAddress;
pcpa_callback mdkPcpAbDvd;
pcpa_callback mdkPcpAbSeed;
// Billing
#define BIL_KEYID BILLING##"keyid"
#define BIL_MAINID BILLING##"mainid"
#define BIL_PLAYCOUNT BILLING##"playcount"
#define BIL_PLAYLIMIT BILLING##"playlimit"
#define BIL_NEARFULL BILLING##"nearfull"
#define BIL_SIGNATURE BILLING##"signaturepubkey"
#define BIL_CACERT BILLING##"cacertification"
pcpa_callback mdkPcpPbKeyId;
pcpa_callback mdkPcpPbMainId;
pcpa_callback mdkPcpPbPlayCount;
pcpa_callback mdkPcpPbPlayLimit;
pcpa_callback mdkPcpPbNearfull;
pcpa_callback mdkPcpPbSignaturePubKey;
pcpa_callback mdkPcpPbCaCertification;
// Tracedata
#define TRA_RESTORE TRACEDATA##"restore"
#define TRA_PUT TRACEDATA##"put"
#define TRA_GET TRACEDATA##"get"
#define TRA_LOGICALERASE TRACEDATA##"logicalerase"
#define TRA_SECTOREERASE TRACEDATA##"sectorerase"
pcpa_callback mdkPcpTdRestore;
pcpa_callback mdkPcpTdPut;
pcpa_callback mdkPcpTdGet;
pcpa_callback mdkPcpTdLogicalErase;
pcpa_callback mdkPcpTdSectorErase;
// Storage
#define KC_EEPROM KEYCHIP##"eeprom"
#define KC_NVRAM KEYCHIP##"nvram"
#define KC_NVRAM0 KC_NVRAM##"0"
#define KC_NVRAM1 KC_NVRAM##"1"
#define KC_NVRAM2 KC_NVRAM##"2"
#define KC_NVRAM3 KC_NVRAM##"3"
#define KC_NVRAM4 KC_NVRAM##"4"
#define KC_NVRAM5 KC_NVRAM##"5"
#define KC_NVRAM6 KC_NVRAM##"6"
#define KC_NVRAM7 KC_NVRAM##"7"
#define KC_NVRAM8 KC_NVRAM##"8"
#define KC_NVRAM9 KC_NVRAM##"9"
pcpa_callback mdkPcpEeprom;
pcpa_callback mdkPcpNvram;

View File

@ -0,0 +1,118 @@
#include "dummykeychip.h"
#include "../../lib/ami/amiLog.h"
#include "../../lib/libpcp/libpcp.h"
#include "callbacks.h"
typedef struct {
pcpa_t m_pcp;
pcpa_cb_table_t m_pcpCallbacks[40];
} mdk_t;
void mdkBeforeCb(pcpa_t* stream, void* data) {}
e_pcpa_t mdkPcpStreamInit(mdk_t* mdk, unsigned short textPort, unsigned short binaryPort,
bool global) {
e_pcpa_t err;
err = pcpaInitStream(&mdk->m_pcp);
if (err != e_pcpa_ok) {
amiDebugLog("pcpaInitStream Error. Code:%d", err);
return err;
}
// mdk->m_pcp.before_cb = mdkBeforeCb;
err =
pcpaSetCallbackFuncBuffer(&mdk->m_pcp, mdk->m_pcpCallbacks, _countof(mdk->m_pcpCallbacks));
if (err != e_pcpa_ok) {
amiDebugLog("pcpaSetCallBackFuncBuffer Error. Code:%d", err);
return err;
}
// Misc
pcpaSetCallbackFunc(&mdk->m_pcp, KC_VERSION, mdkPcpVersion, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, KC_STATUS, mdkPcpStatus, NULL);
// Crypto
pcpaSetCallbackFunc(&mdk->m_pcp, DS_COMPUTE, mdkPcpDsCompute, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, SSD_PROOF, mdkPcpSsdProof, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, SSD_HOSTPROOF, mdkPcpSsdHostProof, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, KC_ENCRYPT, mdkPcpEncrypt, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, KC_DECRYPT, mdkPcpDecrypt, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, KC_SETIV, mdkPcpSetIv, NULL);
// Appboot
pcpaSetCallbackFunc(&mdk->m_pcp, AB_GAMEID, mdkPcpAbGameId, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_SYSTEMFLAG, mdkPcpAbSystemFlag, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_MODELTYPE, mdkPcpAbModelType, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_FORMATTYPE, mdkPcpAbFormatType, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_REGION, mdkPcpAbRegion, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_PLATFORMID, mdkPcpAbPlatformId, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_NETWORKADDRESS, mdkPcpAbNetworkAddress, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_DVD, mdkPcpAbDvd, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, AB_SEED, mdkPcpAbSeed, NULL);
// Billing
pcpaSetCallbackFunc(&mdk->m_pcp, BIL_KEYID, mdkPcpPbKeyId, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, BIL_MAINID, mdkPcpPbMainId, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, BIL_PLAYCOUNT, mdkPcpPbPlayCount, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, BIL_PLAYLIMIT, mdkPcpPbPlayLimit, NULL);
pcpaSetCallbackFunc(&mdk->m_pcp, BIL_NEARFULL, mdkPcpPbNearfull, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, BIL_SIGNATURE, mdkPcpPbSignaturePubKey, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, BIL_CACERT, mdkPcpPbCaCertification, NULL);
// Tracedata
// pcpaSetCallbackFunc(&mdk->m_pcp, TRA_RESTORE, mdkPcpTdRestore, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, TRA_PUT, mdkPcpTdPut, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, TRA_GET, mdkPcpTdGet, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, TRA_LOGICALERASE, mdkPcpTdLogicalErase, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, TRA_SECTOREERASE, mdkPcpTdSectorErase, NULL);
// Storage
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_EEPROM, mdkPcpEeprom, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM0, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM1, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM2, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM3, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM4, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM5, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM6, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM7, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM8, mdkPcpNvram, NULL);
// pcpaSetCallbackFunc(&mdk->m_pcp, KC_NVRAM9, mdkPcpNvram, NULL);
err = pcpaOpenServerWithBinary(&mdk->m_pcp, global ? OPEN_MODE_GLOBAL : OPEN_MODE_LOCAL,
textPort, binaryPort, 300000);
if (err != e_pcpa_ok && err != e_pcpa_to) {
amiDebugLog("pcpaOpenServerWithBinary Error. Code %d", err);
return e_pcpa_not_open;
}
if (global)
amiDebugLog("Listening on 0.0.0.0:%d (:%d)", textPort, binaryPort);
else
amiDebugLog("Listening on 127.0.0.1:%d (:%d)", textPort, binaryPort);
return e_pcpa_ok;
}
void miceDummyKeychip(unsigned short textPort, unsigned short binaryPort, bool global) {
mdk_t* mdk = malloc(sizeof *mdk);
e_pcpa_t err;
WSADATA wsaData;
if (WSAStartup(2, &wsaData)) {
amiDebugLog("WSAStartup Error. Code %d", GetLastError());
return;
}
err = mdkPcpStreamInit(mdk, textPort, binaryPort, global);
if (err != e_pcpa_ok) {
amiDebugLog("mdkPcpStreamInit Error. Code %d", err);
return;
}
while (1) {
err = pcpaServer(&mdk->m_pcp, 16);
if (err == e_pcpa_to || err == e_pcpa_closed) err = e_pcpa_ok;
if (err != e_pcpa_ok) {
amiDebugLog("Error pcpaServer. Code %d", err);
pcpaClose(&mdk->m_pcp);
return;
}
}
}

View File

@ -0,0 +1,3 @@
#include <stdbool.h>
void miceDummyKeychip(unsigned short textPort, unsigned short binaryPort, bool global);

View File

@ -0,0 +1,3 @@
#include "dummykeychip.h"
int main() { miceDummyKeychip(40106, 40107, false); }

View File

@ -0,0 +1,22 @@
link_with = [libpcp, amiDebug, util_lib]
sources = [
'callbacks-stub.c',
'callbacks-crypto.c',
'dummykeychip.c',
]
dummykeychip = static_library(
'dummykeychip',
sources: sources,
link_with: link_with,
include_directories: [openssl_inc],
dependencies: [openssl_lib],
)
executable(
'dummykeychip',
win_subsystem: subsystem,
sources: ['main.c'] + sources,
link_with: link_with,
include_directories: [openssl_inc],
dependencies: [openssl_lib],
)

View File

@ -1,2 +1,3 @@
subdir('dummykeychip')
subdir('dummymaster')
subdir('dummyinstaller')

View File

@ -71,3 +71,13 @@ executable(
'test.c',
],
)
executable(
'micegbdisk',
win_subsystem: subsystem,
sources: [
'micegbdisk.c',
],
link_with: [
amiDebug,
],
)

View File

@ -0,0 +1,388 @@
#include <Windows.h>
//
#include <Ntddscsi.h>
#include <stdio.h>
#define _CRT_RAND_S
#include <stdlib.h>
#include <winioctl.h>
#include "../dll/hooks/drive/irb.h"
#include "../lib/ami/amiDebug.h"
#define ATA_VENDOR_HOST_PROOF 0xC1
#define ATA_VENDOR_PROOF_DEVICE 0xC2
#define ATA_IDENTIFY_DEVICE 0xEC
#define ATA_SECURITY_UNLOCK 0xF2
#define ATA_SECURITY_FREEZE_LOCK 0xF5
#pragma pack(push, 1)
typedef struct {
UCHAR bFeaturesReg;
UCHAR bSectorCountReg;
UCHAR bSectorNumberReg;
UCHAR bCylLowReg;
UCHAR bCylHighReg;
UCHAR bDriveHeadReg;
UCHAR bCommandReg;
UCHAR bReserved;
} ATA_TASK_FILE_OUT;
typedef struct {
UCHAR bErrorReg;
UCHAR bSectorCountReg;
UCHAR bSectorNumberReg;
UCHAR bCylLowReg;
UCHAR bCylHighReg;
UCHAR bDriveHeadReg;
UCHAR bStatusReg;
UCHAR bReserved;
} ATA_TASK_FILE_IN;
typedef struct _ATA_PASS_THROUGH_EX_512 {
ATA_PASS_THROUGH_EX Ata;
UCHAR Data[512];
} ATA_PASS_THROUGH_EX_512, *PATA_PASS_THROUGH_EX_512;
typedef struct _ATA_PASS_THROUGH_EX_256 {
ATA_PASS_THROUGH_EX Ata;
UCHAR Data[256];
} ATA_PASS_THROUGH_EX_256, *PATA_PASS_THROUGH_EX_256;
#pragma pack(pop)
#define TASK_FILE_OUT(Ata) (*((ATA_TASK_FILE_OUT *)(void *)(&Ata.CurrentTaskFile)))
#define TASK_FILE_IN(Ata) (*((ATA_TASK_FILE_IN *)(void *)(&Ata.CurrentTaskFile)))
typedef enum {
mseOk = 0,
mseNg = -1,
mseInvalidParam = -2,
mseNoInit = -3,
mseAlreadyInit = -4,
mseDiskError = -5,
mseAtaDeviceError = -6,
} mxk_ssd_err_t;
HANDLE PD0_HANDLE = INVALID_HANDLE_VALUE;
BOOL PD0_HAS_INIT = FALSE;
mxk_ssd_err_t mxkGetSystemDiskNumber(DWORD *disk) {
// TODO: This
if (disk != NULL) *disk = 1;
return mseOk;
}
mxk_ssd_err_t mxkSsdInit(void) {
if (PD0_HAS_INIT) return mseAlreadyInit;
DWORD disk;
mxk_ssd_err_t err = mxkGetSystemDiskNumber(&disk);
if (err != mseOk) return mseDiskError;
char path[32] = { 0 };
sprintf_s(path, sizeof path, "\\\\.\\PhysicalDrive%d", disk);
amiDebugLog("Using disk: %s", path);
PD0_HANDLE = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (PD0_HANDLE == INVALID_HANDLE_VALUE) {
amiDebugLog("CreateFile Error : Error No = %d", GetLastError());
return mseDiskError;
}
PD0_HAS_INIT = TRUE;
return mseOk;
}
mxk_ssd_err_t mxkSsdExit(void) {
if (!PD0_HAS_INIT) return mseNoInit;
if (PD0_HANDLE != INVALID_HANDLE_VALUE) CloseHandle(PD0_HANDLE);
PD0_HAS_INIT = FALSE;
return mseOk;
}
mxk_ssd_err_t mxkAtaPioOutCommand(HANDLE hDrive, PATA_PASS_THROUGH_EX pAtaBuffer, UCHAR *data) {
ATA_PASS_THROUGH_EX response;
ATA_PASS_THROUGH_EX_512 request;
ZeroMemory(&request, sizeof request);
memcpy(&request.Ata, pAtaBuffer, sizeof request.Ata);
DWORD sendBytes;
if (data == NULL) {
sendBytes = sizeof request.Ata;
} else {
memcpy(request.Data, data, sizeof request.Data);
request.Ata.DataTransferLength = sizeof request.Data;
sendBytes = sizeof request;
}
request.Ata.Length = sizeof request.Ata;
request.Ata.DataBufferOffset = sizeof request.Ata;
request.Ata.AtaFlags = ATA_FLAGS_DATA_OUT;
request.Ata.TimeOutValue = 35;
DWORD dwBytesReturned = 0;
BOOL bResult = DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, &request, sendBytes, &response,
sizeof response, &dwBytesReturned, NULL);
memcpy(pAtaBuffer, &response, sizeof response);
if (!bResult || (TASK_FILE_IN(response).bStatusReg & 1) != 0) {
amiDebugLog("Error DeviceIoControl() : %d/%02x:%02x", GetLastError(),
TASK_FILE_IN(response).bStatusReg, TASK_FILE_IN(response).bErrorReg);
return mseAtaDeviceError;
}
return mseOk;
}
mxk_ssd_err_t mxkAtaPioInCommand(HANDLE hDrive, PATA_PASS_THROUGH_EX pAtaBuffer, UCHAR *dataOut) {
ATA_PASS_THROUGH_EX request;
ATA_PASS_THROUGH_EX_512 response;
ZeroMemory(&response.Ata, sizeof response.Ata);
memcpy(&request, pAtaBuffer, sizeof request);
request.Length = sizeof request;
request.DataBufferOffset = sizeof request;
request.AtaFlags = ATA_FLAGS_DATA_IN;
request.TimeOutValue = 5;
DWORD dwBytesReturned = 0;
BOOL bResult = DeviceIoControl(hDrive, IOCTL_ATA_PASS_THROUGH, &request, sizeof request,
&response, sizeof response, &dwBytesReturned, NULL);
memcpy(pAtaBuffer, &response, sizeof response.Ata);
if (!bResult || (TASK_FILE_IN(response.Ata).bStatusReg & 1) != 0) {
amiDebugLog("Error DeviceIoControl() : %d", GetLastError());
return mseAtaDeviceError;
}
memcpy(dataOut, response.Data, sizeof response.Data);
return mseOk;
}
mxk_ssd_err_t mxkSsdDeviceProofSet(UCHAR *data) {
ATA_PASS_THROUGH_EX request;
UCHAR localData[512];
if (!PD0_HAS_INIT) return mseNoInit;
if (data == NULL) return mseInvalidParam;
ZeroMemory(&request, sizeof request);
memcpy(localData, data, 128);
TASK_FILE_OUT(request).bCommandReg = ATA_VENDOR_PROOF_DEVICE;
TASK_FILE_OUT(request).bFeaturesReg = 17;
return mxkAtaPioOutCommand(PD0_HANDLE, &request, localData);
}
mxk_ssd_err_t mxkSsdDeviceProofGet(UCHAR *data) {
ATA_PASS_THROUGH_EX request;
UCHAR buffer[512];
if (!PD0_HAS_INIT) return mseNoInit;
if (data == NULL) return mseInvalidParam;
ZeroMemory(&request, sizeof request);
TASK_FILE_OUT(request).bCommandReg = ATA_VENDOR_PROOF_DEVICE;
TASK_FILE_OUT(request).bFeaturesReg = 18;
request.DataTransferLength = sizeof buffer;
mxk_ssd_err_t err = mxkAtaPioInCommand(PD0_HANDLE, &request, buffer);
if (err != 0) return err;
memcpy(data, buffer, 128);
return mseOk;
}
#define SSD_PROOF_NBYTES 16
int mxkSsdProofDevice(UCHAR *seed, UCHAR *response, UCHAR *code) {
UCHAR workBuf[128];
if (response == NULL || seed == NULL) {
if (code != NULL) *code = 54;
return 3;
}
if (code == NULL) return 3;
*code = 0;
memcpy_s(workBuf, sizeof workBuf, seed, SSD_PROOF_NBYTES);
unsigned int randVal;
for (int i = SSD_PROOF_NBYTES; i < sizeof workBuf; i++) {
rand_s(&randVal);
workBuf[i] = randVal & 0xFF;
}
mxk_ssd_err_t err;
err = mxkSsdDeviceProofSet(workBuf);
if (err != mseOk) {
amiDebugLog("Error mxkSsdDeviceProofSet()!!! Code:%d", err);
*code = 2;
return 1;
}
ZeroMemory(workBuf, sizeof workBuf);
err = mxkSsdDeviceProofGet(workBuf);
if (err != mseOk) {
amiDebugLog("Error mxkSsdDeviceProofGet()!!! Code:%d", err);
*code = 2;
return 1;
}
memcpy_s(response, SSD_PROOF_NBYTES, workBuf, SSD_PROOF_NBYTES);
return 0;
}
mxk_ssd_err_t mxkSsdSecurityUnlock(UCHAR *password, DWORD nPassword, BOOL userPassword) {
ATA_PASS_THROUGH_EX request;
UCHAR localData[512];
if (!PD0_HAS_INIT) return mseNoInit;
if (password == NULL) return mseInvalidParam;
ZeroMemory(&request, sizeof request);
ZeroMemory(localData, sizeof localData);
if (userPassword)
localData[0] = 0x00;
else
localData[0] = 0x01;
memcpy_s(localData + 2, sizeof localData, password, nPassword);
TASK_FILE_OUT(request).bCommandReg = ATA_SECURITY_UNLOCK;
return mxkAtaPioOutCommand(PD0_HANDLE, &request, localData);
}
mxk_ssd_err_t mxkSsdIdentify(PIDENTIFY_DEVICE_DATA response) {
if (!PD0_HAS_INIT) return mseNoInit;
if (response == NULL) return mseInvalidParam;
ATA_PASS_THROUGH_EX_256 ata = { 0 };
ata.Ata.Length = sizeof ata.Ata;
ata.Ata.AtaFlags = ATA_FLAGS_DATA_IN | ATA_FLAGS_DRDY_REQUIRED;
ata.Ata.DataTransferLength = sizeof ata.Data;
ata.Ata.DataBufferOffset = sizeof ata.Ata;
ata.Ata.TimeOutValue = 10;
ata.Ata.CurrentTaskFile[6] = ATA_IDENTIFY_DEVICE;
ata.Ata.CurrentTaskFile[7] = 0;
DWORD dwBytesReturned = 0;
BOOL bResult = DeviceIoControl(PD0_HANDLE, IOCTL_ATA_PASS_THROUGH, &ata, sizeof(ata), &ata,
sizeof(ata), &dwBytesReturned, NULL);
if (!bResult) {
amiDebugLog("Error DeviceIoControl() : %d", GetLastError());
return mseAtaDeviceError;
}
memcpy(response, ata.Data, sizeof ata.Data);
return mseOk;
}
void printf_word_string(UCHAR *wordString, DWORD nShorts) {
while (nShorts--) {
printf("%c", wordString[1]);
printf("%c", wordString[0]);
wordString += 2;
}
}
void printIdentity(PIDENTIFY_DEVICE_DATA identity) {
puts("[ Identification ]");
printf("Serial number : ");
printf_word_string(identity->SerialNumber, 10);
printf("\nModel number : ");
printf_word_string(identity->ModelNumber, 20);
puts("\n[ Security ]");
printf(" Supported : %s\n", identity->SecurityStatus.SecuritySupported ? "YES" : "NO");
printf(" Enabled : %s\n", identity->SecurityStatus.SecurityEnabled ? "YES" : "NO");
printf(" Frozen : %s\n", identity->SecurityStatus.SecurityFrozen ? "YES" : "NO");
printf(" Locked : %s\n", identity->SecurityStatus.SecurityLocked ? "YES" : "NO");
printf(" # Expired : %s\n", identity->SecurityStatus.SecurityCountExpired ? "YES" : "NO");
printf(" Master Pass : %s\n", identity->SecurityStatus.SecurityLevel ? "Maximum" : "High");
}
int main(int argc, char **argv) {
puts("mice GBDisk utility tool.");
printf("Opening drive\n");
mxk_ssd_err_t err;
err = mxkSsdInit();
if (err != mseOk) {
printf("Failed to open SSD: %d\n", err);
return 1;
}
puts("Requesting identity");
IDENTIFY_DEVICE_DATA identity;
err = mxkSsdIdentify(&identity);
if (err != mseOk) {
printf("Failed to identify: %d\n", err);
mxkSsdExit();
return 1;
}
printIdentity(&identity);
if (!identity.SecurityStatus.SecurityLocked) {
puts("Security is not enabled. Nothing to do!");
mxkSsdExit();
return 0;
}
if (identity.SecurityStatus.SecurityFrozen) {
puts("Security is frozen. We have no hope of unlocking this drive!");
mxkSsdExit();
return 2;
}
puts("Sending security unlock");
UCHAR password[32] = {
0x72, 0x42, 0x52, 0x5A, 0xBA, 0x52, 0x6A, 0x5A, 0xEA, 0x72, 0x62,
0x78, 0xCA, 0x42, 0xDA, 0x4A, 0x2A, 0x22, 0x3A, 0x2A, 0x0A, 0x22,
0x1A, 0x2A, 0x6A, 0x02, 0x7A, 0x0A, 0x5C, 0xCE, 0x4A, 0x0A,
};
err = mxkSsdSecurityUnlock(password, sizeof password, TRUE);
printf("Security unlock result: %d\n", err);
mxkSsdExit();
return 0;
}
// int main() {
// HANDLE hDevice = CreateFile("\\\\.\\PhysicalDrive1", GENERIC_READ | GENERIC_WRITE,
// FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0,
// NULL);
// if (hDevice == INVALID_HANDLE_VALUE) {
// printf("Error: could not open device\n");
// return 1;
// }
// ATA_PASS_THROUGH_EX_256 ata = { 0 };
// ata.Ata.Length = sizeof ata.Ata;
// ata.Ata.AtaFlags = ATA_FLAGS_DATA_IN | ATA_FLAGS_DRDY_REQUIRED;
// ata.Ata.DataTransferLength = 256;
// ata.Ata.DataBufferOffset = sizeof ata.Ata;
// ata.Ata.TimeOutValue = 10;
// ata.Ata.CurrentTaskFile[6] = ATA_IDENTIFY_DEVICE;
// ata.Ata.CurrentTaskFile[7] = 0;
// DWORD dwBytesReturned = 0;
// BOOL bResult = DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH, &ata, sizeof(ata), &ata,
// sizeof(ata), &dwBytesReturned, NULL);
// if (!bResult) {
// printf("Error: could not send IDENTIFY DEVICE request %d\n", GetLastError());
// CloseHandle(hDevice);
// return 1;
// }
// for (int i = 0; i < 256; i++) {
// printf(" %02x", ata.Data[i]);
// if (i % 32 == 31) {
// printf(" ");
// for (int j = i - 31; j <= i; j++) {
// if (10 <= ata.Data[j] && ata.Data[j] < 128)
// printf("%c", ata.Data[j]);
// else
// printf(".");
// }
// puts("");
// }
// }
// }