Insane amount of stuff including a bunch of amlib
This commit is contained in:
parent
52a66a2623
commit
60ccfbede6
4
Makefile
4
Makefile
@ -52,6 +52,7 @@ dist:
|
||||
@-mkdir $(DIST_DIR)\Execute\S > NUL 2>&1
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micekeychip\micekeychip.exe" "$(DIST_DIR)/micekeychip.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micemaster\micemaster.exe" "$(DIST_DIR)/micemaster.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/lib/libpcp\libpcp.lib" "$(DIST_DIR)/libpcp.lib"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice86.exe"
|
||||
@ -66,11 +67,10 @@ dist:
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\TrueCrypt.exe" "$(DIST_DIR)/Execute/TrueCrypt.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\mxmaster.exe" "$(DIST_DIR)/Execute/S/mxmaster.exe"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/util/micepatch.exe"
|
||||
# @copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/util/micepatch.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\kcproxy.exe" "$(DIST_DIR)/util/kcproxy.exe"
|
||||
|
||||
@copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd"
|
||||
|
||||
|
11
meson.build
11
meson.build
@ -35,13 +35,14 @@ add_project_arguments(
|
||||
# Strip out as much crud as we can to keep XP builds small
|
||||
'/Os', '/EHc-', '/EHa-', '/EHs-', '/GL', '/GR-',
|
||||
|
||||
'/wd4706', # assignment within conditional expression
|
||||
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
|
||||
'/wd4201', # ewfapi.h: nameless struct/union
|
||||
'/wd4200', # zero-sized arrays
|
||||
'/wd4152', # hooks: function/data pointer conversion in expression
|
||||
'/wd4100', # basically every hook causes "unreferenced formal parameter"
|
||||
'/wd4152', # hooks: function/data pointer conversion in expression
|
||||
'/wd4200', # zero-sized arrays
|
||||
'/wd4201', # ewfapi.h: nameless struct/union
|
||||
'/wd4204', # non-constant aggregate initializer
|
||||
'/wd4206', # empty C files
|
||||
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
|
||||
'/wd4706', # assignment within conditional expression
|
||||
|
||||
'/wd4189', # lots of keychip functions aren't 100% implemented yet
|
||||
|
||||
|
@ -2,4 +2,9 @@ inih = subproject('inih_dep')
|
||||
cimgui = subproject('cimgui_dep', default_options: ['win32=enabled', 'dx9=enabled'])
|
||||
|
||||
libs_dir = meson.current_source_dir()
|
||||
|
||||
incdir = [
|
||||
include_directories('micetools'),
|
||||
]
|
||||
|
||||
subdir('micetools')
|
||||
|
212
src/micetools/amBackupStructs.h
Normal file
212
src/micetools/amBackupStructs.h
Normal file
@ -0,0 +1,212 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Flag;
|
||||
uint32_t m_IpAddress;
|
||||
uint32_t m_SubnetMask;
|
||||
uint32_t m_Gateway;
|
||||
uint32_t m_PrimaryDns;
|
||||
uint32_t m_SecondaryDns;
|
||||
} AM_SYSDATA_NETWORK_IF;
|
||||
|
||||
typedef struct {
|
||||
uint64_t m_TimeStamp;
|
||||
char GameId[4];
|
||||
uint16_t m_Error;
|
||||
uint8_t m_AppStartCount;
|
||||
uint8_t Rsv0f[17];
|
||||
} ERROR_LOG_BODY;
|
||||
|
||||
typedef struct {
|
||||
uint8_t ChuteType;
|
||||
uint8_t ServiceType;
|
||||
uint8_t Operation;
|
||||
uint8_t CoinRate[2];
|
||||
uint8_t BonusAdder;
|
||||
uint8_t CreditRate;
|
||||
uint8_t Cost[8];
|
||||
uint8_t Rsv0F;
|
||||
} AM_CREDIT_CONFIG;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Credit;
|
||||
uint8_t Remain;
|
||||
} AM_CREDIT_PDATA;
|
||||
|
||||
typedef struct {
|
||||
AM_CREDIT_PDATA Player[4];
|
||||
uint8_t Rsv08[8];
|
||||
} AM_CREDIT_DATA;
|
||||
|
||||
typedef struct {
|
||||
uint32_t CoinChute[4];
|
||||
uint32_t TotalCoin;
|
||||
uint32_t CoinCredit;
|
||||
uint32_t ServiceCredit;
|
||||
uint32_t TotalCredit;
|
||||
} AM_CREDIT_BOOKKEEPING;
|
||||
|
||||
typedef struct {
|
||||
uint8_t m_month;
|
||||
uint8_t m_week;
|
||||
uint8_t m_dayOfWeek;
|
||||
uint8_t m_hour;
|
||||
uint8_t m_minute;
|
||||
uint8_t m_rsv5[3];
|
||||
} alpbSysdataDst_T;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
AM_SYSDATA_NETWORK_IF m_Eth;
|
||||
} AM_SYSDATAwH_NETWORK;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[8];
|
||||
uint8_t m_Region;
|
||||
uint8_t m_Rental;
|
||||
uint8_t Rsv0F;
|
||||
char m_strSerialId[17];
|
||||
} AM_SYSDATAwH_STATIC;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
AM_CREDIT_CONFIG m_Config;
|
||||
uint8_t Rsv18[8];
|
||||
} AM_SYSDATAwH_CREDIT;
|
||||
|
||||
typedef AM_SYSDATAwH_NETWORK AM_SYSDATAwH_NETWORK_ETH0;
|
||||
typedef AM_SYSDATAwH_NETWORK AM_SYSDATAwH_NETWORK_ETH1;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
char m_GameId[4];
|
||||
uint8_t m_Region;
|
||||
uint8_t Rsv0D[3];
|
||||
} AM_SYSDATAwH_HISTORY;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
uint8_t m_WritePointer;
|
||||
uint8_t m_LogNum;
|
||||
uint8_t Rsv0a[22];
|
||||
ERROR_LOG_BODY m_Body[15];
|
||||
} AM_SYSDATAwH_ERROR_LOG;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
AM_CREDIT_DATA m_CreditData;
|
||||
AM_CREDIT_BOOKKEEPING m_Bookkeeping;
|
||||
uint8_t Rsv38[456];
|
||||
} AM_SYSDATAwH_BACKUP;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
alpbSysdataDst_T m_Daylight;
|
||||
alpbSysdataDst_T m_Standard;
|
||||
uint32_t m_Bias;
|
||||
uint32_t m_ServerBias;
|
||||
uint8_t Rsv20[480];
|
||||
} AM_SYSDATAwH_TIMEZONE;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
uint32_t m_Caution;
|
||||
uint32_t m_Peak;
|
||||
uint8_t Rsv10[496];
|
||||
} AM_SYSDATAwH_HM_PEAK;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint8_t Rsv04[4];
|
||||
uint8_t m_MountSleepS;
|
||||
uint8_t Rsv09[55];
|
||||
} AM_SYSDATAwH_ALPB_DEV_CONFIG;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint32_t m_Uk1;
|
||||
uint32_t m_Uk2;
|
||||
uint32_t m_Uk3;
|
||||
} AM_SYSDATAwH_ALPB_CARD_ID;
|
||||
|
||||
typedef struct {
|
||||
uint32_t m_Crc;
|
||||
uint32_t m_Uk1;
|
||||
uint32_t m_Uk2;
|
||||
uint32_t m_Uk3;
|
||||
uint32_t m_Uk4;
|
||||
uint32_t m_Uk5;
|
||||
uint32_t m_Uk6;
|
||||
uint32_t m_Uk7;
|
||||
} AM_SYSDATAwH_ALPB_COMPUTER_NAME;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define AM_SYSDATAwH_STATIC_REG 0x000
|
||||
#define AM_SYSDATAwH_STATIC_DUP 0x200
|
||||
#define AM_SYSDATAwH_CREDIT_REG 0x020
|
||||
#define AM_SYSDATAwH_CREDIT_DUP 0x220
|
||||
#define AM_SYSDATAwH_NETWORK_ETH0_REG 0x040
|
||||
#define AM_SYSDATAwH_NETWORK_ETH0_DUP 0x240
|
||||
#define AM_SYSDATAwH_NETWORK_ETH1_REG 0x060
|
||||
#define AM_SYSDATAwH_NETWORK_ETH1_DUP 0x260
|
||||
#define AM_SYSDATAwH_HISTORY_REG 0x080
|
||||
#define AM_SYSDATAwH_HISTORY_DUP 0x280
|
||||
#define AM_SYSDATAwH_ALPB_CARD_ID_REG 0x090
|
||||
#define AM_SYSDATAwH_ALPB_CARD_ID_DUP 0x290
|
||||
#define AM_SYSDATAwH_ALPB_COMPUTER_NAME_REG 0x0a0
|
||||
#define AM_SYSDATAwH_ALPB_COMPUTER_NAME_DUP 0x2a0
|
||||
#define AM_SYSDATAwH_ALPB_DEV_CONFIG_REG 0x0c0
|
||||
#define AM_SYSDATAwH_ALPB_DEV_CONFIG_DUP 0x2c0
|
||||
|
||||
/**
|
||||
* Storage locations:
|
||||
*
|
||||
* Static: (AM_SYSDATAwH_STATIC)
|
||||
* 0x000 - 0x01f, eeprom
|
||||
* 0x200 - 0x21f, eeprom
|
||||
* Credit: (AM_SYSDATAwH_CREDIT)
|
||||
* 0x020 - 0x03f, eeprom
|
||||
* 0x220 - 0x23f, eeprom
|
||||
* Network Eth0: (AM_SYSDATAwH_NETWORK_ETH0)
|
||||
* 0x040 - 0x05f, eeprom
|
||||
* 0x240 - 0x25f, eeprom
|
||||
* Network Eth1: (AM_SYSDATAwH_NETWORK_ETH1)
|
||||
* 0x060 - 0x07f, eeprom
|
||||
* 0x260 - 0x27f, eeprom
|
||||
* History: (AM_SYSDATAwH_HISTORY)
|
||||
* 0x080 - 0x08f, eeprom
|
||||
* 0x280 - 0x28f, eeprom
|
||||
* Alpb Card Id: (AM_SYSDATAwH_ALPB_CARD_ID)
|
||||
* 0x090 - 0x09f, eeprom
|
||||
* 0x290 - 0x29f, eeprom
|
||||
* Computer Name: (AM_SYSDATAwH_ALPB_COMPUTER_NAME)
|
||||
* 0x0a0 - 0x0bf, eeprom
|
||||
* 0x2a0 - 0x2bf, eeprom
|
||||
* Dev Config (AM_SYSDATAwH_ALPB_DEV_CONFIG)
|
||||
* 0x0c0 - 0x0ff, eeprom
|
||||
* 0x2c0 - 0x2ff, eeprom
|
||||
*
|
||||
* Backup: (AM_SYSDATAwH_BACKUP)
|
||||
* 0x0000 - 0x01ff, sram
|
||||
* 0x1000 - 0x11ff, sram
|
||||
* HM Peak: (AM_SYSDATAwH_HM_PEAK)
|
||||
* 0x0200 - 0x03ff, sram
|
||||
* 0x1200 - 0x13ff, sram
|
||||
* Timezone: (AM_SYSDATAwH_TIMEZONE)
|
||||
* 0x0400 - 0x05ff, sram
|
||||
* 0x1400 - 0x15ff, sram
|
||||
* Error Log: (AM_SYSDATAwH_ERROR_LOG)
|
||||
* 0x0600 - 0x07ff, sram
|
||||
* 0x1600 - 0x17ff, sram
|
||||
*/
|
@ -1,25 +1,29 @@
|
||||
#include "comdevice.h"
|
||||
|
||||
BOOL DevGetCommState(void* data, LPDCB lpDCB) { return TRUE; }
|
||||
BOOL DevSetCommState(void* data, LPDCB lpDCB) { return TRUE; }
|
||||
BOOL DevGetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; }
|
||||
BOOL DevSetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; }
|
||||
BOOL DevSetupComm(void* data, DWORD dwInQueue, DWORD dwOutQueue) { return TRUE; }
|
||||
BOOL DevPurgeComm(void* data, DWORD dwFlags) {
|
||||
if (dwFlags & PURGE_RXCLEAR) ringbuf_purge(&((com_device_t*)data)->out);
|
||||
com_device_t* GetComDevice(HANDLE hFile) {
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
return pHData->hook->com_hook->com_device;
|
||||
}
|
||||
|
||||
BOOL DevGetCommState(HANDLE hFile, LPDCB lpDCB) { return TRUE; }
|
||||
BOOL DevSetCommState(HANDLE hFile, LPDCB lpDCB) { return TRUE; }
|
||||
BOOL DevGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; }
|
||||
BOOL DevSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; }
|
||||
BOOL DevSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) { return TRUE; }
|
||||
BOOL DevPurgeComm(HANDLE hFile, DWORD dwFlags) {
|
||||
if (dwFlags & PURGE_RXCLEAR) ringbuf_purge(&(GetComDevice(hFile)->out));
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevGetCommModemStatus(void* data, LPDWORD lpModelStat) {
|
||||
BOOL DevGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
|
||||
// TODO: JVS SENSE
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevWaitCommEvent(void* data, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
||||
WaitForSingleObject(((com_device_t*)data)->event, INFINITE);
|
||||
BOOL DevWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
||||
WaitForSingleObject(GetComDevice(hFile)->event, INFINITE);
|
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
BOOL DevClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
if (lpErrors != NULL) *lpErrors = 0;
|
||||
if (lpStat != NULL) {
|
||||
lpStat->fCtsHold = FALSE;
|
||||
@ -30,30 +34,30 @@ BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
lpStat->fEof = FALSE;
|
||||
lpStat->fTxim = FALSE;
|
||||
lpStat->fReserved = 0;
|
||||
lpStat->cbInQue = ringbuf_available(&((com_device_t*)data)->out);
|
||||
lpStat->cbOutQue = ringbuf_available(&((com_device_t*)data)->in);
|
||||
lpStat->cbInQue = ringbuf_available(&(GetComDevice(hFile)->out));
|
||||
lpStat->cbOutQue = ringbuf_available(&(GetComDevice(hFile)->in));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
BOOL DevWriteFile(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToWrite > 0xffff) return FALSE;
|
||||
// Ignore overflow
|
||||
ringbuf_write(&((com_device_t*)file)->in, lpBuffer, nNumberOfBytesToWrite & 0xffff);
|
||||
ringbuf_write(&(GetComDevice(ctx->m_Handle)->in), lpBuffer, nNumberOfBytesToWrite & 0xffff);
|
||||
if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
BOOL DevReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToRead > 0xffff) return FALSE;
|
||||
|
||||
com_device_t* comdev = GetComDevice(ctx->m_Handle);
|
||||
// Make sure we have at least one byte to return
|
||||
// while (!ringbuf_available(&((com_device_t*)file)->out)) {
|
||||
// WaitForSingleObject(((com_device_t*)file)->event, INFINITE);
|
||||
// while (!ringbuf_available(&(comdev->out))) {
|
||||
// WaitForSingleObject(comdev->event, INFINITE);
|
||||
// }
|
||||
|
||||
short read = ringbuf_read(&((com_device_t*)file)->out, lpBuffer, nNumberOfBytesToRead & 0xffff);
|
||||
short read = ringbuf_read(&(comdev->out), lpBuffer, nNumberOfBytesToRead & 0xffff);
|
||||
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = read;
|
||||
|
||||
if (read != 0) {
|
||||
@ -158,14 +162,15 @@ void com_device_thread(com_device_t* com, FnComDeviceThread* thread) {
|
||||
}
|
||||
|
||||
com_device_t* new_com_device(BYTE port) {
|
||||
com_device_t* hook = (com_device_t*)malloc(sizeof *hook);
|
||||
com_device_t* com_device = (com_device_t*)malloc(sizeof *com_device);
|
||||
com_hook_t* com = new_com_hook(port);
|
||||
file_hook_t* file = new_file_hook(com->wName);
|
||||
file->com_hook = com;
|
||||
com->com_device = com_device;
|
||||
|
||||
file->altFilename = com->wDosName;
|
||||
com->data = hook;
|
||||
file->data = hook;
|
||||
hook->com = com;
|
||||
hook->file = file;
|
||||
com_device->com = com;
|
||||
com_device->file = file;
|
||||
|
||||
com->GetCommState = DevGetCommState;
|
||||
com->SetCommState = DevSetCommState;
|
||||
@ -180,12 +185,11 @@ com_device_t* new_com_device(BYTE port) {
|
||||
file->ReadFile = DevReadFile;
|
||||
file->WriteFile = DevWriteFile;
|
||||
|
||||
ringbuf_purge(&hook->in);
|
||||
ringbuf_purge(&hook->out);
|
||||
hook->event = CreateEventW(NULL, TRUE, FALSE, hook->com->wName);
|
||||
ringbuf_purge(&com_device->in);
|
||||
ringbuf_purge(&com_device->out);
|
||||
com_device->event = CreateEventW(NULL, TRUE, FALSE, com_device->com->wName);
|
||||
|
||||
hook_file(file);
|
||||
hook_com(com);
|
||||
|
||||
return hook;
|
||||
return com_device;
|
||||
}
|
||||
|
@ -23,3 +23,6 @@
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "./util/_util.h"
|
||||
|
||||
extern WCHAR exePath[MAX_PATH + 1];
|
||||
extern DWORD imageOffset;
|
||||
|
@ -4,4 +4,19 @@ void install_devices() {
|
||||
install_led_bd();
|
||||
install_touch_bd();
|
||||
install_aime_bd();
|
||||
|
||||
smbus_install(0x20, &smbus_PCA9535_write, &smbus_PCA9535_read);
|
||||
|
||||
// mxkN2CmdWriteData(byte addr,byte *data,ushort nbytes,ushort *nbytesOut)
|
||||
// -> smbusWriteByte(addr, command:0xcc, byte:data[i])
|
||||
// -> smbusWriteI2C(addr, command:0xcc, data+i, n)
|
||||
smbus_install(0x30, &smbus_N2_write, &smbus_N2_read);
|
||||
|
||||
// mxkDsExioRequestComputeMac() -> smbusWriteByte(addr:0x54, command:0x5c, byte:0x94)
|
||||
smbus_install(0x54, &smbus_EXIO_write, &smbus_EXIO_read);
|
||||
|
||||
// mxkDsKeychipComputeMac
|
||||
smbus_install(0x55, &smbus_DS_write, &smbus_DS_read);
|
||||
|
||||
smbus_install(0x57, &smbus_AT24C64AN_write, &smbus_AT24C64AN_read);
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
#pragma once
|
||||
#include "../comdevice.h"
|
||||
#include "../common.h"
|
||||
#include "smbus.h"
|
||||
|
||||
void install_led_bd();
|
||||
void install_touch_bd();
|
||||
void install_aime_bd();
|
||||
|
||||
void install_devices();
|
||||
smbus_callback_t smbus_PCA9535_write;
|
||||
smbus_callback_t smbus_PCA9535_read;
|
||||
smbus_callback_t smbus_DS_write;
|
||||
smbus_callback_t smbus_DS_read;
|
||||
smbus_callback_t smbus_N2_write;
|
||||
smbus_callback_t smbus_N2_read;
|
||||
smbus_callback_t smbus_AT24C64AN_write;
|
||||
smbus_callback_t smbus_AT24C64AN_read;
|
||||
smbus_callback_t smbus_EXIO_write;
|
||||
smbus_callback_t smbus_EXIO_read;
|
||||
|
||||
void install_devices();
|
||||
|
@ -1,6 +1,13 @@
|
||||
devices_files = files(
|
||||
'_devices.c',
|
||||
'led_bd.c',
|
||||
'touch_bd.c',
|
||||
'aime_bd.c',
|
||||
# Serial devices
|
||||
'ser_led_bd.c',
|
||||
'ser_maitouch.c',
|
||||
'ser_tn32msec.c',
|
||||
# SMBus devices
|
||||
'smb_exio.c',
|
||||
'smb_pca9535.c',
|
||||
'smb_ds.c',
|
||||
'smb_n2.c',
|
||||
'smb_at24c64a.c',
|
||||
)
|
@ -1,229 +1,229 @@
|
||||
#include "../hooks/gui.h"
|
||||
#include "_devices.h"
|
||||
|
||||
/*
|
||||
[0] = e0
|
||||
[1] = dest?
|
||||
[2] = dst?
|
||||
[3] = length
|
||||
[4] = op code
|
||||
[...] length-1 bytes
|
||||
[.] = sum
|
||||
|
||||
[0] = e0
|
||||
[2] = dst?
|
||||
[1] = dest?
|
||||
[3] = length
|
||||
[4] = status
|
||||
[5] = op
|
||||
[6] = report
|
||||
[...]
|
||||
[.] = sum
|
||||
|
||||
OP codes:
|
||||
3c: FUN_005735c0 (1)
|
||||
|
||||
10: FUN_00580c00 (1)
|
||||
7c: FUN_00580c00 (2)
|
||||
3c: FUN_00580c00 (1)
|
||||
39: FUN_00580c00 (4)
|
||||
3b: FUN_00580c00 (1)
|
||||
|
||||
31: FUN_00581350 (5)
|
||||
32: FUN_005813b0 (8)
|
||||
33: FUN_00581430 (8) -> something at [16]??
|
||||
39: FUN_005814b0 (4)
|
||||
3f: FUN_00581220 (7)
|
||||
|
||||
7b: FUN_005812a0 (3)
|
||||
7c: FUN_00581310 (2)
|
||||
|
||||
01: was this just an error?
|
||||
10:
|
||||
|
||||
31: Set button. [button] [r] [g] [b]
|
||||
0-7 = buttons
|
||||
8 = woofer
|
||||
9 = center
|
||||
32: Set multiple. [00] [idx hi] [idx lo] [r] [g] [b]
|
||||
33: Fade multiple?. [09] [?] [?] [r] [g] [b]
|
||||
39: Set body light. [intensity] [-] [-]
|
||||
3b:
|
||||
3c: Commit?
|
||||
3f:
|
||||
|
||||
7c:
|
||||
7b:
|
||||
|
||||
initial setup: 7c 0-7, 32, 3c, 39, 3f, 3b
|
||||
*/
|
||||
|
||||
unsigned char COLOURS[10][3];
|
||||
double positions[10][2] = {
|
||||
{ 0.337963, 0.470833 }, { 0.469444, 0.619792 }, { 0.469444, 0.828125 }, { 0.337037, 0.977083 },
|
||||
{ 0.152778, 0.976042 }, { 0.020370, 0.828125 }, { 0.020370, 0.618750 }, { 0.151852, 0.472917 },
|
||||
{ 0.5, 0.75 }, { 0.5, 0.5 },
|
||||
};
|
||||
|
||||
typedef struct rs232c_recv_head {
|
||||
BYTE sync;
|
||||
BYTE src;
|
||||
BYTE dst;
|
||||
BYTE length;
|
||||
BYTE op;
|
||||
} rs232c_recv_head_t;
|
||||
|
||||
BYTE extra[0xff];
|
||||
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
log_info("led_bd", "%ls woke up", dev->com->wName);
|
||||
|
||||
while (1) {
|
||||
rs232c_recv_head_t head;
|
||||
if (comdev_available(dev) < sizeof head) {
|
||||
// Sleep(100);
|
||||
continue;
|
||||
}
|
||||
comdev_read(dev, (unsigned char*)&head, sizeof head);
|
||||
comdev_read(dev, extra, head.length);
|
||||
|
||||
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst);
|
||||
|
||||
switch (head.op) {
|
||||
case 0x01:
|
||||
log_trace("led_bd", "01");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
log_trace("led_bd", "10");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
COLOURS[extra[0]][0] = extra[1];
|
||||
COLOURS[extra[0]][1] = extra[2];
|
||||
COLOURS[extra[0]][2] = extra[3];
|
||||
|
||||
log_trace("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2],
|
||||
extra[3]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x32:
|
||||
log_trace("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]);
|
||||
|
||||
for (unsigned char i = extra[2] - 1; i < extra[1]; i++) {
|
||||
COLOURS[i][0] = extra[3];
|
||||
COLOURS[i][1] = extra[4];
|
||||
COLOURS[i][2] = extra[5];
|
||||
}
|
||||
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x33:
|
||||
log_trace("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
COLOURS[extra[0]][0] = extra[extra[5]];
|
||||
COLOURS[extra[0]][1] = extra[extra[6]];
|
||||
COLOURS[extra[0]][2] = extra[extra[7]];
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
log_trace("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
|
||||
COLOURS[9][0] = extra[0];
|
||||
COLOURS[9][1] = extra[0];
|
||||
COLOURS[9][2] = extra[0];
|
||||
break;
|
||||
case 0x3b:
|
||||
log_trace("led_bd", "3b");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3c:
|
||||
log_trace("led_bd", "3c (I am %ls)", dev->com->wName);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3f:
|
||||
log_trace("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x7c:
|
||||
// extra[0] goes from 0 to 7
|
||||
// Could this be some sort of calibration for the buttons?
|
||||
log_trace("led_bd", "7c: %02x", extra[0]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||
// \/ causes 7b to be used
|
||||
// comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||
// syn dst src len sts op. rep --- chk
|
||||
break;
|
||||
case 0x7b:
|
||||
log_trace("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI led_null_thread(com_device_t* dev) {
|
||||
while (1) Sleep(10000000);
|
||||
}
|
||||
|
||||
void led_overlay(IDirect3DDevice9* dev) {
|
||||
ShowCursor(true);
|
||||
D3DDEVICE_CREATION_PARAMETERS cparams;
|
||||
RECT rect;
|
||||
|
||||
dev->lpVtbl->GetCreationParameters(dev, &cparams);
|
||||
GetClientRect(cparams.hFocusWindow, &rect);
|
||||
|
||||
if (GetAsyncKeyState(VK_LBUTTON) & 1) {
|
||||
POINT cursor;
|
||||
GetCursorPos(&cursor);
|
||||
|
||||
// log_info("led_overlay", "x: %d, y: %d", cursor.x, cursor.y);
|
||||
// log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
|
||||
// (float)(cursor.y - 26) / (float)rect.bottom);
|
||||
}
|
||||
|
||||
for (unsigned char i = 0; i < 10; i++) {
|
||||
int x = (int)(rect.right * positions[i][0]);
|
||||
int y = (int)(rect.bottom * positions[i][1]);
|
||||
draw_rect(dev, x - 25, y - 25, 50, 50, COLOURS[i][0], COLOURS[i][1], COLOURS[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
void install_led_bd() {
|
||||
register_gui_hook(&led_overlay);
|
||||
|
||||
char* text = MiceConfig.devices.led_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port) com_device_thread(new_com_device(com_port), led_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
||||
#include "../hooks/gui.h"
|
||||
#include "_devices.h"
|
||||
|
||||
/*
|
||||
[0] = e0
|
||||
[1] = dest?
|
||||
[2] = dst?
|
||||
[3] = length
|
||||
[4] = op code
|
||||
[...] length-1 bytes
|
||||
[.] = sum
|
||||
|
||||
[0] = e0
|
||||
[2] = dst?
|
||||
[1] = dest?
|
||||
[3] = length
|
||||
[4] = status
|
||||
[5] = op
|
||||
[6] = report
|
||||
[...]
|
||||
[.] = sum
|
||||
|
||||
OP codes:
|
||||
3c: FUN_005735c0 (1)
|
||||
|
||||
10: FUN_00580c00 (1)
|
||||
7c: FUN_00580c00 (2)
|
||||
3c: FUN_00580c00 (1)
|
||||
39: FUN_00580c00 (4)
|
||||
3b: FUN_00580c00 (1)
|
||||
|
||||
31: FUN_00581350 (5)
|
||||
32: FUN_005813b0 (8)
|
||||
33: FUN_00581430 (8) -> something at [16]??
|
||||
39: FUN_005814b0 (4)
|
||||
3f: FUN_00581220 (7)
|
||||
|
||||
7b: FUN_005812a0 (3)
|
||||
7c: FUN_00581310 (2)
|
||||
|
||||
01: was this just an error?
|
||||
10:
|
||||
|
||||
31: Set button. [button] [r] [g] [b]
|
||||
0-7 = buttons
|
||||
8 = woofer
|
||||
9 = center
|
||||
32: Set multiple. [00] [idx hi] [idx lo] [r] [g] [b]
|
||||
33: Fade multiple?. [09] [?] [?] [r] [g] [b]
|
||||
39: Set body light. [intensity] [-] [-]
|
||||
3b:
|
||||
3c: Commit?
|
||||
3f:
|
||||
|
||||
7c:
|
||||
7b:
|
||||
|
||||
initial setup: 7c 0-7, 32, 3c, 39, 3f, 3b
|
||||
*/
|
||||
|
||||
unsigned char COLOURS[10][3];
|
||||
double positions[10][2] = {
|
||||
{ 0.337963, 0.470833 }, { 0.469444, 0.619792 }, { 0.469444, 0.828125 }, { 0.337037, 0.977083 },
|
||||
{ 0.152778, 0.976042 }, { 0.020370, 0.828125 }, { 0.020370, 0.618750 }, { 0.151852, 0.472917 },
|
||||
{ 0.5, 0.75 }, { 0.5, 0.5 },
|
||||
};
|
||||
|
||||
typedef struct rs232c_recv_head {
|
||||
BYTE sync;
|
||||
BYTE src;
|
||||
BYTE dst;
|
||||
BYTE length;
|
||||
BYTE op;
|
||||
} rs232c_recv_head_t;
|
||||
|
||||
BYTE extra[0xff];
|
||||
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
log_info("led_bd", "%ls woke up", dev->com->wName);
|
||||
|
||||
while (1) {
|
||||
rs232c_recv_head_t head;
|
||||
if (comdev_available(dev) < sizeof head) {
|
||||
// Sleep(100);
|
||||
continue;
|
||||
}
|
||||
comdev_read(dev, (unsigned char*)&head, sizeof head);
|
||||
comdev_read(dev, extra, head.length);
|
||||
|
||||
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst);
|
||||
|
||||
switch (head.op) {
|
||||
case 0x01:
|
||||
log_trace("led_bd", "01");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
log_trace("led_bd", "10");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
COLOURS[extra[0]][0] = extra[1];
|
||||
COLOURS[extra[0]][1] = extra[2];
|
||||
COLOURS[extra[0]][2] = extra[3];
|
||||
|
||||
log_trace("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2],
|
||||
extra[3]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x32:
|
||||
log_trace("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]);
|
||||
|
||||
for (unsigned char i = extra[2] - 1; i < extra[1]; i++) {
|
||||
COLOURS[i][0] = extra[3];
|
||||
COLOURS[i][1] = extra[4];
|
||||
COLOURS[i][2] = extra[5];
|
||||
}
|
||||
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x33:
|
||||
log_trace("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6], extra[7]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
COLOURS[extra[0]][0] = extra[extra[5]];
|
||||
COLOURS[extra[0]][1] = extra[extra[6]];
|
||||
COLOURS[extra[0]][2] = extra[extra[7]];
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
log_trace("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
|
||||
COLOURS[9][0] = extra[0];
|
||||
COLOURS[9][1] = extra[0];
|
||||
COLOURS[9][2] = extra[0];
|
||||
break;
|
||||
case 0x3b:
|
||||
log_trace("led_bd", "3b");
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3c:
|
||||
log_trace("led_bd", "3c (I am %ls)", dev->com->wName);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3f:
|
||||
log_trace("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1],
|
||||
extra[2], extra[3], extra[4], extra[5], extra[6]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x7c:
|
||||
// extra[0] goes from 0 to 7
|
||||
// Could this be some sort of calibration for the buttons?
|
||||
log_trace("led_bd", "7c: %02x", extra[0]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||
// \/ causes 7b to be used
|
||||
// comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||
// syn dst src len sts op. rep --- chk
|
||||
break;
|
||||
case 0x7b:
|
||||
log_trace("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI led_null_thread(com_device_t* dev) {
|
||||
while (1) Sleep(10000000);
|
||||
}
|
||||
|
||||
void led_overlay(IDirect3DDevice9* dev) {
|
||||
ShowCursor(true);
|
||||
D3DDEVICE_CREATION_PARAMETERS cparams;
|
||||
RECT rect;
|
||||
|
||||
dev->lpVtbl->GetCreationParameters(dev, &cparams);
|
||||
GetClientRect(cparams.hFocusWindow, &rect);
|
||||
|
||||
if (GetAsyncKeyState(VK_LBUTTON) & 1) {
|
||||
POINT cursor;
|
||||
GetCursorPos(&cursor);
|
||||
|
||||
// log_info("led_overlay", "x: %d, y: %d", cursor.x, cursor.y);
|
||||
// log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
|
||||
// (float)(cursor.y - 26) / (float)rect.bottom);
|
||||
}
|
||||
|
||||
for (unsigned char i = 0; i < 10; i++) {
|
||||
int x = (int)(rect.right * positions[i][0]);
|
||||
int y = (int)(rect.bottom * positions[i][1]);
|
||||
draw_rect(dev, x - 25, y - 25, 50, 50, COLOURS[i][0], COLOURS[i][1], COLOURS[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
void install_led_bd() {
|
||||
// register_gui_hook(&led_overlay);
|
||||
|
||||
char* text = MiceConfig.devices.led_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port) com_device_thread(new_com_device(com_port), led_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
@ -1,97 +1,97 @@
|
||||
#include "_devices.h"
|
||||
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
const BYTE TOUCH_ID_LUT[] = "ABCD\0EFGH\0IJKL\0MNOPQRSTU\0VWXY\0";
|
||||
static BYTE get_touch_id(BYTE id) {
|
||||
for (BYTE i = 0; i < sizeof(TOUCH_ID_LUT); i++) {
|
||||
if (TOUCH_ID_LUT[i] == id) return i;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
BOOL touch_is_enabled = false;
|
||||
BYTE thresh = 0x00; // Lazy caching of single value
|
||||
DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||
log_info("touch_bd", "%ls woke up", dev->com->wName);
|
||||
|
||||
while (1) {
|
||||
if (touch_is_enabled && !comdev_available(dev)) {
|
||||
// Active mode!
|
||||
comdev_write(dev, (unsigned char*)"(@@@@@@@@@@@@)", 14);
|
||||
Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (read_one(dev) != '{') continue;
|
||||
while (comdev_available(dev) < 5) {
|
||||
log_info("touch", "<. .>");
|
||||
Sleep(50);
|
||||
}
|
||||
BYTE command[5];
|
||||
comdev_read(dev, command, 5);
|
||||
BYTE response[6];
|
||||
memcpy(response, "( )", 6);
|
||||
|
||||
if (memcmp(command, "HALT}", 5) == 0) {
|
||||
if (touch_is_enabled)
|
||||
log_info("touch", "Touchscreen left active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen not in active mode");
|
||||
touch_is_enabled = false;
|
||||
} else if (memcmp(command, "STAT}", 5) == 0) {
|
||||
if (!touch_is_enabled)
|
||||
log_info("touch", "Touchscreen entered active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen already in active mode");
|
||||
touch_is_enabled = true;
|
||||
} else if (command[2] == 'k' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
log_misc("touch", "k-command recieved: %d >=%d", sensor, command[3]);
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <> )
|
||||
response[1] = command[0];
|
||||
response[2] = command[1];
|
||||
thresh = command[3];
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else if (command[2] == 't' && command[3] == 'h' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
// { <L/R> <sensor> t h }
|
||||
log_misc("touch", "th-command recieved: %d", sensor);
|
||||
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <threshold> )
|
||||
response[1] = command[0]; // 'L' or 'R'
|
||||
response[2] = command[1]; // Sensor
|
||||
response[4] = thresh;
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else {
|
||||
log_error("touch", "Unhandled: {%.*s", 5, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void install_touch_bd() {
|
||||
char* text = MiceConfig.devices.touch_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port) com_device_thread(new_com_device(com_port), touch_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
||||
#include "_devices.h"
|
||||
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
const BYTE TOUCH_ID_LUT[] = "ABCD\0EFGH\0IJKL\0MNOPQRSTU\0VWXY\0";
|
||||
static BYTE get_touch_id(BYTE id) {
|
||||
for (BYTE i = 0; i < sizeof(TOUCH_ID_LUT); i++) {
|
||||
if (TOUCH_ID_LUT[i] == id) return i;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
BOOL touch_is_enabled = false;
|
||||
BYTE thresh = 0x00; // Lazy caching of single value
|
||||
DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||
log_info("touch_bd", "%ls woke up", dev->com->wName);
|
||||
|
||||
while (1) {
|
||||
if (touch_is_enabled && !comdev_available(dev)) {
|
||||
// Active mode!
|
||||
comdev_write(dev, (unsigned char*)"(@@@@@@@@@@@@)", 14);
|
||||
Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (read_one(dev) != '{') continue;
|
||||
while (comdev_available(dev) < 5) {
|
||||
log_info("touch", "<. .>");
|
||||
Sleep(50);
|
||||
}
|
||||
BYTE command[5];
|
||||
comdev_read(dev, command, 5);
|
||||
BYTE response[6];
|
||||
memcpy(response, "( )", 6);
|
||||
|
||||
if (memcmp(command, "HALT}", 5) == 0) {
|
||||
if (touch_is_enabled)
|
||||
log_info("touch", "Touchscreen left active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen not in active mode");
|
||||
touch_is_enabled = false;
|
||||
} else if (memcmp(command, "STAT}", 5) == 0) {
|
||||
if (!touch_is_enabled)
|
||||
log_info("touch", "Touchscreen entered active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen already in active mode");
|
||||
touch_is_enabled = true;
|
||||
} else if (command[2] == 'k' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
log_misc("touch", "k-command recieved: %d >=%d", sensor, command[3]);
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <> )
|
||||
response[1] = command[0];
|
||||
response[2] = command[1];
|
||||
thresh = command[3];
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else if (command[2] == 't' && command[3] == 'h' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
// { <L/R> <sensor> t h }
|
||||
log_misc("touch", "th-command recieved: %d", sensor);
|
||||
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <threshold> )
|
||||
response[1] = command[0]; // 'L' or 'R'
|
||||
response[2] = command[1]; // Sensor
|
||||
response[4] = thresh;
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else {
|
||||
log_error("touch", "Unhandled: {%.*s", 5, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void install_touch_bd() {
|
||||
char* text = MiceConfig.devices.touch_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port) com_device_thread(new_com_device(com_port), touch_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
@ -1,290 +1,328 @@
|
||||
#include "_devices.h"
|
||||
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
BYTE extra[0xff];
|
||||
|
||||
#define GetFWVersion 0x30
|
||||
#define GetHWVersion 0x32
|
||||
#define RadioOn 0x40
|
||||
#define RadioOff 0x41
|
||||
#define Poll 0x2
|
||||
#define MifareSelectTag 0x43
|
||||
#define Unknown1 0x44 // Present in code, not seen used
|
||||
#define SetKeyBana 0x50
|
||||
#define Unknown2 0x51 // Present in code, not seen used
|
||||
#define ReadBlock 0x52
|
||||
#define SetKeyAime 0x54
|
||||
#define Authenticate 0x55
|
||||
#define Unknown3 0x60 // Present in code, not seen used
|
||||
#define Unknown4 0x61 // Present in code, not seen used
|
||||
#define Reset 0x62
|
||||
#define Unknown5 0x70 // Present in code, not seen used
|
||||
#define FelicaEncap 0x71
|
||||
|
||||
#define LedReset 0xf5
|
||||
#define LedGetInfo 0xf0
|
||||
#define LedSetColour 0x81
|
||||
|
||||
#define FWVer "TN32MSEC003S F/W Ver1.2"
|
||||
#define HWVer "TN32MSEC003S H/W Ver3.0"
|
||||
|
||||
#define CardType_Mifare 0x10
|
||||
#define CardType_FeliCa 0x20
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct NFCMifare {
|
||||
BYTE type;
|
||||
BYTE id_len;
|
||||
DWORD uid;
|
||||
} NFCMifare_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct NFCFelica {
|
||||
BYTE type;
|
||||
BYTE id_len;
|
||||
uint64_t IDm;
|
||||
uint64_t PMm;
|
||||
} NFCFelica_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct MifareBlock {
|
||||
BYTE bytes[16];
|
||||
} MifareBlock_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct MifareSector {
|
||||
MifareBlock_t blocks[4];
|
||||
} MifareSector_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct MifareMemory_t {
|
||||
MifareSector_t sectors[16];
|
||||
} MifareMemory_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct FelicaBlock {
|
||||
BYTE bytes[16];
|
||||
} FelicaBlock_t;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct FelicaMemory {
|
||||
FelicaBlock_t dataBlocks[15];
|
||||
FelicaBlock_t systemBlocks[9];
|
||||
} FelicaMemory_t;
|
||||
|
||||
MifareMemory_t mifareMemory;
|
||||
FelicaMemory_t felicaMemory;
|
||||
BYTE luid[10] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89 };
|
||||
#define PMm_VALUE 0x00F1000000014300ULL
|
||||
|
||||
#define FelicaSystemBlock_RC 0x00
|
||||
#define FelicaSystemBlock_MAC 0x01
|
||||
#define FelicaSystemBlock_ID 0x02
|
||||
#define FelicaSystemBlock_D_ID 0x03
|
||||
#define FelicaSystemBlock_SER_C 0x04
|
||||
#define FelicaSystemBlock_SYS_C 0x05
|
||||
#define FelicaSystemBlock_CKV 0x06
|
||||
#define FelicaSystemBlock_CK 0x07
|
||||
#define FelicaSystemBlock_MC 0x08
|
||||
|
||||
void populate_felica(NFCFelica_t* card) {
|
||||
card->type = CardType_FeliCa;
|
||||
card->id_len = sizeof(card->IDm) + sizeof(card->PMm);
|
||||
card->IDm = _byteswap_uint64(0x012E4CD8A30A39B3ULL);
|
||||
card->PMm = _byteswap_uint64(PMm_VALUE);
|
||||
|
||||
// Key name
|
||||
felicaMemory.dataBlocks[0x0D].bytes[0] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[1] = 0x02;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[2] = 'N';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[3] = 'B';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[4] = 'G';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[5] = 'I';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[6] = 'C';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[7] = '0';
|
||||
// Setup the fake blowfish data
|
||||
felicaMemory.dataBlocks[0x0D].bytes[8] = 0x89;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[9] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[10] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[11] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[12] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[13] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[14] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[15] = 0x00;
|
||||
|
||||
BYTE block0[16] = {
|
||||
0xC2, 0x1C, 0xCB, 0xC7, 0x58, 0xCA, 0x81, 0xB7,
|
||||
0xC0, 0x0B, 0x8E, 0x3A, 0x45, 0x43, 0xFE, 0xFC,
|
||||
};
|
||||
memcpy(felicaMemory.dataBlocks[0].bytes, block0, 16);
|
||||
memset(felicaMemory.dataBlocks[0x0e].bytes, 0xFF, 16);
|
||||
BYTE blockID[16] = {
|
||||
// IDd (=IDm)
|
||||
0x01, 0x2E, 0x4C, 0xD8, 0xA3, 0x0A, 0x39, 0xB3,
|
||||
// ID
|
||||
0x00, 0x2a, 0x05, 0x73, 0x02, 0x01, 0x03, 0x00,
|
||||
// ^DFC^ ^~~~~~ arbitary value
|
||||
};
|
||||
memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_ID].bytes, blockID, 16);
|
||||
BYTE blockDID[16] = {
|
||||
// IDd (=IDm)
|
||||
0x01,
|
||||
0x2E,
|
||||
0x4C,
|
||||
0xD8,
|
||||
0xA3,
|
||||
0x0A,
|
||||
0x39,
|
||||
0xB3,
|
||||
// PMm
|
||||
0x00,
|
||||
0xF1,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x43,
|
||||
0x00,
|
||||
};
|
||||
memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_D_ID].bytes, blockDID, 16);
|
||||
}
|
||||
void populate_mifare(NFCMifare_t* card) {
|
||||
card->type = CardType_Mifare;
|
||||
card->id_len = sizeof(card->uid);
|
||||
card->uid = _byteswap_ulong(0x01020304);
|
||||
|
||||
// TODO: Better state haha
|
||||
// Flash the card memory
|
||||
for (BYTE i = 0; i < 10; i++) {
|
||||
BYTE b = luid[i];
|
||||
mifareMemory.sectors[0].blocks[2].bytes[i + 6] = b;
|
||||
mifareMemory.sectors[0].blocks[1].bytes[i + 6] = b;
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_poll(com_device_t* dev, comio_recv_head_t* req) {
|
||||
BYTE data[256];
|
||||
BYTE nbytes = 1;
|
||||
|
||||
// felica present
|
||||
if (GetAsyncKeyState('L') < 0) {
|
||||
NFCFelica_t card;
|
||||
populate_felica(&card);
|
||||
memcpy(data + nbytes, &card, sizeof card);
|
||||
nbytes += sizeof card;
|
||||
data[0]++;
|
||||
}
|
||||
// mifare (aime, bana) present
|
||||
if (GetAsyncKeyState('P') < 0) {
|
||||
NFCMifare_t card;
|
||||
populate_mifare(&card);
|
||||
memcpy(data + nbytes, &card, sizeof card);
|
||||
nbytes += sizeof card;
|
||||
data[0]++;
|
||||
}
|
||||
|
||||
comio_reply(dev, req, COMIO_STATUS_OK, nbytes, data);
|
||||
}
|
||||
|
||||
DWORD WINAPI aime_bd_thread(com_device_t* dev) {
|
||||
log_info("aime_bd", "%ls woke up", dev->com->wName);
|
||||
bool radio = false;
|
||||
|
||||
while (1) {
|
||||
comio_recv_head_t req;
|
||||
comio_next_req(dev, &req, extra);
|
||||
|
||||
log_info("aime_bd", "(%d) %02x", req.dst, req.op);
|
||||
|
||||
if (req.dst == 0x00 || req.dst == 0x01) {
|
||||
// Aime readers
|
||||
switch (req.op) {
|
||||
case Reset:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case GetFWVersion:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1, (LPBYTE)FWVer);
|
||||
break;
|
||||
case GetHWVersion:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1, (LPBYTE)HWVer);
|
||||
break;
|
||||
case SetKeyAime:
|
||||
log_info("aime_bd", "Aime key: %.*s", req.length, extra);
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case SetKeyBana:
|
||||
log_info("aime_bd", "Bana key: %.*s", req.length, extra);
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case RadioOn:
|
||||
radio = true;
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case RadioOff:
|
||||
radio = false;
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case Poll:
|
||||
nfc_poll(dev, &req);
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
case 0x51:
|
||||
case MifareSelectTag:
|
||||
case Authenticate:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
|
||||
// TODO: These
|
||||
case ReadBlock:
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
break;
|
||||
case FelicaEncap:
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
break;
|
||||
}
|
||||
} else if (req.dst == 0x08 || req.dst == 0x09) {
|
||||
// LED sub-boards
|
||||
switch (req.op) {
|
||||
case LedReset:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case LedGetInfo:
|
||||
// TODO: I'm not sure what this actually means.
|
||||
// 838-15084 is probably a part number
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12");
|
||||
break;
|
||||
case LedSetColour:
|
||||
log_misc("nfc", "Set LED: #%02x%02x%02x", extra[0], extra[1], extra[2]);
|
||||
printf("\033[48;2;%d;%d;%dm \033[0m",
|
||||
extra[0], extra[1], extra[2]);
|
||||
// No response expected here!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
void install_aime_bd() {
|
||||
char* text = MiceConfig.devices.aime_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port) com_device_thread(new_com_device(com_port), aime_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
||||
#include "_devices.h"
|
||||
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
BYTE extra[0xff];
|
||||
|
||||
/**
|
||||
* 51 and 55 are guesses based on the code. Makes sense given their opcodes
|
||||
* too.
|
||||
* TODO: Validate against a real board
|
||||
*/
|
||||
enum TN32_Opcode {
|
||||
TN32Op_Unknown20 = 0x20,
|
||||
TN32Op_GetFWVersion = 0x30,
|
||||
TN32Op_GetHWVersion = 0x32,
|
||||
TN32Op_RadioOn = 0x40,
|
||||
TN32Op_RadioOff = 0x41,
|
||||
TN32Op_Poll = 0x42,
|
||||
TN32Op_MifareSelectTag = 0x43,
|
||||
TN32Op_Unknown44 = 0x44, // Present in code, not seen used
|
||||
TN32Op_SetKeyBana = 0x50,
|
||||
TN32Op_GetKeyBana = 0x51,
|
||||
TN32Op_ReadBlock = 0x52,
|
||||
TN32Op_Unknown53 = 0x53, // Present in code, not seen used
|
||||
TN32Op_SetKeyAime = 0x54,
|
||||
TN32Op_GetKeyAime = 0x55,
|
||||
TN32Op_Unknown60 = 0x60, // Present in code, not seen used
|
||||
TN32Op_Unknown61 = 0x61, // Present in code, not seen used
|
||||
TN32Op_Reset = 0x62,
|
||||
TN32Op_Unknown70 = 0x70, // Present in code, not seen used
|
||||
TN32Op_FelicaEncap = 0x71,
|
||||
};
|
||||
|
||||
#define LedReset 0xf5
|
||||
#define LedGetInfo 0xf0
|
||||
#define LedSetColour 0x81
|
||||
|
||||
const char FWVer[] = "TN32MSEC003S F/W Ver1.2";
|
||||
const char HWVer[] = "TN32MSEC003S H/W Ver3.0";
|
||||
|
||||
#define CardType_Mifare 0x10
|
||||
#define CardType_FeliCa 0x20
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct NFCMifare {
|
||||
BYTE type;
|
||||
BYTE id_len;
|
||||
DWORD uid;
|
||||
} NFCMifare_t;
|
||||
|
||||
typedef struct NFCFelica {
|
||||
BYTE type;
|
||||
BYTE id_len;
|
||||
uint64_t IDm;
|
||||
uint64_t PMm;
|
||||
} NFCFelica_t;
|
||||
|
||||
typedef struct MifareBlock {
|
||||
BYTE bytes[16];
|
||||
} MifareBlock_t;
|
||||
|
||||
typedef struct MifareSector {
|
||||
MifareBlock_t blocks[4];
|
||||
} MifareSector_t;
|
||||
|
||||
typedef struct MifareMemory_t {
|
||||
MifareSector_t sectors[16];
|
||||
} MifareMemory_t;
|
||||
|
||||
typedef struct FelicaBlock {
|
||||
BYTE bytes[16];
|
||||
} FelicaBlock_t;
|
||||
|
||||
typedef struct FelicaMemory {
|
||||
FelicaBlock_t dataBlocks[15];
|
||||
FelicaBlock_t systemBlocks[9];
|
||||
} FelicaMemory_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
MifareMemory_t mifareMemory;
|
||||
FelicaMemory_t felicaMemory;
|
||||
BYTE luid[10] = {0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89};
|
||||
#define PMm_VALUE 0x00F1000000014300ULL
|
||||
|
||||
#define FelicaSystemBlock_RC 0x00
|
||||
#define FelicaSystemBlock_MAC 0x01
|
||||
#define FelicaSystemBlock_ID 0x02
|
||||
#define FelicaSystemBlock_D_ID 0x03
|
||||
#define FelicaSystemBlock_SER_C 0x04
|
||||
#define FelicaSystemBlock_SYS_C 0x05
|
||||
#define FelicaSystemBlock_CKV 0x06
|
||||
#define FelicaSystemBlock_CK 0x07
|
||||
#define FelicaSystemBlock_MC 0x08
|
||||
|
||||
void populate_felica(NFCFelica_t* card) {
|
||||
card->type = CardType_FeliCa;
|
||||
card->id_len = sizeof(card->IDm) + sizeof(card->PMm);
|
||||
card->IDm = _byteswap_uint64(0x012E4CD8A30A39B3ULL);
|
||||
card->PMm = _byteswap_uint64(PMm_VALUE);
|
||||
|
||||
// Key name
|
||||
felicaMemory.dataBlocks[0x0D].bytes[0] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[1] = 0x02;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[2] = 'N';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[3] = 'B';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[4] = 'G';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[5] = 'I';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[6] = 'C';
|
||||
felicaMemory.dataBlocks[0x0D].bytes[7] = '0';
|
||||
// Setup the fake blowfish data
|
||||
felicaMemory.dataBlocks[0x0D].bytes[8] = 0x89;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[9] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[10] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[11] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[12] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[13] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[14] = 0x00;
|
||||
felicaMemory.dataBlocks[0x0D].bytes[15] = 0x00;
|
||||
|
||||
BYTE block0[16] = {
|
||||
0xC2, 0x1C, 0xCB, 0xC7, 0x58, 0xCA, 0x81, 0xB7,
|
||||
0xC0, 0x0B, 0x8E, 0x3A, 0x45, 0x43, 0xFE, 0xFC,
|
||||
};
|
||||
memcpy(felicaMemory.dataBlocks[0].bytes, block0, 16);
|
||||
memset(felicaMemory.dataBlocks[0x0e].bytes, 0xFF, 16);
|
||||
BYTE blockID[16] = {
|
||||
// IDd (=IDm)
|
||||
0x01, 0x2E, 0x4C, 0xD8, 0xA3, 0x0A, 0x39, 0xB3,
|
||||
// ID
|
||||
0x00, 0x2a, 0x05, 0x73, 0x02, 0x01, 0x03, 0x00,
|
||||
// ^DFC^ ^~~~~~ arbitary value
|
||||
};
|
||||
memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_ID].bytes, blockID,
|
||||
16);
|
||||
BYTE blockDID[16] = {
|
||||
// IDd (=IDm)
|
||||
0x01,
|
||||
0x2E,
|
||||
0x4C,
|
||||
0xD8,
|
||||
0xA3,
|
||||
0x0A,
|
||||
0x39,
|
||||
0xB3,
|
||||
// PMm
|
||||
0x00,
|
||||
0xF1,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x01,
|
||||
0x43,
|
||||
0x00,
|
||||
};
|
||||
memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_D_ID].bytes, blockDID,
|
||||
16);
|
||||
}
|
||||
void populate_mifare(NFCMifare_t* card) {
|
||||
card->type = CardType_Mifare;
|
||||
card->id_len = sizeof(card->uid);
|
||||
card->uid = _byteswap_ulong(0x01020304);
|
||||
|
||||
// TODO: Better state haha
|
||||
// Flash the card memory
|
||||
for (BYTE i = 0; i < 10; i++) {
|
||||
BYTE b = luid[i];
|
||||
mifareMemory.sectors[0].blocks[2].bytes[i + 6] = b;
|
||||
mifareMemory.sectors[0].blocks[1].bytes[i + 6] = b;
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_poll(com_device_t* dev, comio_recv_head_t* req) {
|
||||
BYTE data[256];
|
||||
BYTE nbytes = 1;
|
||||
|
||||
// felica present
|
||||
if (GetAsyncKeyState('L') < 0) {
|
||||
NFCFelica_t card;
|
||||
populate_felica(&card);
|
||||
memcpy(data + nbytes, &card, sizeof card);
|
||||
nbytes += sizeof card;
|
||||
data[0]++;
|
||||
}
|
||||
// mifare (aime, bana) present
|
||||
if (GetAsyncKeyState('P') < 0) {
|
||||
NFCMifare_t card;
|
||||
populate_mifare(&card);
|
||||
memcpy(data + nbytes, &card, sizeof card);
|
||||
nbytes += sizeof card;
|
||||
data[0]++;
|
||||
}
|
||||
|
||||
comio_reply(dev, req, COMIO_STATUS_OK, nbytes, data);
|
||||
}
|
||||
|
||||
BYTE AIME_KEY[6];
|
||||
BYTE BANA_KEY[6];
|
||||
|
||||
DWORD WINAPI aime_bd_thread(com_device_t* dev) {
|
||||
log_info("aime_bd", "%ls woke up", dev->com->wName);
|
||||
bool radio = false;
|
||||
|
||||
while (1) {
|
||||
comio_recv_head_t req;
|
||||
comio_next_req(dev, &req, extra);
|
||||
|
||||
log_info("aime_bd", "(%d) %02x", req.dst, req.op);
|
||||
|
||||
if (req.dst == 0x00 || req.dst == 0x01) {
|
||||
// Aime readers
|
||||
switch (req.op) {
|
||||
case TN32Op_Reset:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case TN32Op_GetFWVersion:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1,
|
||||
(LPBYTE)FWVer);
|
||||
break;
|
||||
case TN32Op_GetHWVersion:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1,
|
||||
(LPBYTE)HWVer);
|
||||
break;
|
||||
case TN32Op_SetKeyAime:
|
||||
if (req.length != sizeof AIME_KEY) {
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
} else {
|
||||
memcpy(AIME_KEY, extra, sizeof AIME_KEY);
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
|
||||
log_info("aime_bd",
|
||||
"Aime key: %02x %02x %02x %02x %02x %02x",
|
||||
AIME_KEY[0], AIME_KEY[1], AIME_KEY[2],
|
||||
AIME_KEY[3], AIME_KEY[4], AIME_KEY[5]);
|
||||
}
|
||||
break;
|
||||
case TN32Op_SetKeyBana:
|
||||
if (req.length != sizeof BANA_KEY) {
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
} else {
|
||||
memcpy(BANA_KEY, extra, sizeof BANA_KEY);
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
|
||||
log_info("aime_bd",
|
||||
"Bana key: %02x %02x %02x %02x %02x %02x",
|
||||
BANA_KEY[0], BANA_KEY[1], BANA_KEY[2],
|
||||
BANA_KEY[3], BANA_KEY[4], BANA_KEY[5]);
|
||||
}
|
||||
break;
|
||||
case TN32Op_RadioOn:
|
||||
radio = true;
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case TN32Op_RadioOff:
|
||||
radio = false;
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case TN32Op_Poll:
|
||||
nfc_poll(dev, &req);
|
||||
break;
|
||||
|
||||
case TN32Op_GetKeyBana:
|
||||
case TN32Op_GetKeyAime:
|
||||
if (req.length != 5) {
|
||||
//
|
||||
}
|
||||
|
||||
case TN32Op_Unknown44:
|
||||
case TN32Op_MifareSelectTag:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
|
||||
// TODO: These
|
||||
case TN32Op_ReadBlock:
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
break;
|
||||
case TN32Op_FelicaEncap:
|
||||
comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL);
|
||||
break;
|
||||
}
|
||||
} else if (req.dst == 0x08 || req.dst == 0x09) {
|
||||
// LED sub-boards
|
||||
switch (req.op) {
|
||||
case LedReset:
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
|
||||
break;
|
||||
case LedGetInfo:
|
||||
// TODO: I'm not sure what this actually means.
|
||||
// 838-15084 is probably a part number
|
||||
comio_reply(dev, &req, COMIO_STATUS_OK, 9,
|
||||
(BYTE*)"15084\xff\x10\x00\x12");
|
||||
break;
|
||||
case LedSetColour:
|
||||
log_misc("nfc", "Set LED: #%02x%02x%02x", extra[0],
|
||||
extra[1], extra[2]);
|
||||
printf(
|
||||
"\033[48;2;%d;%d;%dm "
|
||||
" \033[0m",
|
||||
extra[0], extra[1], extra[2]);
|
||||
// No response expected here!
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
void install_aime_bd() {
|
||||
char* text = MiceConfig.devices.aime_bd;
|
||||
char* copy = (char*)malloc(strlen(text) + 1);
|
||||
memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1);
|
||||
|
||||
char* next_token;
|
||||
char* token = strtok_s(copy, ",", &next_token);
|
||||
while (token != NULL) {
|
||||
BYTE com_port = atoi(token) & 0xFF;
|
||||
if (com_port)
|
||||
com_device_thread(new_com_device(com_port), aime_bd_thread);
|
||||
token = strtok_s(NULL, ",", &next_token);
|
||||
}
|
||||
|
||||
free(copy);
|
||||
}
|
173
src/micetools/dll/devices/smb_at24c64a.c
Normal file
173
src/micetools/dll/devices/smb_at24c64a.c
Normal file
@ -0,0 +1,173 @@
|
||||
#include "../../amBackupStructs.h"
|
||||
#include "../../maiBackupStructs.h"
|
||||
#include "_devices.h"
|
||||
|
||||
#define EEPROM_DUMP L"dev/eeprom.bin"
|
||||
|
||||
// 8192 x 8 (64kbit) of eeprom
|
||||
BYTE EEPROM_DATA[0x2000];
|
||||
|
||||
void eeprom_dump() {
|
||||
HANDLE dump =
|
||||
_CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed: %03x", GetLastError());
|
||||
return;
|
||||
} else {
|
||||
log_info("eeprom", "Wrote eeprom to %ls", EEPROM_DUMP);
|
||||
}
|
||||
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
|
||||
FlushFileBuffers(dump);
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
void eeprom_restore() {
|
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
// Make the file, even though it'll probably be empty
|
||||
eeprom_dump();
|
||||
return;
|
||||
}
|
||||
DWORD read;
|
||||
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL))
|
||||
log_error("eeprom", "failed to restore (%d)", GetLastError());
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
|
||||
#define SET_IP(val, a, b, c, d) \
|
||||
do { \
|
||||
*(uint32_t*)&val = (uint32_t)((a << 24) | (b << 16) | (c << 8) | d); \
|
||||
} while (0)
|
||||
|
||||
#define fix_crc(block) \
|
||||
do { \
|
||||
(block).m_Crc = amCrc32RGet(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \
|
||||
} while (0)
|
||||
|
||||
void set_eeprom_network_config() {
|
||||
AM_SYSDATAwH_NETWORK_ETH0 NetEth0 = { 0 };
|
||||
NetEth0.m_Eth.m_Flag = 0;
|
||||
NetEth0.m_Eth.m_IpAddress = MiceConfig.network.ip_address;
|
||||
NetEth0.m_Eth.m_SubnetMask = MiceConfig.network.subnet_mask;
|
||||
NetEth0.m_Eth.m_Gateway = MiceConfig.network.gateway;
|
||||
NetEth0.m_Eth.m_PrimaryDns = MiceConfig.network.primary_dns;
|
||||
NetEth0.m_Eth.m_SecondaryDns = MiceConfig.network.secondary_dns;
|
||||
fix_crc(NetEth0);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH0_REG], &NetEth0, sizeof NetEth0);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH0_DUP], &NetEth0, sizeof NetEth0);
|
||||
|
||||
AM_SYSDATAwH_NETWORK_ETH1 NetEth1 = { 0 };
|
||||
fix_crc(NetEth1);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH1_REG], &NetEth1, sizeof NetEth1);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_NETWORK_ETH1_DUP], &NetEth1, sizeof NetEth1);
|
||||
}
|
||||
|
||||
int build_eeprom() {
|
||||
static BOOL built = false;
|
||||
if (built) return 0;
|
||||
built = true;
|
||||
|
||||
if (FileExists(EEPROM_DUMP)) {
|
||||
eeprom_restore();
|
||||
// Our network config always gets priority
|
||||
set_eeprom_network_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("eeprom", "Building default EEPROM file");
|
||||
|
||||
memset(EEPROM_DATA, 0xff, sizeof EEPROM_DATA);
|
||||
|
||||
AM_SYSDATAwH_STATIC Static = {
|
||||
.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8),
|
||||
.m_Rental = MiceConfig.sysconf.rental,
|
||||
};
|
||||
strcpy_s(Static.m_strSerialId, sizeof Static.m_strSerialId, MiceConfig.sysconf.serial);
|
||||
fix_crc(Static);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_REG], &Static, sizeof Static);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_DUP], &Static, sizeof Static);
|
||||
|
||||
AM_SYSDATAwH_CREDIT Credit = { 0 };
|
||||
fix_crc(Credit);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_REG], &Credit, sizeof Credit);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_DUP], &Credit, sizeof Credit);
|
||||
|
||||
set_eeprom_network_config();
|
||||
|
||||
AM_SYSDATAwH_HISTORY History = { 0 };
|
||||
// TODO: Game ID here should be configurable.
|
||||
History.m_GameId[0] = 'S';
|
||||
History.m_GameId[1] = 'D';
|
||||
History.m_GameId[2] = 'E';
|
||||
History.m_GameId[3] = 'Y';
|
||||
History.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8);
|
||||
fix_crc(History);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_REG], &History, sizeof History);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_DUP], &History, sizeof History);
|
||||
AM_SYSDATAwH_ALPB_CARD_ID CardInfo = { 0 };
|
||||
fix_crc(CardInfo);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_CARD_ID_REG] + (sizeof History), &CardInfo,
|
||||
sizeof CardInfo);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_CARD_ID_DUP] + (sizeof History), &CardInfo,
|
||||
sizeof CardInfo);
|
||||
|
||||
AM_SYSDATAwH_ALPB_COMPUTER_NAME CompuerName = { 0 };
|
||||
fix_crc(CompuerName);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_COMPUTER_NAME_REG], &CompuerName, sizeof CompuerName);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_COMPUTER_NAME_DUP], &CompuerName, sizeof CompuerName);
|
||||
|
||||
AM_SYSDATAwH_ALPB_DEV_CONFIG DevConfig = { 0 };
|
||||
fix_crc(DevConfig);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_DEV_CONFIG_REG], &DevConfig, sizeof DevConfig);
|
||||
memcpy(&EEPROM_DATA[AM_SYSDATAwH_ALPB_DEV_CONFIG_DUP], &DevConfig, sizeof DevConfig);
|
||||
|
||||
eeprom_dump();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void eeprom_read(WORD addr, BYTE* data, BYTE length) {
|
||||
if (!build_eeprom()) eeprom_restore();
|
||||
|
||||
if (addr >= sizeof EEPROM_DATA) return;
|
||||
if (length + addr > sizeof EEPROM_DATA) length = (sizeof EEPROM_DATA - addr) & 0xff;
|
||||
|
||||
memcpy(data, &EEPROM_DATA[addr], length);
|
||||
}
|
||||
void eeprom_write(WORD addr, BYTE* data, BYTE length) {
|
||||
if (!build_eeprom()) eeprom_restore();
|
||||
|
||||
if (addr >= sizeof EEPROM_DATA) return;
|
||||
if (length + addr > sizeof EEPROM_DATA) length = (sizeof EEPROM_DATA - addr) & 0xff;
|
||||
|
||||
memcpy(&EEPROM_DATA[addr], data, length);
|
||||
eeprom_dump();
|
||||
}
|
||||
|
||||
BOOL smbus_AT24C64AN_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BLOCK: {
|
||||
log_misc("eeprom", "write %d bytes at 0x%03x", dlen, code);
|
||||
eeprom_write(code, data, dlen);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
log_error("eeprom", "Unsupported write mode: %01x, %02x", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL smbus_AT24C64AN_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case ICH9_CMD_BLOCK: {
|
||||
log_misc("eeprom", "read %d bytes at 0x%03x", dlen, code);
|
||||
eeprom_read(code, data, dlen);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
log_error("eeprom", "Unsupported read mode: %01x, %02x", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
85
src/micetools/dll/devices/smb_ds.c
Normal file
85
src/micetools/dll/devices/smb_ds.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include "_devices.h"
|
||||
|
||||
/**
|
||||
* TODO: This whole device, properly
|
||||
*/
|
||||
|
||||
BOOL smbus_DS_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
static unsigned char challenge[7];
|
||||
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BLOCK: {
|
||||
switch (code) {
|
||||
case 0xa9d0:
|
||||
case 0xa9d1:
|
||||
case 0xa9d2:
|
||||
case 0xa9d3: {
|
||||
if (dlen != 7) {
|
||||
log_error("smb-ds", "Expected challenge length of 7 (saw %d)!", dlen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(challenge, &(data[2]), 7);
|
||||
|
||||
char* challenge_s = malloc(dlen * 3 + 1);
|
||||
if (challenge_s == NULL) {
|
||||
log_info("smb-ds", "Challenge: (buffer failed)");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dlen; i++) {
|
||||
sprintf_s(challenge_s + i * 3, 4, "%02x ", data[2 + i]);
|
||||
}
|
||||
challenge_s[dlen * 3 + 1] = '\0';
|
||||
log_info("smb-ds", "Challenge: %s", challenge_s);
|
||||
free(challenge_s);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
log_error("smb-ds", "Unknown write command: %04x", code);
|
||||
}
|
||||
}
|
||||
case ICH9_CMD_I2C_READ: {
|
||||
switch (code) {
|
||||
case DS_I2C_CHALLENGE_RESPONSE:
|
||||
// This just has to match EXIO!
|
||||
for (int i = 0; i < dlen; i++) data[i] = 0x69;
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("smb-ds", "Unknown I2C read command: %04x", code);
|
||||
}
|
||||
}
|
||||
default:
|
||||
log_error("smb-ds", "Unsupported write mode: %01x (%04x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL smbus_DS_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
static unsigned char DS_eeprom[3][0x20];
|
||||
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE_DATA:
|
||||
if (code < 0x80) {
|
||||
BYTE page = (code >> 5) & 0b11;
|
||||
BYTE offset = code & 0x1f;
|
||||
|
||||
data[0] = DS_eeprom[page][offset];
|
||||
|
||||
return TRUE;
|
||||
} else if (code >= DS_GET_UNIQUE_NUMBER && code < DS_GET_UNIQUE_NUMBER + 0xf) {
|
||||
data[0] = 0x04; // chosen by fair dice roll.
|
||||
return TRUE;
|
||||
} else if (code == DS_GET_STATUS) {
|
||||
// Polled until DS_STATUS_FLAG_BUSY low
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
} else {
|
||||
log_error("smb-ds", "Unknown read command: %04x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("smb-ds", "Unsupported read mode: %01x (%04x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
53
src/micetools/dll/devices/smb_exio.c
Normal file
53
src/micetools/dll/devices/smb_exio.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include "_devices.h"
|
||||
|
||||
BOOL smbus_EXIO_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case 0x5c:
|
||||
if (data[0] == 0x94) return TRUE;
|
||||
default:
|
||||
log_error("smb-exio", "Unknown write command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
case ICH9_CMD_BLOCK: {
|
||||
WORD reg = *(WORD*)(&data[-1]);
|
||||
dlen = data[1];
|
||||
|
||||
// char* data_s = malloc(dlen * 3 + 1);
|
||||
// for (int i = 0; i < dlen; i++) {
|
||||
// sprintf_s(data_s + i * 3, 3, "%02x ", data[2 + i]);
|
||||
// }
|
||||
// data_s[dlen * 3 + 1] = '\0';
|
||||
|
||||
log_info("smb-exio", "Block write, %d @ %04x: ", dlen, reg);
|
||||
// free(data_s);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
log_error("smb-exio", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL smbus_EXIO_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE_DATA:
|
||||
if (0x40 <= code < 0x40 + 0x14) {
|
||||
// mxkDsExioReadMacOutputBuffer
|
||||
// This just has to match N2_I2C_CHALLENGE_RESPONSE!
|
||||
data[0] = 0x69;
|
||||
return TRUE;
|
||||
} else if (code == EXIO_GET_BUSY) {
|
||||
data[0] = 0x00; // Anything non-zero = busy
|
||||
return TRUE;
|
||||
} else {
|
||||
log_error("smx-exio", "Unknown read command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("smb-exio", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
421
src/micetools/dll/devices/smb_n2.c
Normal file
421
src/micetools/dll/devices/smb_n2.c
Normal file
@ -0,0 +1,421 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "../../lib/mxk/mxk.h"
|
||||
#include "_devices.h"
|
||||
|
||||
#define N2_TAG_OFFSET 0
|
||||
#define N2_PARAMSIZE_OFFSET 2
|
||||
#define N2_COMMAND_OFFSET 4
|
||||
#define N2_TAG_SIZE 2
|
||||
#define N2_PARAMSIZE_SIZE 2
|
||||
#define N2_COMMAND_SIZE 2
|
||||
#define N2_CHECKSUM_SIZE 20
|
||||
#define N2_AUTH_SIZE 20
|
||||
#define N2_HEADER_SIZE (N2_TAG_SIZE + N2_PARAMSIZE_SIZE + N2_COMMAND_SIZE)
|
||||
|
||||
#define N2_TAG_RQU_COMMAND 0xC1
|
||||
#define N2_TAG_RQU_AUTH_COMMAND 0xC2
|
||||
#define N2_TAG_RSP_COMMAND 0xC3
|
||||
#define N2_TAG_RSP_AUTH_COMMAND 0xC4
|
||||
// TODO: Uncomment these if actually used, and adjust lazy +2 logic alongside
|
||||
// #define N2_TAG_RQU_RSA_COMMAND 0xC5
|
||||
// #define N2_TAG_RSP_RSA_COMMAND 0xC6
|
||||
|
||||
#define N2_ORD_ENABLE_SESSION 1
|
||||
#define N2_ORD_DISABLE_SESSION 2
|
||||
#define N2_ORD_SET_AUTH_KEY 3
|
||||
#define N2_ORD_SET_ENC_KEY 4
|
||||
// GAP!
|
||||
#define N2_ORD_GET_AUTH_LEVEL 9
|
||||
// GAP!
|
||||
#define N2_ORD_GET_ERROR_CODE 11
|
||||
#define N2_ORD_GET_VERSION 12
|
||||
// GAP! (-> keychip info write?)
|
||||
#define N2_ORD_READ_KEYCHIP_ID 14
|
||||
// GAP! (-> gkey write?)
|
||||
#define N2_ORD_ENCRYPT_WITH_GKEY 16 // keychip.encrypt
|
||||
#define N2_ORD_DECRYPT_WITH_GKEY 17 // keychip.decrypt
|
||||
#define N2_ORD_ADD_PLAY_COUNT 18
|
||||
#define N2_ORD_READ_PLAY_COUNT 19
|
||||
// GAP! (-> storage? is that still on pic?)
|
||||
#define N2_ORD_GET_RANDOM_VALUE 24
|
||||
#define N2_ORD_ENCRYPT_WITH_SKEY 25 // keychip.ssd.hostproof
|
||||
#define N2_ORD_DECRYPT_WITH_SKEY 26
|
||||
|
||||
#define N2_SUCCESS 0
|
||||
#define N2_INVALID_AUTH 1
|
||||
#define N2_AUTHFAIL 2
|
||||
#define N2_LV_ERROR 3
|
||||
#define N2_BAD_PARAMETER 4
|
||||
#define N2_EEP_WRITEFAIL 5
|
||||
#define N2_BAD_TAG 6
|
||||
#define N2_BAD_ORDINAL 7
|
||||
#define N2_SUMFAIL 8
|
||||
#define N2_EEPWRITE_DISABLE 9
|
||||
#define N2_BAD_DATASIZE 10
|
||||
#define N2_FAIL 11
|
||||
|
||||
#define N2_IO_BUFFER 0x1000
|
||||
|
||||
BYTE n2_in_buffer[N2_IO_BUFFER];
|
||||
WORD n2_in_pointer = 0;
|
||||
BYTE n2_out_buffer[N2_IO_BUFFER];
|
||||
WORD n2_out_pointer = 0;
|
||||
|
||||
WORD n2_error_code = 0;
|
||||
|
||||
BYTE n2_auth_key[20] = { 0x96, 0xed, 0x31, 0xb2, 0x28, 0x71, 0x05, 0xa5, 0xa3, 0x30,
|
||||
0x54, 0x0f, 0x25, 0xbe, 0xd8, 0x51, 0xa5, 0xc8, 0x36, 0x21 };
|
||||
|
||||
BYTE n2_session_nonce[20];
|
||||
struct {
|
||||
BYTE key[16];
|
||||
BYTE iv[16];
|
||||
} n2_enc_key = {
|
||||
.key = { 0x76, 0xec, 0x42, 0xb6, 0xae, 0x0c, 0xb0, 0x48, 0x10, 0x51, 0x71, 0xad, 0x8c, 0xb2,
|
||||
0xfb, 0x07 },
|
||||
.iv = { 0x8e, 0x30, 0x0b, 0xa4, 0x2e, 0x15, 0x4b, 0xaf, 0x65, 0x15, 0x32, 0xf5, 0x70, 0x04,
|
||||
0x1f, 0x5b },
|
||||
};
|
||||
|
||||
#define fix_endian(x) (((x & 0xff00) >> 8) | (((x)&0xff) << 8))
|
||||
|
||||
typedef struct {
|
||||
WORD tag;
|
||||
WORD paramSize;
|
||||
WORD (*handler)(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut);
|
||||
} n2_command;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
DWORD m_Crc;
|
||||
BYTE Rsv04[12];
|
||||
char m_KeyId[16];
|
||||
struct {
|
||||
DWORD m_Crc;
|
||||
DWORD m_Format;
|
||||
char m_GameId[4];
|
||||
BYTE m_Region;
|
||||
BYTE m_ModelType;
|
||||
BYTE m_SystemFlag;
|
||||
BYTE Rsv0f;
|
||||
//
|
||||
char m_PlatformId[3];
|
||||
BYTE m_DvdFlag;
|
||||
DWORD m_NetworkAddr;
|
||||
BYTE Unk00[88];
|
||||
BYTE m_Seed[16];
|
||||
} m_Appboot;
|
||||
} N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
N2_KEYCHIP_INFO n2_keychip_info = {
|
||||
.m_KeyId = { 'A', '7', '2', 'E', '-', '0', '2', 'D', '1', '1', '2', '6', '1', '1', '1', '6' },
|
||||
.m_Appboot = {
|
||||
.m_Format = 1,
|
||||
.m_GameId = { 'S' , 'D', 'E', 'Y' },
|
||||
.m_Region = 0xff,
|
||||
.m_ModelType = 2,
|
||||
.m_SystemFlag = 0x24,
|
||||
.m_PlatformId = {'A', 'A', 'S'},
|
||||
.m_DvdFlag = 1,
|
||||
.m_NetworkAddr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24),
|
||||
}
|
||||
};
|
||||
|
||||
WORD n2_enable_session(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 20;
|
||||
|
||||
RAND_bytes(n2_session_nonce, sizeof n2_session_nonce);
|
||||
memcpy(dataOut, n2_session_nonce, sizeof n2_session_nonce);
|
||||
|
||||
log_misc("smb-n2", "Session open");
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_set_auth_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 0;
|
||||
log_misc("smb-n2", "Auth key set");
|
||||
|
||||
BYTE pt[32];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn, pt, sizeof pt);
|
||||
memcpy(n2_auth_key, pt, sizeof n2_auth_key);
|
||||
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_set_enc_key(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 0;
|
||||
log_misc("smb-n2", "Enc key set");
|
||||
|
||||
BYTE pt[32];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn, pt, sizeof pt);
|
||||
memcpy(n2_enc_key.key, pt, sizeof n2_enc_key.key);
|
||||
memcpy(n2_enc_key.iv, pt + sizeof n2_enc_key.key, sizeof n2_enc_key.iv);
|
||||
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_get_auth_level(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 1;
|
||||
dataOut[0] = 3; // TODO: ?
|
||||
log_misc("smb-n2", "Auth level get");
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_get_error_code(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 2;
|
||||
((PWORD)dataOut)[0] = fix_endian(n2_error_code);
|
||||
log_misc("smb-n2", "Error get");
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_read_keychip_id(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
DWORD nbytes = (dataIn[0] << 24) | (dataIn[1] << 16) | (dataIn[2] << 8) | dataIn[3];
|
||||
|
||||
*nOut = (nbytes & 0xff) + 2;
|
||||
|
||||
n2_keychip_info.m_Appboot.m_Crc = amCrc32RGet(sizeof n2_keychip_info.m_Appboot - 4, (LPBYTE)&n2_keychip_info.m_Appboot + 4, 0);
|
||||
n2_keychip_info.m_Crc = amCrc32RGet(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0);
|
||||
|
||||
mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut + 2, (LPBYTE)&n2_keychip_info, nbytes);
|
||||
|
||||
log_misc("smb-n2", "Read keychip ID: %08x", nbytes);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_get_version(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 2;
|
||||
dataOut[0] = 0x01;
|
||||
dataOut[1] = 0x04;
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
|
||||
WORD n2_encrypt_with_gkey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 16;
|
||||
BYTE temp[16];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn + 1, temp, sizeof temp);
|
||||
|
||||
for(size_t i=0;i<17;i++)printf(" %02x",dataIn[i]);
|
||||
puts("");
|
||||
for(size_t i=0;i<17;i++)printf(" %02x",temp[i]);
|
||||
puts("");
|
||||
|
||||
// Do Gkey encryption
|
||||
|
||||
mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut, temp, sizeof temp);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_decrypt_with_gkey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 16;
|
||||
BYTE temp[16];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn + 1, temp, sizeof temp);
|
||||
|
||||
// Do Gkey decryption
|
||||
|
||||
mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut, temp, sizeof temp);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_add_play_count(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 0;
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_read_play_count(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 4;
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_get_random_value(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 16;
|
||||
RAND_bytes(dataOut, 16);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_encrypt_with_skey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 16;
|
||||
BYTE temp[16];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn + 1, temp, sizeof temp);
|
||||
|
||||
// Do Skey encryption
|
||||
|
||||
mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut, temp, sizeof temp);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
WORD n2_decrypt_with_skey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) {
|
||||
*nOut = 16;
|
||||
BYTE temp[16];
|
||||
mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn + 1, temp, sizeof temp);
|
||||
|
||||
// Do Skey decryption
|
||||
|
||||
mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut, temp, sizeof temp);
|
||||
return N2_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
n2_command N2_COMMANDS[0xff];
|
||||
#define N2_INSTALL_COMMAND(ord, tag_, paramSize_, handler_) \
|
||||
do { \
|
||||
N2_COMMANDS[ord].tag = (tag_); \
|
||||
N2_COMMANDS[ord].paramSize = (paramSize_); \
|
||||
N2_COMMANDS[ord].handler = &(handler_); \
|
||||
} while (0)
|
||||
|
||||
void n2_install_commands() {
|
||||
static bool installed = false;
|
||||
if (installed) return;
|
||||
installed = true;
|
||||
|
||||
ZeroMemory(N2_COMMANDS, sizeof N2_COMMANDS);
|
||||
N2_INSTALL_COMMAND(N2_ORD_ENABLE_SESSION, N2_TAG_RQU_COMMAND, 0, n2_enable_session);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_SET_AUTH_KEY, N2_TAG_RQU_AUTH_COMMAND, 32, n2_set_auth_key);
|
||||
N2_INSTALL_COMMAND(N2_ORD_SET_ENC_KEY, N2_TAG_RQU_AUTH_COMMAND, 32, n2_set_enc_key);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_GET_AUTH_LEVEL, N2_TAG_RQU_COMMAND, 0, n2_get_auth_level);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_GET_ERROR_CODE, N2_TAG_RQU_COMMAND, 0, n2_get_error_code);
|
||||
N2_INSTALL_COMMAND(N2_ORD_GET_VERSION, N2_TAG_RQU_COMMAND, 0, n2_get_version);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_READ_KEYCHIP_ID, N2_TAG_RQU_AUTH_COMMAND, 4, n2_read_keychip_id);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_ENCRYPT_WITH_GKEY, N2_TAG_RQU_AUTH_COMMAND, 17, n2_encrypt_with_gkey);
|
||||
N2_INSTALL_COMMAND(N2_ORD_DECRYPT_WITH_GKEY, N2_TAG_RQU_AUTH_COMMAND, 17, n2_decrypt_with_gkey);
|
||||
N2_INSTALL_COMMAND(N2_ORD_ADD_PLAY_COUNT, N2_TAG_RQU_AUTH_COMMAND, 1, n2_add_play_count);
|
||||
N2_INSTALL_COMMAND(N2_ORD_READ_PLAY_COUNT, N2_TAG_RQU_AUTH_COMMAND, 0, n2_read_play_count);
|
||||
|
||||
N2_INSTALL_COMMAND(N2_ORD_GET_RANDOM_VALUE, N2_TAG_RQU_AUTH_COMMAND, 0, n2_get_random_value);
|
||||
N2_INSTALL_COMMAND(N2_ORD_ENCRYPT_WITH_SKEY, N2_TAG_RQU_AUTH_COMMAND, 17, n2_encrypt_with_skey);
|
||||
N2_INSTALL_COMMAND(N2_ORD_DECRYPT_WITH_SKEY, N2_TAG_RQU_AUTH_COMMAND, 17, n2_decrypt_with_skey);
|
||||
}
|
||||
|
||||
void do_n2_command(WORD tag, WORD paramSize, WORD command, LPBYTE data) {
|
||||
n2_install_commands();
|
||||
|
||||
log_info("smb-n2", "Processing command: %04x/%04x (%d bytes)", tag, command, paramSize);
|
||||
|
||||
ZeroMemory(n2_out_buffer, sizeof n2_out_buffer);
|
||||
|
||||
// We nede to sign with the old key, so need a copy
|
||||
BYTE auth_key[20];
|
||||
memcpy(auth_key, n2_auth_key, sizeof auth_key);
|
||||
|
||||
WORD result = N2_SUCCESS;
|
||||
WORD bodyLength = 0;
|
||||
|
||||
WORD expectedExtraData = N2_CHECKSUM_SIZE + N2_HEADER_SIZE;
|
||||
if (tag == N2_TAG_RQU_AUTH_COMMAND) expectedExtraData += N2_AUTH_SIZE;
|
||||
|
||||
n2_command handler = N2_COMMANDS[command & 0xff];
|
||||
if (handler.handler == NULL) {
|
||||
result = N2_BAD_ORDINAL;
|
||||
} else if (handler.tag != tag) {
|
||||
result = N2_BAD_TAG;
|
||||
} else if (handler.paramSize + expectedExtraData != paramSize) {
|
||||
result = N2_BAD_DATASIZE;
|
||||
} else {
|
||||
result = (*handler.handler)(paramSize, n2_in_buffer + N2_HEADER_SIZE,
|
||||
n2_out_buffer + N2_HEADER_SIZE, &bodyLength);
|
||||
}
|
||||
|
||||
WORD paramSizeOut = bodyLength + expectedExtraData;
|
||||
((PWORD)n2_out_buffer)[0] = fix_endian(tag + 2);
|
||||
((PWORD)n2_out_buffer)[1] = fix_endian(paramSizeOut);
|
||||
((PWORD)n2_out_buffer)[2] = fix_endian(result);
|
||||
|
||||
EVP_MD_CTX* ctx;
|
||||
unsigned int outlen;
|
||||
|
||||
WORD fixed_command = fix_endian(command);
|
||||
|
||||
// Calculate a SHA1 of the packet, and append it
|
||||
ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit(ctx, EVP_sha1());
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer, N2_HEADER_SIZE);
|
||||
EVP_DigestUpdate(ctx, &fixed_command, 2);
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer + N2_HEADER_SIZE, bodyLength);
|
||||
EVP_DigestFinal_ex(ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength, &outlen);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
|
||||
if (tag == N2_TAG_RQU_AUTH_COMMAND) {
|
||||
BYTE crypto_buffer[N2_CHECKSUM_SIZE];
|
||||
|
||||
// Calculate a new SHA1 of the packet, including the SHA1 we just appeneded
|
||||
ctx = EVP_MD_CTX_create();
|
||||
EVP_DigestInit(ctx, EVP_sha1());
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer, N2_HEADER_SIZE);
|
||||
EVP_DigestUpdate(ctx, &fixed_command, 2);
|
||||
EVP_DigestUpdate(ctx, n2_out_buffer + N2_HEADER_SIZE, bodyLength);
|
||||
EVP_DigestFinal_ex(ctx, crypto_buffer, &outlen);
|
||||
EVP_MD_CTX_destroy(ctx);
|
||||
|
||||
// Calculate an HMAC, and append it
|
||||
HMAC_CTX hmac_ctx;
|
||||
HMAC_CTX_init(&hmac_ctx);
|
||||
HMAC_Init_ex(&hmac_ctx, auth_key, sizeof auth_key, EVP_sha1(), NULL);
|
||||
|
||||
// SHA1(header | data)
|
||||
HMAC_Update(&hmac_ctx, crypto_buffer, sizeof crypto_buffer);
|
||||
// SHA1(header | auth | packet))
|
||||
HMAC_Update(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength, N2_CHECKSUM_SIZE);
|
||||
// Request nonce
|
||||
HMAC_Update(&hmac_ctx, n2_in_buffer + paramSize - N2_AUTH_SIZE - N2_CHECKSUM_SIZE,
|
||||
N2_CHECKSUM_SIZE);
|
||||
|
||||
HMAC_Final(&hmac_ctx, n2_out_buffer + N2_HEADER_SIZE + bodyLength + N2_CHECKSUM_SIZE,
|
||||
&outlen);
|
||||
HMAC_CTX_cleanup(&hmac_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL smbus_N2_write(ich9_cmd_t cmd, WORD code, BYTE nbytes, LPBYTE data) {
|
||||
static WORD tag;
|
||||
static WORD paramsize = 0xffff;
|
||||
static WORD command;
|
||||
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BLOCK: {
|
||||
switch (code >> 8) {
|
||||
case 0xcc: {
|
||||
// One extra byte of data is stuffed into the command code
|
||||
n2_in_buffer[n2_in_pointer++] = code & 0xff;
|
||||
memcpy(n2_in_buffer + n2_in_pointer, data, nbytes);
|
||||
n2_in_pointer += nbytes;
|
||||
|
||||
if (paramsize == 0xffff &&
|
||||
n2_in_pointer >= N2_PARAMSIZE_OFFSET + N2_PARAMSIZE_SIZE) {
|
||||
paramsize = ((PWORD)(n2_in_buffer + N2_PARAMSIZE_OFFSET))[0];
|
||||
paramsize = fix_endian(paramsize);
|
||||
}
|
||||
|
||||
if (n2_in_pointer >= paramsize) {
|
||||
tag = ((PWORD)(n2_in_buffer + N2_TAG_OFFSET))[0];
|
||||
tag = fix_endian(tag);
|
||||
command = ((PWORD)(n2_in_buffer + N2_COMMAND_OFFSET))[0];
|
||||
command = fix_endian(command);
|
||||
|
||||
do_n2_command(tag, paramsize, command, &n2_in_buffer[N2_HEADER_SIZE]);
|
||||
paramsize = 0xffff;
|
||||
n2_in_pointer = n2_out_pointer = 0;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
log_error("smb-n2", "Unsupported command code: %04x (%d bytes)", code, nbytes);
|
||||
return FALSE;
|
||||
}
|
||||
case ICH9_CMD_I2C_READ: {
|
||||
switch (code) {
|
||||
case 0xc3: {
|
||||
memcpy(data, n2_out_buffer + n2_out_pointer, nbytes);
|
||||
n2_out_pointer += nbytes;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
log_error("smb-n2", "Unsupported i2c command code: %04x (%d bytes)", code, nbytes);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
log_error("smb-n2", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL smbus_N2_read(ich9_cmd_t cmd, WORD code, BYTE nbytes, BYTE* data) {
|
||||
log_error("smb-n2", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
126
src/micetools/dll/devices/smb_pca9535.c
Normal file
126
src/micetools/dll/devices/smb_pca9535.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include "_devices.h"
|
||||
|
||||
uint16_t pca9535_config = 0xffff;
|
||||
|
||||
BOOL smbus_PCA9535_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case PCA9535_IN0:
|
||||
log_error("pca9535", "Write PCA9535_IN0 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_IN1:
|
||||
log_error("pca9535", "Write PCA9535_IN1 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_OUT0:
|
||||
log_info("pca9535", "Out 0: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_OUT1:
|
||||
log_info("pca9535", "Out 1: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_INV0:
|
||||
log_info("pca9535", "Inv 0: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_INV1:
|
||||
log_info("pca9535", "Inv 1: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_CONF0:
|
||||
log_info("pca9535", "Conf 0: %02x", data[0]);
|
||||
pca9535_config = (data[0] << 8) | (pca9535_config & 0xff);
|
||||
return TRUE;
|
||||
case PCA9535_CONF1:
|
||||
log_info("pca9535", "Conf 1: %02x", data[0]);
|
||||
pca9535_config = data[0] | (pca9535_config & 0xff00);
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("pca9535", "Unknown write command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("pca9535", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#define DIPSW_PORTRAIT 0b0000'0'000
|
||||
#define DIPSW_LANDSCAPE 0b0000'1'000
|
||||
|
||||
#define DIPSW_RES_1920x1080 0b0'111'0000
|
||||
#define DIPSW_RES_1360x768 0b0'110'0000
|
||||
#define DIPSW_RES_1280x1024 0b0'101'0000
|
||||
#define DIPSW_RES_1280x720 0b0'100'0000
|
||||
#define DIPSW_RES_1024x768 0b0'011'0000
|
||||
#define DIPSW_RES_1024x600 0b0'010'0000
|
||||
#define DIPSW_RES_640x480 0b0'001'0000
|
||||
#define DIPSW_RES_DEFAULT 0b0'000'0000
|
||||
|
||||
BOOL smbus_PCA9535_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) {
|
||||
switch (cmd) {
|
||||
case ICH9_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case PCA9535_IN0: // DIPSW
|
||||
/*
|
||||
0: ?
|
||||
1: ?
|
||||
2: ?
|
||||
3: Orientation
|
||||
4: / \
|
||||
5: | Resolution |
|
||||
6: \ /
|
||||
7: game specific
|
||||
|
||||
0b00001000 = landscape
|
||||
*/
|
||||
// data[0] = 0b00001000;
|
||||
// data[0] = 0b0'111'0'000;
|
||||
|
||||
data[0] = DIPSW_LANDSCAPE | DIPSW_RES_DEFAULT;
|
||||
|
||||
return TRUE;
|
||||
case PCA9535_IN1: // SW1/2 + extras
|
||||
/*
|
||||
0: unk
|
||||
1: unk
|
||||
2: ¬test
|
||||
3: ¬service
|
||||
4: unk
|
||||
5: unk
|
||||
6: unk
|
||||
7: unk
|
||||
*/
|
||||
byte dip = 0x00;
|
||||
if (GetAsyncKeyState('T') >= 0) {
|
||||
dip |= 0x04;
|
||||
}
|
||||
if (GetAsyncKeyState('S') >= 0) {
|
||||
dip |= 0x08;
|
||||
}
|
||||
data[0] = dip;
|
||||
return TRUE;
|
||||
case PCA9535_OUT0:
|
||||
log_error("pca9535", "Read PCA9535_OUT0 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_OUT1:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_INV0:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_INV1:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_CONF0:
|
||||
data[0] = pca9535_config >> 8;
|
||||
return TRUE;
|
||||
case PCA9535_CONF1:
|
||||
data[0] = pca9535_config & 0xff;
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("pca9535", "Unknown read command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("pca9535", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -4,46 +4,85 @@
|
||||
#include "hooks/_hooks.h"
|
||||
|
||||
WCHAR exePath[MAX_PATH + 1];
|
||||
DWORD imageOffset;
|
||||
|
||||
#define WIN32_EXE_BASE 0x00400000
|
||||
|
||||
DWORD GetImageBase(LPCWSTR sModulePath) {
|
||||
HANDLE hObject =
|
||||
_CreateFileW(sModulePath, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hObject == INVALID_HANDLE_VALUE) return 0;
|
||||
|
||||
IMAGE_DOS_HEADER dosHeader = { 0 };
|
||||
DWORD nRead;
|
||||
_SetFilePointer(hObject, 0, NULL, FILE_BEGIN);
|
||||
_ReadFile(hObject, &dosHeader, sizeof dosHeader, &nRead, NULL);
|
||||
if (nRead != sizeof dosHeader) {
|
||||
log_error(BOOT_LOGGER, "Failed to read DOS header %03x", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
|
||||
log_error(BOOT_LOGGER, "Invalid DOS magic number: %04x", dosHeader.e_magic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMAGE_NT_HEADERS32 ntHeaders32 = { 0 };
|
||||
_SetFilePointer(hObject, dosHeader.e_lfanew, NULL, FILE_BEGIN);
|
||||
_ReadFile(hObject, &ntHeaders32, sizeof ntHeaders32, &nRead, NULL);
|
||||
if (nRead != sizeof ntHeaders32) {
|
||||
log_error(BOOT_LOGGER, "Failed to read NT header %03x", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
if (ntHeaders32.Signature != IMAGE_NT_SIGNATURE) {
|
||||
log_error(BOOT_LOGGER, "Invalid NT signature: %08x", ntHeaders32.Signature);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_CloseHandle(hObject);
|
||||
return ntHeaders32.OptionalHeader.ImageBase;
|
||||
}
|
||||
|
||||
void apply_patches(HMODULE hModule) {
|
||||
void* baseAddress = (void*)hModule;
|
||||
|
||||
DWORD imageBase = GetImageBase(exePath);
|
||||
if (imageBase == 0) {
|
||||
log_error(BOOT_LOGGER, "Failed to locate image base. Patches will not be applied.");
|
||||
return;
|
||||
}
|
||||
imageOffset = (DWORD)hModule - imageBase;
|
||||
|
||||
void apply_patches() {
|
||||
char exePathC[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL);
|
||||
|
||||
patches_t patches;
|
||||
char error[256];
|
||||
if (!load_patches(&patches, MiceConfig.mice.patches_file, error, exePathC)) {
|
||||
log_error(BOOT_LOGGER, "Failed to load patches file: %s", error);
|
||||
if (!load_patches(MiceConfig.mice.patches_file, exePathC)) {
|
||||
log_error(BOOT_LOGGER, "Failed to load patches file %s", MiceConfig.mice.patches_file);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < patches.nopatchsets; i++) {
|
||||
patchset_t* patchset = patches.patchsets[i];
|
||||
patch_t* patch = patch_list->next;
|
||||
if (patch == NULL) {
|
||||
log_warning(BOOT_LOGGER, "No patches to apply. Did you forgot an amiDebug patch file?");
|
||||
}
|
||||
while (patch) {
|
||||
DWORD oldProt;
|
||||
VirtualProtect((void*)((DWORD)patch->address + imageOffset), patch->count,
|
||||
PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
|
||||
// Require the binary explicitly named
|
||||
if (patchset->binary_name == NULL || strcmp(patchset->binary_name, exePathC) != 0) {
|
||||
if (memcmp(patch->match, (void*)((DWORD)patch->address + imageOffset), patch->count) != 0) {
|
||||
log_error(BOOT_LOGGER, "Patch %s failed! from-value missmatch", patch->name);
|
||||
VirtualProtect((void*)((DWORD)patch->address + imageOffset), patch->count, oldProt,
|
||||
&oldProt);
|
||||
patch = patch->next;
|
||||
continue;
|
||||
}
|
||||
if (!patchset->apply) continue;
|
||||
|
||||
for (size_t j = 0; j < patchset->nopatches; j++) {
|
||||
patch_t patch = patchset->patches[j];
|
||||
memcpy((void*)((DWORD)patch->address + imageOffset), patch->replace, patch->count);
|
||||
log_misc(BOOT_LOGGER, "Patched %d bytes at %08x (%s)", patch->count, patch->address,
|
||||
patch->name);
|
||||
|
||||
DWORD oldProt;
|
||||
VirtualProtect((void*)patch.offset, patch.count, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
|
||||
if (memcmp(patch.from, (void*)patch.offset, patch.count) != 0) {
|
||||
log_error(BOOT_LOGGER, "Patch %s[%d] failed! from-value missmatch", patchset->name,
|
||||
j);
|
||||
VirtualProtect((void*)patch.offset, patch.count, oldProt, &oldProt);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy((void*)patch.offset, patch.to, patch.count);
|
||||
log_misc(BOOT_LOGGER, "Patched %d bytes at %08x", patch.count, patch.offset);
|
||||
VirtualProtect((void*)patch.offset, patch.count, oldProt, &oldProt);
|
||||
}
|
||||
patch = patch->next;
|
||||
}
|
||||
free_patches(&patches);
|
||||
}
|
||||
|
||||
void prebind_hooks() {
|
||||
@ -58,14 +97,17 @@ void prebind_hooks() {
|
||||
}
|
||||
}
|
||||
|
||||
void init_injection() {
|
||||
void init_injection(HMODULE hModule) {
|
||||
// Make sure our CRC32 tables are ready for anything that might want to use them
|
||||
amCrc32RCreateTable();
|
||||
|
||||
load_mice_config();
|
||||
|
||||
// We're in a new context now, so need to reconfigure
|
||||
setup_logging();
|
||||
log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath);
|
||||
|
||||
if (MiceConfig.mice.apply_patches) apply_patches();
|
||||
if (MiceConfig.mice.apply_patches) apply_patches(hModule);
|
||||
|
||||
// Columba: Driver-level memory access, used to read the DMI tables
|
||||
if (MiceConfig.drivers.columba) setup_columba();
|
||||
@ -106,12 +148,18 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
|
||||
GetModuleFileNameW(NULL, exePath, MAX_PATH);
|
||||
wcscpy_s(exePath, MAX_PATH + 1, PathFindFileNameW(exePath));
|
||||
|
||||
init_injection();
|
||||
HMODULE exeModule = GetModuleHandleA(NULL);
|
||||
init_injection(exeModule);
|
||||
|
||||
if (wcscmp(exePath, L"InitialD8_GLW_RE_SBZZ_dumped_.exe") == 0) {
|
||||
CreateHook((void*)(0x00407850), &tea_hook_test, 5);
|
||||
// *((DWORD*)(0x00407850)) = (DWORD)(&logcb);
|
||||
}
|
||||
|
||||
if (wcscmp(exePath, L"RingGame.exe") == 0) {
|
||||
log_warning(BOOT_LOGGER, "Bodge hook goo!");
|
||||
CreateHook((void*)(0x005f2580), &tea_hook_test, 5);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1,36 +1,29 @@
|
||||
#include "../lib/am/amOemstring.h"
|
||||
#include "../lib/dmi/dmi.h"
|
||||
#include "mx.h"
|
||||
|
||||
// Much easier than pulling in winddk.h
|
||||
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
||||
typedef struct {
|
||||
PHYSICAL_ADDRESS addr;
|
||||
DWORD data_type;
|
||||
DWORD bytes;
|
||||
} columba_request;
|
||||
|
||||
#define DMI_HEADER_START 0x000f0000
|
||||
#define DMI_TABLES_START 0x000f1000
|
||||
|
||||
BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL WINAPI columba_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_COLUMBA_READ:
|
||||
log_misc("columba", "DeviceIoControl(<columba>, <read>, 0x%p, 0x%x, -, 0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
columba_request* request = (columba_request*)lpInBuffer;
|
||||
log_info("columba", "Physical read: 0x%04x %ss at %08X", request->bytes,
|
||||
request->data_type == 1 ? "byte"
|
||||
: request->data_type == 2 ? "short"
|
||||
: request->data_type == 4 ? "long"
|
||||
: "void",
|
||||
request->addr);
|
||||
DWORD requested_size = request->data_type * request->bytes;
|
||||
AM_COLUMBA_REQUEST* request = (AM_COLUMBA_REQUEST*)lpInBuffer;
|
||||
log_info("columba", "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"
|
||||
: "void",
|
||||
request->m_physAddr.QuadPart);
|
||||
DWORD requested_size = request->m_elementSize * request->m_elementCount;
|
||||
|
||||
memset(lpOutBuffer, 0, nOutBufferSize);
|
||||
|
||||
if (request->addr.QuadPart == DMI_HEADER_START) {
|
||||
if (request->m_physAddr.QuadPart == DMI_HEADER_START) {
|
||||
DMI_HEADER dmi = {
|
||||
.Signature = { '_', 'D', 'M', 'I', '_' },
|
||||
.Checksum = 0,
|
||||
@ -44,12 +37,12 @@ BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
|
||||
memcpy(lpOutBuffer, &dmi, sizeof(DMI_HEADER));
|
||||
if (lpBytesReturned) *lpBytesReturned = requested_size;
|
||||
} else if (request->addr.QuadPart == DMI_TABLES_START) {
|
||||
} else if (request->m_physAddr.QuadPart == DMI_TABLES_START) {
|
||||
memcpy(lpOutBuffer, dmi_table, dmi_size);
|
||||
if (lpBytesReturned) *lpBytesReturned = 0x10000;
|
||||
} else {
|
||||
log_error("columba", "Request to unmapped memory location: %08x",
|
||||
request->addr);
|
||||
request->m_physAddr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "mx.h"
|
||||
|
||||
BOOL mxhwreset_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
BOOL WINAPI mxhwreset_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
|
@ -8,55 +8,44 @@ BOOL JVS_SENSE = false;
|
||||
BOOL coin_solenoid = false;
|
||||
BOOL test_btn = false;
|
||||
|
||||
// #define SCAN_COIN 0x70
|
||||
#define SCAN_TEST VK_OEM_4 // [{
|
||||
// 2 Players, 16 buttons each
|
||||
int jvs_buttons[2][16] = {
|
||||
{
|
||||
'C', // *1P3
|
||||
'P', // NC
|
||||
'E', // *1P1
|
||||
'D', // *1P2
|
||||
'P', // NC
|
||||
'P', // NC
|
||||
'1', // *1P Service
|
||||
'P', // NC
|
||||
'P', // --
|
||||
'P', // --
|
||||
'P', // --
|
||||
'W', // *1P8
|
||||
'Q', // *1P7
|
||||
'A', // *1P6
|
||||
'Z', // *1P5
|
||||
'X', // *1P4
|
||||
},
|
||||
{
|
||||
VK_OEM_PERIOD, // *2P3
|
||||
'P', // NC
|
||||
'O', // *2P1
|
||||
'L', // *2P2
|
||||
'P', // NC
|
||||
'P', // NC
|
||||
'2', // *2P Service
|
||||
'P', // NC
|
||||
'P', // --
|
||||
'P', // --
|
||||
'P', // --
|
||||
'I', // *2P8
|
||||
'U', // *2P7
|
||||
'J', // *2P6
|
||||
'M', // *2P5
|
||||
VK_OEM_COMMA, // *2P4
|
||||
},
|
||||
};
|
||||
#define PLAYER_COUNT 2
|
||||
#define COIN_COUNTERS 2
|
||||
|
||||
const char JVS_837_13551_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
|
||||
|
||||
typedef struct _jvs_board {
|
||||
char test_keybind;
|
||||
char coin_keybinds[COIN_COUNTERS];
|
||||
|
||||
char keybinds[PLAYER_COUNT][16];
|
||||
unsigned char flags[PLAYER_COUNT][16];
|
||||
|
||||
unsigned short coin_counts[COIN_COUNTERS];
|
||||
|
||||
unsigned char (*handler)(struct _jvs_board* board, unsigned char* inData, short inCount,
|
||||
unsigned char* outData, unsigned char* outCount);
|
||||
const char* id;
|
||||
|
||||
} jvs_board_t;
|
||||
#define JVS_FLAG_NONE 0
|
||||
#define JVS_FLAG_NC 1
|
||||
#define JVS_FLAG_INVERT 2
|
||||
|
||||
jvs_board_t (*jvs_config)[];
|
||||
size_t jvs_num_boards;
|
||||
|
||||
// unsigned short coin_data[COIN_COUNTERS];
|
||||
// #define JVS_BUTTON_COIN_1 '1'
|
||||
// #define JVS_BUTTON_COIN_2 '2'
|
||||
|
||||
short jvs_unpad(unsigned char* paddedData, short length, unsigned char* unpaddedData) {
|
||||
short index = 0;
|
||||
bool escape = false;
|
||||
for (short i = 0; i < length; i++) {
|
||||
if (escape)
|
||||
if (escape) {
|
||||
unpaddedData[index++] = paddedData[i] + 1;
|
||||
else if (paddedData[i] == JVS_MARK)
|
||||
escape = false;
|
||||
} else if (paddedData[i] == JVS_MARK)
|
||||
escape = true;
|
||||
else
|
||||
unpaddedData[index++] = paddedData[i];
|
||||
@ -80,80 +69,41 @@ short jvs_pad(unsigned char* unpaddedData, short length, unsigned char* paddedDa
|
||||
return index;
|
||||
}
|
||||
|
||||
const char JVS_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
|
||||
unsigned char jvs_exchange(jvs_board_t* board, unsigned char* inData, short inCount,
|
||||
unsigned char* response, unsigned char* outCount) {
|
||||
short jvsIndex = 0;
|
||||
unsigned char respIndex = 0;
|
||||
|
||||
void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outData, short maxOut,
|
||||
int* outCount) {
|
||||
unsigned char* inData = malloc(inCount);
|
||||
inCount = jvs_unpad(paddedIn, inCount, inData);
|
||||
unsigned char* response = malloc(maxOut);
|
||||
|
||||
unsigned char status = JVS_STATUS_OK;
|
||||
|
||||
// JVS frame is 4 bytes in total
|
||||
if (inCount < 4) {
|
||||
log_error("mxjvs", "inCount impossibly small: %d", inCount);
|
||||
status = JVS_STATUS_UNKNOWN;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
// This isn't a JVS packet
|
||||
if (inData[0] != JVS_SYNC) {
|
||||
log_error("mxjvs", "SYNC missing. Saw 0x%02x", inData[0]);
|
||||
status = JVS_STATUS_UNKNOWN;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
|
||||
// Validate the checksum before proceeding
|
||||
unsigned char sum = 0;
|
||||
for (int i = 1; i < inCount - 1; i++) sum += inData[i];
|
||||
if (sum != inData[inCount - 1]) {
|
||||
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum,
|
||||
inData[inCount - 1]);
|
||||
status = JVS_STATUS_SUM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
|
||||
unsigned char destination = inData[1];
|
||||
unsigned char length = inData[2];
|
||||
// length 0 is nonsensical because there's a checksum!
|
||||
if (length == 0) {
|
||||
status = JVS_STATUS_SUM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
short jvsIndex = 3; // D0
|
||||
|
||||
response[0] = JVS_SYNC;
|
||||
response[1] = JVS_NODE_MASTER;
|
||||
short respIndex = 4; // D0
|
||||
#define jvs_read(x) \
|
||||
if (jvsIndex - 2 >= length) { \
|
||||
status = JVS_STATUS_OVERFLOW; \
|
||||
goto jvs_exchange_error; \
|
||||
} else { \
|
||||
(x) = inData[jvsIndex++]; \
|
||||
#define jvs_read(x) \
|
||||
if (jvsIndex >= inCount) { \
|
||||
return JVS_STATUS_OVERFLOW; \
|
||||
} else { \
|
||||
(x) = inData[jvsIndex++]; \
|
||||
}
|
||||
#define jvs_write(x) response[respIndex++] = (x);
|
||||
|
||||
while (jvsIndex - 2 < length) {
|
||||
static bool flipflop = false;
|
||||
|
||||
while (jvsIndex < inCount) {
|
||||
unsigned char cmd;
|
||||
jvs_read(cmd);
|
||||
// log_info("jvs", "jvs cmd: %02x", cmd);
|
||||
|
||||
// log_info("mxjvs", "CMD: %02x", cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case JVS_CMD_RESET:
|
||||
unsigned char reset_assert;
|
||||
jvs_read(reset_assert);
|
||||
if (reset_assert != JVS_CMD_RESET_ASSERT) {
|
||||
status = JVS_STATUS_UKCOM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
if (reset_assert != JVS_CMD_RESET_ASSERT) return JVS_STATUS_UKCOM;
|
||||
|
||||
JVS_SENSE = true;
|
||||
// Special case
|
||||
*outCount = 0;
|
||||
return;
|
||||
return JVS_STATUS_OK;
|
||||
case JVS_CMD_CHANGE_COMMS:
|
||||
// Special case
|
||||
*outCount = 0;
|
||||
return;
|
||||
return JVS_STATUS_OK;
|
||||
|
||||
case JVS_CMD_ASSIGN_ADDR:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
@ -166,7 +116,7 @@ void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outDa
|
||||
|
||||
case JVS_CMD_READ_ID:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
for (int i = 0; i < sizeof JVS_ID; i++) jvs_write(JVS_ID[i]);
|
||||
for (size_t i = 0; i < strlen(board->id); i++) jvs_write(board->id[i]);
|
||||
break;
|
||||
case JVS_CMD_GET_CMD_VERSION:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
@ -185,11 +135,11 @@ void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outDa
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
|
||||
jvs_write(JVS_FEATURE_PLAYERS);
|
||||
jvs_write(2);
|
||||
jvs_write(PLAYER_COUNT);
|
||||
jvs_write(13);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_COINS);
|
||||
jvs_write(2);
|
||||
jvs_write(COIN_COUNTERS);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_ANALOG);
|
||||
@ -215,43 +165,30 @@ void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outDa
|
||||
unsigned char switch_bytes;
|
||||
jvs_read(players);
|
||||
jvs_read(switch_bytes);
|
||||
if (players > 2 || switch_bytes != 2) {
|
||||
if (players > PLAYER_COUNT || switch_bytes != 2) {
|
||||
jvs_write(JVS_REPORT_PARAM_INVALID);
|
||||
break;
|
||||
}
|
||||
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
unsigned char buttons = 0x00;
|
||||
if (GetAsyncKeyState(SCAN_TEST) < 0) buttons |= 0x80;
|
||||
if (GetAsyncKeyState(board->test_keybind) < 0) buttons |= 0x80;
|
||||
jvs_write(buttons);
|
||||
|
||||
for (int i = 0; i < players; i++) {
|
||||
for (int player = 0; player < players; player++) {
|
||||
for (int j = 0; j < switch_bytes; j++) {
|
||||
buttons = 0x00;
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int scancode = jvs_buttons[i][j * 8 + bit];
|
||||
int scancode =
|
||||
board->keybinds[player][(switch_bytes - j - 1) * 8 + bit];
|
||||
unsigned char flags =
|
||||
board->flags[player][(switch_bytes - j - 1) * 8 + bit];
|
||||
|
||||
// Buttons on maimai use beam interrupt sensors, so logical high =
|
||||
// unpressed.
|
||||
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) ||
|
||||
(j == 1 && bit >= 3));
|
||||
|
||||
if (invert)
|
||||
if (flags & JVS_FLAG_NC) continue;
|
||||
if (flags & JVS_FLAG_INVERT)
|
||||
buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
|
||||
else
|
||||
buttons |= (GetAsyncKeyState(scancode) < 0) << bit;
|
||||
|
||||
// JAMMA does **NOT** do any of this lol
|
||||
// Service is pull-down for some reason
|
||||
// bool pulse = (j == 0) && (bit == 6);
|
||||
// // JAMMA uses the falling edge of a pull-up switch
|
||||
// if (pulse) {
|
||||
// buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
|
||||
// buttons |= (!(GetAsyncKeyState(scancode) & 1)) << bit;
|
||||
// } else {
|
||||
// buttons |= (GetAsyncKeyState(scancode) < 0) << bit;
|
||||
// buttons |= (GetAsyncKeyState(scancode) & 1) << bit;
|
||||
// }
|
||||
}
|
||||
jvs_write(buttons);
|
||||
}
|
||||
@ -263,9 +200,15 @@ void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outDa
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
unsigned char coin_count;
|
||||
jvs_read(coin_count);
|
||||
for (; coin_count; coin_count--) {
|
||||
jvs_write(0x00); // coin MSB
|
||||
jvs_write(0x00); // coin LSB
|
||||
|
||||
if (board->coin_keybinds[0] && GetAsyncKeyState(board->coin_keybinds[0]) & 1)
|
||||
board->coin_counts[0]++;
|
||||
if (board->coin_keybinds[1] && GetAsyncKeyState(board->coin_keybinds[1]) & 1)
|
||||
board->coin_counts[1]++;
|
||||
|
||||
for (unsigned char slot = 0; slot < coin_count; slot++) {
|
||||
jvs_write(board->coin_counts[slot] >> 8);
|
||||
jvs_write(board->coin_counts[slot] & 0xff);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -300,44 +243,117 @@ void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outDa
|
||||
}
|
||||
break;
|
||||
|
||||
case JVS_CMD_COIN_DECREASE:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
|
||||
unsigned char slot;
|
||||
jvs_read(slot);
|
||||
unsigned char cAmount[2];
|
||||
jvs_read(cAmount[0]);
|
||||
jvs_read(cAmount[1]);
|
||||
unsigned short sAmount = cAmount[0] << 8 | cAmount[1];
|
||||
board->coin_counts[slot] -= sAmount;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("mxjvs", "Unknown command: 0x%02x", cmd);
|
||||
|
||||
status = JVS_STATUS_UKCOM;
|
||||
goto jvs_exchange_error;
|
||||
return JVS_STATUS_UKCOM;
|
||||
}
|
||||
}
|
||||
#undef jvs_read
|
||||
#undef jvs_write
|
||||
|
||||
goto jvs_exchange_complete;
|
||||
jvs_exchange_error:
|
||||
log_error("mxjvs", "JVS status: 0x%02x", status);
|
||||
respIndex = 4; // As if we've just written status, but nothing else
|
||||
|
||||
jvs_exchange_complete:
|
||||
response[2] = (respIndex - 2) & 0xFF; // respIndex doesn't include SUM yet
|
||||
response[3] = status;
|
||||
|
||||
// Compute and set the checksum
|
||||
sum = 0;
|
||||
for (int i = 1; i < respIndex; i++) sum += response[i];
|
||||
response[respIndex++] = sum;
|
||||
|
||||
short paddedLength = jvs_pad(response, respIndex, outData, maxOut);
|
||||
// We failed hard. It's not worth sending an overflow response
|
||||
if (paddedLength == -1)
|
||||
*outCount = 0;
|
||||
else
|
||||
*outCount = 0x00000000 | paddedLength;
|
||||
|
||||
free(response);
|
||||
free(inData);
|
||||
*outCount = respIndex;
|
||||
return JVS_STATUS_OK;
|
||||
}
|
||||
|
||||
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
void jvs_send_status(unsigned char status, unsigned char* outData, LPDWORD outCount) {
|
||||
short respIndex = 4;
|
||||
|
||||
outData[0] = JVS_SYNC;
|
||||
outData[1] = JVS_NODE_MASTER;
|
||||
outData[2] = 2;
|
||||
if (status == JVS_MARK || status == JVS_SYNC) {
|
||||
outData[3] = JVS_MARK;
|
||||
outData[4] = status - 1;
|
||||
outData[5] = JVS_NODE_MASTER + 2 + status;
|
||||
*outCount = 6;
|
||||
} else {
|
||||
outData[3] = status;
|
||||
outData[4] = JVS_NODE_MASTER + 2 + status;
|
||||
*outCount = 5;
|
||||
}
|
||||
}
|
||||
|
||||
void mxjvs_handle(unsigned char* paddedIn, short inCount, unsigned char* outData, short maxOut,
|
||||
LPDWORD outCount) {
|
||||
*outCount = 0;
|
||||
|
||||
unsigned char* inData = malloc(inCount);
|
||||
inCount = jvs_unpad(paddedIn, inCount, inData);
|
||||
|
||||
// JVS frame is 4 bytes in total
|
||||
if (inCount < 4) {
|
||||
log_error("mxjvs", "inCount impossibly small: %d", inCount);
|
||||
jvs_send_status(JVS_STATUS_UNKNOWN, outData, outCount);
|
||||
free(inData);
|
||||
return;
|
||||
}
|
||||
// This isn't a JVS packet
|
||||
if (inData[0] != JVS_SYNC) {
|
||||
log_error("mxjvs", "SYNC missing. Saw 0x%02x", inData[0]);
|
||||
jvs_send_status(JVS_STATUS_UNKNOWN, outData, outCount);
|
||||
free(inData);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the checksum before proceeding
|
||||
unsigned char sum = 0;
|
||||
bool escape = false;
|
||||
for (int i = 1; i < inCount - 1; i++) sum += inData[i];
|
||||
if (sum != inData[inCount - 1]) {
|
||||
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum,
|
||||
inData[inCount - 1]);
|
||||
jvs_send_status(JVS_STATUS_SUM, outData, outCount);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char destination = inData[1];
|
||||
if (destination == 0 || destination > jvs_num_boards) return;
|
||||
|
||||
unsigned char* response = malloc(maxOut);
|
||||
jvs_board_t* board = &(*jvs_config)[jvs_num_boards - destination];
|
||||
unsigned char packetSize;
|
||||
unsigned char status =
|
||||
board->handler(board, inData + 3, inData[2] - 1, response + 4, &packetSize);
|
||||
free(inData);
|
||||
|
||||
if (status == JVS_STATUS_OK) {
|
||||
if (packetSize == 0) return;
|
||||
|
||||
response[0] = JVS_SYNC;
|
||||
response[1] = JVS_NODE_MASTER;
|
||||
response[2] = packetSize + 2;
|
||||
response[3] = status;
|
||||
|
||||
sum = 0;
|
||||
for (int i = 1; i < packetSize + 4; i++) sum += response[i];
|
||||
response[packetSize + 4] = sum;
|
||||
|
||||
short paddedLength = jvs_pad(response, packetSize + 5, outData, maxOut);
|
||||
*outCount = (paddedLength == -1) ? 0 : paddedLength;
|
||||
|
||||
free(response);
|
||||
} else {
|
||||
log_error("mxjvs", "JVS board %d returned status %d", destination, status);
|
||||
free(response);
|
||||
jvs_send_status(status, outData, outCount);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI mxjvs_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXJVS_EXCHANGE:
|
||||
log_trace("mxjvs",
|
||||
@ -345,8 +361,8 @@ BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize & 0xFFFF,
|
||||
(int*)lpBytesReturned);
|
||||
mxjvs_handle(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize & 0xFFFF,
|
||||
lpBytesReturned);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -375,11 +391,231 @@ BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
|
||||
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_13551_ID,
|
||||
} };
|
||||
|
||||
jvs_board_t under_night_jvs_config[2] = {
|
||||
{
|
||||
.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
|
||||
},
|
||||
},
|
||||
.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_13551_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_13551_ID,
|
||||
},
|
||||
};
|
||||
|
||||
// jvs_board_t (*jvs_config)[] = &maimai_jvs_config;
|
||||
// size_t jvs_num_boards = sizeof maimai_jvs_config / sizeof maimai_jvs_config[0];
|
||||
jvs_board_t (*jvs_config)[] = &under_night_jvs_config;
|
||||
size_t jvs_num_boards = sizeof under_night_jvs_config / sizeof under_night_jvs_config[0];
|
||||
|
||||
void setup_mxjvs() {
|
||||
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
|
||||
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl;
|
||||
hook_file(mxjvs);
|
||||
|
||||
com_hook_t* jvscom = new_com_hook(0);
|
||||
com_hook_t* jvscom = new_com_hook(4);
|
||||
wcscpy_s(jvscom->wName, sizeof jvscom->wName, L"\\\\.\\mxjvs");
|
||||
wcscpy_s(jvscom->wDosName, sizeof jvscom->wDosName, L"\\\\.\\mxjvs");
|
||||
jvscom->GetCommState = mxjvs_GetCommState;
|
||||
@ -389,6 +625,9 @@ void setup_mxjvs() {
|
||||
jvscom->PurgeComm = mxjvs_PurgeComm;
|
||||
jvscom->GetCommModemStatus = mxjvs_GetCommModemStatus;
|
||||
|
||||
hook_file(mxjvs);
|
||||
hook_com(jvscom);
|
||||
mxjvs->com_hook = jvscom;
|
||||
|
||||
// TODO: Looks like some things might use JVS on COM4. We should setup a comdevice for this!
|
||||
// file_hook_t* jvscom_file = new_file_hook(jvscom->wName);
|
||||
// hook_file(jvscom_file);
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ uint32_t BILLING_PLAYCOUNT = 69420;
|
||||
overlappedComplete(len); \
|
||||
} while (0)
|
||||
|
||||
BOOL mxparallel_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
BOOL WINAPI mxparallel_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
log_trace("mxparallel", "DeviceIoControl(<mxparallel>, 0x%08x, 0x%p, 0x%x, -, 0x%x, -, -)",
|
||||
@ -155,7 +155,7 @@ void init_nv_storage() {
|
||||
billing_info.nearfull = 512;
|
||||
mxkSignValue(billing_info.nearfull, billing_info.nearfull_sig);
|
||||
mxkSignValue(billing_info.playlimit, billing_info.playlimit_sig);
|
||||
billing_info.crc = crc32(sizeof billing_info - 4, (unsigned char*)&billing_info + 4, 0);
|
||||
billing_info.crc = amCrc32RGet(sizeof billing_info - 4, (unsigned char*)&billing_info + 4, 0);
|
||||
|
||||
memcpy(&flash[0x7a000], &billing_info, sizeof billing_info);
|
||||
memcpy(&flash[0x7b000], &billing_info, sizeof billing_info);
|
||||
@ -263,7 +263,7 @@ void mxparallel_process_packet(BYTE* request) {
|
||||
log_warning("mxparallel", "GetAppBootInfo[%d] unexpected!", request[1]);
|
||||
}
|
||||
|
||||
APPBOOT.crc = crc32(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0);
|
||||
APPBOOT.crc = amCrc32RGet(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0);
|
||||
for (int i = 0; i < sizeof APPBOOT; i += 16) {
|
||||
micexkSendPacket((unsigned char*)(&APPBOOT) + i);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "../../lib/mxk/mxk.h"
|
||||
#include "mx.h"
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint32_t crc;
|
||||
uint32_t playlimit;
|
||||
@ -11,11 +11,11 @@ typedef struct {
|
||||
uint32_t nearfull;
|
||||
uint8_t nearfull_sig[128];
|
||||
} billing_t;
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
uint32_t length;
|
||||
uint8_t data[0x400 - 4];
|
||||
} nvram_data_block_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
void micexkTransportSend(unsigned char* send_data, int nbytes);
|
||||
|
@ -3,531 +3,70 @@
|
||||
#include "mx.h"
|
||||
#include "smbus.h"
|
||||
|
||||
#define EEPROM_DUMP L"dev/eeprom.bin"
|
||||
typedef struct eeprom_reg {
|
||||
BYTE data[32];
|
||||
} eeprom_reg_t;
|
||||
typedef struct eeprom_bank {
|
||||
eeprom_reg_t reg[0x100];
|
||||
} eeprom_bank_t;
|
||||
smbus_callback_t* smbus_devices[256] = { NULL };
|
||||
|
||||
// 256 registers, 32 bytes each
|
||||
eeprom_bank_t EEPROM_DATA;
|
||||
|
||||
void eeprom_dump() {
|
||||
HANDLE dump =
|
||||
_CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
|
||||
return;
|
||||
} else {
|
||||
log_info("eeprom", "Wrote eeprom to %ls", EEPROM_DUMP);
|
||||
}
|
||||
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
|
||||
FlushFileBuffers(dump);
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
void eeprom_restore() {
|
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
// Make the file, even though it'll probably be empty
|
||||
eeprom_dump();
|
||||
return;
|
||||
}
|
||||
DWORD read;
|
||||
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL))
|
||||
log_error("eeprom", "failed to restore (%d)", GetLastError());
|
||||
_CloseHandle(dump);
|
||||
void smbus_install(BYTE v_addr, smbus_callback_t* write, smbus_callback_t* read) {
|
||||
smbus_devices[v_addr << 1] = write;
|
||||
smbus_devices[(v_addr << 1) + 1] = read;
|
||||
}
|
||||
|
||||
DWORD eeprom_crc(BYTE reg) {
|
||||
if (reg == 0x04 || reg == 0x14 || reg == 0x80 || reg == 0x280) {
|
||||
// Some registers are only treated as 16 byte values
|
||||
return crc32(12, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||
}
|
||||
|
||||
return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||
}
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
uint32_t checksum;
|
||||
uint8_t pad1[8];
|
||||
uint8_t region;
|
||||
uint8_t pad2[2];
|
||||
char mainId[17];
|
||||
} eeprom_block_1;
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
uint32_t checksum;
|
||||
uint32_t unk;
|
||||
uint32_t dhcp_enabled;
|
||||
uint32_t machine_ip;
|
||||
uint32_t netmask;
|
||||
uint32_t gateway;
|
||||
uint32_t primary_dns;
|
||||
uint32_t secondary_dns;
|
||||
} eeprom_block_3;
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
uint32_t checksum;
|
||||
byte pad[4];
|
||||
char game_id[4];
|
||||
uint32_t unk;
|
||||
} eeprom_block_5_1;
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
uint32_t checksum;
|
||||
uint32_t unk1;
|
||||
uint32_t unk2;
|
||||
uint32_t unk3;
|
||||
} eeprom_block_5_2;
|
||||
|
||||
#define SET_IP(val, a, b, c, d) \
|
||||
do { \
|
||||
*(uint32_t*)&val = (a << 24) | (b << 16) | (c << 8) | d; \
|
||||
} while (0)
|
||||
|
||||
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
eeprom_restore();
|
||||
for (BYTE i = index; i < index + length; i++) {
|
||||
if (i > 0x1f) break;
|
||||
|
||||
BYTE byte = EEPROM_DATA.reg[reg].data[i];
|
||||
|
||||
// TODO: Reg 1 and 17 in the EEPROM are system info. We should fake these!
|
||||
|
||||
if (reg == 0x00 || reg == 0x10) {
|
||||
eeprom_block_1 block;
|
||||
memset(&block, 0, sizeof block);
|
||||
|
||||
block.region = 0b111;
|
||||
strcpy(block.mainId, "AASE-01A65646203");
|
||||
|
||||
block.checksum = crc32(28, (BYTE*)(&block) + 4, 0);
|
||||
|
||||
byte = ((BYTE*)(&block))[i];
|
||||
}
|
||||
if (reg == 0x02) {
|
||||
eeprom_block_3 block;
|
||||
memset(&block, 0, sizeof block);
|
||||
|
||||
// TODO: Load network config!
|
||||
SET_IP(block.machine_ip, 192, 168, 103, 101);
|
||||
SET_IP(block.netmask, 255, 255, 255, 0);
|
||||
SET_IP(block.gateway, 192, 168, 103, 254);
|
||||
SET_IP(block.primary_dns, 192, 168, 103, 254);
|
||||
SET_IP(block.secondary_dns, 0, 0, 0, 0);
|
||||
block.dhcp_enabled = 0;
|
||||
|
||||
block.unk = 4835744;
|
||||
|
||||
block.checksum = crc32(28, (BYTE*)(&block) + 4, 0);
|
||||
|
||||
byte = ((BYTE*)(&block))[i];
|
||||
}
|
||||
if (reg == 0x04) {
|
||||
eeprom_block_5_1 block1;
|
||||
eeprom_block_5_2 block2;
|
||||
|
||||
memset(&block1, 0, sizeof block1);
|
||||
memset(&block2, 0, sizeof block2);
|
||||
block1.game_id[0] = 'S';
|
||||
block1.game_id[1] = 'D';
|
||||
block1.game_id[2] = 'E';
|
||||
block1.game_id[3] = 'Y';
|
||||
|
||||
block2.unk2 = 0xffffffff;
|
||||
block2.unk3 = 0xffffffff;
|
||||
|
||||
block1.checksum = crc32(12, (BYTE*)(&block1) + 4, 0);
|
||||
block2.checksum = crc32(12, (BYTE*)(&block2) + 4, 0);
|
||||
|
||||
if (i < 16)
|
||||
byte = ((BYTE*)(&block1))[i];
|
||||
else
|
||||
byte = ((BYTE*)(&block2))[i - 16];
|
||||
}
|
||||
|
||||
// If register has a CRC
|
||||
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
|
||||
// == 0x11 || reg == 0x12 || reg == 0x200) {
|
||||
if (false) {
|
||||
// Intercept the read and inject a CRC instead
|
||||
if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) {
|
||||
DWORD crc = eeprom_crc(reg);
|
||||
byte = crc >> 8 * i & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
data[i - index] = byte;
|
||||
}
|
||||
}
|
||||
void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
log_misc("eeprom", "write reg=%d idx=%d len=%d", reg, index, length);
|
||||
|
||||
for (BYTE i = index; i < index + length; i++) {
|
||||
if (i > 0x1f) break;
|
||||
EEPROM_DATA.reg[reg].data[i] = data[i - index];
|
||||
}
|
||||
eeprom_dump();
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
SMB_CMD_QUICK = 0b000,
|
||||
SMB_CMD_BYTE = 0b001,
|
||||
SMB_CMD_BYTE_DATA = 0b010,
|
||||
SMB_CMD_WORD_DATA = 0b011,
|
||||
SMB_CMD_PROCESS_CALL = 0b100,
|
||||
SMB_CMD_BLOCK = 0b101,
|
||||
SMB_CMD_I2C_READ = 0b110,
|
||||
SMB_CMD_BLOCK_PROCESS = 0b111,
|
||||
} smb_cmd_t;
|
||||
|
||||
// EEPROM
|
||||
BOOL smbus_AT24C64AN(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) {
|
||||
BOOL read = addr & 1 == 1;
|
||||
if (read) {
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE:
|
||||
data[0] = 0x00;
|
||||
break;
|
||||
case SMB_CMD_BLOCK: {
|
||||
WORD reg = *(WORD*)(&data[-1]);
|
||||
dlen = data[1];
|
||||
log_info("eeprom", "Block read, %d @ %02x", dlen, reg);
|
||||
|
||||
eeprom_read(reg >> 5, reg & 0x1f, &data[2], dlen);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
log_error("eeprom", "Unsupported read mode: %01x, %02x", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BLOCK: {
|
||||
WORD reg = *(WORD*)(&data[-1]);
|
||||
dlen = data[1];
|
||||
log_info("eeprom", "Block write, %d @ %02x", dlen, reg);
|
||||
|
||||
eeprom_write(reg >> 5, reg & 0x1f, &data[2], dlen);
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
log_error("eeprom", "Unsupported write mode: %01x, %02x", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// dipsw
|
||||
BOOL smbus_PCA9535(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) {
|
||||
static uint16_t pca9535_config = 0xffff;
|
||||
|
||||
BOOL read = addr & 1 == 1;
|
||||
if (read) {
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case PCA9535_IN0: // DIPSW
|
||||
/*
|
||||
0: ?
|
||||
1: ?
|
||||
2: ?
|
||||
3: Orientation
|
||||
4: / \
|
||||
5: | Resolution |
|
||||
6: \ /
|
||||
7: game specific
|
||||
|
||||
0b00001000 = landscape
|
||||
*/
|
||||
data[0] = 0b00001000;
|
||||
return TRUE;
|
||||
case PCA9535_IN1: // SW1/2 + extras
|
||||
/*
|
||||
0: unk
|
||||
1: unk
|
||||
2: ¬test
|
||||
3: ¬service
|
||||
4: unk
|
||||
5: unk
|
||||
6: unk
|
||||
7: unk
|
||||
*/
|
||||
byte dip = 0x00;
|
||||
if (GetAsyncKeyState('T') >= 0) {
|
||||
dip |= 0x04;
|
||||
}
|
||||
if (GetAsyncKeyState('S') >= 0) {
|
||||
dip |= 0x08;
|
||||
}
|
||||
data[0] = dip;
|
||||
return TRUE;
|
||||
case PCA9535_OUT0:
|
||||
log_error("pca9535", "Read PCA9535_OUT0 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_OUT1:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_INV0:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_INV1:
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
case PCA9535_CONF0:
|
||||
data[0] = pca9535_config >> 8;
|
||||
return TRUE;
|
||||
case PCA9535_CONF1:
|
||||
data[0] = pca9535_config & 0xff;
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("pca9535", "Unknown read command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("pca9535", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case PCA9535_IN0:
|
||||
log_error("pca9535", "Write PCA9535_IN0 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_IN1:
|
||||
log_error("pca9535", "Write PCA9535_IN1 unimplemented!");
|
||||
return FALSE;
|
||||
case PCA9535_OUT0:
|
||||
log_info("pca9535", "Out 0: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_OUT1:
|
||||
log_info("pca9535", "Out 1: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_INV0:
|
||||
log_info("pca9535", "Inv 0: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_INV1:
|
||||
log_info("pca9535", "Inv 1: %02x", data[0]);
|
||||
return TRUE;
|
||||
case PCA9535_CONF0:
|
||||
log_info("pca9535", "Conf 0: %02x", data[0]);
|
||||
pca9535_config = (data[0] << 8) | (pca9535_config & 0xff);
|
||||
return TRUE;
|
||||
case PCA9535_CONF1:
|
||||
log_info("pca9535", "Conf 1: %02x", data[0]);
|
||||
pca9535_config = data[0] | (pca9535_config & 0xff00);
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("pca9535", "Unknown write command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("pca9535", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Very incomplete keychip
|
||||
BOOL smbus_N2(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) {
|
||||
static unsigned char challenge[7];
|
||||
static unsigned char n2_eeprom[3][0x20];
|
||||
|
||||
BOOL read = addr & 1 == 1;
|
||||
if (read) {
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE_DATA:
|
||||
if (code < 0x80) {
|
||||
BYTE page = (code >> 5) & 0b11;
|
||||
BYTE offset = code & 0x1f;
|
||||
|
||||
data[0] = n2_eeprom[page][offset];
|
||||
|
||||
return TRUE;
|
||||
} else if (code >= N2_GET_UNIQUE_NUMBER && code < N2_GET_UNIQUE_NUMBER + 0xf) {
|
||||
data[0] = 0x04; // chosen by fair dice roll.
|
||||
return TRUE;
|
||||
} else if (code == N2_GET_STATUS) {
|
||||
// Polled until N2_STATUS_FLAG_BUSY low
|
||||
data[0] = 0x00;
|
||||
return TRUE;
|
||||
} else {
|
||||
log_error("smb-keychip", "Unknown read command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("smb-keychip", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BLOCK: {
|
||||
WORD reg = *(WORD*)(&data[-1]);
|
||||
dlen = data[1];
|
||||
|
||||
if (dlen != 7) {
|
||||
log_error("smb-keychip", "Expected challenge length of 7 (saw %d)!", dlen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy(challenge, &(data[2]), 7);
|
||||
|
||||
char* challenge_s = malloc(dlen * 3 + 1);
|
||||
for (int i = 0; i < dlen; i++) {
|
||||
sprintf(challenge_s + i * 3, "%02x ", data[2 + i]);
|
||||
}
|
||||
challenge_s[dlen * 3 + 1] = '\0';
|
||||
log_info("smb-keychip", "Challenge: %s", challenge_s);
|
||||
free(challenge_s);
|
||||
return TRUE;
|
||||
}
|
||||
case SMB_CMD_I2C_READ: {
|
||||
switch (code) {
|
||||
case N2_I2C_CHALLENGE_RESPONSE:
|
||||
// This just has to match EXIO!
|
||||
for (int i = 0; i < dlen; i++) data[i] = 0x69;
|
||||
return TRUE;
|
||||
default:
|
||||
log_error("smb-keychip", "Unknown I2C command: %02x", code);
|
||||
}
|
||||
}
|
||||
default:
|
||||
log_error("smb-keychip", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
BOOL smbus_EXIO(BYTE addr, smb_cmd_t cmd, BYTE code, BYTE dlen, BYTE* data) {
|
||||
BOOL read = addr & 1 == 1;
|
||||
if (read) {
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE_DATA:
|
||||
if (0x40 <= code < 0x40 + 0x14) {
|
||||
// mxkDsExioReadMacOutputBuffer
|
||||
// This just has to match N2_I2C_CHALLENGE_RESPONSE!
|
||||
data[0] = 0x69;
|
||||
return TRUE;
|
||||
} else if (code == EXIO_GET_BUSY) {
|
||||
data[0] = 0x00; // Anything non-zero = busy
|
||||
return TRUE;
|
||||
} else {
|
||||
log_error("smx-exio", "Unknown read command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
default:
|
||||
log_error("smb-exio", "Unsupported read mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SMB_CMD_BYTE_DATA:
|
||||
switch (code) {
|
||||
case 0x5c:
|
||||
if (data[0] == 0x94) return TRUE;
|
||||
default:
|
||||
log_error("smb-exio", "Unknown write command: %02x", code);
|
||||
return FALSE;
|
||||
}
|
||||
case SMB_CMD_BLOCK: {
|
||||
WORD reg = *(WORD*)(&data[-1]);
|
||||
dlen = data[1];
|
||||
|
||||
char* data_s = malloc(dlen * 3 + 1);
|
||||
for (int i = 0; i < dlen; i++) {
|
||||
sprintf(data_s + i * 3, "%02x ", data[2 + i]);
|
||||
}
|
||||
data_s[dlen * 3 + 1] = '\0';
|
||||
|
||||
log_info("smb-exio", "Block write, %d @ %04x: %s", dlen, reg, data_s);
|
||||
free(data_s);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
default:
|
||||
log_error("smb-exio", "Unsupported write mode: %01x (%02x)", cmd, code);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL handle_smbus(BYTE* request) {
|
||||
BYTE command = request[1];
|
||||
BYTE v_addr = request[2] & 0x7f;
|
||||
BYTE command_code = request[3];
|
||||
|
||||
BYTE p_addr = request[2] << 1;
|
||||
smb_cmd_t smb_cmd = SMB_CMD_QUICK;
|
||||
BOOL handle_smbus(BYTE command, WORD v_addr, WORD command_code, BYTE nbytes, BYTE* data) {
|
||||
WORD p_addr = (v_addr & 0x7fff) << 1;
|
||||
ich9_cmd_t smb_cmd = ICH9_CMD_QUICK;
|
||||
switch (command) {
|
||||
case 0:
|
||||
case MXSMBUS_CMD_WRITE_QUICK:
|
||||
break;
|
||||
case 1:
|
||||
case MXSMBUS_CMD_READ_QUICK:
|
||||
p_addr++;
|
||||
break;
|
||||
case 2:
|
||||
smb_cmd = SMB_CMD_BYTE;
|
||||
case MXSMBUS_CMD_WRITE_BYTE:
|
||||
smb_cmd = ICH9_CMD_BYTE;
|
||||
break;
|
||||
case 3:
|
||||
case MXSMBUS_CMD_READ_BYTE:
|
||||
p_addr++;
|
||||
smb_cmd = SMB_CMD_BYTE;
|
||||
smb_cmd = ICH9_CMD_BYTE;
|
||||
break;
|
||||
case 4:
|
||||
smb_cmd = SMB_CMD_BYTE_DATA;
|
||||
case MXSMBUS_CMD_WRITE_BYTE_DATA:
|
||||
smb_cmd = ICH9_CMD_BYTE_DATA;
|
||||
break;
|
||||
case 5:
|
||||
case MXSMBUS_CMD_READ_BYTE_DATA:
|
||||
p_addr++;
|
||||
smb_cmd = SMB_CMD_BYTE_DATA;
|
||||
smb_cmd = ICH9_CMD_BYTE_DATA;
|
||||
break;
|
||||
case 6:
|
||||
smb_cmd = SMB_CMD_WORD_DATA;
|
||||
case MXSMBUS_CMD_WRITE_WORD_DATA:
|
||||
smb_cmd = ICH9_CMD_WORD_DATA;
|
||||
break;
|
||||
case 7:
|
||||
case MXSMBUS_CMD_READ_WORD_DATA:
|
||||
p_addr++;
|
||||
smb_cmd = SMB_CMD_WORD_DATA;
|
||||
smb_cmd = ICH9_CMD_WORD_DATA;
|
||||
break;
|
||||
case 8:
|
||||
smb_cmd = SMB_CMD_BLOCK;
|
||||
case MXSMBUS_CMD_WRITE_BLOCK:
|
||||
smb_cmd = ICH9_CMD_BLOCK;
|
||||
break;
|
||||
case 9:
|
||||
case MXSMBUS_CMD_READ_BLOCK:
|
||||
p_addr++;
|
||||
smb_cmd = SMB_CMD_BLOCK;
|
||||
smb_cmd = ICH9_CMD_BLOCK;
|
||||
break;
|
||||
case 10:
|
||||
smb_cmd = SMB_CMD_PROCESS_CALL;
|
||||
case MXSMBUS_CMD_PROCESS_CALL:
|
||||
smb_cmd = ICH9_CMD_PROCESS_CALL;
|
||||
break;
|
||||
case 11:
|
||||
smb_cmd = SMB_CMD_I2C_READ;
|
||||
case MXSMBUS_CMD_I2C:
|
||||
smb_cmd = ICH9_CMD_I2C_READ;
|
||||
break;
|
||||
}
|
||||
|
||||
log_trace("smbus", "Making request to %02X (virtual: %02X/%02x, cmd: %01X, code: %02X)", p_addr,
|
||||
log_trace("smbus", "Making request to %02X (virtual: %04X/%04x, cmd: %01X, code: %04X)", p_addr,
|
||||
v_addr, command, smb_cmd, command_code);
|
||||
|
||||
switch (p_addr) {
|
||||
case SMBUS_EEPROM:
|
||||
case SMBUS_EEPROM + 1:
|
||||
return smbus_AT24C64AN(p_addr, smb_cmd, command_code, request[4], &request[5]);
|
||||
case SMBUS_PCA9535:
|
||||
case SMBUS_PCA9535 + 1:
|
||||
return smbus_PCA9535(p_addr, smb_cmd, command_code, request[4], &request[5]);
|
||||
case SMBUS_N2:
|
||||
case SMBUS_N2 + 1:
|
||||
return smbus_N2(p_addr, smb_cmd, command_code, request[4], &request[5]);
|
||||
case SMBUS_EXIO:
|
||||
case SMBUS_EXIO + 1:
|
||||
return smbus_EXIO(p_addr, smb_cmd, command_code, request[4], &request[5]);
|
||||
default:
|
||||
log_error("smbus", "Request to unregistered address: %02x", p_addr);
|
||||
return FALSE;
|
||||
smbus_callback_t* callback = smbus_devices[p_addr];
|
||||
if (callback == NULL) {
|
||||
log_error("smbus", "Request to unregistered address: %02x", p_addr);
|
||||
return FALSE;
|
||||
}
|
||||
return (*callback)(smb_cmd, command_code, nbytes, data);
|
||||
}
|
||||
|
||||
BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
BOOL WINAPI mxsmbus_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer;
|
||||
@ -547,12 +86,14 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||
break;
|
||||
case IOCTL_MXSMBUS_I2C: {
|
||||
BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||
// BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||
PMXSMBUS_I2C_PACKET packet = (PMXSMBUS_I2C_PACKET)lpInBuffer;
|
||||
BYTE command = packet->command;
|
||||
if (command > 10) {
|
||||
((BYTE*)lpOutBuffer)[0] = 0x19;
|
||||
return FALSE;
|
||||
}
|
||||
if (handle_smbus(lpInBuffer)) {
|
||||
if (handle_smbus(command, packet->v_addr & 0x7fff, packet->command_code, packet->nbytes, packet->data)) {
|
||||
((BYTE*)lpOutBuffer)[0] = 0x00;
|
||||
return TRUE;
|
||||
} else {
|
||||
@ -561,12 +102,14 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
};
|
||||
}
|
||||
case IOCTL_MXSMBUS_REQUEST: {
|
||||
BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||
// BYTE command = ((BYTE*)lpInBuffer)[1];
|
||||
PMXSMBUS_REQUEST_PACKET packet = (PMXSMBUS_REQUEST_PACKET)lpInBuffer;
|
||||
BYTE command = packet->command;
|
||||
if (command > 11) {
|
||||
((BYTE*)lpOutBuffer)[0] = 0x19;
|
||||
return FALSE;
|
||||
}
|
||||
if (handle_smbus(lpInBuffer)) {
|
||||
if (handle_smbus(command, packet->v_addr & 0x7f, packet->command_code, packet->nbytes, packet->data)) {
|
||||
((BYTE*)lpOutBuffer)[0] = 0x00;
|
||||
return TRUE;
|
||||
} else {
|
||||
|
@ -1,12 +1,14 @@
|
||||
#include "../../amBackupStructs.h"
|
||||
#include "../../maiBackupStructs.h"
|
||||
#include "mx.h"
|
||||
|
||||
#define SRAM_DUMP L"dev/sram.bin"
|
||||
#define SRAM_SIZE 1024 * 2084
|
||||
LPBYTE SRAM;
|
||||
DWORD SRAM_POINTER = 0;
|
||||
|
||||
void sram_dump() {
|
||||
HANDLE dump = _CreateFileW(SRAM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
HANDLE dump =
|
||||
_CreateFileW(SRAM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
log_error("sram", "CreateFileA(SRAM_DUMP) failed");
|
||||
return;
|
||||
@ -16,18 +18,62 @@ void sram_dump() {
|
||||
}
|
||||
|
||||
void sram_restore() {
|
||||
HANDLE dump =
|
||||
_CreateFileW(SRAM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
HANDLE dump = _CreateFileW(SRAM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) return;
|
||||
DWORD read;
|
||||
if (!_ReadFile(dump, SRAM, SRAM_SIZE, &read, NULL)) log_error("sram", "failed to restore (%d)", GetLastError());
|
||||
if (!_ReadFile(dump, SRAM, SRAM_SIZE, &read, NULL))
|
||||
log_error("sram", "failed to restore (%d)", GetLastError());
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
|
||||
BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DWORD SRAM_VERSION = 0x0001;
|
||||
#define ADDR_BACKUP 0x0000
|
||||
#define ADDR_HM_PEAK 0x0200
|
||||
#define ADDR_TIMEZONE 0x0400
|
||||
#define ADDR_ERROR_LOG 0x0600
|
||||
#define ADDR_DUP 0x1000
|
||||
|
||||
#define fix_crc(block) \
|
||||
do { \
|
||||
(block).m_Crc = amCrc32RGet(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \
|
||||
} while (0)
|
||||
|
||||
int build_sram() {
|
||||
static BOOL built = false;
|
||||
if (built) return 0;
|
||||
built = true;
|
||||
|
||||
log_info("mxsram", "Building default SRAM file");
|
||||
|
||||
AM_SYSDATAwH_BACKUP Backup = { 0 };
|
||||
fix_crc(Backup);
|
||||
memcpy(SRAM + ADDR_BACKUP, (unsigned char*)&Backup, sizeof Backup);
|
||||
memcpy(SRAM + ADDR_BACKUP + ADDR_DUP, (unsigned char*)&Backup, sizeof Backup);
|
||||
|
||||
AM_SYSDATAwH_HM_PEAK HmPeak = { 0 };
|
||||
fix_crc(HmPeak);
|
||||
memcpy(SRAM + ADDR_HM_PEAK, (unsigned char*)&HmPeak, sizeof HmPeak);
|
||||
memcpy(SRAM + ADDR_HM_PEAK + ADDR_DUP, (unsigned char*)&HmPeak, sizeof HmPeak);
|
||||
|
||||
AM_SYSDATAwH_TIMEZONE Timezone = { 0 };
|
||||
fix_crc(Timezone);
|
||||
memcpy(SRAM + ADDR_TIMEZONE, (unsigned char*)&Timezone, sizeof Timezone);
|
||||
memcpy(SRAM + ADDR_TIMEZONE + ADDR_DUP, (unsigned char*)&Timezone, sizeof Timezone);
|
||||
|
||||
AM_SYSDATAwH_ERROR_LOG ErrorLog = { 0 };
|
||||
fix_crc(ErrorLog);
|
||||
memcpy(SRAM + ADDR_ERROR_LOG, (unsigned char*)&ErrorLog, sizeof ErrorLog);
|
||||
memcpy(SRAM + ADDR_ERROR_LOG + ADDR_DUP, (unsigned char*)&ErrorLog, sizeof ErrorLog);
|
||||
|
||||
sram_dump();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
BOOL WINAPI mxsram_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
DWORD SRAM_VERSION = 0x01000001;
|
||||
DWORD SRAM_SECTOR_SIZE = 4; // Max is 0x800
|
||||
|
||||
switch (dwIoControlCode) {
|
||||
@ -46,15 +92,18 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||
"0x%x, -, 0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
DISK_GEOMETRY out = *(PDISK_GEOMETRY)lpOutBuffer;
|
||||
memset(&out, 0, sizeof(out));
|
||||
out.Cylinders.QuadPart = 256;
|
||||
out.MediaType = FixedMedia;
|
||||
out.TracksPerCylinder = 24;
|
||||
out.SectorsPerTrack = 8;
|
||||
out.BytesPerSector = 512;
|
||||
PDISK_GEOMETRY out = (PDISK_GEOMETRY)lpOutBuffer;
|
||||
memset(out, 0, sizeof *out);
|
||||
out->Cylinders.QuadPart = 256;
|
||||
out->MediaType = FixedMedia;
|
||||
out->TracksPerCylinder = 2;
|
||||
out->SectorsPerTrack = 8;
|
||||
out->BytesPerSector = 512;
|
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
|
||||
break;
|
||||
case IOCTL_DISK_GET_LENGTH_INFO:
|
||||
log_error("mxsram", "Unhandled IOCTL_DISK_GET_LENGTH_INFO");
|
||||
return FALSE;
|
||||
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
|
||||
log_info("mxsram",
|
||||
"DeviceIoControl(<mxsram>, <get sector size>, 0x%p, "
|
||||
@ -72,35 +121,28 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
if (dwMoveMethod == FILE_BEGIN) {
|
||||
SRAM_POINTER = lDistanceToMove;
|
||||
} else if (dwMoveMethod == FILE_CURRENT) {
|
||||
SRAM_POINTER += lDistanceToMove;
|
||||
BOOL mxsram_WriteFile(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram write 0x%04x bytes at 0x%04x", nNumberOfBytesToWrite,
|
||||
ctx->m_Pointer.LowPart);
|
||||
if (ctx->m_Pointer.LowPart + nNumberOfBytesToWrite >= SRAM_SIZE) {
|
||||
nNumberOfBytesToWrite = SRAM_SIZE - ctx->m_Pointer.LowPart;
|
||||
}
|
||||
return SRAM_POINTER;
|
||||
}
|
||||
|
||||
BOOL mxsram_WriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram write 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToWrite);
|
||||
if (SRAM_POINTER + nNumberOfBytesToWrite >= SRAM_SIZE) {
|
||||
nNumberOfBytesToWrite = SRAM_SIZE - SRAM_POINTER;
|
||||
}
|
||||
memcpy(SRAM + SRAM_POINTER, lpBuffer, nNumberOfBytesToWrite);
|
||||
memcpy(SRAM + ctx->m_Pointer.LowPart, lpBuffer, nNumberOfBytesToWrite);
|
||||
sram_dump();
|
||||
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mxsram_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram read 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToRead);
|
||||
if (SRAM_POINTER + nNumberOfBytesToRead >= SRAM_SIZE) {
|
||||
nNumberOfBytesToRead = SRAM_SIZE - SRAM_POINTER;
|
||||
BOOL mxsram_ReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram read 0x%04x bytes at 0x%04x", nNumberOfBytesToRead,
|
||||
ctx->m_Pointer.LowPart);
|
||||
if (ctx->m_Pointer.LowPart + nNumberOfBytesToRead >= SRAM_SIZE) {
|
||||
nNumberOfBytesToRead = SRAM_SIZE - ctx->m_Pointer.LowPart;
|
||||
}
|
||||
sram_restore();
|
||||
memcpy((LPVOID)lpBuffer, SRAM + SRAM_POINTER, nNumberOfBytesToRead);
|
||||
memcpy((LPVOID)lpBuffer, SRAM + ctx->m_Pointer.LowPart, nNumberOfBytesToRead);
|
||||
*lpNumberOfBytesRead = nNumberOfBytesToRead;
|
||||
return TRUE;
|
||||
}
|
||||
@ -112,12 +154,14 @@ void setup_mxsram() {
|
||||
log_error(BOOT_LOGGER, "unable to allocate 2MiB for SRAM");
|
||||
exit(1);
|
||||
}
|
||||
memset(SRAM, 0, SRAM_SIZE);
|
||||
sram_restore();
|
||||
memset(SRAM, 0xff, SRAM_SIZE);
|
||||
if (FileExists(SRAM_DUMP))
|
||||
sram_restore();
|
||||
else
|
||||
build_sram();
|
||||
|
||||
file_hook_t* mxsram = new_file_hook(L"\\\\.\\mxsram");
|
||||
mxsram->DeviceIoControl = &mxsram_DeviceIoControl;
|
||||
mxsram->SetFilePointer = &mxsram_SetFilePointer;
|
||||
mxsram->ReadFile = &mxsram_ReadFile;
|
||||
mxsram->WriteFile = &mxsram_WriteFile;
|
||||
|
||||
|
@ -256,7 +256,7 @@ void hwmon_write(superio_packet* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
BOOL WINAPI mxsuperio_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
superio_packet* lpc_packet = (superio_packet*)lpInBuffer;
|
||||
|
@ -1,17 +1,17 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
BYTE index;
|
||||
BYTE reg;
|
||||
BYTE data;
|
||||
} superio_packet;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
BYTE chip;
|
||||
BYTE device;
|
||||
BYTE reg;
|
||||
BYTE data;
|
||||
} superio_lpc_packet;
|
||||
#pragma pack(pop)
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include "../hooks/gui.h"
|
||||
|
||||
#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
#endif
|
||||
#include "cimgui.h"
|
||||
|
||||
BOOL initialized = false;
|
||||
BOOL haveFirstFrame = false;
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
static HWND window;
|
||||
|
||||
extern bool ImGui_ImplWin32_Init(void* hwnd);
|
||||
@ -34,72 +33,104 @@ void InitImGui(IDirect3DDevice9* pDevice) {
|
||||
|
||||
ImGui_ImplWin32_Init(window);
|
||||
ImGui_ImplDX9_Init(pDevice);
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
extern int jvs_buttons[2][16];
|
||||
extern BOOL JVS_SENSE;
|
||||
void jvs_tab() {
|
||||
int coin_count_1 = 0;
|
||||
int coin_count_2 = 0;
|
||||
|
||||
igText("Player 1 Coins: %d", coin_count_1);
|
||||
igText("Player 2 Coins: %d", coin_count_2);
|
||||
igSeparator();
|
||||
igText("Sense: %d", JVS_SENSE);
|
||||
igSeparator();
|
||||
ImVec4 white = { 1.0, 1.0, 1.0, 1.0 };
|
||||
ImVec4 red = { 1.0, 0.0, 0.0, 1.0 };
|
||||
igText("Player 1 Coins: %d", coin_count_1);
|
||||
igText("Player 2 Coins: %d", coin_count_2);
|
||||
igSeparator();
|
||||
igText("Sense: %d", JVS_SENSE);
|
||||
igSeparator();
|
||||
ImVec4 white = { 1.0, 1.0, 1.0, 1.0 };
|
||||
ImVec4 red = { 1.0, 0.0, 0.0, 1.0 };
|
||||
|
||||
igColumns(5, NULL, true);
|
||||
// for (auto s : scancodes) {
|
||||
// igTextColored((GetKeyState(s.second) < 0) ? red : white, "%s: %x", s.first, s.second);
|
||||
// igNextColumn();
|
||||
// }
|
||||
igColumns(1, NULL, true);
|
||||
igColumns(8, NULL, true);
|
||||
for (int player = 0; player < 2; player++) {
|
||||
for (int button = 0; button < 16; button++) {
|
||||
int scan = jvs_buttons[player][button];
|
||||
igTextColored((GetKeyState(scan) < 0) ? red : white, "p%d_%02d: %02x", player, button, scan);
|
||||
igNextColumn();
|
||||
}
|
||||
}
|
||||
igColumns(1, NULL, true);
|
||||
igColumns(5, NULL, true);
|
||||
// for (auto s : scancodes) {
|
||||
// igTextColored((GetKeyState(s.second) < 0) ? red : white, "%s: %x", s.first, s.second);
|
||||
// igNextColumn();
|
||||
// }
|
||||
igColumns(1, NULL, true);
|
||||
igColumns(8, NULL, true);
|
||||
for (int player = 0; player < 2; player++) {
|
||||
for (int button = 0; button < 16; button++) {
|
||||
// int scan = jvs_buttons[player][button];
|
||||
// igTextColored((GetKeyState(scan) < 0) ? red : white, "p%d_%02d: %02x", player, button,
|
||||
// scan);
|
||||
igNextColumn();
|
||||
}
|
||||
}
|
||||
igColumns(1, NULL, true);
|
||||
|
||||
igSeparator();
|
||||
igText("JVS Count");
|
||||
// for (auto c : jvsCount) {
|
||||
// igText("%x: %d", c.first, c.second);
|
||||
// }
|
||||
igSeparator();
|
||||
igText("Comio Count");
|
||||
// for (auto c : comioCount) {
|
||||
// igText("%x: %d", c.first, c.second);
|
||||
// }
|
||||
igSeparator();
|
||||
igText("JVS Count");
|
||||
// for (auto c : jvsCount) {
|
||||
// igText("%x: %d", c.first, c.second);
|
||||
// }
|
||||
igSeparator();
|
||||
igText("Comio Count");
|
||||
// for (auto c : comioCount) {
|
||||
// igText("%x: %d", c.first, c.second);
|
||||
// }
|
||||
}
|
||||
|
||||
void hud_fps() {
|
||||
if (igBegin("FPS", NULL,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoFocusOnAppearing |
|
||||
ImGuiWindowFlags_NoNavFocus | ImGuiWindowFlags_NoNavInputs)) {
|
||||
ImGuiIO* io = igGetIO();
|
||||
|
||||
void hud_gui(IDirect3DDevice9* dev) {
|
||||
static bool showMenu = false;
|
||||
ImVec2 win_pos;
|
||||
win_pos.x = io->DisplaySize.x - 120;
|
||||
win_pos.y = 10;
|
||||
igSetWindowPos_Vec2(win_pos, ImGuiCond_Once);
|
||||
|
||||
// if (GetAsyncKeyState(scancodes["openMenu"]) & 1) {
|
||||
// showMenu = !showMenu;
|
||||
// }
|
||||
|
||||
if (!initialized) {
|
||||
InitImGui(dev);
|
||||
return;
|
||||
igText("FPS: %.1f", io->Framerate);
|
||||
igText(" dT: %.2fms", 1000 / io->Framerate);
|
||||
}
|
||||
// if (!showMenu) return;
|
||||
|
||||
ImGui_ImplDX9_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
igEnd();
|
||||
}
|
||||
void hud_eeprom(ImGuiKey open_key) {
|
||||
static MemoryEditor editor;
|
||||
static bool has_init = false;
|
||||
if (!has_init) {
|
||||
MemoryEditor_Init(&editor);
|
||||
editor.Open = false;
|
||||
has_init = true;
|
||||
}
|
||||
if (igIsKeyPressed_Bool(open_key, false)) editor.Open = !editor.Open;
|
||||
|
||||
igNewFrame();
|
||||
// TODO: Less hacky :)
|
||||
extern BYTE EEPROM_DATA[0x2000];
|
||||
|
||||
if (editor.Open)
|
||||
MemoryEditor_DrawWindow(&editor, "EEPROM Editor", EEPROM_DATA, sizeof EEPROM_DATA, 0x000);
|
||||
}
|
||||
void hud_sram(ImGuiKey open_key) {
|
||||
static MemoryEditor editor;
|
||||
static bool has_init = false;
|
||||
if (!has_init) {
|
||||
MemoryEditor_Init(&editor);
|
||||
editor.Open = false;
|
||||
has_init = true;
|
||||
}
|
||||
if (igIsKeyPressed_Bool(open_key, false)) editor.Open = !editor.Open;
|
||||
|
||||
// TODO: Less hacky :)
|
||||
extern LPBYTE SRAM;
|
||||
if (editor.Open)
|
||||
MemoryEditor_DrawWindow(&editor, "SRAM Editor", SRAM, 1024 * 1024, 0x0000);
|
||||
}
|
||||
|
||||
void hud_control() {
|
||||
igBegin("maimai control", NULL, 0);
|
||||
static bool haveFirstFrame = false;
|
||||
if (!haveFirstFrame) {
|
||||
ImVec2 size = { 600, 700 };
|
||||
igSetWindowSize_Vec2(size, 0);
|
||||
@ -123,6 +154,34 @@ void hud_gui(IDirect3DDevice9* dev) {
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
|
||||
igEnd();
|
||||
}
|
||||
|
||||
void hud_gui(IDirect3DDevice9* dev) {
|
||||
static bool showMenu = false;
|
||||
|
||||
// if (GetAsyncKeyState(scancodes["openMenu"]) & 1) {
|
||||
// showMenu = !showMenu;
|
||||
// }
|
||||
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
InitImGui(dev);
|
||||
initialized = true;
|
||||
}
|
||||
// if (!showMenu) return;
|
||||
|
||||
ImGui_ImplDX9_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
||||
igNewFrame();
|
||||
|
||||
static bool showFps = false;
|
||||
if (igIsKeyPressed_Bool(ImGuiKey_F12, false)) showFps = !showFps;
|
||||
if (showFps) hud_fps();
|
||||
|
||||
hud_eeprom(ImGuiKey_F11);
|
||||
hud_sram(ImGuiKey_F10);
|
||||
// hud_control();
|
||||
|
||||
igEndFrame();
|
||||
igRender();
|
||||
|
720
src/micetools/dll/gui/imgui_memory_editor.c
Normal file
720
src/micetools/dll/gui/imgui_memory_editor.c
Normal file
@ -0,0 +1,720 @@
|
||||
#pragma once
|
||||
// Ported to C from
|
||||
// https://github.com/ocornut/imgui_club/blob/master/imgui_memory_editor/imgui_memory_editor.h
|
||||
|
||||
#include "imgui_memory_editor.h"
|
||||
|
||||
// FIXME: We should have a way to retrieve the text edit cursor position
|
||||
// more easily in the API, this is rather tedious. This is such a ugly mess
|
||||
// we may be better off not using InputText() at all here.
|
||||
static int UserData_Callback(ImGuiInputTextCallbackData* data) {
|
||||
UserData* user_data = (UserData*)data->UserData;
|
||||
if (!ImGuiInputTextCallbackData_HasSelection(data)) user_data->CursorPos = data->CursorPos;
|
||||
if (data->SelectionStart == 0 && data->SelectionEnd == data->BufTextLen) {
|
||||
// When not editing a byte, always refresh its InputText content
|
||||
// pulled from underlying memory data (this is a bit tricky, since
|
||||
// InputText technically "owns" the master copy of the buffer we
|
||||
// edit it in there)
|
||||
ImGuiInputTextCallbackData_DeleteChars(data, 0, data->BufTextLen);
|
||||
ImGuiInputTextCallbackData_InsertChars(data, 0, user_data->CurrentBufOverwrite, NULL);
|
||||
data->SelectionStart = 0;
|
||||
data->SelectionEnd = 2;
|
||||
data->CursorPos = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MemoryEditor_Init(MemoryEditor* editor) {
|
||||
// Settings
|
||||
editor->Open = true;
|
||||
editor->ReadOnly = false;
|
||||
editor->Cols = 16;
|
||||
editor->OptShowOptions = true;
|
||||
editor->OptShowDataPreview = false;
|
||||
editor->OptShowHexII = false;
|
||||
editor->OptShowAscii = true;
|
||||
editor->OptGreyOutZeroes = true;
|
||||
editor->OptUpperCaseHex = true;
|
||||
editor->OptMidColsCount = 8;
|
||||
editor->OptAddrDigitsCount = 0;
|
||||
editor->OptFooterExtraHeight = 0.0f;
|
||||
editor->HighlightColor = IM_COL32(255, 255, 255, 50);
|
||||
editor->ReadFn = NULL;
|
||||
editor->WriteFn = NULL;
|
||||
editor->HighlightFn = NULL;
|
||||
|
||||
// State/Internals
|
||||
editor->ContentsWidthChanged = false;
|
||||
editor->DataPreviewAddr = editor->DataEditingAddr = (size_t)-1;
|
||||
editor->DataEditingTakeFocus = false;
|
||||
memset(editor->DataInputBuf, 0, sizeof(editor->DataInputBuf));
|
||||
memset(editor->AddrInputBuf, 0, sizeof(editor->AddrInputBuf));
|
||||
editor->GotoAddr = (size_t)-1;
|
||||
editor->HighlightMin = editor->HighlightMax = (size_t)-1;
|
||||
editor->PreviewEndianess = 0;
|
||||
editor->PreviewDataType = ImGuiDataType_S32;
|
||||
}
|
||||
|
||||
void MemoryEditor_GotoAddrAndHighlight(MemoryEditor* editor, size_t addr_min, size_t addr_max) {
|
||||
editor->GotoAddr = addr_min;
|
||||
editor->HighlightMin = addr_min;
|
||||
editor->HighlightMax = addr_max;
|
||||
}
|
||||
|
||||
void MemoryEditor_CalcSizes(MemoryEditor* editor, Sizes* s, size_t mem_size,
|
||||
size_t base_display_addr) {
|
||||
ImGuiStyle* style = igGetStyle();
|
||||
s->AddrDigitsCount = editor->OptAddrDigitsCount;
|
||||
if (s->AddrDigitsCount == 0)
|
||||
for (size_t n = base_display_addr + mem_size - 1; n > 0; n >>= 4) s->AddrDigitsCount++;
|
||||
s->LineHeight = igGetTextLineHeight();
|
||||
ImVec2 textSize;
|
||||
igCalcTextSize(&textSize, "F", NULL, false, -1.0f);
|
||||
s->GlyphWidth = textSize.x + 1; // We assume the font is mono-space
|
||||
s->HexCellWidth =
|
||||
(float)(int)(s->GlyphWidth * 2.5f); // "FF " we include trailing space in the
|
||||
// width to easily catch clicks everywhere
|
||||
s->SpacingBetweenMidCols =
|
||||
(float)(int)(s->HexCellWidth *
|
||||
0.25f); // Every OptMidColsCount columns we add a bit of extra spacing
|
||||
s->PosHexStart = (s->AddrDigitsCount + 2) * s->GlyphWidth;
|
||||
s->PosHexEnd = s->PosHexStart + (s->HexCellWidth * editor->Cols);
|
||||
s->PosAsciiStart = s->PosAsciiEnd = s->PosHexEnd;
|
||||
if (editor->OptShowAscii) {
|
||||
s->PosAsciiStart = s->PosHexEnd + s->GlyphWidth * 1;
|
||||
if (editor->OptMidColsCount > 0)
|
||||
s->PosAsciiStart +=
|
||||
(float)((editor->Cols + editor->OptMidColsCount - 1) / editor->OptMidColsCount) *
|
||||
s->SpacingBetweenMidCols;
|
||||
s->PosAsciiEnd = s->PosAsciiStart + editor->Cols * s->GlyphWidth;
|
||||
}
|
||||
s->WindowWidth =
|
||||
s->PosAsciiEnd + style->ScrollbarSize + style->WindowPadding.x * 2 + s->GlyphWidth;
|
||||
}
|
||||
|
||||
// Standalone Memory Editor window
|
||||
void MemoryEditor_DrawWindow(MemoryEditor* editor, const char* title, void* mem_data,
|
||||
size_t mem_size, size_t base_display_addr) {
|
||||
Sizes s;
|
||||
MemoryEditor_CalcSizes(editor, &s, mem_size, base_display_addr);
|
||||
|
||||
ImVec2 vec1, vec2;
|
||||
vec1.x = s.WindowWidth;
|
||||
vec1.y = s.WindowWidth * 0.60f;
|
||||
igSetNextWindowSize(vec1, ImGuiCond_FirstUseEver);
|
||||
vec1.x = 0.0f;
|
||||
vec1.y = 0.0f;
|
||||
vec2.x = s.WindowWidth;
|
||||
vec2.y = FLT_MAX;
|
||||
igSetNextWindowSizeConstraints(vec1, vec2, NULL, NULL);
|
||||
|
||||
editor->Open = true;
|
||||
if (igBegin(title, &editor->Open, ImGuiWindowFlags_NoScrollbar)) {
|
||||
if (igIsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows) &&
|
||||
igIsMouseReleased_Nil(ImGuiMouseButton_Right))
|
||||
igOpenPopup_Str("context", 0);
|
||||
MemoryEditor_DrawContents(editor, mem_data, mem_size, base_display_addr);
|
||||
if (editor->ContentsWidthChanged) {
|
||||
MemoryEditor_CalcSizes(editor, &s, mem_size, base_display_addr);
|
||||
igGetWindowSize(&vec1);
|
||||
vec1.x = s.WindowWidth;
|
||||
igSetWindowSize_Vec2(vec1, 0);
|
||||
}
|
||||
}
|
||||
igEnd();
|
||||
}
|
||||
|
||||
// Memory Editor contents only
|
||||
void MemoryEditor_DrawContents(MemoryEditor* editor, void* mem_data_void, size_t mem_size,
|
||||
size_t base_display_addr) {
|
||||
if (editor->Cols < 1) editor->Cols = 1;
|
||||
|
||||
ImU8* mem_data = (ImU8*)mem_data_void;
|
||||
Sizes s;
|
||||
MemoryEditor_CalcSizes(editor, &s, mem_size, base_display_addr);
|
||||
ImGuiStyle* style = igGetStyle();
|
||||
|
||||
// We begin into our scrolling region with the 'ImGuiWindowFlags_NoMove' in order to prevent
|
||||
// click from moving the window. This is used as a facility since our main click detection code
|
||||
// doesn't assign an ActiveId so the click would normally be caught as a window-move.
|
||||
const float height_separator = style->ItemSpacing.y;
|
||||
float footer_height = editor->OptFooterExtraHeight;
|
||||
if (editor->OptShowOptions)
|
||||
footer_height += height_separator + igGetFrameHeightWithSpacing() * 1;
|
||||
if (editor->OptShowDataPreview)
|
||||
footer_height += height_separator + igGetFrameHeightWithSpacing() * 1 +
|
||||
igGetTextLineHeightWithSpacing() * 3;
|
||||
|
||||
ImVec2 vec1, vec2;
|
||||
vec1.x = 0;
|
||||
vec1.y = -footer_height;
|
||||
igBeginChild_Str("##scrolling", vec1, false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoNav);
|
||||
ImDrawList* draw_list = igGetWindowDrawList();
|
||||
|
||||
vec1.y = 0;
|
||||
igPushStyleVar_Vec2(ImGuiStyleVar_FramePadding, vec1);
|
||||
igPushStyleVar_Vec2(ImGuiStyleVar_ItemSpacing, vec1);
|
||||
|
||||
// We are not really using the clipper API correctly here, because we rely on
|
||||
// visible_start_addr/visible_end_addr for our scrolling function.
|
||||
const int line_total_count = (int)((mem_size + editor->Cols - 1) / editor->Cols);
|
||||
ImGuiListClipper clipper;
|
||||
ImGuiListClipper_Begin(&clipper, line_total_count, s.LineHeight);
|
||||
|
||||
bool data_next = false;
|
||||
|
||||
if (editor->ReadOnly || editor->DataEditingAddr >= mem_size)
|
||||
editor->DataEditingAddr = (size_t)-1;
|
||||
if (editor->DataPreviewAddr >= mem_size) editor->DataPreviewAddr = (size_t)-1;
|
||||
|
||||
size_t preview_data_type_size =
|
||||
editor->OptShowDataPreview ? MemoryEditor_DataTypeGetSize(editor->PreviewDataType) : 0;
|
||||
|
||||
size_t data_editing_addr_next = (size_t)-1;
|
||||
if (editor->DataEditingAddr != (size_t)-1) {
|
||||
// Move cursor but only apply on next frame so scrolling with be synchronized (because
|
||||
// currently we can't change the scrolling while the window is being rendered)
|
||||
if (igIsKeyPressed_Bool(igGetKeyIndex(ImGuiKey_UpArrow), true) &&
|
||||
(ptrdiff_t)editor->DataEditingAddr >= (ptrdiff_t)editor->Cols) {
|
||||
data_editing_addr_next = editor->DataEditingAddr - editor->Cols;
|
||||
} else if (igIsKeyPressed_Bool(igGetKeyIndex(ImGuiKey_DownArrow), true) &&
|
||||
(ptrdiff_t)editor->DataEditingAddr < (ptrdiff_t)mem_size - editor->Cols) {
|
||||
data_editing_addr_next = editor->DataEditingAddr + editor->Cols;
|
||||
} else if (igIsKeyPressed_Bool(igGetKeyIndex(ImGuiKey_LeftArrow), true) &&
|
||||
(ptrdiff_t)editor->DataEditingAddr > (ptrdiff_t)0) {
|
||||
data_editing_addr_next = editor->DataEditingAddr - 1;
|
||||
} else if (igIsKeyPressed_Bool(igGetKeyIndex(ImGuiKey_RightArrow), true) &&
|
||||
(ptrdiff_t)editor->DataEditingAddr < (ptrdiff_t)mem_size - 1) {
|
||||
data_editing_addr_next = editor->DataEditingAddr + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw vertical separator
|
||||
ImVec2 window_pos;
|
||||
igGetWindowPos(&window_pos);
|
||||
if (editor->OptShowAscii) {
|
||||
vec1.x = window_pos.x + s.PosAsciiStart - s.GlyphWidth;
|
||||
vec1.y = window_pos.y;
|
||||
vec2.x = window_pos.x + s.PosAsciiStart - s.GlyphWidth;
|
||||
vec2.y = window_pos.y + 9999;
|
||||
ImDrawList_AddLine(draw_list, vec1, vec2, igGetColorU32_Col(ImGuiCol_Border, 1.0f), 1);
|
||||
}
|
||||
|
||||
const ImU32 color_text = igGetColorU32_Col(ImGuiCol_Text, 1.0f);
|
||||
const ImU32 color_disabled =
|
||||
editor->OptGreyOutZeroes ? igGetColorU32_Col(ImGuiCol_TextDisabled, 1.0f) : color_text;
|
||||
|
||||
const char* format_address =
|
||||
editor->OptUpperCaseHex ? "%0*" _PRISizeT "X: " : "%0*" _PRISizeT "x: ";
|
||||
const char* format_data = editor->OptUpperCaseHex ? "%0*" _PRISizeT "X" : "%0*" _PRISizeT "x";
|
||||
const char* format_byte = editor->OptUpperCaseHex ? "%02X" : "%02x";
|
||||
const char* format_byte_space = editor->OptUpperCaseHex ? "%02X " : "%02x ";
|
||||
|
||||
while (ImGuiListClipper_Step(&clipper))
|
||||
for (int line_i = clipper.DisplayStart; line_i < clipper.DisplayEnd;
|
||||
line_i++) // display only visible lines
|
||||
{
|
||||
size_t addr = (size_t)(line_i * editor->Cols);
|
||||
igText(format_address, s.AddrDigitsCount, base_display_addr + addr);
|
||||
|
||||
// Draw Hexadecimal
|
||||
for (int n = 0; n < editor->Cols && addr < mem_size; n++, addr++) {
|
||||
float byte_pos_x = s.PosHexStart + s.HexCellWidth * n;
|
||||
if (editor->OptMidColsCount > 0)
|
||||
byte_pos_x += (float)(n / editor->OptMidColsCount) * s.SpacingBetweenMidCols;
|
||||
igSameLine(byte_pos_x, -1.0f);
|
||||
|
||||
// Draw highlight
|
||||
bool is_highlight_from_user_range =
|
||||
(addr >= editor->HighlightMin && addr < editor->HighlightMax);
|
||||
bool is_highlight_from_user_func =
|
||||
(editor->HighlightFn && editor->HighlightFn(mem_data, addr));
|
||||
bool is_highlight_from_preview =
|
||||
(addr >= editor->DataPreviewAddr &&
|
||||
addr < editor->DataPreviewAddr + preview_data_type_size);
|
||||
if (is_highlight_from_user_range || is_highlight_from_user_func ||
|
||||
is_highlight_from_preview) {
|
||||
ImVec2 pos;
|
||||
igGetCursorScreenPos(&pos);
|
||||
float highlight_width = s.GlyphWidth * 2;
|
||||
bool is_next_byte_highlighted =
|
||||
(addr + 1 < mem_size) &&
|
||||
((editor->HighlightMax != (size_t)-1 && addr + 1 < editor->HighlightMax) ||
|
||||
(editor->HighlightFn && editor->HighlightFn(mem_data, addr + 1)));
|
||||
if (is_next_byte_highlighted || (n + 1 == editor->Cols)) {
|
||||
highlight_width = s.HexCellWidth;
|
||||
if (editor->OptMidColsCount > 0 && n > 0 && (n + 1) < editor->Cols &&
|
||||
((n + 1) % editor->OptMidColsCount) == 0)
|
||||
highlight_width += s.SpacingBetweenMidCols;
|
||||
}
|
||||
|
||||
vec1.x = pos.x = highlight_width;
|
||||
vec1.y = pos.y + s.LineHeight;
|
||||
ImDrawList_AddRectFilled(draw_list, pos, vec1, editor->HighlightColor, 0, 0);
|
||||
}
|
||||
|
||||
if (editor->DataEditingAddr == addr) {
|
||||
// Display text input on current byte
|
||||
bool data_write = false;
|
||||
igPushID_Ptr((void*)addr);
|
||||
if (editor->DataEditingTakeFocus) {
|
||||
igSetKeyboardFocusHere(0);
|
||||
sprintf(editor->AddrInputBuf, format_data, s.AddrDigitsCount,
|
||||
base_display_addr + addr);
|
||||
sprintf(editor->DataInputBuf, format_byte,
|
||||
editor->ReadFn ? editor->ReadFn(mem_data, addr) : mem_data[addr]);
|
||||
}
|
||||
UserData user_data;
|
||||
user_data.CursorPos = -1;
|
||||
sprintf(user_data.CurrentBufOverwrite, format_byte,
|
||||
editor->ReadFn ? editor->ReadFn(mem_data, addr) : mem_data[addr]);
|
||||
ImGuiInputTextFlags flags =
|
||||
ImGuiInputTextFlags_CharsHexadecimal |
|
||||
ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll |
|
||||
ImGuiInputTextFlags_NoHorizontalScroll |
|
||||
ImGuiInputTextFlags_CallbackAlways | ImGuiInputTextFlags_AlwaysOverwrite;
|
||||
igSetNextItemWidth(s.GlyphWidth * 2);
|
||||
if (igInputText("##data", editor->DataInputBuf,
|
||||
IM_ARRAYSIZE(editor->DataInputBuf), flags, UserData_Callback,
|
||||
&user_data))
|
||||
data_write = data_next = true;
|
||||
else if (!editor->DataEditingTakeFocus && !igIsItemActive())
|
||||
editor->DataEditingAddr = data_editing_addr_next = (size_t)-1;
|
||||
editor->DataEditingTakeFocus = false;
|
||||
if (user_data.CursorPos >= 2) data_write = data_next = true;
|
||||
if (data_editing_addr_next != (size_t)-1) data_write = data_next = false;
|
||||
unsigned int data_input_value = 0;
|
||||
if (data_write && sscanf(editor->DataInputBuf, "%X", &data_input_value) == 1) {
|
||||
if (editor->WriteFn)
|
||||
editor->WriteFn(mem_data, addr, (ImU8)data_input_value);
|
||||
else
|
||||
mem_data[addr] = (ImU8)data_input_value;
|
||||
}
|
||||
igPopID();
|
||||
} else {
|
||||
// NB: The trailing space is not visible but ensure there's no gap that the
|
||||
// mouse cannot click on.
|
||||
ImU8 b = editor->ReadFn ? editor->ReadFn(mem_data, addr) : mem_data[addr];
|
||||
|
||||
if (editor->OptShowHexII) {
|
||||
if ((b >= 32 && b < 128))
|
||||
igText(".%c ", b);
|
||||
else if (b == 0xFF && editor->OptGreyOutZeroes)
|
||||
igTextDisabled("## ");
|
||||
else if (b == 0x00)
|
||||
igText(" ");
|
||||
else
|
||||
igText(format_byte_space, b);
|
||||
} else {
|
||||
if (b == 0 && editor->OptGreyOutZeroes)
|
||||
igTextDisabled("00 ");
|
||||
else
|
||||
igText(format_byte_space, b);
|
||||
}
|
||||
if (!editor->ReadOnly && igIsItemHovered(0) && igIsMouseClicked_Bool(0, false)) {
|
||||
editor->DataEditingTakeFocus = true;
|
||||
data_editing_addr_next = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (editor->OptShowAscii) {
|
||||
// Draw ASCII values
|
||||
igSameLine(s.PosAsciiStart, -1.0f);
|
||||
ImVec2 pos;
|
||||
igGetCursorScreenPos(&pos);
|
||||
addr = line_i * editor->Cols;
|
||||
igPushID_Int(line_i);
|
||||
vec1.x = s.PosAsciiEnd - s.PosAsciiStart;
|
||||
vec1.y = s.LineHeight;
|
||||
if (igInvisibleButton("igInvisibleButtonascii", vec1, 0)) {
|
||||
editor->DataEditingAddr = editor->DataPreviewAddr =
|
||||
addr + (size_t)((igGetIO()->MousePos.x - pos.x) / s.GlyphWidth);
|
||||
editor->DataEditingTakeFocus = true;
|
||||
}
|
||||
igPopID();
|
||||
for (int n = 0; n < editor->Cols && addr < mem_size; n++, addr++) {
|
||||
if (addr == editor->DataEditingAddr) {
|
||||
vec1.x = pos.x + s.GlyphWidth;
|
||||
vec1.y = pos.y + s.LineHeight;
|
||||
ImDrawList_AddRectFilled(draw_list, pos, vec1,
|
||||
igGetColorU32_Col(ImGuiCol_FrameBg, 1.0f), 0, 0);
|
||||
ImDrawList_AddRectFilled(draw_list, pos, vec1,
|
||||
igGetColorU32_Col(ImGuiCol_TextSelectedBg, 1.0f), 0, 0);
|
||||
}
|
||||
unsigned char c =
|
||||
editor->ReadFn ? editor->ReadFn(mem_data, addr) : mem_data[addr];
|
||||
char display_c = (c < 32 || c >= 128) ? '.' : c;
|
||||
|
||||
ImDrawList_AddText_Vec2(draw_list, pos,
|
||||
(display_c == c) ? color_text : color_disabled,
|
||||
&display_c, &display_c + 1);
|
||||
pos.x += s.GlyphWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
igPopStyleVar(2);
|
||||
igEndChild();
|
||||
|
||||
// Notify the main window of our ideal child content size (FIXME: we are missing an API to get
|
||||
// the contents size from the child)
|
||||
igSetCursorPosX(s.WindowWidth);
|
||||
|
||||
if (data_next && editor->DataEditingAddr + 1 < mem_size) {
|
||||
editor->DataEditingAddr = editor->DataPreviewAddr = editor->DataEditingAddr + 1;
|
||||
editor->DataEditingTakeFocus = true;
|
||||
} else if (data_editing_addr_next != (size_t)-1) {
|
||||
editor->DataEditingAddr = editor->DataPreviewAddr = data_editing_addr_next;
|
||||
editor->DataEditingTakeFocus = true;
|
||||
}
|
||||
|
||||
const bool lock_show_data_preview = editor->OptShowDataPreview;
|
||||
if (editor->OptShowOptions) {
|
||||
igSeparator();
|
||||
MemoryEditor_DrawOptionsLine(editor, &s, mem_data, mem_size, base_display_addr);
|
||||
}
|
||||
|
||||
if (lock_show_data_preview) {
|
||||
igSeparator();
|
||||
MemoryEditor_DrawPreviewLine(editor, &s, mem_data, mem_size, base_display_addr);
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryEditor_DrawOptionsLine(MemoryEditor* editor, const Sizes* s, void* mem_data,
|
||||
size_t mem_size, size_t base_display_addr) {
|
||||
IM_UNUSED(mem_data);
|
||||
ImGuiStyle* style = igGetStyle();
|
||||
const char* format_range = editor->OptUpperCaseHex
|
||||
? "Range %0*" _PRISizeT "X..%0*" _PRISizeT "X"
|
||||
: "Range %0*" _PRISizeT "x..%0*" _PRISizeT "x";
|
||||
|
||||
ImVec2 vec1 = { 0 };
|
||||
// Options menu
|
||||
if (igButton("Options", vec1)) igOpenPopup_Str("context", 0);
|
||||
if (igBeginPopup("context", 0)) {
|
||||
igSetNextItemWidth(s->GlyphWidth * 7 + style->FramePadding.x * 2.0f);
|
||||
if (igDragInt("##cols", &editor->Cols, 0.2f, 4, 32, "%d cols", 0)) {
|
||||
editor->ContentsWidthChanged = true;
|
||||
if (editor->Cols < 1) editor->Cols = 1;
|
||||
}
|
||||
igCheckbox("Show Data Preview", &editor->OptShowDataPreview);
|
||||
igCheckbox("Show HexII", &editor->OptShowHexII);
|
||||
if (igCheckbox("Show Ascii", &editor->OptShowAscii)) {
|
||||
editor->ContentsWidthChanged = true;
|
||||
}
|
||||
igCheckbox("Grey out zeroes", &editor->OptGreyOutZeroes);
|
||||
igCheckbox("Uppercase Hex", &editor->OptUpperCaseHex);
|
||||
|
||||
igEndPopup();
|
||||
}
|
||||
|
||||
igSameLine(0, -1);
|
||||
igText(format_range, s->AddrDigitsCount, base_display_addr, s->AddrDigitsCount,
|
||||
base_display_addr + mem_size - 1);
|
||||
igSameLine(0, -1);
|
||||
igSetNextItemWidth((s->AddrDigitsCount + 1) * s->GlyphWidth + style->FramePadding.x * 2.0f);
|
||||
if (igInputText("##addr", editor->AddrInputBuf, IM_ARRAYSIZE(editor->AddrInputBuf),
|
||||
ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_EnterReturnsTrue,
|
||||
NULL, NULL)) {
|
||||
size_t goto_addr;
|
||||
if (sscanf(editor->AddrInputBuf, "%" _PRISizeT "X", &goto_addr) == 1) {
|
||||
editor->GotoAddr = goto_addr - base_display_addr;
|
||||
editor->HighlightMin = editor->HighlightMax = (size_t)-1;
|
||||
}
|
||||
}
|
||||
|
||||
if (editor->GotoAddr != (size_t)-1) {
|
||||
if (editor->GotoAddr < mem_size) {
|
||||
vec1.x = 0;
|
||||
vec1.y = 0;
|
||||
igBeginChild_Str("##scrolling", vec1, false, 0);
|
||||
igGetCursorStartPos(&vec1);
|
||||
igSetScrollFromPosY_Float(
|
||||
vec1.y + (editor->GotoAddr / editor->Cols) * igGetTextLineHeight(), 0.5f);
|
||||
igEndChild();
|
||||
editor->DataEditingAddr = editor->DataPreviewAddr = editor->GotoAddr;
|
||||
editor->DataEditingTakeFocus = true;
|
||||
}
|
||||
editor->GotoAddr = (size_t)-1;
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryEditor_DrawPreviewLine(MemoryEditor* editor, const Sizes* s, void* mem_data_void,
|
||||
size_t mem_size, size_t base_display_addr) {
|
||||
IM_UNUSED(base_display_addr);
|
||||
ImVec2 vec1 = { 0 };
|
||||
ImU8* mem_data = (ImU8*)mem_data_void;
|
||||
ImGuiStyle* style = igGetStyle();
|
||||
igAlignTextToFramePadding();
|
||||
igText("Preview as:");
|
||||
igSameLine(0, -1);
|
||||
igSetNextItemWidth((s->GlyphWidth * 10.0f) + style->FramePadding.x * 2.0f +
|
||||
style->ItemInnerSpacing.x);
|
||||
if (igBeginCombo("##combo_type", MemoryEditor_DataTypeGetDesc(editor->PreviewDataType),
|
||||
ImGuiComboFlags_HeightLargest)) {
|
||||
for (int n = 0; n < ImGuiDataType_COUNT; n++)
|
||||
if (igSelectable_Bool(MemoryEditor_DataTypeGetDesc((ImGuiDataType)n),
|
||||
editor->PreviewDataType == n, 0, vec1))
|
||||
editor->PreviewDataType = (ImGuiDataType)n;
|
||||
igEndCombo();
|
||||
}
|
||||
igSameLine(0, -1);
|
||||
igSetNextItemWidth((s->GlyphWidth * 6.0f) + style->FramePadding.x * 2.0f +
|
||||
style->ItemInnerSpacing.x);
|
||||
igCombo_Str("##combo_endianess", &editor->PreviewEndianess, "LE\0BE\0\0", -1);
|
||||
|
||||
char buf[128] = "";
|
||||
float x = s->GlyphWidth * 6.0f;
|
||||
bool has_value = editor->DataPreviewAddr != (size_t)-1;
|
||||
if (has_value)
|
||||
MemoryEditor_DrawPreviewData(editor, editor->DataPreviewAddr, mem_data, mem_size,
|
||||
editor->PreviewDataType, DataFormat_Dec, buf,
|
||||
(size_t)IM_ARRAYSIZE(buf));
|
||||
igText("Dec");
|
||||
igSameLine(x, -1);
|
||||
igTextUnformatted(has_value ? buf : "N/A", NULL);
|
||||
if (has_value)
|
||||
MemoryEditor_DrawPreviewData(editor, editor->DataPreviewAddr, mem_data, mem_size,
|
||||
editor->PreviewDataType, DataFormat_Hex, buf,
|
||||
(size_t)IM_ARRAYSIZE(buf));
|
||||
igText("Hex");
|
||||
igSameLine(x, -1);
|
||||
igTextUnformatted(has_value ? buf : "N/A", NULL);
|
||||
if (has_value)
|
||||
MemoryEditor_DrawPreviewData(editor, editor->DataPreviewAddr, mem_data, mem_size,
|
||||
editor->PreviewDataType, DataFormat_Bin, buf,
|
||||
(size_t)IM_ARRAYSIZE(buf));
|
||||
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
||||
igText("Bin");
|
||||
igSameLine(x, -1);
|
||||
igTextUnformatted(has_value ? buf : "N/A", NULL);
|
||||
}
|
||||
|
||||
// Utilities for Data Preview
|
||||
const char* MemoryEditor_DataTypeGetDesc(ImGuiDataType data_type) {
|
||||
const char* descs[] = { "Int8", "Uint8", "Int16", "Uint16", "Int32",
|
||||
"Uint32", "Int64", "Uint64", "Float", "Double" };
|
||||
// IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
|
||||
return descs[data_type];
|
||||
}
|
||||
|
||||
size_t MemoryEditor_DataTypeGetSize(ImGuiDataType data_type) {
|
||||
const size_t sizes[] = { 1, 1, 2, 2, 4, 4, 8, 8, sizeof(float), sizeof(double) };
|
||||
// IM_ASSERT(data_type >= 0 && data_type < ImGuiDataType_COUNT);
|
||||
return sizes[data_type];
|
||||
}
|
||||
|
||||
const char* MemoryEditor_DataFormatGetDesc(DataFormat data_format) {
|
||||
const char* descs[] = { "Bin", "Dec", "Hex" };
|
||||
// IM_ASSERT(data_format >= 0 && data_format < DataFormat_COUNT);
|
||||
return descs[data_format];
|
||||
}
|
||||
|
||||
bool MemoryEditor_IsBigEndian() {
|
||||
uint16_t x = 1;
|
||||
char c[2];
|
||||
memcpy(c, &x, 2);
|
||||
return c[0] != 0;
|
||||
}
|
||||
|
||||
static void* MemoryEditor_EndianessCopyBigEndian(void* _dst, void* _src, size_t s,
|
||||
int is_little_endian) {
|
||||
if (is_little_endian) {
|
||||
uint8_t* dst = (uint8_t*)_dst;
|
||||
uint8_t* src = (uint8_t*)_src + s - 1;
|
||||
for (int i = 0, n = (int)s; i < n; ++i) memcpy(dst++, src--, 1);
|
||||
return _dst;
|
||||
} else {
|
||||
return memcpy(_dst, _src, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void* MemoryEditor_EndianessCopyLittleEndian(void* _dst, void* _src, size_t s,
|
||||
int is_little_endian) {
|
||||
if (is_little_endian) {
|
||||
return memcpy(_dst, _src, s);
|
||||
} else {
|
||||
uint8_t* dst = (uint8_t*)_dst;
|
||||
uint8_t* src = (uint8_t*)_src + s - 1;
|
||||
for (int i = 0, n = (int)s; i < n; ++i) memcpy(dst++, src--, 1);
|
||||
return _dst;
|
||||
}
|
||||
}
|
||||
|
||||
void* MemoryEditor_EndianessCopy(MemoryEditor* editor, void* dst, void* src, size_t size) {
|
||||
static void* (*fp)(void*, void*, size_t, int) = NULL;
|
||||
if (fp == NULL)
|
||||
fp = MemoryEditor_IsBigEndian() ? MemoryEditor_EndianessCopyBigEndian
|
||||
: MemoryEditor_EndianessCopyLittleEndian;
|
||||
return fp(dst, src, size, editor->PreviewEndianess);
|
||||
}
|
||||
|
||||
const char* MemoryEditor_FormatBinary(const uint8_t* buf, int width) {
|
||||
// IM_ASSERT(width <= 64);
|
||||
size_t out_n = 0;
|
||||
static char out_buf[64 + 8 + 1];
|
||||
int n = width / 8;
|
||||
for (int j = n - 1; j >= 0; --j) {
|
||||
for (int i = 0; i < 8; ++i) out_buf[out_n++] = (buf[j] & (1 << (7 - i))) ? '1' : '0';
|
||||
out_buf[out_n++] = ' ';
|
||||
}
|
||||
// IM_ASSERT(out_n < IM_ARRAYSIZE(out_buf));
|
||||
out_buf[out_n] = 0;
|
||||
return out_buf;
|
||||
}
|
||||
|
||||
// [Internal]
|
||||
void MemoryEditor_DrawPreviewData(MemoryEditor* editor, size_t addr, const ImU8* mem_data,
|
||||
size_t mem_size, ImGuiDataType data_type, DataFormat data_format,
|
||||
char* out_buf, size_t out_buf_size) {
|
||||
uint8_t buf[8];
|
||||
size_t elem_size = MemoryEditor_DataTypeGetSize(data_type);
|
||||
size_t size = addr + elem_size > mem_size ? mem_size - addr : elem_size;
|
||||
if (editor->ReadFn)
|
||||
for (int i = 0, n = (int)size; i < n; ++i) buf[i] = editor->ReadFn(mem_data, addr + i);
|
||||
else
|
||||
memcpy(buf, mem_data + addr, size);
|
||||
|
||||
if (data_format == DataFormat_Bin) {
|
||||
uint8_t binbuf[8];
|
||||
MemoryEditor_EndianessCopy(editor, binbuf, buf, size);
|
||||
ImSnprintf(out_buf, out_buf_size, "%s", MemoryEditor_FormatBinary(binbuf, (int)size * 8));
|
||||
return;
|
||||
}
|
||||
|
||||
out_buf[0] = 0;
|
||||
switch (data_type) {
|
||||
case ImGuiDataType_S8: {
|
||||
int8_t int8 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &int8, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%hhd", int8);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%02x", int8 & 0xFF);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U8: {
|
||||
uint8_t uint8 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &uint8, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%hhu", uint8);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%02x", uint8 & 0XFF);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S16: {
|
||||
int16_t int16 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &int16, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%hd", int16);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%04x", int16 & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U16: {
|
||||
uint16_t uint16 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &uint16, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%hu", uint16);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%04x", uint16 & 0xFFFF);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S32: {
|
||||
int32_t int32 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &int32, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%d", int32);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%08x", int32);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U32: {
|
||||
uint32_t uint32 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &uint32, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%u", uint32);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%08x", uint32);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_S64: {
|
||||
int64_t int64 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &int64, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%lld", (long long)int64);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)int64);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_U64: {
|
||||
uint64_t uint64 = 0;
|
||||
MemoryEditor_EndianessCopy(editor, &uint64, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%llu", (long long)uint64);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "0x%016llx", (long long)uint64);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_Float: {
|
||||
float float32 = 0.0f;
|
||||
MemoryEditor_EndianessCopy(editor, &float32, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%f", float32);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%a", float32);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_Double: {
|
||||
double float64 = 0.0;
|
||||
MemoryEditor_EndianessCopy(editor, &float64, buf, size);
|
||||
if (data_format == DataFormat_Dec) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%f", float64);
|
||||
return;
|
||||
}
|
||||
if (data_format == DataFormat_Hex) {
|
||||
ImSnprintf(out_buf, out_buf_size, "%a", float64);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ImGuiDataType_COUNT:
|
||||
break;
|
||||
}
|
||||
}
|
135
src/micetools/dll/gui/imgui_memory_editor.h
Normal file
135
src/micetools/dll/gui/imgui_memory_editor.h
Normal file
@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
// Ported to C from
|
||||
// https://github.com/ocornut/imgui_club/blob/master/imgui_memory_editor/imgui_memory_editor.h
|
||||
|
||||
#include <float.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
#define CIMGUI_DEFINE_ENUMS_AND_STRUCTS
|
||||
#endif
|
||||
#include "cimgui.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define _PRISizeT "I"
|
||||
#define ImSnprintf _snprintf
|
||||
#else
|
||||
#define _PRISizeT "z"
|
||||
#define ImSnprintf snprintf
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning( \
|
||||
disable : 4996) // warning C4996: 'sprintf': This function or variable may be unsafe.
|
||||
#endif
|
||||
|
||||
typedef enum DataFormat_ {
|
||||
DataFormat_Bin = 0,
|
||||
DataFormat_Dec = 1,
|
||||
DataFormat_Hex = 2,
|
||||
DataFormat_COUNT
|
||||
} DataFormat;
|
||||
|
||||
typedef struct UserData_ {
|
||||
char CurrentBufOverwrite[3]; // Input
|
||||
int CursorPos; // Output
|
||||
} UserData;
|
||||
// FIXME: We should have a way to retrieve the text edit cursor position
|
||||
// more easily in the API, this is rather tedious. This is such a ugly mess
|
||||
// we may be better off not using InputText() at all here.
|
||||
static int UserData_Callback(ImGuiInputTextCallbackData* data);
|
||||
|
||||
typedef struct MemoryEditor_ {
|
||||
// Settings
|
||||
bool Open; // = true // set to false when DrawWindow() was closed. ignore if not using
|
||||
// DrawWindow().
|
||||
bool ReadOnly; // = false // disable any editing.
|
||||
int Cols; // = 16 // number of columns to display.
|
||||
bool OptShowOptions; // = true // display options button/context menu. when disabled, options
|
||||
// will be locked unless you provide your own UI for them.
|
||||
bool
|
||||
OptShowDataPreview; // = false // display a footer previewing the decimal/binary/hex/float
|
||||
// representation of the currently selected bytes.
|
||||
bool OptShowHexII; // = false // display values in HexII representation instead of regular
|
||||
// hexadecimal: hide null/zero bytes, ascii values as ".X".
|
||||
bool OptShowAscii; // = true // display ASCII representation on the right side.
|
||||
bool OptGreyOutZeroes; // = true // display null/zero bytes using the TextDisabled color.
|
||||
bool OptUpperCaseHex; // = true // display hexadecimal values as "FF" instead of "ff".
|
||||
int OptMidColsCount; // = 8 // set to 0 to disable extra spacing between every mid-cols.
|
||||
int OptAddrDigitsCount; // = 0 // number of addr digits to display (default calculated
|
||||
// based on maximum displayed addr).
|
||||
float OptFooterExtraHeight; // = 0 // space to reserve at the bottom of the widget to add
|
||||
// custom widgets
|
||||
ImU32 HighlightColor; // // background color of highlighted bytes.
|
||||
ImU8 (*ReadFn)(const ImU8* data, size_t off); // = 0 // optional handler to read bytes.
|
||||
void (*WriteFn)(ImU8* data, size_t off,
|
||||
ImU8 d); // = 0 // optional handler to write bytes.
|
||||
bool (*HighlightFn)(const ImU8* data,
|
||||
size_t off); //= 0 // optional handler to return Highlight property
|
||||
//(to support non-contiguous highlighting).
|
||||
|
||||
// [Internal State]
|
||||
bool ContentsWidthChanged;
|
||||
size_t DataPreviewAddr;
|
||||
size_t DataEditingAddr;
|
||||
bool DataEditingTakeFocus;
|
||||
char DataInputBuf[32];
|
||||
char AddrInputBuf[32];
|
||||
size_t GotoAddr;
|
||||
size_t HighlightMin, HighlightMax;
|
||||
int PreviewEndianess;
|
||||
ImGuiDataType PreviewDataType;
|
||||
} MemoryEditor;
|
||||
|
||||
void MemoryEditor_Init(MemoryEditor* editor);
|
||||
|
||||
void MemoryEditor_GotoAddrAndHighlight(MemoryEditor* editor, size_t addr_min, size_t addr_max);
|
||||
|
||||
typedef struct Sizes_ {
|
||||
int AddrDigitsCount;
|
||||
float LineHeight;
|
||||
float GlyphWidth;
|
||||
float HexCellWidth;
|
||||
float SpacingBetweenMidCols;
|
||||
float PosHexStart;
|
||||
float PosHexEnd;
|
||||
float PosAsciiStart;
|
||||
float PosAsciiEnd;
|
||||
float WindowWidth;
|
||||
} Sizes;
|
||||
|
||||
void MemoryEditor_CalcSizes(MemoryEditor* editor, Sizes* s, size_t mem_size,
|
||||
size_t base_display_addr);
|
||||
|
||||
// Standalone Memory Editor window
|
||||
void MemoryEditor_DrawWindow(MemoryEditor* editor, const char* title, void* mem_data,
|
||||
size_t mem_size, size_t base_display_addr);
|
||||
|
||||
// Memory Editor contents only
|
||||
void MemoryEditor_DrawContents(MemoryEditor* editor, void* mem_data_void, size_t mem_size,
|
||||
size_t base_display_addr);
|
||||
void MemoryEditor_DrawOptionsLine(MemoryEditor* editor, const Sizes* s, void* mem_data,
|
||||
size_t mem_size, size_t base_display_addr);
|
||||
void MemoryEditor_DrawPreviewLine(MemoryEditor* editor, const Sizes* s, void* mem_data_void,
|
||||
size_t mem_size, size_t base_display_addr);
|
||||
|
||||
// Utilities for Data Preview
|
||||
const char* MemoryEditor_DataTypeGetDesc(ImGuiDataType data_type);
|
||||
size_t MemoryEditor_DataTypeGetSize(ImGuiDataType data_type);
|
||||
const char* MemoryEditor_DataFormatGetDesc(DataFormat data_format);
|
||||
bool MemoryEditor_IsBigEndian(void);
|
||||
|
||||
static void* MemoryEditor_EndianessCopyBigEndian(void* _dst, void* _src, size_t s,
|
||||
int is_little_endian);
|
||||
static void* MemoryEditor_EndianessCopyLittleEndian(void* _dst, void* _src, size_t s,
|
||||
int is_little_endian);
|
||||
void* MemoryEditor_EndianessCopy(MemoryEditor* editor, void* dst, void* src, size_t size);
|
||||
const char* MemoryEditor_FormatBinary(const uint8_t* buf, int width);
|
||||
// [Internal]
|
||||
void MemoryEditor_DrawPreviewData(MemoryEditor* editor, size_t addr, const ImU8* mem_data,
|
||||
size_t mem_size, ImGuiDataType data_type, DataFormat data_format,
|
||||
char* out_buf, size_t out_buf_size);
|
@ -1,3 +1,4 @@
|
||||
gui_files = files(
|
||||
'imgui_memory_editor.c',
|
||||
'gui.c',
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
#define _MICE_COM
|
||||
#include "com.h"
|
||||
|
||||
#include "files.h"
|
||||
|
||||
com_hook_t* com_hook_list = NULL;
|
||||
com_hook_t* new_com_hook(BYTE port) {
|
||||
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook);
|
||||
|
||||
@ -26,145 +26,136 @@ com_hook_t* new_com_hook(BYTE port) {
|
||||
return hook;
|
||||
}
|
||||
|
||||
void hook_com(com_hook_t* hook) {
|
||||
hook->next = NULL;
|
||||
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
|
||||
*hook->virtual_handle = NULL;
|
||||
if (com_hook_list == NULL) {
|
||||
com_hook_list = hook;
|
||||
return;
|
||||
}
|
||||
|
||||
com_hook_t* hl = com_hook_list;
|
||||
while (hl->next != NULL) hl = hl->next;
|
||||
hl->next = hook;
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p) (%08x)", hFile, lpDCB, hook);
|
||||
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommState(hook->data, lpDCB);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL) return TrueGetCommState(hFile, lpDCB);
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
|
||||
if (com_hook->GetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueGetCommState(hFile, lpDCB);
|
||||
return com_hook->GetCommState(hFile, lpDCB);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||
log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetCommState(hook->data, lpDCB);
|
||||
}
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL) return TrueSetCommState(hFile, lpDCB);
|
||||
|
||||
return TrueSetCommState(hFile, lpDCB);
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->SetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return com_hook->SetCommState(hFile, lpDCB);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||
log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->GetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
|
||||
return com_hook->GetCommTimeouts(hFile, lpCommTimeouts);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||
log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->SetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
|
||||
return com_hook->SetCommTimeouts(hFile, lpCommTimeouts);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
|
||||
log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetupComm == NULL) {
|
||||
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->SetupComm == NULL) {
|
||||
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
|
||||
return com_hook->SetupComm(hFile, dwInQueue, dwOutQueue);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
|
||||
log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->PurgeComm == NULL) {
|
||||
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->PurgeComm(hook->data, dwFlags);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL) return TruePurgeComm(hFile, dwFlags);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->PurgeComm == NULL) {
|
||||
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TruePurgeComm(hFile, dwFlags);
|
||||
return com_hook->PurgeComm(hFile, dwFlags);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
|
||||
log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommModemStatus == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommModemStatus(hook->data, lpModelStat);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueGetCommModemStatus(hFile, lpModelStat);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->GetCommModemStatus == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueGetCommModemStatus(hFile, lpModelStat);
|
||||
return com_hook->GetCommModemStatus(hFile, lpModelStat);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
||||
log_misc(COMM_LOGGER, "WaitCommEvent(0x%p)", hFile);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->WaitCommEvent == NULL) {
|
||||
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->WaitCommEvent == NULL) {
|
||||
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
||||
return com_hook->WaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
log_trace(COMM_LOGGER, "ClearCommError(0x%p)", hFile);
|
||||
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->ClearCommError == NULL) {
|
||||
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->ClearCommError(hook->data, lpErrors, lpStat);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL || pHData->hook->com_hook == NULL)
|
||||
return TrueClearCommError(hFile, lpErrors, lpStat);
|
||||
|
||||
com_hook_t* com_hook = pHData->hook->com_hook;
|
||||
if (com_hook->ClearCommError == NULL) {
|
||||
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", com_hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueClearCommError(hFile, lpErrors, lpStat);
|
||||
return com_hook->ClearCommError(hFile, lpErrors, lpStat);
|
||||
}
|
||||
|
||||
void hook_commio() {
|
||||
|
@ -1,26 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _MICE_COM
|
||||
#define _MICE_COM extern
|
||||
#endif
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
static BOOL(WINAPI* TrueGetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
static BOOL(WINAPI* TrueSetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
static BOOL(WINAPI* TrueGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
static BOOL(WINAPI* TrueSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
static BOOL(WINAPI* TrueSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
|
||||
static BOOL(WINAPI* TruePurgeComm)(HANDLE hFile, DWORD dwFlags);
|
||||
static BOOL(WINAPI* TrueGetCommModemStatus)(HANDLE hFile, LPDWORD lpModelStat);
|
||||
static BOOL(WINAPI* TrueWaitCommEvent)(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
_MICE_COM BOOL(WINAPI* TrueGetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
_MICE_COM BOOL(WINAPI* TrueSetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
_MICE_COM BOOL(WINAPI* TrueGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
_MICE_COM BOOL(WINAPI* TrueSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
_MICE_COM BOOL(WINAPI* TrueSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
|
||||
_MICE_COM BOOL(WINAPI* TruePurgeComm)(HANDLE hFile, DWORD dwFlags);
|
||||
_MICE_COM BOOL(WINAPI* TrueGetCommModemStatus)(HANDLE hFile, LPDWORD lpModelStat);
|
||||
_MICE_COM BOOL(WINAPI* TrueWaitCommEvent)(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
|
||||
_MICE_COM BOOL(WINAPI* TrueClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
|
||||
typedef BOOL(FnGetCommState)(void* com, LPDCB lpDCB);
|
||||
typedef BOOL(FnSetCommState)(void* com, LPDCB lpDCB);
|
||||
typedef BOOL(FnGetCommTimeouts)(void* com, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
typedef BOOL(FnSetCommTimeouts)(void* com, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
typedef BOOL(FnSetupComm)(void* com, DWORD dwInQueue, DWORD dwOutQueue);
|
||||
typedef BOOL(FnPurgeComm)(void* com, DWORD dwFlags);
|
||||
typedef BOOL(FnGetCommModemStatus)(void* com, LPDWORD lpModelStat);
|
||||
typedef BOOL(FnWaitCommEvent)(void* com, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
typedef BOOL(FnGetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
typedef BOOL(FnSetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
typedef BOOL(FnGetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
typedef BOOL(FnSetCommTimeouts)(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts);
|
||||
typedef BOOL(FnSetupComm)(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue);
|
||||
typedef BOOL(FnPurgeComm)(HANDLE hFile, DWORD dwFlags);
|
||||
typedef BOOL(FnGetCommModemStatus)(HANDLE hFile, LPDWORD lpModelStat);
|
||||
typedef BOOL(FnWaitCommEvent)(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnClearCommError)(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
|
||||
typedef struct com_hook {
|
||||
LPHANDLE virtual_handle;
|
||||
@ -38,13 +42,11 @@ typedef struct com_hook {
|
||||
FnWaitCommEvent* WaitCommEvent;
|
||||
FnClearCommError* ClearCommError;
|
||||
|
||||
void* data;
|
||||
void* com_device;
|
||||
|
||||
struct com_hook* next;
|
||||
} com_hook_t;
|
||||
|
||||
extern com_hook_t* com_hook_list;
|
||||
|
||||
com_hook_t* new_com_hook(BYTE port);
|
||||
void hook_com(com_hook_t* hook);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,9 @@ void hook_drives();
|
||||
#define MBR_FS_NTFS 0x07
|
||||
#define MBR_FS_EXT_LBA 0x0F
|
||||
|
||||
#pragma pack(1)
|
||||
#pragma pack(push, 1)
|
||||
typedef struct mbr {
|
||||
BYTE bootstrap_code[446];
|
||||
#pragma pack(1)
|
||||
struct {
|
||||
BYTE status;
|
||||
BYTE start_chs[3];
|
||||
@ -32,6 +31,7 @@ typedef struct mbr {
|
||||
#define SPD_VERSION 1
|
||||
#define SBR_VERSION 1
|
||||
|
||||
// Sega Partition Descriptor
|
||||
enum spd_slot {
|
||||
SPD_Original0 = 0x10,
|
||||
SPD_Original1 = 0x11,
|
||||
@ -40,4 +40,86 @@ enum spd_slot {
|
||||
SPD_OS = 0x30,
|
||||
SPD_AppData = 0x40,
|
||||
};
|
||||
typedef uint8_t spd_slot_t;
|
||||
typedef uint8_t spd_slot_t;
|
||||
|
||||
typedef struct spd {
|
||||
uint32_t crc;
|
||||
uint8_t version;
|
||||
uint8_t _[11];
|
||||
struct {
|
||||
/*
|
||||
(BCD)
|
||||
1.0 = original0
|
||||
1.1 = original1
|
||||
2.0 = patch0
|
||||
2.1 = patch1
|
||||
3.0 = os
|
||||
4.0 = app_data
|
||||
*/
|
||||
spd_slot_t slot_content;
|
||||
/*
|
||||
Guess: Filesystem type
|
||||
0: Encrypted FAT16
|
||||
1: Decrypted NTFS
|
||||
*/
|
||||
uint8_t uk1;
|
||||
uint16_t block_size;
|
||||
uint32_t block_count;
|
||||
uint8_t __[8];
|
||||
} slots[31];
|
||||
} spd_t;
|
||||
|
||||
// Sega Boot Record
|
||||
typedef struct {
|
||||
uint16_t year;
|
||||
uint8_t mon;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t min;
|
||||
uint8_t sec;
|
||||
uint8_t _;
|
||||
} slot_time_t;
|
||||
|
||||
typedef struct {
|
||||
char id[4];
|
||||
slot_time_t time;
|
||||
uint32_t version;
|
||||
uint32_t _[2];
|
||||
uint32_t segcount;
|
||||
uint32_t segsize;
|
||||
|
||||
char hw[3];
|
||||
uint8_t instant;
|
||||
slot_time_t orgtime;
|
||||
uint32_t orgversion;
|
||||
uint32_t osver;
|
||||
uint32_t ossegcount;
|
||||
|
||||
uint8_t __[8];
|
||||
} sbr_slot_t;
|
||||
|
||||
enum {
|
||||
Slot_Check = 0x00, // status=error
|
||||
Slot_Install = 0x01, // status=install -> FAILED TO READ PREMADE BLOCK!!
|
||||
Slot_Complete = 0x02, // status=complete
|
||||
Slot_Empty = 0x03, // status=error
|
||||
Slot_Error = 0x04, // status=error
|
||||
Slot_Invalid = 0xff,
|
||||
};
|
||||
|
||||
typedef uint8_t slot_status_t;
|
||||
typedef struct {
|
||||
uint32_t crc;
|
||||
uint8_t version;
|
||||
uint8_t _[11 + 16 + 32];
|
||||
uint8_t bootslot;
|
||||
uint8_t __[2];
|
||||
slot_status_t slot_status[5];
|
||||
uint8_t ___[8 + 16 + 32 + 64];
|
||||
sbr_slot_t slot_os;
|
||||
sbr_slot_t slot_original0;
|
||||
sbr_slot_t slot_appdata;
|
||||
sbr_slot_t slot_patch0;
|
||||
sbr_slot_t slot_patch1;
|
||||
} sbr_t;
|
||||
#pragma pack(pop)
|
||||
|
@ -1,67 +1,20 @@
|
||||
#define _MICE_FILES
|
||||
#include "files.h"
|
||||
|
||||
open_hook_t* open_hooks_list = NULL;
|
||||
HANDLE open_hook(file_hook_t* file_hook, com_hook_t* com_hook) {
|
||||
HANDLE open_hook(file_hook_t* file_hook) {
|
||||
open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t));
|
||||
memset(opened, 0, sizeof *opened);
|
||||
ZeroMemory(opened, sizeof *opened);
|
||||
|
||||
opened->file_hook = file_hook;
|
||||
opened->com_hook = com_hook;
|
||||
opened->hook = file_hook;
|
||||
|
||||
CHAR path[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||
HANDLE handle =
|
||||
_CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
log_error(HOOKS_LOGGER, "Failed to create dummy handle: %03x", GetLastError());
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
opened->handle = handle;
|
||||
opened->next = open_hooks_list;
|
||||
open_hooks_list = opened;
|
||||
HANDLE handle = GetDummyHandle();
|
||||
opened->ctx.m_Handle = handle;
|
||||
opened->ctx.m_HookData = file_hook->hook_data;
|
||||
|
||||
SetDataForHandle(handle, HDATA_FILE, opened, TRUE);
|
||||
|
||||
return handle;
|
||||
}
|
||||
void close_hook(HANDLE handle) {
|
||||
if (handle == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
_CloseHandle(handle);
|
||||
|
||||
open_hook_t* opened = NULL;
|
||||
open_hook_t* root = open_hooks_list;
|
||||
if (open_hooks_list->handle == handle) {
|
||||
open_hook_t* next = open_hooks_list->next;
|
||||
free(open_hooks_list);
|
||||
open_hooks_list = next;
|
||||
return;
|
||||
}
|
||||
|
||||
while (root != NULL) {
|
||||
if (root->next && root->next->handle == handle) {
|
||||
opened = root->next;
|
||||
root->next = opened->next;
|
||||
free(opened);
|
||||
return;
|
||||
}
|
||||
root = root->next;
|
||||
}
|
||||
}
|
||||
file_hook_t* get_handle_file_hook(HANDLE handle) {
|
||||
open_hook_t* root = open_hooks_list;
|
||||
while (root != NULL) {
|
||||
if (root->handle == handle) return root->file_hook;
|
||||
root = root->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
com_hook_t* get_handle_com_hook(HANDLE handle) {
|
||||
open_hook_t* root = open_hooks_list;
|
||||
while (root != NULL) {
|
||||
if (root->handle == handle) return root->com_hook;
|
||||
root = root->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_hook_t* file_hook_list = NULL;
|
||||
file_hook_t* new_file_hook(LPCWSTR filename) {
|
||||
@ -92,26 +45,16 @@ drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
||||
|
||||
char _redirected_path[MAX_PATH];
|
||||
|
||||
void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) {
|
||||
file_hook_t* find_hook(LPCWSTR lpFileName) {
|
||||
file_hook_t* file_hook = file_hook_list;
|
||||
while (file_hook != NULL) {
|
||||
if (wcscmp(lpFileName, file_hook->filename) == 0 ||
|
||||
(file_hook->altFilename != NULL && wcscmp(lpFileName, file_hook->altFilename) == 0)) {
|
||||
*found_fh = file_hook;
|
||||
break;
|
||||
return file_hook;
|
||||
}
|
||||
file_hook = file_hook->next;
|
||||
}
|
||||
|
||||
com_hook_t* com_hook = com_hook_list;
|
||||
while (com_hook != NULL) {
|
||||
if (wcscmp(lpFileName, com_hook->wName) == 0 ||
|
||||
wcscmp(lpFileName, com_hook->wDosName) == 0) {
|
||||
*found_ch = com_hook;
|
||||
break;
|
||||
}
|
||||
com_hook = com_hook->next;
|
||||
}
|
||||
return NULL;
|
||||
};
|
||||
|
||||
void make_dirs(char* path) {
|
||||
@ -135,8 +78,20 @@ void make_dirs(char* path) {
|
||||
}
|
||||
}
|
||||
|
||||
char WORKING_DIR[MAX_PATH + 1] = { 0 };
|
||||
char get_gamedata_drive() {
|
||||
if (WORKING_DIR[0] == 0x00) {
|
||||
GetCurrentDirectoryA(sizeof WORKING_DIR, WORKING_DIR);
|
||||
}
|
||||
return WORKING_DIR[0];
|
||||
}
|
||||
|
||||
inline char char_lower(char value) {
|
||||
if ('A' <= value <= 'Z') return value - 'A' + 'a';
|
||||
return value;
|
||||
}
|
||||
|
||||
BOOL redirect_path(LPCSTR path, LPCSTR* redirected) {
|
||||
return FALSE;
|
||||
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
||||
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
|
||||
if (strncmp(path, row.drive, strlen(row.drive)) == 0) {
|
||||
@ -161,14 +116,14 @@ BOOL redirect_path(LPCSTR path, LPCSTR* redirected) {
|
||||
|
||||
if ((('a' <= path[0] && path[0] <= 'z') || ('A' <= path[0] && path[0] <= 'Z')) &&
|
||||
path[1] == ':' && (path[2] == '/' || path[2] == '\\')) {
|
||||
char drive;
|
||||
if ('A' <= path[0] && path[0] <= 'Z') {
|
||||
drive = path[0] - 'A' + 'a';
|
||||
} else {
|
||||
drive = path[0];
|
||||
// TODO: Ca
|
||||
if (char_lower(path[0]) == char_lower(get_gamedata_drive())) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ZeroMemory(_redirected_path, sizeof _redirected_path);
|
||||
snprintf(_redirected_path, sizeof _redirected_path, "dev\\%c\\%s", drive, path + 3);
|
||||
snprintf(_redirected_path, sizeof _redirected_path, "dev\\%c\\%s", char_lower(path[0]),
|
||||
path + 3);
|
||||
|
||||
make_dirs(_redirected_path);
|
||||
*redirected = _redirected_path;
|
||||
@ -189,11 +144,9 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile) {
|
||||
file_hook_t* found_fh = NULL;
|
||||
com_hook_t* found_ch = NULL;
|
||||
find_hooks(lpFileName, &found_fh, &found_ch);
|
||||
if (found_fh != NULL || found_ch != NULL) {
|
||||
HANDLE handle = open_hook(found_fh, found_ch);
|
||||
file_hook_t* found_fh = find_hook(lpFileName);
|
||||
if (found_fh != NULL) {
|
||||
HANDLE handle = open_hook(found_fh);
|
||||
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
@ -220,11 +173,9 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw
|
||||
WCHAR wideFileName[MAX_PATH + 1];
|
||||
MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&wideFileName, MAX_PATH + 1);
|
||||
|
||||
file_hook_t* found_fh = NULL;
|
||||
com_hook_t* found_ch = NULL;
|
||||
find_hooks(wideFileName, &found_fh, &found_ch);
|
||||
if (found_fh != NULL || found_ch != NULL) {
|
||||
HANDLE handle = open_hook(found_fh, found_ch);
|
||||
file_hook_t* found_fh = find_hook(wideFileName);
|
||||
if (found_fh != NULL) {
|
||||
HANDLE handle = open_hook(found_fh);
|
||||
log_info(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
@ -240,149 +191,162 @@ BOOL WINAPI FakePathFileExistsA(LPCSTR pszPath) {
|
||||
redirect_path(pszPath, &pszPath);
|
||||
return TruePathFileExistsA(pszPath);
|
||||
}
|
||||
BOOL WINAPI FakePathFileExistsW(LPCSTR pszPath) {
|
||||
BOOL WINAPI FakePathFileExistsW(LPCWSTR pszPath) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path(pszPath, &redirected)) {
|
||||
if (redirect_path_w(pszPath, &redirected)) {
|
||||
return TruePathFileExistsA(redirected);
|
||||
}
|
||||
return TruePathFileExistsW(pszPath);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeDeleteFileA(LPCSTR pszPath) {
|
||||
redirect_path(pszPath, &pszPath);
|
||||
return TrueDeleteFileA(pszPath);
|
||||
}
|
||||
BOOL WINAPI FakeDeleteFileW(LPCSTR pszPath) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path(pszPath, &redirected)) {
|
||||
return TrueDeleteFileA(redirected);
|
||||
}
|
||||
return TrueDeleteFileA(pszPath);
|
||||
}
|
||||
BOOL WINAPI FakeDeleteFileW(LPCWSTR pszPath) {
|
||||
LPCSTR redirected;
|
||||
if (redirect_path_w(pszPath, &redirected)) {
|
||||
return TrueDeleteFileA(redirected);
|
||||
}
|
||||
return TrueDeleteFileW(pszPath);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = get_handle_file_hook(hDevice);
|
||||
if (hook != NULL) {
|
||||
if (hook->DeviceIoControl) {
|
||||
// TODO: Less jank
|
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||
open_hook_t* pHData = GetDataForHandle(hDevice, HDATA_FILE);
|
||||
if (pHData == NULL) {
|
||||
log_trace(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice,
|
||||
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
BOOL ret =
|
||||
hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize,
|
||||
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
if (ret && lpOverlapped && lpBytesReturned) {
|
||||
lpOverlapped->InternalHigh = *lpBytesReturned;
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "DeviceIoControl(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
}
|
||||
|
||||
log_trace(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice,
|
||||
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
file_hook_t* file_hook = pHData->hook;
|
||||
if (!file_hook->DeviceIoControl) {
|
||||
log_error(HOOKS_LOGGER, "DeviceIoControl(%ls) unimplemented", file_hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
BOOL ret =
|
||||
file_hook->DeviceIoControl(&(pHData->ctx), dwIoControlCode, lpInBuffer, nInBufferSize,
|
||||
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
if (lpOverlapped) {
|
||||
SetEvent(lpOverlapped->hEvent);
|
||||
if (ret && lpBytesReturned) {
|
||||
lpOverlapped->InternalHigh = *lpBytesReturned;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetFilePointer) {
|
||||
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh,
|
||||
dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL)
|
||||
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
|
||||
if (dwMoveMethod == FILE_BEGIN) {
|
||||
if (*lpDistanceToMoveHigh)
|
||||
pHData->ctx.m_Pointer.HighPart = *lpDistanceToMoveHigh;
|
||||
else
|
||||
pHData->ctx.m_Pointer.HighPart = 0;
|
||||
pHData->ctx.m_Pointer.LowPart = lDistanceToMove;
|
||||
} else if (dwMoveMethod == FILE_END) {
|
||||
log_error("files", "FILE_END unimplemented");
|
||||
return 0xFFFFFFFF;
|
||||
} else {
|
||||
if (lpDistanceToMoveHigh) pHData->ctx.m_Pointer.HighPart += *lpDistanceToMoveHigh;
|
||||
pHData->ctx.m_Pointer.LowPart += lDistanceToMove;
|
||||
}
|
||||
|
||||
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
return pHData->ctx.m_Pointer.LowPart;
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetFilePointerEx) {
|
||||
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer,
|
||||
dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointerEx(%ls) unimplemented", hook->filename);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData != NULL) {
|
||||
if (dwMoveMethod == FILE_BEGIN) {
|
||||
pHData->ctx.m_Pointer = liDistanceToMove;
|
||||
} else if (dwMoveMethod == FILE_END) {
|
||||
log_error("files", "FILE_END unimplemented");
|
||||
return FALSE;
|
||||
} else {
|
||||
pHData->ctx.m_Pointer.QuadPart += liDistanceToMove.QuadPart;
|
||||
}
|
||||
if (lpNewFilePointer) lpNewFilePointer->QuadPart = pHData->ctx.m_Pointer.QuadPart;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetFileSizeEx) {
|
||||
return hook->GetFileSizeEx(hook->data, lpFileSize);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "GetFileSizeEx(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL) {
|
||||
return TrueGetFileSizeEx(hFile, lpFileSize);
|
||||
}
|
||||
|
||||
return TrueGetFileSizeEx(hFile, lpFileSize);
|
||||
file_hook_t* file_hook = pHData->hook;
|
||||
if (!file_hook->GetFileSizeEx) {
|
||||
log_error(HOOKS_LOGGER, "GetFileSizeEx(%ls) unimplemented", file_hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
return file_hook->GetFileSizeEx(&(pHData->ctx), lpFileSize);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||
if (hFile == GetStdHandle(STD_INPUT_HANDLE) || hFile == GetStdHandle(STD_OUTPUT_HANDLE) ||
|
||||
hFile == GetStdHandle(STD_ERROR_HANDLE)) {
|
||||
if (hFile == GetStdHandle(STD_OUTPUT_HANDLE) || hFile == GetStdHandle(STD_ERROR_HANDLE)) {
|
||||
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
log_trace("file", "WriteFile(%08x)", hFile);
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->WriteFile) {
|
||||
return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite,
|
||||
lpNumberOfBytesWritten, lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL) {
|
||||
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
// return FALSE;
|
||||
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
file_hook_t* file_hook = pHData->hook;
|
||||
if (!file_hook->WriteFile) {
|
||||
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", file_hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
return file_hook->WriteFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToWrite,
|
||||
lpNumberOfBytesWritten, lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->ReadFile) {
|
||||
return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||
lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
if (hFile == GetStdHandle(STD_INPUT_HANDLE)) {
|
||||
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||
open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE);
|
||||
if (pHData == NULL) {
|
||||
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
file_hook_t* file_hook = pHData->hook;
|
||||
|
||||
if (!file_hook->ReadFile) {
|
||||
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", file_hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
return file_hook->ReadFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
||||
file_hook_t* hook = get_handle_file_hook(hObject);
|
||||
if (hook != NULL) {
|
||||
log_misc("file", "close %08x", hObject);
|
||||
close_hook(hObject);
|
||||
return TRUE;
|
||||
}
|
||||
RemoveDataForHandle(hObject, HDATA_ANY);
|
||||
return TrueCloseHandle(hObject);
|
||||
}
|
||||
|
||||
@ -407,8 +371,8 @@ void hook_io() {
|
||||
|
||||
hook("Shlwapi.dll", "PathFileExistsA", FakePathFileExistsA, (void**)&TruePathFileExistsA, 5);
|
||||
hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW, 5);
|
||||
hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA, 5);
|
||||
hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW, 5);
|
||||
hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA, 7);
|
||||
hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW, 7);
|
||||
|
||||
hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5);
|
||||
}
|
||||
|
@ -2,51 +2,64 @@
|
||||
#include "../common.h"
|
||||
#include "com.h"
|
||||
|
||||
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
#ifndef _MICE_FILES
|
||||
#define _MICE_FILES extern
|
||||
#endif
|
||||
|
||||
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
_MICE_FILES HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
_MICE_FILES HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
|
||||
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove,
|
||||
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||
_MICE_FILES BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode,
|
||||
LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
_MICE_FILES DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove,
|
||||
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
_MICE_FILES BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||
// logging needs access to WriteFile, so we can't static it!
|
||||
BOOL(WINAPI* TrueWriteFile)
|
||||
(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
||||
static BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath);
|
||||
static BOOL(WINAPI* TruePathFileExistsW)(LPCWSTR pszPath);
|
||||
static BOOL(WINAPI* TrueDeleteFileA)(LPCSTR lpFileName);
|
||||
static BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName);
|
||||
_MICE_FILES BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
_MICE_FILES BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
_MICE_FILES BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
||||
_MICE_FILES BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath);
|
||||
_MICE_FILES BOOL(WINAPI* TruePathFileExistsW)(LPCWSTR pszPath);
|
||||
_MICE_FILES BOOL(WINAPI* TrueDeleteFileA)(LPCSTR lpFileName);
|
||||
_MICE_FILES BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName);
|
||||
|
||||
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
|
||||
typedef struct {
|
||||
HANDLE m_Handle;
|
||||
LARGE_INTEGER m_Pointer;
|
||||
void* m_HookData;
|
||||
} file_context_t;
|
||||
|
||||
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod);
|
||||
typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove,
|
||||
typedef BOOL(WINAPI FnDeviceIoControl)(file_context_t* ctx, DWORD dwIoControlCode,
|
||||
LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef DWORD(FnSetFilePointer)(file_context_t* ctx, LONG lDistanceToMove,
|
||||
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
typedef BOOL(FnSetFilePointerEx)(file_context_t* ctx, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||
typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
typedef BOOL(FnWriteFile)(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnReadFile)(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
typedef BOOL(FnReadFile)(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef BOOL(FnGetFileSizeEx)(void* file, PLARGE_INTEGER lpFileSize);
|
||||
typedef BOOL(FnGetFileSizeEx)(file_context_t* ctx, PLARGE_INTEGER lpFileSize);
|
||||
|
||||
typedef struct _stat64i32 _stat64i32_t;
|
||||
static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
|
||||
@ -56,6 +69,7 @@ static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
|
||||
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
|
||||
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
|
||||
#define _CreateFileA (TrueCreateFileA ? TrueCreateFileA : CreateFileA)
|
||||
#define _SetFilePointer (TrueSetFilePointer ? TrueSetFilePointer : SetFilePointer)
|
||||
|
||||
typedef struct drive_redirect {
|
||||
const CHAR* drive;
|
||||
@ -72,22 +86,20 @@ typedef struct file_hook {
|
||||
LPCWSTR altFilename;
|
||||
|
||||
FnDeviceIoControl* DeviceIoControl;
|
||||
FnSetFilePointer* SetFilePointer;
|
||||
FnSetFilePointerEx* SetFilePointerEx;
|
||||
FnWriteFile* WriteFile;
|
||||
FnReadFile* ReadFile;
|
||||
FnGetFileSizeEx* GetFileSizeEx;
|
||||
|
||||
void* data;
|
||||
com_hook_t* com_hook;
|
||||
|
||||
void* hook_data;
|
||||
LPHANDLE virtual_handle;
|
||||
struct file_hook* next;
|
||||
} file_hook_t;
|
||||
|
||||
typedef struct open_hook {
|
||||
HANDLE handle;
|
||||
file_hook_t* file_hook;
|
||||
com_hook_t* com_hook;
|
||||
file_context_t ctx;
|
||||
file_hook_t* hook;
|
||||
struct open_hook* next;
|
||||
} open_hook_t;
|
||||
|
||||
@ -96,7 +108,3 @@ extern file_hook_t* file_hook_list;
|
||||
file_hook_t* new_file_hook(LPCWSTR filename);
|
||||
void hook_file(file_hook_t* hook);
|
||||
void hook_io();
|
||||
|
||||
void close_hook(HANDLE handle);
|
||||
file_hook_t* get_handle_file_hook(HANDLE handle);
|
||||
com_hook_t* get_handle_com_hook(HANDLE handle);
|
||||
|
@ -17,10 +17,49 @@ HWND GetProcessWindow() {
|
||||
EnumWindows(EnumWindowsCallback, 0);
|
||||
return window;
|
||||
}
|
||||
|
||||
BOOL UnFrameWindow(HWND hwnd) {
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
LONG style = GetWindowLongW(hwnd, GWL_STYLE);
|
||||
if (GetLastError() != ERROR_SUCCESS) return FALSE;
|
||||
|
||||
RECT rect;
|
||||
if (!GetClientRect(hwnd, &rect)) return FALSE;
|
||||
|
||||
style &= ~(WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU);
|
||||
if (!AdjustWindowRect(&rect, style, FALSE)) return FALSE;
|
||||
|
||||
SetWindowLongW(hwnd, GWL_STYLE, style);
|
||||
if (!SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOMOVE))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FrameWindow(HWND hwnd) {
|
||||
SetLastError(ERROR_SUCCESS);
|
||||
LONG style = GetWindowLongW(hwnd, GWL_STYLE);
|
||||
if (GetLastError() != ERROR_SUCCESS) return FALSE;
|
||||
|
||||
RECT rect;
|
||||
if (!GetClientRect(hwnd, &rect)) return FALSE;
|
||||
|
||||
style |= WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU;
|
||||
if (!AdjustWindowRect(&rect, style, FALSE)) return FALSE;
|
||||
|
||||
SetWindowLongW(hwnd, GWL_STYLE, style);
|
||||
|
||||
if (!SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left,
|
||||
rect.bottom - rect.top, SWP_FRAMECHANGED | SWP_NOMOVE))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL GetD3D9Device(void** pTable, size_t Size) {
|
||||
if (!pTable) return false;
|
||||
|
||||
IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
IDirect3D9* pD3D =
|
||||
(TrueDirect3DCreate9 ? TrueDirect3DCreate9 : Direct3DCreate9)(D3D_SDK_VERSION);
|
||||
if (!pD3D) return false;
|
||||
|
||||
IDirect3DDevice9* pDummyDevice = NULL;
|
||||
@ -92,8 +131,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UIN
|
||||
}
|
||||
|
||||
void post_win_create(HWND hWnd) {
|
||||
void* d3d9Device[119];
|
||||
// Don't double-hook!
|
||||
if (TrueEndScene != NULL) return;
|
||||
|
||||
void* d3d9Device[119];
|
||||
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device))) {
|
||||
*((PVOID*)&TrueEndScene) = CreateHook((PVOID)d3d9Device[42], (PVOID)hkEndScene, 7);
|
||||
}
|
||||
@ -103,10 +144,46 @@ void post_win_create(HWND hWnd) {
|
||||
}
|
||||
}
|
||||
|
||||
RECT monitorRect = { 0 };
|
||||
int monitorIndex = 0;
|
||||
BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor,
|
||||
LPARAM dwData) {
|
||||
if (monitorIndex == MiceConfig.window.adaptor)
|
||||
memcpy(&monitorRect, lprcMonitor, sizeof monitorRect);
|
||||
monitorIndex++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupWindowPosition(int* X, int* Y, int* nWidth, int* nHeight) {
|
||||
monitorIndex = 0;
|
||||
EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)NULL);
|
||||
|
||||
if (MiceConfig.window.w) *nWidth = MiceConfig.window.w;
|
||||
if (MiceConfig.window.h) *nHeight = MiceConfig.window.h;
|
||||
|
||||
if (MiceConfig.window.centre) {
|
||||
*X = ((monitorRect.right - monitorRect.left) - *nWidth) / 2;
|
||||
*Y = ((monitorRect.bottom - monitorRect.top) - *nHeight) / 2;
|
||||
} else {
|
||||
*X = MiceConfig.window.x;
|
||||
*Y = MiceConfig.window.y;
|
||||
}
|
||||
*X += monitorRect.left;
|
||||
*Y += monitorRect.top;
|
||||
}
|
||||
|
||||
HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName,
|
||||
DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
|
||||
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) {
|
||||
HWND hWnd = TrueCreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth,
|
||||
// Pass-through for system stuff
|
||||
if (lpWindowName == NULL || strcmp(lpWindowName, "OleMainThreadWndName") == 0 ||
|
||||
strcmp(lpWindowName, "CicMarshalWnd") == 0) {
|
||||
return TrueCreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth,
|
||||
nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
}
|
||||
|
||||
SetupWindowPosition(&X, &Y, &nWidth, &nHeight);
|
||||
HWND hWnd = TrueCreateWindowExA(dwExStyle, lpClassName, "Micetools", dwStyle, X, Y, nWidth,
|
||||
nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
post_win_create(hWnd);
|
||||
return hWnd;
|
||||
@ -114,14 +191,87 @@ HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWi
|
||||
HWND WINAPI FakeCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName,
|
||||
DWORD dwStyle, int X, int Y, int nWidth, int nHeight,
|
||||
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) {
|
||||
HWND hWnd = TrueCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth,
|
||||
// Pass-through for system stuff
|
||||
if (lpWindowName == NULL || wcscmp(lpWindowName, L"OleMainThreadWndName") == 0 ||
|
||||
wcscmp(lpWindowName, L"CicMarshalWnd") == 0) {
|
||||
return TrueCreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth,
|
||||
nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
}
|
||||
|
||||
SetupWindowPosition(&X, &Y, &nWidth, &nHeight);
|
||||
HWND hWnd = TrueCreateWindowExW(dwExStyle, lpClassName, L"Micetools", dwStyle, X, Y, nWidth,
|
||||
nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
post_win_create(hWnd);
|
||||
return hWnd;
|
||||
}
|
||||
|
||||
static HRESULT(STDMETHODCALLTYPE* TrueCreateDevice)(IDirect3D9* this, UINT Adapter,
|
||||
D3DDEVTYPE DeviceType, HWND hFocusWindow,
|
||||
DWORD BehaviorFlags,
|
||||
D3DPRESENT_PARAMETERS* pPresentationParameters,
|
||||
IDirect3DDevice9** ppReturnedDeviceInterface);
|
||||
|
||||
extern RECT monitorRect;
|
||||
HRESULT STDMETHODCALLTYPE FakeCreateDevice(IDirect3D9* this, UINT Adapter, D3DDEVTYPE DeviceType,
|
||||
HWND hFocusWindow, DWORD BehaviorFlags,
|
||||
D3DPRESENT_PARAMETERS* pPresentationParameters,
|
||||
IDirect3DDevice9** ppReturnedDeviceInterface) {
|
||||
if (MiceConfig.window.windowed) {
|
||||
pPresentationParameters->Windowed = TRUE;
|
||||
pPresentationParameters->FullScreen_RefreshRateInHz = 0;
|
||||
} else if (pPresentationParameters->Windowed) {
|
||||
D3DDISPLAYMODE d3ddm;
|
||||
this->lpVtbl->GetAdapterDisplayMode(this, Adapter, &d3ddm);
|
||||
|
||||
pPresentationParameters->Windowed = FALSE;
|
||||
pPresentationParameters->FullScreen_RefreshRateInHz = d3ddm.RefreshRate;
|
||||
}
|
||||
if (MiceConfig.window.borderless)
|
||||
UnFrameWindow(hFocusWindow);
|
||||
else
|
||||
FrameWindow(hFocusWindow);
|
||||
Adapter = MiceConfig.window.adaptor;
|
||||
|
||||
RECT winRect;
|
||||
GetWindowRect(hFocusWindow, &winRect);
|
||||
int w = MiceConfig.window.w ? MiceConfig.window.w : (winRect.right - winRect.left);
|
||||
int h = MiceConfig.window.h ? MiceConfig.window.h : (winRect.bottom - winRect.top);
|
||||
int x = MiceConfig.window.x;
|
||||
int y = MiceConfig.window.y;
|
||||
if (MiceConfig.window.centre) {
|
||||
x = ((monitorRect.right - monitorRect.left) - w) / 2;
|
||||
y = ((monitorRect.bottom - monitorRect.top) - h) / 2;
|
||||
}
|
||||
|
||||
x += monitorRect.left;
|
||||
y += monitorRect.top;
|
||||
|
||||
SetWindowPos(hFocusWindow, HWND_TOP, x, y, w, h, 0);
|
||||
|
||||
return TrueCreateDevice(this, Adapter, DeviceType, hFocusWindow, BehaviorFlags,
|
||||
pPresentationParameters, ppReturnedDeviceInterface);
|
||||
}
|
||||
|
||||
IDirect3D9* WINAPI FakeDirect3DCreate9(UINT SDKVersion) {
|
||||
IDirect3D9* pD3D = TrueDirect3DCreate9(D3D_SDK_VERSION);
|
||||
|
||||
TrueCreateDevice = pD3D->lpVtbl->CreateDevice;
|
||||
DWORD patch = (DWORD)&FakeCreateDevice;
|
||||
patch_at(&pD3D->lpVtbl->CreateDevice, (char*)&patch, 4);
|
||||
|
||||
return pD3D;
|
||||
};
|
||||
|
||||
int WINAPI FakeGetSystemMetrics(int nIndex) {
|
||||
int real = TrueGetSystemMetrics(nIndex);
|
||||
if (nIndex == SM_CXSCREEN && MiceConfig.window.w) return MiceConfig.window.w;
|
||||
if (nIndex == SM_CYSCREEN && MiceConfig.window.h) return MiceConfig.window.h;
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
void hook_gui() {
|
||||
//
|
||||
hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7);
|
||||
hook("User32.dll", "CreateWindowExW", FakeCreateWindowExW, (void**)&TrueCreateWindowExW, 7);
|
||||
hook("User32.dll", "GetSystemMetrics", FakeGetSystemMetrics, (void**)&TrueGetSystemMetrics, 7);
|
||||
hook("D3d9.dll", "Direct3DCreate9", FakeDirect3DCreate9, (void**)&TrueDirect3DCreate9, 5);
|
||||
}
|
||||
|
@ -10,6 +10,10 @@ static HWND(WINAPI* TrueCreateWindowExW)(DWORD dwExStyle, LPCWSTR lpClassName, L
|
||||
HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
|
||||
LPVOID lpParam);
|
||||
static BOOL(WINAPI* TrueSetSystemCursor)(HCURSOR hcur, DWORD id);
|
||||
static IDirect3D9*(WINAPI* TrueDirect3DCreate9)(UINT SDKVersion);
|
||||
static int(WINAPI* TrueGetSystemMetrics)(int nIndex);
|
||||
|
||||
#define _GetSystemMetrics (TrueGetSystemMetrics ? TrueGetSystemMetrics : GetSystemMetrics)
|
||||
|
||||
void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g,
|
||||
unsigned char b);
|
||||
|
@ -3,13 +3,18 @@
|
||||
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);
|
||||
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
||||
(addr >> 8) & 0xff, addr & 0xff, port);
|
||||
// Poorly exclude pcps. TODO: better
|
||||
if (port < 40100 || port > 40120) {
|
||||
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
||||
(addr >> 8) & 0xff, addr & 0xff, port);
|
||||
}
|
||||
return True_connect(s, name, namelen);
|
||||
}
|
||||
|
||||
static uint8_t spoof_mac[6] = { 0xD8, 0xBB, 0xC1, 0x0A, 0x2F, 0x1D };
|
||||
#define IF_INDEX 1
|
||||
#define MAC_PREFIX_0 0xD8
|
||||
#define MAC_PREFIX_1 0xBB
|
||||
#define MAC_PREFIX_2 0xC1
|
||||
DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
|
||||
log_info("network", "Injecting fake IfTable");
|
||||
|
||||
@ -35,8 +40,13 @@ DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
|
||||
row->dwType = IF_TYPE_ETHERNET_CSMACD;
|
||||
row->dwMtu = 4200;
|
||||
row->dwSpeed = 1000000000;
|
||||
row->dwPhysAddrLen = sizeof(spoof_mac);
|
||||
memcpy(row->bPhysAddr, spoof_mac, sizeof(spoof_mac));
|
||||
row->dwPhysAddrLen = 6;
|
||||
row->bPhysAddr[0] = MAC_PREFIX_0;
|
||||
row->bPhysAddr[1] = MAC_PREFIX_1;
|
||||
row->bPhysAddr[2] = MAC_PREFIX_2;
|
||||
row->bPhysAddr[3] = (MiceConfig.network.mac >> 16) & 0xff;
|
||||
row->bPhysAddr[4] = (MiceConfig.network.mac >> 8) & 0xff;
|
||||
row->bPhysAddr[5] = MiceConfig.network.mac & 0xff;
|
||||
row->dwAdminStatus = 1;
|
||||
row->dwOperStatus = IF_OPER_STATUS_OPERATIONAL;
|
||||
|
||||
@ -55,20 +65,21 @@ DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
unsigned char address[4];
|
||||
unsigned int* address;
|
||||
} dns;
|
||||
|
||||
dns INTERCEPT_DNS[] = {
|
||||
// Startup
|
||||
{ "naominet.jp", { 10, 79, 140, 238 } },
|
||||
{ "naominet.jp", &(MiceConfig.network.naominet_jp) },
|
||||
// Billing
|
||||
{ "ib.naominet.jp", { 10, 79, 140, 238 } },
|
||||
{ "ib.naominet.jp", &(MiceConfig.network.ib_naominet_jp) },
|
||||
// Aime
|
||||
{ "aime.naominet.jp", { 10, 79, 140, 238 } },
|
||||
{ "aime.naominet.jp", &(MiceConfig.network.aime_naominet_jp) },
|
||||
// Routers (ping targets)
|
||||
{ "tenporouter.loc", { 10, 79, 140, 238 } },
|
||||
{ "bbrouter.loc", { 10, 79, 140, 238 } }, // Must match tenporouter
|
||||
{ "mobirouter.loc", { 10, 79, 140, 238 } },
|
||||
{ "dslrouter.loc", { 10, 79, 140, 238 } },
|
||||
{ "tenporouter.loc", &(MiceConfig.network.tenporouter_loc) },
|
||||
{ "bbrouter.loc", &(MiceConfig.network.bbrouter_loc) }, // Must match tenporouter
|
||||
{ "mobirouter.loc", &(MiceConfig.network.mobirouter_loc) },
|
||||
{ "dslrouter.loc", &(MiceConfig.network.dslrouter_loc) },
|
||||
};
|
||||
|
||||
DNS_RECORDA dummy_record;
|
||||
@ -78,19 +89,15 @@ DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID
|
||||
if (ppQueryResults) {
|
||||
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||
if (strcmp(pszName, INTERCEPT_DNS[i].name) == 0) {
|
||||
#define spoof (INTERCEPT_DNS[i].address)
|
||||
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, spoof[0],
|
||||
spoof[1], spoof[2], spoof[3]);
|
||||
log_info("dns", "Replacing %s with %08x", pszName, *INTERCEPT_DNS[i].address);
|
||||
|
||||
// We only support replacing at most one address, but that's all we'll ever need to!
|
||||
(*ppQueryResults) = &dummy_record;
|
||||
(*ppQueryResults)->pNext = NULL;
|
||||
(*ppQueryResults)->wType = DNS_TYPE_A;
|
||||
(*ppQueryResults)->Data.A.IpAddress =
|
||||
(spoof[0]) | (spoof[1] << 8) | (spoof[2] << 16) | (spoof[3] << 24);
|
||||
(*ppQueryResults)->Data.A.IpAddress = _byteswap_ulong(*INTERCEPT_DNS[i].address);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
#undef spoof
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,19 +111,11 @@ INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily,
|
||||
log_misc("dns", "(WSA)DNS lookup for %s", AddressString);
|
||||
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||
if (strcmp(AddressString, INTERCEPT_DNS[i].name) == 0) {
|
||||
#define spoof (INTERCEPT_DNS[i].address)
|
||||
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, spoof[0],
|
||||
spoof[1], spoof[2], spoof[3]);
|
||||
log_info("dns", "(WSA)Replacing %s with %08x", AddressString, INTERCEPT_DNS[i].address);
|
||||
|
||||
lpAddress->sa_family = AF_INET;
|
||||
// ... :)
|
||||
lpAddress->sa_data[2] = spoof[0];
|
||||
lpAddress->sa_data[3] = spoof[1];
|
||||
lpAddress->sa_data[4] = spoof[2];
|
||||
lpAddress->sa_data[5] = spoof[3];
|
||||
|
||||
memcpy(&lpAddress->sa_data, INTERCEPT_DNS[i].address, 4);
|
||||
return ERROR_SUCCESS;
|
||||
#undef spoof
|
||||
}
|
||||
}
|
||||
log_warning("dns", "(WSA)DNS passthrough for %s", AddressString);
|
||||
|
@ -22,7 +22,7 @@ BOOL WINAPI FakeCreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
||||
if (lpProcessInformation) {
|
||||
lpProcessInformation->hProcess = fake_evt;
|
||||
}
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
@ -36,6 +36,8 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
// #else
|
||||
// log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||
log_info("spawn", "CreateProcessW %ls", lpApplicationName);
|
||||
|
||||
lpProcessInformation->hThread = GetDummyHandle();
|
||||
return TRUE;
|
||||
|
||||
CHAR applicationName[MAX_PATH + 1];
|
||||
|
@ -8,6 +8,7 @@ shared_library(
|
||||
name_prefix: '',
|
||||
vs_module_defs: 'mice.def',
|
||||
sources: [
|
||||
'util/misc.c',
|
||||
'util/log.c',
|
||||
'util/hook.c',
|
||||
|
||||
@ -23,7 +24,7 @@ shared_library(
|
||||
link_with: [
|
||||
dmi_lib,
|
||||
mice_lib,
|
||||
amlib,
|
||||
amiTimer,
|
||||
mxklib,
|
||||
],
|
||||
include_directories: [
|
||||
|
@ -120,15 +120,17 @@ IOCTL_MXSUPERIO_READ:
|
||||
#define SMBUS_EEPROM 0xAE
|
||||
|
||||
// Keychip
|
||||
#define N2_GET_EEPROM 0x40
|
||||
#define N2_GET_UNIQUE_NUMBER 0xA0
|
||||
#define N2_GET_STATUS 0xA8
|
||||
#define N2_STATUS_FLAG_BUSY 2
|
||||
#define N2_I2C_CHALLENGE_RESPONSE 0xB0
|
||||
#define DS_GET_EEPROM 0x40
|
||||
#define DS_GET_UNIQUE_NUMBER 0xA0
|
||||
#define DS_GET_STATUS 0xA8
|
||||
#define DS_STATUS_FLAG_BUSY 2
|
||||
#define DS_I2C_CHALLENGE_RESPONSE 0xB0
|
||||
|
||||
#define EXIO_GET_BUSY 0x00
|
||||
|
||||
#pragma pack(1)
|
||||
// Old
|
||||
// TODO: Check for uses, then delete
|
||||
#pragma pack(push, 1)
|
||||
typedef struct mxsmbus_request_packet_ {
|
||||
BYTE status;
|
||||
BYTE prt;
|
||||
@ -137,8 +139,6 @@ typedef struct mxsmbus_request_packet_ {
|
||||
BYTE dlen;
|
||||
BYTE data[32];
|
||||
} mxsmbus_request_packet;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct mxsmbus_i2c_packet_ {
|
||||
BYTE status;
|
||||
BYTE prt;
|
||||
@ -147,3 +147,53 @@ typedef struct mxsmbus_i2c_packet_ {
|
||||
BYTE dlen;
|
||||
BYTE data[32];
|
||||
} mxsmbus_i2c_packet;
|
||||
|
||||
typedef struct _MXSMBUS_REQUEST_PACKET {
|
||||
BYTE status;
|
||||
BYTE command;
|
||||
BYTE v_addr;
|
||||
BYTE command_code;
|
||||
BYTE nbytes;
|
||||
BYTE data[32];
|
||||
} MXSMBUS_REQUEST_PACKET, *PMXSMBUS_REQUEST_PACKET;
|
||||
|
||||
typedef struct _MXSMBUS_I2C_PACKET {
|
||||
BYTE status;
|
||||
BYTE command;
|
||||
WORD v_addr;
|
||||
WORD command_code;
|
||||
BYTE nbytes;
|
||||
BYTE data[32];
|
||||
} MXSMBUS_I2C_PACKET, *PMXSMBUS_I2C_PACKET;
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
typedef enum {
|
||||
ICH9_CMD_QUICK = 0b000,
|
||||
ICH9_CMD_BYTE = 0b001,
|
||||
ICH9_CMD_BYTE_DATA = 0b010,
|
||||
ICH9_CMD_WORD_DATA = 0b011,
|
||||
ICH9_CMD_PROCESS_CALL = 0b100,
|
||||
ICH9_CMD_BLOCK = 0b101,
|
||||
ICH9_CMD_I2C_READ = 0b110,
|
||||
ICH9_CMD_BLOCK_PROCESS = 0b111,
|
||||
} ich9_cmd_t;
|
||||
|
||||
typedef enum {
|
||||
MXSMBUS_CMD_WRITE_QUICK = 0,
|
||||
MXSMBUS_CMD_READ_QUICK = 1,
|
||||
MXSMBUS_CMD_WRITE_BYTE = 2,
|
||||
MXSMBUS_CMD_READ_BYTE = 3,
|
||||
MXSMBUS_CMD_WRITE_BYTE_DATA = 4,
|
||||
MXSMBUS_CMD_READ_BYTE_DATA = 5,
|
||||
MXSMBUS_CMD_WRITE_WORD_DATA = 6,
|
||||
MXSMBUS_CMD_READ_WORD_DATA = 7,
|
||||
MXSMBUS_CMD_WRITE_BLOCK = 8,
|
||||
MXSMBUS_CMD_READ_BLOCK = 9,
|
||||
MXSMBUS_CMD_PROCESS_CALL = 10,
|
||||
MXSMBUS_CMD_I2C = 11,
|
||||
} mxsmbus_cmd_t;
|
||||
|
||||
typedef BOOL smbus_callback_t(ich9_cmd_t cmd, WORD code, BYTE nbytes, BYTE* data);
|
||||
|
||||
void smbus_install(BYTE v_addr, smbus_callback_t* write, smbus_callback_t* read);
|
||||
|
@ -2,3 +2,14 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "hook.h"
|
||||
|
||||
#define HDATA_FILE 0
|
||||
#define HDATA_FIND_VOLUME 1
|
||||
#define HDATA_ANY 0xFFFFFFFF
|
||||
|
||||
BOOL FileExists(wchar_t* szPath);
|
||||
PVOID GetDataForHandle(HANDLE hObject, DWORD type);
|
||||
void SetDataForHandle(HANDLE hObject, DWORD type, PVOID pData, BOOL isHeap);
|
||||
BOOL RemoveDataForHandle(HANDLE hObject, DWORD type);
|
||||
HANDLE GetDummyHandle();
|
||||
void BytesToHex(char* hex_buffer, BYTE* bytes, DWORD nbytes);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "hook.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "log.h"
|
||||
|
@ -1,13 +1,18 @@
|
||||
#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/logging.h"
|
||||
|
||||
extern WCHAR exePath[MAX_PATH + 1];
|
||||
extern DWORD imageOffset;
|
||||
|
||||
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
@ -72,19 +77,18 @@ void __stdcall amLogCallback(DWORD level, char* format) {
|
||||
DWORD pLogcb;
|
||||
DWORD* ppLogcb;
|
||||
|
||||
extern WCHAR exePath[MAX_PATH + 1];
|
||||
int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) {
|
||||
// TODO: These are all horrible bodges
|
||||
if (wcscmp(exePath, L"mxnetwork.exe") == 0) {
|
||||
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
|
||||
*((DWORD*)(0x004438e8)) = 0x00000000;
|
||||
// *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
|
||||
*((DWORD*)(imageOffset + 0x004438e8)) = 0x00000000;
|
||||
}
|
||||
if (wcscmp(exePath, L"maimai_dump_.exe") == 0) {
|
||||
*((DWORD*)(0x00c820ec)) = 0x00000001;
|
||||
*((DWORD*)(imageOffset + 0x00c820ec)) = 0x00000001;
|
||||
pLogcb = (DWORD)(&amLogCallback);
|
||||
ppLogcb = &pLogcb;
|
||||
*((DWORD***)(0x00c820F4)) = &ppLogcb;
|
||||
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
|
||||
*((DWORD***)(imageOffset + 0x00c820F4)) = &ppLogcb;
|
||||
// *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb);
|
||||
}
|
||||
|
||||
force_console_bind();
|
||||
@ -214,3 +218,44 @@ void setup_logging() {
|
||||
CREATE_ALWAYS, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void log_stack(const char* caller) {
|
||||
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(caller, "%02u called from 0x%08X STACK=0x%08X FRAME=0x%08X %s\n", frame,
|
||||
(ULONG64)stack.AddrPC.Offset, (ULONG64)stack.AddrStack.Offset,
|
||||
(ULONG64)stack.AddrFrame.Offset, symbol->Name);
|
||||
|
||||
if (result == FALSE) {
|
||||
DWORD frameError = GetLastError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,4 +30,6 @@ int vlog_warning(const char* caller, const char* format, va_list args);
|
||||
int vlog_error(const char* caller, const char* format, va_list args);
|
||||
int vlog_game(const char* caller, const char* format, va_list args);
|
||||
|
||||
void log_stack(const char* caller);
|
||||
|
||||
void setup_logging();
|
||||
|
98
src/micetools/dll/util/misc.c
Normal file
98
src/micetools/dll/util/misc.c
Normal file
@ -0,0 +1,98 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../hooks/files.h"
|
||||
|
||||
BOOL FileExists(wchar_t* szPath) {
|
||||
DWORD dwAttrib = GetFileAttributesW(szPath);
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
typedef struct _handle_list {
|
||||
HANDLE m_Handle;
|
||||
PVOID m_pData;
|
||||
DWORD m_Type;
|
||||
BOOL m_IsOnHeap;
|
||||
struct _handle_list* m_Next;
|
||||
} handle_list_t;
|
||||
handle_list_t handle_list_root = {
|
||||
.m_Handle = INVALID_HANDLE_VALUE,
|
||||
.m_pData = NULL,
|
||||
.m_Type = 0xffffffff,
|
||||
.m_IsOnHeap = FALSE,
|
||||
.m_Next = NULL,
|
||||
};
|
||||
|
||||
PVOID GetDataForHandle(HANDLE hObject, DWORD type) {
|
||||
if (hObject == INVALID_HANDLE_VALUE) return NULL;
|
||||
|
||||
handle_list_t* head = &handle_list_root;
|
||||
while (head) {
|
||||
if (head->m_Handle == hObject && (type == HDATA_ANY || head->m_Type == type))
|
||||
return head->m_pData;
|
||||
head = head->m_Next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void SetDataForHandle(HANDLE hObject, DWORD type, PVOID pData, BOOL isHeap) {
|
||||
if (hObject == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
handle_list_t* head = &handle_list_root;
|
||||
while (1) {
|
||||
if (head->m_Handle == hObject && (type == HDATA_ANY || head->m_Type == type)) {
|
||||
if (head->m_IsOnHeap) free(head->m_pData);
|
||||
head->m_pData = pData;
|
||||
head->m_IsOnHeap = isHeap;
|
||||
return;
|
||||
}
|
||||
if (head->m_Next == NULL) break;
|
||||
head = head->m_Next;
|
||||
}
|
||||
head->m_Next = malloc(sizeof *head);
|
||||
head->m_Next->m_Handle = hObject;
|
||||
head->m_Next->m_pData = pData;
|
||||
head->m_Next->m_Next = NULL;
|
||||
head->m_Next->m_IsOnHeap = isHeap;
|
||||
head->m_Next->m_Type = type;
|
||||
}
|
||||
BOOL RemoveDataForHandle(HANDLE hObject, DWORD type) {
|
||||
if (hObject == INVALID_HANDLE_VALUE) return FALSE;
|
||||
|
||||
handle_list_t* head = &handle_list_root;
|
||||
handle_list_t* previous = &handle_list_root;
|
||||
BOOL ret = FALSE;
|
||||
while (head) {
|
||||
if (head->m_Handle == hObject && (type == HDATA_ANY || head->m_Type == type)) {
|
||||
previous->m_Next = head->m_Next;
|
||||
if (head->m_IsOnHeap) free(head->m_pData);
|
||||
handle_list_t* next = head->m_Next;
|
||||
free(head);
|
||||
head = next;
|
||||
if (type != HDATA_ANY) return TRUE;
|
||||
ret = TRUE;
|
||||
} else {
|
||||
previous = head;
|
||||
head = head->m_Next;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HANDLE GetDummyHandle() {
|
||||
CHAR path[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||
HANDLE hObject =
|
||||
_CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hObject == INVALID_HANDLE_VALUE) {
|
||||
log_error(HOOKS_LOGGER, "Failed to create dummy handle: %03x", GetLastError());
|
||||
}
|
||||
|
||||
return hObject;
|
||||
}
|
||||
|
||||
void BytesToHex(char* hex_buffer, BYTE* bytes, DWORD nbytes) {
|
||||
for (size_t i = 0; i < nbytes; i++) {
|
||||
sprintf(hex_buffer + i * 3, "%02x ", bytes[i]);
|
||||
}
|
||||
hex_buffer[nbytes * 3] = '\0';
|
||||
}
|
@ -5,6 +5,11 @@
|
||||
const char* KNOWN_GAMES[] = {
|
||||
// Preferentially use a decrypted dump if present
|
||||
"maimai_dump_.exe",
|
||||
|
||||
// Generic
|
||||
"RingGame.exe",
|
||||
|
||||
// We currently have no hope of running undumped maimai but whatever
|
||||
"maimai.exe",
|
||||
};
|
||||
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "locate.h"
|
||||
|
||||
const char* VERSION = "0.0-pre";
|
||||
|
||||
bool debug_wait = false;
|
||||
int boot_delay = 0;
|
||||
bool gametest = false;
|
||||
@ -57,7 +55,7 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
load_mice_config();
|
||||
|
||||
fprintf(stderr, "Micetools version: %s\n", VERSION);
|
||||
fprintf(stderr, "Micetools version: %s\n", MICE_VERSION);
|
||||
|
||||
parse_cmdline(argc, argv);
|
||||
|
||||
|
10
src/micetools/lib/_am.h
Normal file
10
src/micetools/lib/_am.h
Normal file
@ -0,0 +1,10 @@
|
||||
#include "../mice/version_fallback.h"
|
||||
|
||||
#define AM_LIB_C_HEADER(name, storage_type) \
|
||||
int name##DebugLevel = 0; \
|
||||
struct _##storage_type name; \
|
||||
char* name##Version = #name " Ver.mice" MICE_VERSION " Build:" __DATE__ " " __TIME__;
|
||||
#define AM_LIB_H_HEADER(name, storage_type) \
|
||||
extern int name##DebugLevel; \
|
||||
extern struct _##storage_type name; \
|
||||
extern char* name##Version;
|
6
src/micetools/lib/am/am.h
Normal file
6
src/micetools/lib/am/am.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "amEeprom.h"
|
||||
#include "amOemstring.h"
|
||||
#include "amPlatform.h"
|
||||
#include "amSram.h"
|
8
src/micetools/lib/am/amAime.h
Normal file
8
src/micetools/lib/am/amAime.h
Normal file
@ -0,0 +1,8 @@
|
||||
void amAimeInit(void);
|
||||
void amAimeExit(void);
|
||||
void amAimeGetResult(void);
|
||||
void amAimeCancelToGetCardInfo(void);
|
||||
void amAimeUpdate(void);
|
||||
void amAimeGetCardInfo(void);
|
||||
void amAimeGetAimeId(void);
|
||||
void amAimeRegistCard(void);
|
4
src/micetools/lib/am/amAta.h
Normal file
4
src/micetools/lib/am/amAta.h
Normal file
@ -0,0 +1,4 @@
|
||||
void amAtaOpenDevice(void);
|
||||
void amAtaCloseDevice(void);
|
||||
void amAtaPioInCommand(void);
|
||||
void amAtaPioOutCommand(void);
|
11
src/micetools/lib/am/amAuth.h
Normal file
11
src/micetools/lib/am/amAuth.h
Normal file
@ -0,0 +1,11 @@
|
||||
void amAuthInit(void);
|
||||
void amAuthExit(void);
|
||||
void amAuthGetSerialId(void);
|
||||
void amAuthGetCurrentStatus(void);
|
||||
void amAuthAccount(void);
|
||||
void amAuthCancelAccount(void);
|
||||
void amAuthGetCurrentTime(void);
|
||||
void amAuthGetPlaceInfo(void);
|
||||
void amAuthGetCloseTime(void);
|
||||
void amAuthDiffTime(void);
|
||||
void amAuthGetTitleServerAddress(void);
|
1
src/micetools/lib/am/amAuthDisk.h
Normal file
1
src/micetools/lib/am/amAuthDisk.h
Normal file
@ -0,0 +1 @@
|
||||
void amAuthDiscRead(void);
|
10
src/micetools/lib/am/amBackup.h
Normal file
10
src/micetools/lib/am/amBackup.h
Normal file
@ -0,0 +1,10 @@
|
||||
void amBackupInit(void);
|
||||
void amBackupExit(void);
|
||||
void amBackupRead(void);
|
||||
void amBackupRecordCheckValid(void);
|
||||
void amBackupRecordReadDup(void);
|
||||
void amBackupRecordWriteDup(void);
|
||||
void amBackupRecordValidate(void);
|
||||
void amBackupRecordWrite(void);
|
||||
void amBackupRecordWriteDup(void);
|
||||
void amBackupWrite(void);
|
3
src/micetools/lib/am/amCmos.h
Normal file
3
src/micetools/lib/am/amCmos.h
Normal file
@ -0,0 +1,3 @@
|
||||
void amCmosReadByteInRearpart(void);
|
||||
void amCmosSetPartition(void);
|
||||
void amCmosWriteByteInRearpart(void);
|
17
src/micetools/lib/am/amCredit.h
Normal file
17
src/micetools/lib/am/amCredit.h
Normal file
@ -0,0 +1,17 @@
|
||||
void amCreditClear(void);
|
||||
void amCreditExit(void);
|
||||
void amCreditGetEvent(void);
|
||||
void amCreditGetMaxCredit(void);
|
||||
void amCreditGetStatus(void);
|
||||
void amCreditInit(void);
|
||||
void amCreditIsEnough(void);
|
||||
void amCreditIsModifiedBookkeeping(void);
|
||||
void amCreditIsModifiedData(void);
|
||||
void amCreditIsValidConfig(void);
|
||||
void amCreditIsValidCustomBonusAdder(void);
|
||||
void amCreditLoadBookkeeping(void);
|
||||
void amCreditLoadConfig(void);
|
||||
void amCreditLoadData(void);
|
||||
void amCreditSetCustomBonusAdder(void);
|
||||
void amCreditSetDistribution(void);
|
||||
void amCreditUpdateJVS(void);
|
23
src/micetools/lib/am/amDipsw.h
Normal file
23
src/micetools/lib/am/amDipsw.h
Normal file
@ -0,0 +1,23 @@
|
||||
void amDipswCreateDeviceFile(void);
|
||||
void amDipswCreateMutex(void);
|
||||
void amDipswExit(void);
|
||||
void amDipswGetDriverVerision(void);
|
||||
void amDipswInit(void);
|
||||
void amDipswModifyByte(void);
|
||||
void amDipswModifyByteEx(void);
|
||||
void amDipswModifyByteInternal(void);
|
||||
void amDipswModifyByteInternalEx(void);
|
||||
void amDipswMxsmbusStatusCheck(void);
|
||||
void amDipswReadByte(void);
|
||||
void amDipswReadByteInternal(void);
|
||||
void amDipswReadByteInternalEx(void);
|
||||
void amDipswRequestGetDipsw(void);
|
||||
void amDipswRequestGetPushsw(void);
|
||||
void amDipswRequestReadByte(void);
|
||||
void amDipswRequestSetJvsIoctl(void);
|
||||
void amDipswRequestSetLed(void);
|
||||
void amDipswResponse(void);
|
||||
void amDipswResponseInternalEx(void);
|
||||
void amDipswWriteByte(void);
|
||||
void amDipswWriteByteInternal(void);
|
||||
void amDipswWriteByteInternalEx(void);
|
1127
src/micetools/lib/am/amDongle.c
Normal file
1127
src/micetools/lib/am/amDongle.c
Normal file
File diff suppressed because it is too large
Load Diff
211
src/micetools/lib/am/amDongle.h
Normal file
211
src/micetools/lib/am/amDongle.h
Normal file
@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
#include "../libpcp/pcpa.h"
|
||||
|
||||
typedef struct _AM_DONGLE_DS_CHALLENGE {
|
||||
byte challenge[7];
|
||||
byte pages[4][20];
|
||||
} AM_DONGLE_DS_CHALLENGE;
|
||||
|
||||
typedef struct _AM_DONGLE_SSD_CHALLENGE {
|
||||
byte challenge[16];
|
||||
byte response[16];
|
||||
} AM_DONGLE_SSD_CHALLENGE;
|
||||
|
||||
typedef enum {
|
||||
AM_DONGLE_SEQ_NONE = 0,
|
||||
AM_DONGLE_SEQ_WAIT_OPEN = 1,
|
||||
AM_DONGLE_SEQ_OPEN = 2,
|
||||
AM_DONGLE_SEQ_BINARY = 5,
|
||||
AM_DONGLE_SEQ_SEND_BINARY = 6,
|
||||
AM_DONGLE_SEQ_RECV_BINARY = 7,
|
||||
AM_DONGLE_SEQ_DONE = 8,
|
||||
} AM_DONGLE_SEQ;
|
||||
|
||||
typedef struct _AM_DONGLE {
|
||||
BOOL m_init;
|
||||
BOOL done_init;
|
||||
BOOL available;
|
||||
BOOL develop;
|
||||
BOOL auth_ready;
|
||||
int authCondition;
|
||||
//
|
||||
int setupSeq;
|
||||
int setupSeqNext;
|
||||
int setupRetries;
|
||||
AM_DONGLE_SEQ seq;
|
||||
int field19_0x40;
|
||||
int result;
|
||||
//
|
||||
int challengeNum;
|
||||
ushort version;
|
||||
ushort ctrl_port;
|
||||
ushort data_port;
|
||||
byte requestCode;
|
||||
//
|
||||
pcpa_t pcpa;
|
||||
//
|
||||
byte ssdChallenge[16];
|
||||
byte ssdResponse[16];
|
||||
byte ssdExpResponse[16];
|
||||
byte dsChallenge[16];
|
||||
byte dsResponse[16];
|
||||
byte dsExpResponse[16];
|
||||
byte challengePage;
|
||||
AM_DONGLE_DS_CHALLENGE dsTable[100];
|
||||
AM_DONGLE_SSD_CHALLENGE ssdTable[100];
|
||||
void *valueBuffer;
|
||||
void *dataBuffer;
|
||||
uint *field_0x3444;
|
||||
} AM_DONGLE;
|
||||
|
||||
typedef enum {
|
||||
AM_DONGLE_STATUS_OK = 0,
|
||||
AM_DONGLE_STATUS_BUSY = 1,
|
||||
AM_DONGLE_STATUS_PENDING = 2,
|
||||
AM_DONGLE_STATUS_NG = -1,
|
||||
AM_DONGLE_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_DONGLE_STATUS_ERR_NO_INIT = -3,
|
||||
AM_DONGLE_STATUS_ERR_ALREADY_INIT = -4,
|
||||
AM_DONGLE_STATUS_ERR_PCP = -5,
|
||||
AM_DONGLE_STATUS_ERR_COMMAND = -6,
|
||||
AM_DONGLE_STATUS_ERR_VERIFY = -7,
|
||||
AM_DONGLE_STATUS_ERR_LOG_FULL = -8,
|
||||
AM_DONGLE_STATUS_ERR_NO_LOG = -9,
|
||||
AM_DONGLE_STATUS_ERR_ONE_WRITE = -10,
|
||||
AM_DONGLE_STATUS_ERR_KEYCHIP_DATA = -11,
|
||||
AM_DONGLE_STATUS_ERR_KEYCHIP = -12,
|
||||
AM_DONGLE_STATUS_ERR_NO_SERVER = -13,
|
||||
AM_DONGLE_STATUS_ERR_AUTH_READY = -14,
|
||||
AM_DONGLE_STATUS_ERR_NO_COMMAND = -15,
|
||||
AM_DONGLE_STATUS_ERR_SYS = -16,
|
||||
AM_DONGLE_STATUS_ERR_PRECONDITION = -17,
|
||||
} AM_DONGLE_STATUS;
|
||||
|
||||
typedef enum {
|
||||
AM_DONGLE_BLOCK = 0,
|
||||
AM_DONGLE_NOBLOCK = 1,
|
||||
} AM_DONGLE_BLOCKING;
|
||||
|
||||
typedef enum {
|
||||
AM_DONGLE_REQUEST_SET_IV = 1,
|
||||
AM_DONGLE_REQUEST_DECRYPT = 2,
|
||||
AM_DONGLE_REQUEST_ENCRYPT = 3,
|
||||
AM_DONGLE_REQUEST_GET_GAME_ID = 4,
|
||||
AM_DONGLE_REQUEST_GET_SYSTEMFLAG = 5,
|
||||
AM_DONGLE_REQUEST_GET_MODEL_TYPE = 6,
|
||||
AM_DONGLE_REQUEST_GET_REGION = 7,
|
||||
AM_DONGLE_REQUEST_GET_PLATFORM_ID = 8,
|
||||
AM_DONGLE_REQUEST_GET_NETWORK_ADDRESS = 9,
|
||||
AM_DONGLE_REQUEST_GET_VERSION = 10,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_KEYCHIP_ID = 11,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_MAIN_ID = 12,
|
||||
AM_DONGLE_REQUEST_BILLING_SET_MAIN_ID = 13,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_PLAYCOUNT = 14,
|
||||
AM_DONGLE_REQUEST_BILLING_ADD_PLAYCOUNT = 15,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_PLAYLIMIT = 16,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_NEARFULL = 17,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_RESTORE = 18,
|
||||
AM_DONGLE_REQUEST_BILLING_PUT_TRACEDATA = 19,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_GET_LOG_NUM = 20,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_GET_FREE_LOG_NUM = 21,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_LOGICAL_ERASE = 22,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_ERASE_USED_SECTOR = 23,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_ERASE_ALL = 24,
|
||||
AM_DONGLE_REQUEST_BILLING_TD_RESERVE_ERASABLE_SECTOR = 25,
|
||||
AM_DONGLE_REQUEST_GET_DVDFLAG = 26,
|
||||
AM_DONGLE_REQUEST_GET_DS_COMPUTE = 27,
|
||||
AM_DONGLE_REQUEST_GET_SSD_PROOF = 28,
|
||||
// 29
|
||||
AM_DONGLE_REQUEST_GET_FORMAT_TYPE = 30,
|
||||
|
||||
AM_DONGLE_WTF_80 = 0x80 | 0,
|
||||
AM_DONGLE_WTF_81 = 0x80 | 1,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_TRACEDATA = 0x80 | 2,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_SIGNATURE_PK = 0x80 | 3,
|
||||
AM_DONGLE_REQUEST_BILLING_GET_CA_CERT = 0x80 | 4,
|
||||
AM_DONGLE_WTF_85 = 0x80 | 5,
|
||||
|
||||
AM_DONGLE_WTF_C0 = 0xc0 | 0,
|
||||
AM_DONGLE_REQUEST_BILLING_UPDATE_PLAYLIMIT = 0xc0 | 1,
|
||||
AM_DONGLE_REQUEST_BILLING_UPDATE_NEARFULL = 0xc0 | 2,
|
||||
AM_DONGLE_WTF_C3 = 0xc0 | 3,
|
||||
} AM_DONGLE_REQUEST;
|
||||
|
||||
typedef enum _AM_DONGLE_SETUP_SEQ {
|
||||
AM_DONGLE_SETUP_SEQ_NONE = 0,
|
||||
AM_DONGLE_SETUP_SEQ_START = 1,
|
||||
AM_DONGLE_SETUP_SEQ_WAIT = 2,
|
||||
AM_DONGLE_SETUP_SEQ_SEND = 3,
|
||||
AM_DONGLE_SETUP_SEQ_RECV = 4,
|
||||
AM_DONGLE_SETUP_SEQ_READ_RESPONSE = 5,
|
||||
AM_DONGLE_SETUP_SEQ_CLOSE = 6,
|
||||
AM_DONGLE_SETUP_SEQ_RETRY = 7,
|
||||
AM_DONGLE_SETUP_SEQ_DONE = 8,
|
||||
AM_DONGLE_SETUP_SEQ_ERR = 9,
|
||||
} AM_DONGLE_SETUP_SEQ;
|
||||
|
||||
AM_LIB_H_HEADER(amDongle, AM_DONGLE)
|
||||
|
||||
AM_DONGLE_STATUS amDongleInit(void);
|
||||
AM_DONGLE_STATUS amDongleOpen(void);
|
||||
AM_DONGLE_STATUS amDongleOpenEx(void);
|
||||
BOOL amDongleIsDevelop(void);
|
||||
BOOL amDongleIsAvailable(void);
|
||||
AM_DONGLE_STATUS amDongleCodeToStatus(void);
|
||||
AM_DONGLE_STATUS amDongleSetupKeychip(void);
|
||||
AM_DONGLE_STATUS amDongleSendAndReceiveEx(void);
|
||||
AM_DONGLE_STATUS amDongleResponseCheck(void);
|
||||
AM_DONGLE_STATUS amDongleExit(void);
|
||||
AM_DONGLE_STATUS amDongleSetAuthConfig(char *authConfig);
|
||||
|
||||
AM_DONGLE_STATUS amDongleGetGameId(char *gameId, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetPlatformId(char *platformId, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetSystemFlag(unsigned char *systemFlag, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetModelType(unsigned char *modelType, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetRegion(unsigned char *region, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetNetworkAddress(unsigned int *networkAddress,
|
||||
AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetVersion(unsigned short *version, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleGetPicVersion(unsigned short *picVersion, AM_DONGLE_BLOCKING blocking);
|
||||
|
||||
AM_DONGLE_STATUS amDongleBillingGetKeychipId(void *keychipId, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleBillingGetPlayCount(unsigned int *playCount, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleBillingGetPlayLimit(unsigned int *playLimit, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleBillingAddPlayCount(void *playCount, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleBillingGetNearfull(unsigned int *nearfull, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleEncrypt(unsigned char *pt, unsigned char *ct, AM_DONGLE_BLOCKING blocking);
|
||||
AM_DONGLE_STATUS amDongleDecrypt(unsigned char *ct, unsigned char *pt, AM_DONGLE_BLOCKING blocking);
|
||||
|
||||
void amDongleBillingGetCaCertification(void);
|
||||
void amDongleBillingGetMainId(void);
|
||||
void amDongleBillingGetPlaylimit(void);
|
||||
void amDongleBillingGetSignaturePubKey(void);
|
||||
void amDongleBillingGetTraceData(void);
|
||||
void amDongleBillingPutTraceData(void);
|
||||
void amDongleBillingSetMainId(void);
|
||||
void amDongleBillingTdEraseAll(void);
|
||||
void amDongleBillingTdEraseUsedSector(void);
|
||||
void amDongleBillingTdGetFreeLogNum(void);
|
||||
void amDongleBillingTdGetLogNum(void);
|
||||
void amDongleBillingTdLogicalErase(void);
|
||||
void amDongleBillingTdReserveErasableSector(void);
|
||||
void amDongleBillingTdRestore(void);
|
||||
void amDongleBillingUpdateNearfull(void);
|
||||
void amDongleBillingUpdatePlaylimit(void);
|
||||
|
||||
void amDongleBusy(void);
|
||||
void amDongleGetAuthCondition(void);
|
||||
void amDongleGetDsMac(void);
|
||||
void amDongleGetDvdFlag(void);
|
||||
void amDongleGetFormatType(void);
|
||||
void amDongleGetResult(void);
|
||||
void amDongleGetSeed(void);
|
||||
void amDongleGetSsdResponse(void);
|
||||
void amDongleRequestSsdHostProof(void);
|
||||
void amDongleSetAuthCondition(void);
|
||||
void amDongleSetIv(void);
|
||||
void amDongleUpdate(void);
|
@ -1,86 +1,397 @@
|
||||
#include "amEeprom.h"
|
||||
#include "../mice/crc.h"
|
||||
#pragma comment(lib, "Setupapi.lib")
|
||||
|
||||
#include "../../dll/smbus.h"
|
||||
#include "../ami/ami.h"
|
||||
|
||||
AM_LIB_C_HEADER(amEeprom, AM_EEPROM)
|
||||
|
||||
HANDLE amEepromCreateDeviceFile(const GUID *guid, LPCSTR resource, DWORD member_index) {
|
||||
SP_DEVICE_INTERFACE_DATA interface_data;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A interface_detail[204];
|
||||
SP_DEVICE_INTERFACE_DATA interfaceData;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetail[204];
|
||||
|
||||
if (!guid) return INVALID_HANDLE_VALUE;
|
||||
if (!guid) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("PARAM Error.");
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HDEVINFO DeviceInfoSet =
|
||||
SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
|
||||
if (DeviceInfoSet == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
|
||||
|
||||
interface_data.cbSize = 0x1c;
|
||||
BOOL s;
|
||||
s = SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, guid, member_index, &interface_data);
|
||||
if (!s) goto fail;
|
||||
|
||||
interface_detail[0].cbSize = 5;
|
||||
s = SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &interface_data, interface_detail,
|
||||
sizeof interface_detail, NULL, NULL);
|
||||
if (!s) goto fail;
|
||||
|
||||
char device_path[260];
|
||||
strcpy_s(device_path, sizeof device_path, interface_detail[0].DevicePath);
|
||||
|
||||
if (resource != NULL) {
|
||||
strcat_s(device_path, 4, "\\");
|
||||
strcat_s(device_path, 4, resource);
|
||||
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("SetupDiGetClassDevs Error(%ld).", GetLastError());
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
interfaceData.cbSize = 28;
|
||||
BOOL s;
|
||||
s = SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, guid, member_index, &interfaceData);
|
||||
if (!s) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("SetupDiEnumDeviceInterfaces Error(%ld).", GetLastError());
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
interfaceDetail[0].cbSize = 5;
|
||||
s = SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &interfaceData, interfaceDetail,
|
||||
sizeof interfaceDetail, NULL, NULL);
|
||||
if (!s) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("SetupDiGetDeviceInterfaceDetailA Error(%ld).", GetLastError());
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
char fileName[260];
|
||||
strcpy_s(fileName, sizeof fileName, interfaceDetail[0].DevicePath);
|
||||
|
||||
if (resource != NULL) {
|
||||
strcat_s(fileName, 4, "\\");
|
||||
strcat_s(fileName, 4, resource);
|
||||
}
|
||||
|
||||
printf("Using device located at %s\n", device_path);
|
||||
HANDLE device =
|
||||
CreateFileA(device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_SUPPORTS_GHOSTING, NULL);
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
return device;
|
||||
|
||||
fail:
|
||||
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
||||
mxsmbus_i2c_packet smbus_req = {
|
||||
.status = 0,
|
||||
.prt = 0x09,
|
||||
.addr = SMBUS_EEPROM,
|
||||
.reg = reg << 5,
|
||||
.dlen = len,
|
||||
.data = { 0 },
|
||||
};
|
||||
AM_EEPROM_STATUS amEepromGetDriverVersion(AM_EEPROM *device, LPDWORD version) {
|
||||
if (device == NULL || version == NULL) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("PARAM Error.");
|
||||
return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (device->m_superio == INVALID_HANDLE_VALUE) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("Device not opened.");
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
DWORD _dummy;
|
||||
BOOL s = DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req,
|
||||
&smbus_req, sizeof smbus_req, &_dummy, NULL);
|
||||
if (!s) return FALSE;
|
||||
if (smbus_req.status) return FALSE;
|
||||
memcpy(data, smbus_req.data, len);
|
||||
return TRUE;
|
||||
DWORD bytesReturned;
|
||||
DWORD buffer;
|
||||
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &buffer, 4,
|
||||
&bytesReturned, NULL);
|
||||
|
||||
if (s && bytesReturned == sizeof buffer) {
|
||||
*version = buffer;
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("DeviceIoControl error(%ld).", GetLastError());
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
|
||||
mxsmbus_i2c_packet smbus_req = {
|
||||
.status = 0,
|
||||
.prt = 0x08,
|
||||
.addr = SMBUS_EEPROM,
|
||||
.reg = reg << 5,
|
||||
.dlen = len,
|
||||
.data = { 0 },
|
||||
};
|
||||
memcpy(smbus_req.data, data, sizeof smbus_req.data);
|
||||
AM_EEPROM_STATUS amEepromCreateMutex(AM_EEPROM *device) {
|
||||
SECURITY_ATTRIBUTES muxAttrs;
|
||||
SECURITY_DESCRIPTOR securityDescriptor;
|
||||
SID_IDENTIFIER_AUTHORITY idAuth;
|
||||
|
||||
DWORD _dummy;
|
||||
BOOL s = DeviceIoControl(mxsmbus, IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req,
|
||||
&smbus_req, sizeof smbus_req, &_dummy, NULL);
|
||||
if (!s) return FALSE;
|
||||
if (smbus_req.status) return FALSE;
|
||||
memcpy(data, smbus_req.data, len);
|
||||
return TRUE;
|
||||
PSID *pSid = &device->m_sid;
|
||||
idAuth.Value[0] = 0;
|
||||
idAuth.Value[1] = 0;
|
||||
idAuth.Value[2] = 0;
|
||||
idAuth.Value[3] = 0;
|
||||
idAuth.Value[4] = 0;
|
||||
idAuth.Value[5] = 1;
|
||||
|
||||
if (!AllocateAndInitializeSid(&idAuth, 1, 0, 0, 0, 0, 0, 0, 0, 0, pSid)) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("AllocateAndInitializeSid Error in amEepromInit.");
|
||||
*pSid = NULL;
|
||||
goto amEepromCreateMutexError;
|
||||
}
|
||||
|
||||
if (!InitializeSecurityDescriptor(&securityDescriptor, 1)) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("InitializeSecurityDescriptor Error in amEepromInit.");
|
||||
goto amEepromCreateMutexError;
|
||||
}
|
||||
|
||||
if (!SetSecurityDescriptorDacl(&securityDescriptor, TRUE, NULL, FALSE)) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("SetSecurityDescriptorDacl Error in amEepromInit.");
|
||||
goto amEepromCreateMutexError;
|
||||
}
|
||||
|
||||
muxAttrs.lpSecurityDescriptor = &securityDescriptor;
|
||||
muxAttrs.nLength = 12;
|
||||
muxAttrs.bInheritHandle = FALSE;
|
||||
if ((device->m_mutex = CreateMutexA(&muxAttrs, FALSE, "Global\\AM_EEPROM_MUTEX")) != NULL) {
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("CreateMutexA Error(%ld).", GetLastError());
|
||||
|
||||
amEepromCreateMutexError:
|
||||
if (device->m_mutex != NULL) {
|
||||
CloseHandle(device->m_mutex);
|
||||
device->m_mutex = NULL;
|
||||
}
|
||||
if (*pSid != NULL) {
|
||||
FreeSid(*pSid);
|
||||
*pSid = NULL;
|
||||
}
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
void amEepromRepairChecksum(BYTE *data) {
|
||||
DWORD check = crc32(28, data + 4, 0);
|
||||
((DWORD*)data)[0] = check;
|
||||
AM_EEPROM_STATUS amEepromInit(AM_EEPROM_TIMEOUT *timeout) {
|
||||
if (amEeprom.m_init) return AM_EEPROM_STATUS_ERR_ALREADY_INIT;
|
||||
|
||||
amEeprom.m_prt = AM_EEPROM_ADDR;
|
||||
amEeprom.m_timeout.ReadTimeout = AM_EEPROM_DEFAULT_TIMEOUT;
|
||||
amEeprom.m_timeout.WriteTimeout = AM_EEPROM_DEFAULT_TIMEOUT;
|
||||
|
||||
int ret = amEepromCreateMutex(&amEeprom);
|
||||
if (ret != 0) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("amEepromCreateMutex Error!! Error Code is %ld!!", ret);
|
||||
ret = AM_EEPROM_STATUS_ERR_SYS;
|
||||
goto amEepromInitError;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("amEepromCreateMutex Error!! Error Code is %ld!!", ret);
|
||||
ret = AM_EEPROM_STATUS_ERR_SYS;
|
||||
goto amEepromInitError;
|
||||
}
|
||||
|
||||
amEeprom.m_superio = amEepromCreateDeviceFile(&MXSMBUS_GUID, 0, 0);
|
||||
if (amEeprom.m_superio == INVALID_HANDLE_VALUE) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("amEepromCreateDeviceFile Error in amEepromInit.");
|
||||
ret = AM_EEPROM_STATUS_ERR_SYS;
|
||||
goto amEepromInitError;
|
||||
}
|
||||
|
||||
DWORD driverVersion;
|
||||
ret = amEepromGetDriverVersion(&amEeprom, &driverVersion);
|
||||
if (ret != 0) {
|
||||
amiDebugLog("amEepromGetDriverVerision Error.");
|
||||
goto amEepromInitError;
|
||||
}
|
||||
|
||||
if ((driverVersion & 0xffff) != 1) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog(
|
||||
"Unknown SMBUS Driver Protocol(0x%08x). Please update SMBUS driver or user "
|
||||
"program.\n",
|
||||
driverVersion);
|
||||
|
||||
ret = AM_EEPROM_STATUS_ERR_PROTOCOL_VER;
|
||||
goto amEepromInitError;
|
||||
}
|
||||
|
||||
if (timeout != NULL) {
|
||||
amEeprom.m_timeout.ReadTimeout = timeout->ReadTimeout;
|
||||
amEeprom.m_timeout.WriteTimeout = timeout->WriteTimeout;
|
||||
}
|
||||
amEeprom.m_init = TRUE;
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
|
||||
amEepromInitError:
|
||||
amEeprom.m_init = TRUE;
|
||||
amEepromExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
AM_EEPROM_STATUS amEepromExit() {
|
||||
if (!amEeprom.m_init) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error!!");
|
||||
return AM_EEPROM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
if (amEeprom.m_superio != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(amEeprom.m_superio);
|
||||
amEeprom.m_superio = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (amEeprom.m_mutex != NULL) {
|
||||
CloseHandle(amEeprom.m_mutex);
|
||||
amEeprom.m_mutex = NULL;
|
||||
}
|
||||
if (amEeprom.m_sid != NULL) {
|
||||
FreeSid(amEeprom.m_sid);
|
||||
amEeprom.m_sid = NULL;
|
||||
}
|
||||
amEeprom.m_init = FALSE;
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
}
|
||||
|
||||
BOOL amEepromI2CReadBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer) {
|
||||
if (device == NULL || buffer == NULL || nBytes == 0 || nBytes >= 0x21) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MXSMBUS_I2C_PACKET packet;
|
||||
packet.v_addr = device->m_prt;
|
||||
packet.command_code = reg;
|
||||
packet.status = 0;
|
||||
packet.command = MXSMBUS_CMD_READ_BLOCK;
|
||||
packet.nbytes = nBytes;
|
||||
|
||||
DWORD bytesReturned;
|
||||
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_I2C, &packet, sizeof packet, &packet,
|
||||
sizeof packet, &bytesReturned, NULL);
|
||||
if (!s || bytesReturned != sizeof packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packet.status != 0) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog(" .. SMBus read error. prt=0x%02x addr=0x%02x reg=0x%04x",
|
||||
packet.command, packet.v_addr, packet.command_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, packet.data, nBytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL amEepromI2CWriteBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer) {
|
||||
if (device == NULL || buffer == NULL || nBytes == 0 || nBytes >= 0x21) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MXSMBUS_I2C_PACKET packet;
|
||||
packet.v_addr = device->m_prt;
|
||||
packet.command_code = reg;
|
||||
packet.status = 0;
|
||||
packet.command = MXSMBUS_CMD_WRITE_BLOCK;
|
||||
packet.nbytes = nBytes;
|
||||
memcpy(packet.data, buffer, nBytes);
|
||||
|
||||
DWORD bytesReturned;
|
||||
BOOL s = DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_I2C, &packet, sizeof packet, &packet,
|
||||
sizeof packet, &bytesReturned, NULL);
|
||||
if (!s || bytesReturned != sizeof packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (packet.status != 0) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog(
|
||||
" .. SMBus write error. status=0x%02x, prt=0x%02x addr=0x%02x reg=0x%04x\n",
|
||||
packet.status, packet.command, packet.v_addr, packet.command_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL amiEepromWait(AM_EEPROM *device, int timeout) {
|
||||
amtime_t startTime;
|
||||
amtime_t nowTime;
|
||||
|
||||
if (device == NULL) return FALSE;
|
||||
|
||||
MXSMBUS_REQUEST_PACKET packet;
|
||||
packet.status = 24;
|
||||
packet.command = MXSMBUS_CMD_READ_BYTE;
|
||||
packet.v_addr = device->m_prt;
|
||||
packet.command_code = 0;
|
||||
packet.nbytes = 0;
|
||||
packet.data[0] = 0;
|
||||
packet.data[1] = 0;
|
||||
|
||||
amiTimerGet(&startTime);
|
||||
while (1) {
|
||||
amiTimerGet(&nowTime);
|
||||
DWORD bytesReturned;
|
||||
DeviceIoControl(device->m_superio, IOCTL_MXSMBUS_REQUEST, &packet, sizeof packet, &packet,
|
||||
sizeof packet, &bytesReturned, NULL);
|
||||
if (packet.status == 0) return TRUE;
|
||||
|
||||
if (amiTimerDiffUsec(&startTime, &nowTime) > timeout * 1000) return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
AM_EEPROM_STATUS amEepromRead(WORD reg, LPBYTE buf, DWORD length) {
|
||||
if (amEeprom.m_init == 0) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error.");
|
||||
return AM_EEPROM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
if (buf == NULL || length == 0) return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
|
||||
|
||||
DWORD err = WaitForSingleObject(amEeprom.m_mutex, 256);
|
||||
if (err == WAIT_FAILED) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
if (err == WAIT_TIMEOUT) return AM_EEPROM_STATUS_ERR_GET_MUTEX;
|
||||
|
||||
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(),
|
||||
err);
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
while (length != 0) {
|
||||
BYTE readSize = 0x20;
|
||||
if ((reg & 0x1f) != 0) readSize = 0x20 - (reg & 0x1f);
|
||||
if (length <= readSize) readSize = length & 0xff;
|
||||
|
||||
if (!amiEepromWait(&amEeprom, amEeprom.m_timeout.ReadTimeout))
|
||||
return AM_EEPROM_STATUS_ERR_TIMEOUT;
|
||||
|
||||
if (!amEepromI2CReadBlock(&amEeprom, reg, readSize, buf)) return AM_EEPROM_STATUS_ERR_READ;
|
||||
|
||||
buf += readSize;
|
||||
reg += readSize;
|
||||
length -= readSize;
|
||||
}
|
||||
|
||||
if (!ReleaseMutex(amEeprom.m_mutex)) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_EEPROM_STATUS amEepromWrite(WORD reg, LPBYTE buf, DWORD length) {
|
||||
if (amEeprom.m_init == 0) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("No Init Error.");
|
||||
return AM_EEPROM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
if (buf == NULL || length == 0) return AM_EEPROM_STATUS_ERR_INVALID_PARAM;
|
||||
|
||||
DWORD err = WaitForSingleObject(amEeprom.m_mutex, 256);
|
||||
if (err == WAIT_FAILED) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
if (err == WAIT_TIMEOUT) return AM_EEPROM_STATUS_ERR_GET_MUTEX;
|
||||
|
||||
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
|
||||
if (amEepromDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(),
|
||||
err);
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
while (length != 0) {
|
||||
BYTE writeSize = 0x20;
|
||||
if ((reg & 0x1f) != 0) writeSize = 0x20 - (reg & 0x1f);
|
||||
if (length <= writeSize) writeSize = length & 0xff;
|
||||
|
||||
if (!amiEepromWait(&amEeprom, amEeprom.m_timeout.WriteTimeout))
|
||||
return AM_EEPROM_STATUS_ERR_TIMEOUT;
|
||||
|
||||
if (!amEepromI2CWriteBlock(&amEeprom, reg, writeSize, buf))
|
||||
return AM_EEPROM_STATUS_ERR_WRITE;
|
||||
|
||||
buf += writeSize;
|
||||
reg += writeSize;
|
||||
length -= writeSize;
|
||||
}
|
||||
|
||||
if (!ReleaseMutex(amEeprom.m_mutex)) {
|
||||
if (amEepromDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
|
||||
return AM_EEPROM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
return AM_EEPROM_STATUS_OK;
|
||||
}
|
||||
|
@ -1,13 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../../dll/smbus.h"
|
||||
#include "../_am.h"
|
||||
|
||||
DEFINE_GUID(MXSMBUS_GUID, 0x5C49E1FE, 0x3FEC, 0x4B8D, 0xA4, 0xB5, 0x76, 0xBE, 0x70, 0x25, 0xD8, 0x42);
|
||||
DEFINE_GUID(PLATFORM_GUID, 0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3e, 0x30, 0x1F, 0x73);
|
||||
AM_LIB_H_HEADER(amEeprom, AM_EEPROM)
|
||||
|
||||
typedef enum {
|
||||
AM_EEPROM_STATUS_OK = 0,
|
||||
AM_EEPROM_STATUS_NG = -1,
|
||||
AM_EEPROM_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_EEPROM_STATUS_ERR_NO_INIT = -3,
|
||||
AM_EEPROM_STATUS_ERR_ALREADY_INIT = -4,
|
||||
AM_EEPROM_STATUS_ERR_SYS = -5,
|
||||
AM_EEPROM_STATUS_ERR_READ = -6,
|
||||
AM_EEPROM_STATUS_ERR_WRITE = -7,
|
||||
AM_EEPROM_STATUS_ERR_TIMEOUT = -8,
|
||||
AM_EEPROM_STATUS_ERR_GET_MUTEX = -9,
|
||||
AM_EEPROM_STATUS_ERR_PROTOCOL_VER = -10,
|
||||
} AM_EEPROM_STATUS;
|
||||
|
||||
typedef struct {
|
||||
int ReadTimeout;
|
||||
int WriteTimeout;
|
||||
} AM_EEPROM_TIMEOUT;
|
||||
|
||||
typedef struct _AM_EEPROM {
|
||||
BOOL m_init;
|
||||
AM_EEPROM_TIMEOUT m_timeout;
|
||||
HANDLE m_mutex;
|
||||
HANDLE m_superio;
|
||||
BYTE m_prt;
|
||||
PSID m_sid;
|
||||
} AM_EEPROM;
|
||||
#define AM_EEPROM_DEFAULT_TIMEOUT 6
|
||||
|
||||
#define AM_EEPROM_ADDR 0x57
|
||||
|
||||
DEFINE_GUID(MXSMBUS_GUID, 0x5C49E1FE, 0x3FEC, 0x4B8D, 0xA4, 0xB5, 0x76, 0xBE, 0x70, 0x25, 0xD8,
|
||||
0x42);
|
||||
DEFINE_GUID(PLATFORM_GUID, 0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3e, 0x30, 0x1F,
|
||||
0x73);
|
||||
|
||||
HANDLE amEepromCreateDeviceFile(const GUID *guid, LPCSTR resource, DWORD member_index);
|
||||
AM_EEPROM_STATUS amEepromGetDriverVersion(AM_EEPROM *device, LPDWORD version);
|
||||
AM_EEPROM_STATUS amEepromCreateMutex(AM_EEPROM *device);
|
||||
|
||||
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data);
|
||||
BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data);
|
||||
BOOL amEepromI2CReadBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer);
|
||||
BOOL amEepromI2CWriteBlock(AM_EEPROM *device, WORD reg, BYTE nBytes, LPBYTE buffer);
|
||||
|
||||
void amEepromRepairChecksum(BYTE* data);
|
||||
AM_EEPROM_STATUS amEepromInit(AM_EEPROM_TIMEOUT *timeout);
|
||||
AM_EEPROM_STATUS amEepromExit(void);
|
||||
AM_EEPROM_STATUS amEepromRead(WORD reg, LPBYTE buf, DWORD length);
|
||||
AM_EEPROM_STATUS amEepromWrite(WORD reg, LPBYTE buf, DWORD length);
|
||||
|
||||
// TODO:
|
||||
void amEepromSetTimeout(void);
|
||||
|
4
src/micetools/lib/am/amGcatcher.h
Normal file
4
src/micetools/lib/am/amGcatcher.h
Normal file
@ -0,0 +1,4 @@
|
||||
void amGcatcherInit(void);
|
||||
void amGcatcherIsUpdate(void);
|
||||
void amGcatcherReloadInfo(void);
|
||||
void amGcatcherStartCatcher(void);
|
3
src/micetools/lib/am/amGdeliver.h
Normal file
3
src/micetools/lib/am/amGdeliver.h
Normal file
@ -0,0 +1,3 @@
|
||||
void amGdeliverInit(void);
|
||||
void amGdeliverReadSegment(void);
|
||||
void amGdeliverResSetThread(void);
|
3
src/micetools/lib/am/amGfetcher.h
Normal file
3
src/micetools/lib/am/amGfetcher.h
Normal file
@ -0,0 +1,3 @@
|
||||
void amGfetcherInit(void);
|
||||
void amGfetcherReqIsReleaseEx(void);
|
||||
void amGfetcherReqRestart(void);
|
1
src/micetools/lib/am/amHardware.h
Normal file
1
src/micetools/lib/am/amHardware.h
Normal file
@ -0,0 +1 @@
|
||||
void amHardwareReset(void);
|
23
src/micetools/lib/am/amHm.h
Normal file
23
src/micetools/lib/am/amHm.h
Normal file
@ -0,0 +1,23 @@
|
||||
void amHmChangeBank(void);
|
||||
void amHmExit(void);
|
||||
void amHmGetCautionFlag(void);
|
||||
void amHmGetLPCChipId(void);
|
||||
void amHmI2CReadByte(void);
|
||||
void amHmI2CWriteByte(void);
|
||||
void amHmInit(void);
|
||||
void amHmLpcReadByte(void);
|
||||
void amHmLpcWriteByte(void);
|
||||
void amHmModifyByteWithBankNum(void);
|
||||
void amHmProbeSuperIoDevice(void);
|
||||
void amHmReadByteWithBankNum(void);
|
||||
void amHmReadFanInternal(void);
|
||||
void amHmReadTemperatureInternal(void);
|
||||
void amHmReadVoltageInternal(void);
|
||||
void amHmResetCautionFlag(void);
|
||||
void amHmSetEnable(void);
|
||||
void amHmSetFanconMode(void);
|
||||
void amHmSetFanControlInternal(void);
|
||||
void amHmSetThermoCruise(void);
|
||||
void amHmUpdate(void);
|
||||
void amHmWriteByte(void);
|
||||
void amHmWriteByteWithBankNum(void);
|
580
src/micetools/lib/am/amInstall.c
Normal file
580
src/micetools/lib/am/amInstall.c
Normal file
@ -0,0 +1,580 @@
|
||||
#include "amInstall.h"
|
||||
|
||||
#include "../util/hex.h"
|
||||
|
||||
AM_LIB_C_HEADER(amInstall, AM_INSTALL)
|
||||
|
||||
/*********************************************************/
|
||||
AM_INSTALL_STATUS amInstallResponseCheckQuerySlotStatus(AM_INSTALL_SLOT_STATUS *slotStatus) {
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
int amInstallResponseCheckQuerySemStatus(void) { return -1; }
|
||||
int amInstallResponseCheckQueryAppStatus(void) { return -1; }
|
||||
AM_INSTALL_STATUS amInstallResponseCheckQuerySpd(void *param_1) { return AM_INSTALL_STATUS_OK; }
|
||||
AM_INSTALL_STATUS amInstallResponseCheckQueryAppdataStatus(int *param_1) {
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
AM_INSTALL_STATUS amInstallSuicideSub(char *keyword) { return AM_INSTALL_STATUS_OK; }
|
||||
/*********************************************************/
|
||||
|
||||
bool amInstallPcpaGetUlonglong(unsigned long long *dest, char *keyword) {
|
||||
if (keyword == NULL || dest == NULL) return false;
|
||||
char *command = pcpaGetCommand(&amInstall.m_pcp, keyword);
|
||||
if (command == NULL) return false;
|
||||
|
||||
errno = 0;
|
||||
char *end = NULL;
|
||||
unsigned long long value = strtoull(command, &end, 0);
|
||||
if (errno == ERANGE || end == NULL || end[0] != '\0') return false;
|
||||
*dest = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallResponseCheckQueryBr(AM_INSTALL_BOOT_RECORD *bootRecord) {
|
||||
if (bootRecord == NULL) return AM_INSTALL_STATUS_ERR_INVALID_PARAM;
|
||||
|
||||
ZeroMemory(bootRecord, sizeof bootRecord);
|
||||
|
||||
amInstallPcpaGetUlonglong(&bootRecord->epbr, "epbr");
|
||||
amInstallPcpaGetUlonglong(&bootRecord->original0, "original0");
|
||||
amInstallPcpaGetUlonglong(&bootRecord->original1, "original1");
|
||||
amInstallPcpaGetUlonglong(&bootRecord->patch0, "patch0");
|
||||
amInstallPcpaGetUlonglong(&bootRecord->patch1, "patch1");
|
||||
amInstallPcpaGetUlonglong(&bootRecord->os, "os");
|
||||
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
|
||||
AM_INSTALL_STATUS amInstallInit(void) {
|
||||
if (amInstall.m_init) return AM_INSTALL_STATUS_ERR_ALREADY_INIT;
|
||||
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
amInstall.m_requestCode = 0;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
amInstall.m_sendBufferLen = 0;
|
||||
amInstall.m_semid = 0;
|
||||
amInstall.m_cmdPort = 40102;
|
||||
amInstall.m_dataPort = 40103;
|
||||
|
||||
e_pcpa_t err = pcpaInitStream(&amInstall.m_pcp);
|
||||
if (err == e_pcpa_wsa_noinit) {
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("Error: Winsocket2 Library is not ready.");
|
||||
return AM_INSTALL_STATUS_ERR_PRECONDITION;
|
||||
}
|
||||
if (err != e_pcpa_ok) {
|
||||
if (amInstallDebugLevel > 0)
|
||||
amiDebugLog("Error: System error happened in pcp stream. ErrorCode = %d.", err);
|
||||
return AM_INSTALL_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
amInstall.m_init = true;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallUpdate(void) {
|
||||
AM_INSTALL_STATUS status;
|
||||
|
||||
if (!amInstall.m_init) return AM_INSTALL_STATUS_ERR_NO_INIT;
|
||||
|
||||
switch (amInstall.m_seq) {
|
||||
case AM_INSTALL_SEQ_BUSY:
|
||||
status = amInstallBusy();
|
||||
break;
|
||||
case AM_INSTALL_SEQ_SEND_REQUEST:
|
||||
status = amInstallSendRequest();
|
||||
if (status != AM_INSTALL_STATUS_OK) {
|
||||
amInstall.m_result = status;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_SEQ_RECV_RESPONSE:
|
||||
status = amInstallRecvResponse();
|
||||
break;
|
||||
case AM_INSTALL_SEQ_CHECK_RESPONSE:
|
||||
status = amInstallResponseCheck();
|
||||
if (status != AM_INSTALL_STATUS_OK) {
|
||||
amInstall.m_result = status;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_SEQ_OPEN_BINARY:
|
||||
status = amInstallOpenBinary();
|
||||
break;
|
||||
case AM_INSTALL_SEQ_SEND_BINARY:
|
||||
status = amInstallSendBinaryBuffer(1);
|
||||
if (status != AM_INSTALL_STATUS_OK) {
|
||||
amInstall.m_result = status;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_SEQ_EXIT:
|
||||
amInstallExit();
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
default:
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
if (status != AM_INSTALL_STATUS_OK) {
|
||||
amInstall.m_result = status;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallBusy(void) {
|
||||
e_pcpa_t err = pcpaIsBusy(&amInstall.m_pcp, 0);
|
||||
if (err == e_pcpa_ok) {
|
||||
amInstall.m_seq = amInstall.m_nextSeq;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
} else if (err != e_pcpa_to) {
|
||||
if (amInstallDebugLevel > 0)
|
||||
amiDebugLog("pcpaIsBusy() Error(%d), NextStatus = %d", err, amInstall.m_nextSeq);
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
|
||||
if (err == e_pcpa_no_server) return AM_INSTALL_STATUS_ERR_NO_SERVER;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallSendRequest(void) {
|
||||
e_pcpa_t err = pcpaSendRequest(&amInstall.m_pcp, 0);
|
||||
if (err == e_pcpa_ok) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_RECV_RESPONSE;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == e_pcpa_to) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_BUSY;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_RECV_RESPONSE;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("pcpaSendRequest() Error!!");
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallRecvResponse(void) {
|
||||
e_pcpa_t err = pcpaRecvResponse(&amInstall.m_pcp, 0);
|
||||
if (err == e_pcpa_ok) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_CHECK_RESPONSE;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == e_pcpa_to) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_BUSY;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_CHECK_RESPONSE;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallCodeToStatus(void) {
|
||||
char *sResult = pcpaGetCommand(&amInstall.m_pcp, "result");
|
||||
char *sCode = pcpaGetCommand(&amInstall.m_pcp, "code");
|
||||
if (sResult == NULL) {
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
if (sCode != NULL) {
|
||||
switch (atoi(sCode)) {
|
||||
case 0:
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case 1:
|
||||
return AM_INSTALL_STATUS_ERR_NO_STORAGE;
|
||||
case 2:
|
||||
return AM_INSTALL_STATUS_ERR_FORMAT;
|
||||
case 4:
|
||||
return AM_INSTALL_STATUS_ERR_EX_PARTITION;
|
||||
case 5:
|
||||
return AM_INSTALL_STATUS_ERR_READ_STORAGE;
|
||||
case 6:
|
||||
return AM_INSTALL_STATUS_ERR_WRITE_STORAGE;
|
||||
case 7:
|
||||
return AM_INSTALL_STATUS_ERR_SPD_CRC;
|
||||
case 8:
|
||||
return AM_INSTALL_STATUS_ERR_SPD_VERSION;
|
||||
case 20:
|
||||
return AM_INSTALL_STATUS_ERR_SEMAPHORE_ID;
|
||||
case 21:
|
||||
return AM_INSTALL_STATUS_ERR_GET_SEMAPHORE;
|
||||
case 22:
|
||||
return AM_INSTALL_STATUS_ERR_INVALID_LOCK_ID;
|
||||
case 40:
|
||||
return AM_INSTALL_STATUS_ERR_NO_SLOT;
|
||||
case 41:
|
||||
return AM_INSTALL_STATUS_ERR_READ_SLOT;
|
||||
case 42:
|
||||
return AM_INSTALL_STATUS_ERR_WRITE_SLOT;
|
||||
case 60:
|
||||
return AM_INSTALL_STATUS_ERR_DIFF_APPLICATION;
|
||||
case 61:
|
||||
return AM_INSTALL_STATUS_ERR_APPLICATION_SIZE;
|
||||
case 62:
|
||||
return AM_INSTALL_STATUS_ERR_SEGMENT_OFFSET;
|
||||
case 63:
|
||||
return AM_INSTALL_STATUS_ERR_UPDATE_STATUS;
|
||||
case 64:
|
||||
return AM_INSTALL_STATUS_ERR_REQUEST;
|
||||
}
|
||||
}
|
||||
if (strcmp(sResult, "success") == 0) return AM_INSTALL_STATUS_OK;
|
||||
|
||||
if (strcmp(sResult, "invalid_parameter") != 0) {
|
||||
if (strcmp(sResult, "invalid_request") != 0) {
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
}
|
||||
return AM_INSTALL_STATUS_ERR_INVALID_COMMAND;
|
||||
}
|
||||
|
||||
bool amInstallPcpaGetInt(char *keyword, unsigned int *dest) {
|
||||
if (keyword == NULL || dest == NULL) return false;
|
||||
char *command = pcpaGetCommand(&amInstall.m_pcp, keyword);
|
||||
if (command == NULL) return false;
|
||||
|
||||
errno = 0;
|
||||
char *end = NULL;
|
||||
unsigned int value = strtoul(command, &end, 0);
|
||||
if (errno == ERANGE || end == NULL || end[0] != '\0') return false;
|
||||
*dest = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallTaskRequest(char *keyword) {
|
||||
pcp_send_data_t *sendData;
|
||||
|
||||
if (strcmp(keyword, "query_appdata_status") == 0) {
|
||||
int status;
|
||||
if (amInstallResponseCheckQueryAppdataStatus(&status) != AM_INSTALL_STATUS_OK)
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
|
||||
bool failed = ((status == 1) || (status == 2));
|
||||
if (status == 0) {
|
||||
sendData = pcpaSetSendPacket(&amInstall.m_pcp, "request", "check_appdata");
|
||||
if (sendData == NULL && amInstallDebugLevel > 0)
|
||||
amiDebugLog("Error: pcpaSetSendPacket return NULL\n");
|
||||
sendData = pcpaAddSendPacket(&amInstall.m_pcp, "execute", "1");
|
||||
if (sendData == NULL && amInstallDebugLevel > 0)
|
||||
amiDebugLog("Error: pcpaAddSendPacket return NULL\n");
|
||||
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_SEND_REQUEST;
|
||||
}
|
||||
if (!failed) {
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(keyword, "check_appdata") != 0 && strcmp(keyword, "format_appdata") != 0)
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
sendData = pcpaSetSendPacket(&amInstall.m_pcp, "request", "query_appdata_status");
|
||||
if (sendData == 0 && amInstallDebugLevel > 0)
|
||||
amiDebugLog("Error: pcpaSetSendPacket return NULL\n");
|
||||
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_SEND_REQUEST;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallResponseCheck(void) {
|
||||
char *realKeyword = pcpaGetKeyword(&amInstall.m_pcp, 0);
|
||||
char *keyword = pcpaGetCommand(&amInstall.m_pcp, "response");
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
if (realKeyword == NULL) {
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("Response Error!!! No Keyword.");
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
if (realKeyword[0] == '?') return AM_INSTALL_STATUS_ERR_NO_COMMAND;
|
||||
if (keyword == NULL) {
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("Error : No Response");
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS response_error = amInstallCodeToStatus();
|
||||
if (response_error != AM_INSTALL_STATUS_OK) return response_error;
|
||||
|
||||
switch (amInstall.m_requestCode) {
|
||||
case AM_INSTALL_REQUEST_QUERY_SLOT_STATUS:
|
||||
if (strcmp(keyword, "query_slot_status") != 0) {
|
||||
amInstall.m_result = AM_INSTALL_STATUS_ERR_PCP;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
amInstallResponseCheckQuerySlotStatus((AM_INSTALL_SLOT_STATUS *)amInstall.m_value);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_INSTALL:
|
||||
if (strcmp(keyword, "install") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
unsigned int port = 40103;
|
||||
amInstallPcpaGetInt("port", &port);
|
||||
amInstall = amInstall;
|
||||
amInstall.m_dataPort = port & 0xffff;
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_OPEN_BINARY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_UNINSTALL:
|
||||
if (strcmp(keyword, "uninstall") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_CHECK:
|
||||
if (strcmp(keyword, "check") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_QUERY_APPLICATION_STATUS:
|
||||
if (strcmp(keyword, "query_application_status") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
|
||||
*(unsigned int *)amInstall.m_value = amInstallResponseCheckQueryAppStatus();
|
||||
amInstallPcpaGetInt("busyslot", (unsigned int *)amInstall.Unk51c);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_SET_APPLICATION_STATUS:
|
||||
if (strcmp(keyword, "set_application_status") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
|
||||
if (pcpaGetCommand(&amInstall.m_pcp, "lockid") == NULL) return AM_INSTALL_STATUS_OK;
|
||||
amInstallPcpaGetInt("lockid", (unsigned int *)amInstall.m_value);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_QUERY_SBR_BOOTSLOT:
|
||||
if (strcmp(keyword, "query_sbr_bootslot") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
unsigned int bootslot = 0;
|
||||
amInstallPcpaGetInt("bootslot", &bootslot);
|
||||
*(unsigned int *)amInstall.m_value = bootslot;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_SET_SBR_BOOTSLOT:
|
||||
if (strcmp(keyword, "set_sbr_bootslot") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_QUERY_SEMAPHORE_STATUS:
|
||||
if (strcmp(keyword, "query_semaphore_status") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
*(unsigned int *)amInstall.m_value = amInstallResponseCheckQuerySemStatus();
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_GET_SEMAPHORE:
|
||||
if (strcmp(keyword, "get_semaphore") == 0) {
|
||||
unsigned int semid = 0;
|
||||
amInstallPcpaGetInt("semid", &semid);
|
||||
*(unsigned int *)amInstall.m_value = semid;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
case AM_INSTALL_REQUEST_RELEASE_SEMAPHORE:
|
||||
if (strcmp(keyword, "release_semaphore") == 0) return AM_INSTALL_STATUS_OK;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
case AM_INSTALL_REQUEST_QUERY_SPD:
|
||||
if (strcmp(keyword, "query_spd") == 0) {
|
||||
amInstallResponseCheckQuerySpd(amInstall.m_value);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
case AM_INSTALL_REQUEST_QUERY_BR:
|
||||
if (strcmp(keyword, "query_br") == 0) {
|
||||
amInstallResponseCheckQueryBr(amInstall.m_value);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
case AM_INSTALL_REQUEST_QUERY_APPDATA_STATUS:
|
||||
if (strcmp(keyword, "query_appdata_status") != 0) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
if (amInstallResponseCheckQueryAppdataStatus(amInstall.m_value) != AM_INSTALL_STATUS_OK)
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
|
||||
if ((*(int *)amInstall.m_value != 4) && (*(int *)amInstall.m_value != 5))
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
|
||||
char *sId = pcpaGetCommand(&amInstall.m_pcp, "id");
|
||||
if (sId == NULL) return AM_INSTALL_STATUS_ERR_PCP;
|
||||
strcpy_s(amInstall.Unk51c, 4, sId);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
case AM_INSTALL_REQUEST_15:
|
||||
case AM_INSTALL_REQUEST_16:
|
||||
return amInstallTaskRequest(keyword);
|
||||
case AM_INSTALL_REQUEST_QUERY_VOLUME_NAME:
|
||||
if (strcmp(keyword, "query_volume_name") == 0) {
|
||||
char *sName = pcpaGetCommand(&amInstall.m_pcp, "name");
|
||||
if (sName == NULL) return AM_INSTALL_STATUS_OK;
|
||||
|
||||
size_t hexLen = strlen(sName);
|
||||
if (hexLen > 512) hexLen = 512;
|
||||
hex_to_bin(sName, amInstall.m_value, hexLen);
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
case AM_INSTALL_REQUEST_18:
|
||||
return amInstallSuicideSub(keyword);
|
||||
default:
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallOpenBinary(void) {
|
||||
e_pcpa_t err = pcpaOpenBinaryClient(&amInstall.m_pcp, amInstall.m_dataPort, 0);
|
||||
if (err == e_pcpa_ok) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_SEND_BINARY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == e_pcpa_to) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_BUSY;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_SEND_BINARY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("pcpaOpenBinaryClient() Error!!");
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallSendBinaryBuffer(AM_INSTALL_BLOCKING blocking) {
|
||||
timeout_t timeout = blocking == AM_INSTALL_BLOCK ? TIMEOUT_NONE : 0;
|
||||
if (amInstall.m_requestCode != 2) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
pcpaSetSendBinaryBuffer(&amInstall.m_pcp, amInstall.m_value, amInstall.m_sendBufferLen);
|
||||
e_pcpa_t err = pcpaSendBinary(&amInstall.m_pcp, timeout);
|
||||
if (err == 0) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == 1) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_BUSY;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
AM_INSTALL_STATUS amInstallExit(void) {
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallOpenBinaryEx(void) {
|
||||
e_pcpa_t err = pcpaOpenBinaryClient(&amInstall.m_pcp, amInstall.m_dataPort, TIMEOUT_NONE);
|
||||
if (err != e_pcpa_ok) {
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_SEND_BINARY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallSendAndReceiveEx(void) {
|
||||
AM_INSTALL_STATUS err;
|
||||
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
err = amInstallOpenEx();
|
||||
if (err == AM_INSTALL_STATUS_OK) {
|
||||
do {
|
||||
err = amInstallSendAndRecvEx();
|
||||
if (err != AM_INSTALL_STATUS_OK) return err;
|
||||
|
||||
err = amInstallResponseCheck();
|
||||
if (amInstall.m_result != AM_INSTALL_STATUS_OK) err = amInstall.m_result;
|
||||
|
||||
if (amInstall.m_seq == AM_INSTALL_SEQ_OPEN_BINARY) {
|
||||
err = amInstallOpenBinaryEx();
|
||||
if (err != AM_INSTALL_STATUS_OK) return err;
|
||||
|
||||
err = amInstallSendBinaryBuffer(AM_INSTALL_BLOCK);
|
||||
if (err != AM_INSTALL_STATUS_OK) break;
|
||||
}
|
||||
} while (amInstall.m_seq != AM_INSTALL_SEQ_EXIT);
|
||||
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallSendAndRecvEx(void) {
|
||||
e_pcpa_t err = pcpaSendRequest(&amInstall.m_pcp, TIMEOUT_NONE);
|
||||
if (err != e_pcpa_ok) {
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("pcpaSendRequest Error!!");
|
||||
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall = amInstall;
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_INVALID;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
err = pcpaRecvResponse(&amInstall.m_pcp, TIMEOUT_NONE);
|
||||
if (err != e_pcpa_ok) {
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall = amInstall;
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("pcpaRecvResponse Error!!");
|
||||
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallOpenEx(void) {
|
||||
e_pcpa_t err =
|
||||
pcpaOpenClient(&amInstall.m_pcp, "127.0.0.1", amInstall.m_cmdPort, 60000, TIMEOUT_NONE);
|
||||
if (err == e_pcpa_ok) {
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == e_pcpa_timeout_open) {
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
return amInstallOpenEx();
|
||||
}
|
||||
if (amInstallDebugLevel > 0) amiDebugLog("pcpaOpenClient() Error(%d)", err);
|
||||
pcpaCloseBinary(&amInstall.m_pcp);
|
||||
pcpaClose(&amInstall.m_pcp);
|
||||
amInstall = amInstall;
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_NONE;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
return AM_INSTALL_STATUS_ERR_NO_SERVER;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallOpen(void) {
|
||||
e_pcpa_t err = pcpaOpenClient(&amInstall.m_pcp, "127.0.0.1", amInstall.m_cmdPort, 60000, 0);
|
||||
amInstall = amInstall;
|
||||
if (err == e_pcpa_ok) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_SEND_REQUEST;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_BUSY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
if (err == e_pcpa_to) {
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_BUSY;
|
||||
amInstall.m_nextSeq = AM_INSTALL_SEQ_SEND_REQUEST;
|
||||
amInstall.m_result = AM_INSTALL_STATUS_BUSY;
|
||||
return AM_INSTALL_STATUS_OK;
|
||||
}
|
||||
amInstall.m_seq = AM_INSTALL_SEQ_EXIT;
|
||||
return AM_INSTALL_STATUS_ERR_PCP;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallGetResult(void) {
|
||||
if (amInstall.m_init == 0) {
|
||||
amInstall.m_result = AM_INSTALL_STATUS_OK;
|
||||
return AM_INSTALL_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
return amInstall.m_result;
|
||||
}
|
||||
|
||||
AM_INSTALL_STATUS amInstallGetBr(AM_INSTALL_BOOT_RECORD *bootRecord, AM_INSTALL_BLOCKING blocking) {
|
||||
if (!amInstall.m_init) return AM_INSTALL_STATUS_ERR_NO_INIT;
|
||||
if (amInstall.m_seq != AM_INSTALL_SEQ_NONE) return AM_INSTALL_STATUS_BUSY;
|
||||
if (bootRecord == NULL) return AM_INSTALL_STATUS_ERR_INVALID_PARAM;
|
||||
|
||||
pcp_send_data_t *send_data = pcpaSetSendPacket(&amInstall.m_pcp, "request", "query_br");
|
||||
if (send_data == NULL && amInstallDebugLevel > 0)
|
||||
amiDebugLog("Error: pcpaSetSendPacket return NULL");
|
||||
|
||||
amInstall.m_value = bootRecord;
|
||||
amInstall.m_requestCode = AM_INSTALL_REQUEST_QUERY_BR;
|
||||
if (blocking == AM_INSTALL_BLOCK) return amInstallSendAndReceiveEx();
|
||||
return amInstallOpen();
|
||||
}
|
211
src/micetools/lib/am/amInstall.h
Normal file
211
src/micetools/lib/am/amInstall.h
Normal file
@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
#include "../libpcp/pcpa.h"
|
||||
#include "amSysData.h"
|
||||
|
||||
AM_LIB_H_HEADER(amInstall, AM_INSTALL)
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_APPLICATION_STATUS_INVALID = -1,
|
||||
AM_INSTALL_APPLICATION_STATUS_INACTIVE = 0,
|
||||
AM_INSTALL_APPLICATION_STATUS_ACTIVE = 1,
|
||||
} AM_INSTALL_APPLICATION_STATUS;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_BLOCK = 0,
|
||||
AM_INSTALL_NOBLOCK = 1,
|
||||
} AM_INSTALL_BLOCKING;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_FORMAT_STATUS_ERROR = -1,
|
||||
AM_INSTALL_FORMAT_STATUS_UNKNOWN = 0,
|
||||
AM_INSTALL_FORMAT_STATUS_CHECKING = 1,
|
||||
AM_INSTALL_FORMAT_STATUS_FORMATTING = 2,
|
||||
AM_INSTALL_FORMAT_STATUS_NEEDED = 3,
|
||||
AM_INSTALL_FORMAT_STATUS_AVAILABLE = 4,
|
||||
AM_INSTALL_FORMAT_STATUS_RESTORED = 5,
|
||||
} AM_INSTALL_FORMAT_STATUS;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_INSTALL_STATUS_INVALID = -1,
|
||||
AM_INSTALL_INSTALL_STATUS_EMPTY = 0,
|
||||
AM_INSTALL_INSTALL_STATUS_INSTALL = 1,
|
||||
AM_INSTALL_INSTALL_STATUS_CHECK = 2,
|
||||
AM_INSTALL_INSTALL_STATUS_COMPLETE = 3,
|
||||
} AM_INSTALL_INSTALL_STATUS;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_SLOT_INVALID = -1,
|
||||
AM_INSTALL_SLOT_ORIGINAL_0 = 0,
|
||||
AM_INSTALL_SLOT_ORIGINAL_1 = 1,
|
||||
AM_INSTALL_SLOT_ORIGINAL_F = 2,
|
||||
AM_INSTALL_SLOT_ORIGINAL_B = 3,
|
||||
AM_INSTALL_SLOT_PATCH_0 = 4,
|
||||
AM_INSTALL_SLOT_PATCH_1 = 5,
|
||||
AM_INSTALL_SLOT_PATCH_F = 6,
|
||||
AM_INSTALL_SLOT_PATCH_B = 7,
|
||||
AM_INSTALL_SLOT_OS = 8,
|
||||
AM_INSTALL_SLOT_APPLICATION = 9,
|
||||
} AM_INSTALL_SLOT;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_STATUS_OK = 0,
|
||||
AM_INSTALL_STATUS_BUSY = 1,
|
||||
|
||||
AM_INSTALL_STATUS_NG = -1,
|
||||
AM_INSTALL_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_INSTALL_STATUS_ERR_NO_INIT = -3,
|
||||
AM_INSTALL_STATUS_ERR_ALREADY_INIT = -4,
|
||||
AM_INSTALL_STATUS_ERR_INVALID_COMMAND = -5,
|
||||
AM_INSTALL_STATUS_ERR_PCP = -6,
|
||||
AM_INSTALL_STATUS_ERR_NO_SERVER = -7,
|
||||
AM_INSTALL_STATUS_ERR_NO_STORAGE = -8,
|
||||
AM_INSTALL_STATUS_ERR_FORMAT = -9,
|
||||
AM_INSTALL_STATUS_ERR_EX_PARTITION = -10,
|
||||
AM_INSTALL_STATUS_ERR_READ_STORAGE = -11,
|
||||
AM_INSTALL_STATUS_ERR_WRITE_STORAGE = -12,
|
||||
AM_INSTALL_STATUS_ERR_SPD_CRC = -13,
|
||||
AM_INSTALL_STATUS_ERR_SPD_VERSION = -14,
|
||||
AM_INSTALL_STATUS_ERR_SEMAPHORE_ID = -15,
|
||||
AM_INSTALL_STATUS_ERR_GET_SEMAPHORE = -16,
|
||||
AM_INSTALL_STATUS_ERR_NO_SLOT = -17,
|
||||
AM_INSTALL_STATUS_ERR_READ_SLOT = -18,
|
||||
AM_INSTALL_STATUS_ERR_WRITE_SLOT = -19,
|
||||
AM_INSTALL_STATUS_ERR_DIFF_APPLICATION = -20,
|
||||
AM_INSTALL_STATUS_ERR_APPLICATION_SIZE = -21,
|
||||
AM_INSTALL_STATUS_ERR_SEGMENT_OFFSET = -22,
|
||||
AM_INSTALL_STATUS_ERR_UPDATE_STATUS = -23,
|
||||
AM_INSTALL_STATUS_ERR_REQUEST = -24,
|
||||
AM_INSTALL_STATUS_ERR_INVALID_LOCK_ID = -25,
|
||||
AM_INSTALL_STATUS_ERR_NO_COMMAND = -26,
|
||||
AM_INSTALL_STATUS_ERR_SYS = -27,
|
||||
AM_INSTALL_STATUS_ERR_PRECONDITION = -28,
|
||||
} AM_INSTALL_STATUS;
|
||||
|
||||
typedef struct {
|
||||
AM_INSTALL_INSTALL_STATUS m_Status;
|
||||
char m_GameId[8];
|
||||
unsigned int m_PackageVersion;
|
||||
AM_SYSDATA_TIMESTAMP m_TimeStamp;
|
||||
unsigned int m_NumSegs;
|
||||
unsigned int m_SegSize;
|
||||
char m_PlatformId[4];
|
||||
unsigned int m_Flag;
|
||||
unsigned int m_OsVersion;
|
||||
unsigned int m_OsSegCount;
|
||||
AM_SYSDATA_TIMESTAMP m_OrgTimeStamp;
|
||||
unsigned int m_OrgPackageVersion;
|
||||
unsigned int m_InstalledSegs;
|
||||
} AM_INSTALL_SLOT_STATUS;
|
||||
|
||||
typedef struct {
|
||||
unsigned long long epbr;
|
||||
unsigned long long original0;
|
||||
unsigned long long original1;
|
||||
unsigned long long patch0;
|
||||
unsigned long long patch1;
|
||||
unsigned long long os;
|
||||
} AM_INSTALL_BOOT_RECORD;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_SEQ_INVALID = -1,
|
||||
|
||||
AM_INSTALL_SEQ_NONE = 0,
|
||||
AM_INSTALL_SEQ_BUSY = 1,
|
||||
AM_INSTALL_SEQ_SEND_REQUEST = 2,
|
||||
AM_INSTALL_SEQ_RECV_RESPONSE = 3,
|
||||
AM_INSTALL_SEQ_CHECK_RESPONSE = 4,
|
||||
AM_INSTALL_SEQ_OPEN_BINARY = 5,
|
||||
AM_INSTALL_SEQ_SEND_BINARY = 6,
|
||||
AM_INSTALL_SEQ_EXIT = 7,
|
||||
} AM_INSTALL_SEQ;
|
||||
|
||||
typedef enum {
|
||||
AM_INSTALL_REQUEST_QUERY_SLOT_STATUS = 1,
|
||||
AM_INSTALL_REQUEST_INSTALL = 2,
|
||||
AM_INSTALL_REQUEST_UNINSTALL = 3,
|
||||
AM_INSTALL_REQUEST_CHECK = 4,
|
||||
AM_INSTALL_REQUEST_QUERY_APPLICATION_STATUS = 5,
|
||||
AM_INSTALL_REQUEST_SET_APPLICATION_STATUS = 6,
|
||||
AM_INSTALL_REQUEST_QUERY_SBR_BOOTSLOT = 7,
|
||||
AM_INSTALL_REQUEST_SET_SBR_BOOTSLOT = 8,
|
||||
AM_INSTALL_REQUEST_QUERY_SEMAPHORE_STATUS = 9,
|
||||
AM_INSTALL_REQUEST_GET_SEMAPHORE = 10,
|
||||
AM_INSTALL_REQUEST_RELEASE_SEMAPHORE = 11,
|
||||
AM_INSTALL_REQUEST_QUERY_SPD = 12,
|
||||
AM_INSTALL_REQUEST_QUERY_BR = 13,
|
||||
AM_INSTALL_REQUEST_QUERY_APPDATA_STATUS = 14,
|
||||
AM_INSTALL_REQUEST_15 = 15,
|
||||
AM_INSTALL_REQUEST_16 = 16,
|
||||
AM_INSTALL_REQUEST_QUERY_VOLUME_NAME = 17,
|
||||
AM_INSTALL_REQUEST_18 = 18,
|
||||
} AM_INSTALL_REQUEST;
|
||||
|
||||
typedef struct _AM_INSTALL {
|
||||
BOOL m_init;
|
||||
AM_INSTALL_SEQ m_nextSeq;
|
||||
AM_INSTALL_REQUEST m_requestCode;
|
||||
AM_INSTALL_STATUS m_result;
|
||||
unsigned int m_sendBufferLen;
|
||||
unsigned int m_semid;
|
||||
AM_INSTALL_SEQ m_seq;
|
||||
pcpa_t m_pcp;
|
||||
unsigned int Unk510;
|
||||
unsigned short m_cmdPort;
|
||||
unsigned short m_dataPort;
|
||||
void* m_value;
|
||||
void* Unk51c;
|
||||
} AM_INSTALL;
|
||||
|
||||
bool amInstallPcpaGetUlonglong(unsigned long long *dest, char *keyword);
|
||||
bool amInstallPcpaGetInt(char *keyword, unsigned int *dest);
|
||||
|
||||
AM_INSTALL_STATUS amInstallResponseCheckQueryBr(AM_INSTALL_BOOT_RECORD *bootRecord);
|
||||
|
||||
AM_INSTALL_STATUS amInstallInit(void);
|
||||
AM_INSTALL_STATUS amInstallUpdate(void);
|
||||
AM_INSTALL_STATUS amInstallBusy(void);
|
||||
AM_INSTALL_STATUS amInstallSendRequest(void);
|
||||
AM_INSTALL_STATUS amInstallRecvResponse(void);
|
||||
AM_INSTALL_STATUS amInstallCodeToStatus(void);
|
||||
AM_INSTALL_STATUS amInstallResponseCheck(void);
|
||||
AM_INSTALL_STATUS amInstallOpenBinary(void);
|
||||
AM_INSTALL_STATUS amInstallOpenBinaryEx(void);
|
||||
AM_INSTALL_STATUS amInstallSendBinaryBuffer(AM_INSTALL_BLOCKING blocking);
|
||||
AM_INSTALL_STATUS amInstallExit(void);
|
||||
|
||||
AM_INSTALL_STATUS amInstallSendAndReceiveEx(void);
|
||||
AM_INSTALL_STATUS amInstallSendAndRecvEx(void);
|
||||
AM_INSTALL_STATUS amInstallOpenEx(void);
|
||||
AM_INSTALL_STATUS amInstallOpen(void);
|
||||
|
||||
AM_INSTALL_STATUS amInstallGetBr(void *bootRecord, AM_INSTALL_BLOCKING blocking);
|
||||
AM_INSTALL_STATUS amInstallGetResult(void);
|
||||
|
||||
void amInstallGetAppdataStatus(void);
|
||||
void amInstallGetApplicationStatus(void);
|
||||
void amInstallGetSbrBootslot(void);
|
||||
void amInstallGetSemaphore(void);
|
||||
void amInstallGetSemaphoreStatus(void);
|
||||
void amInstallGetSlotStatus(void);
|
||||
void amInstallGetSpd(void);
|
||||
void amInstallGetVolumeName(void);
|
||||
void amInstallPcpAddCommandApplicationStatus(void);
|
||||
void amInstallPcpAddCommandBootSlot(void);
|
||||
void amInstallPcpAddCommandForce(void);
|
||||
void amInstallPcpAddCommandInteger(void);
|
||||
void amInstallPcpAddCommandSlot(void);
|
||||
void amInstallPcpAddCommandSlotStatus(void);
|
||||
void amInstallReleaseSemaphore(void);
|
||||
void amInstallRequestCheck(void);
|
||||
void amInstallRequestCheckAppdataInternal(void);
|
||||
void amInstallRequestFormatAppdata(void);
|
||||
void amInstallRequestInstall(void);
|
||||
void amInstallRequestUninstall(void);
|
||||
void amInstallSetApplicationStatusEx(void);
|
||||
void amInstallSetSbrBootslot(void);
|
||||
AM_INSTALL_STATUS amInstallTaskRequest(char*);
|
||||
AM_INSTALL_STATUS amInstallSuicideSub(char*);
|
2
src/micetools/lib/am/amJvs.h
Normal file
2
src/micetools/lib/am/amJvs.h
Normal file
@ -0,0 +1,2 @@
|
||||
void amJvsInit(void);
|
||||
void amJvsInitEx(void);
|
1
src/micetools/lib/am/amJvsUpdate.h
Normal file
1
src/micetools/lib/am/amJvsUpdate.h
Normal file
@ -0,0 +1 @@
|
||||
void amJvsUpdate(void);
|
3
src/micetools/lib/am/amJvsp.h
Normal file
3
src/micetools/lib/am/amJvsp.h
Normal file
@ -0,0 +1,3 @@
|
||||
void amJvspAckSwInput(void);
|
||||
void amJvspGetReport(void);
|
||||
void amJvspMakeReportIndex(void);
|
0
src/micetools/lib/am/amJvst.h
Normal file
0
src/micetools/lib/am/amJvst.h
Normal file
3
src/micetools/lib/am/amJvstDriver.h
Normal file
3
src/micetools/lib/am/amJvstDriver.h
Normal file
@ -0,0 +1,3 @@
|
||||
void amJvstDriverExit(void);
|
||||
void amJvstDriverSetup(void);
|
||||
void amJvstDriverSetupComm(void);
|
1
src/micetools/lib/am/amJvstThread.h
Normal file
1
src/micetools/lib/am/amJvstThread.h
Normal file
@ -0,0 +1 @@
|
||||
void amJvstThreadInit(void);
|
2
src/micetools/lib/am/amLib.h
Normal file
2
src/micetools/lib/am/amLib.h
Normal file
@ -0,0 +1,2 @@
|
||||
void amLibSetErrorLog(void);
|
||||
void amLibSetupErrorLogInfo(void);
|
2
src/micetools/lib/am/amLog.h
Normal file
2
src/micetools/lib/am/amLog.h
Normal file
@ -0,0 +1,2 @@
|
||||
void amLogInit(void);
|
||||
void amLogSetEventOption(void);
|
0
src/micetools/lib/am/amMacAddress.h
Normal file
0
src/micetools/lib/am/amMacAddress.h
Normal file
27
src/micetools/lib/am/amMaster.h
Normal file
27
src/micetools/lib/am/amMaster.h
Normal file
@ -0,0 +1,27 @@
|
||||
void amMasterBusy(void);
|
||||
void amMasterCheckResponse(void);
|
||||
void amMasterEraseLog(void);
|
||||
void amMasterExitA(void);
|
||||
void amMasterExitW(void);
|
||||
void amMasterGetBackupEventLogParam(void);
|
||||
void amMasterGetCurrentProcess(void);
|
||||
void amMasterGetFirstApplicationStart(void);
|
||||
void amMasterGetNextProcessA(void);
|
||||
void amMasterGetNextProcessW(void);
|
||||
void amMasterGetProcessActivation(void);
|
||||
void amMasterGetProcessCount(void);
|
||||
void amMasterGetProcessFault(void);
|
||||
void amMasterGetResult(void);
|
||||
void amMasterInit(void);
|
||||
void amMasterIsDevelop(void);
|
||||
void amMasterOpen(void);
|
||||
void amMasterOpenEx(void);
|
||||
void amMasterOutputLog(void);
|
||||
void amMasterReconnectUsbDevice(void);
|
||||
void amMasterRecvResponse(void);
|
||||
void amMasterSendAndRecvEx(void);
|
||||
void amMasterSendRequest(void);
|
||||
void amMasterSetBackupEventLogParam(void);
|
||||
void amMasterSetNextProcessA(void);
|
||||
void amMasterSetProcessActivation(void);
|
||||
void amMasterUpdate(void);
|
15
src/micetools/lib/am/amNetwork.h
Normal file
15
src/micetools/lib/am/amNetwork.h
Normal file
@ -0,0 +1,15 @@
|
||||
void amNetworkBusy(void);
|
||||
void amNetworkInit(void);
|
||||
void amNetworkModifyPropertySub(void);
|
||||
void amNetworkOpen(void);
|
||||
void amNetworkOpenEx(void);
|
||||
void amNetworkRecvResponse(void);
|
||||
void amNetworkRequestDhcpStatusEth(void);
|
||||
void amNetworkRequestMacAddressEth(void);
|
||||
void amNetworkRequestModifyPropertyEth(void);
|
||||
void amNetworkRequestPropertyEth(void);
|
||||
void amNetworkRequestPropertySub(void);
|
||||
void amNetworkResponseCheck(void);
|
||||
void amNetworkSendAndRecvEx(void);
|
||||
void amNetworkSendRequest(void);
|
||||
void amNetworkSetCommandModifyProperty(void);
|
190
src/micetools/lib/am/amOemstring.c
Normal file
190
src/micetools/lib/am/amOemstring.c
Normal file
@ -0,0 +1,190 @@
|
||||
#include "amOemstring.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../dmi/dmi.h"
|
||||
#include "../mice/mice.h"
|
||||
|
||||
AM_LIB_C_HEADER(amOemstring, AM_OEMSTRING)
|
||||
|
||||
#define amOemstringScanStart 0xf0000
|
||||
#define amOemstringScanStep 0x7ff0
|
||||
#define amOemstringScanEnd 0xfffdf
|
||||
void amiOemstringLocateDMITable(HANDLE hColumba, LPDWORD lpDmiBase, LPWORD lpDmiLength) {
|
||||
AM_COLUMBA_REQUEST request;
|
||||
char buffer[amOemstringScanStep + 24];
|
||||
|
||||
int scanAddr = amOemstringScanStart;
|
||||
do {
|
||||
request.m_physAddr.LowPart = scanAddr & 0xffffffff;
|
||||
request.m_physAddr.HighPart = scanAddr >> 31;
|
||||
request.m_elementSize = 1;
|
||||
request.m_elementCount = sizeof buffer;
|
||||
|
||||
DWORD bytesOut = 0;
|
||||
BOOL ret = DeviceIoControl(hColumba, IOCTL_COLUMBA_READ, &request, sizeof request, buffer,
|
||||
sizeof buffer, &bytesOut, NULL);
|
||||
if (ret && bytesOut == sizeof buffer) {
|
||||
LPBYTE pBuffer = (LPBYTE)&buffer;
|
||||
for (int i = 0; i < (sizeof buffer) - 8; i++) {
|
||||
if (memcmp(pBuffer, "_DMI_", 5) == 0) {
|
||||
*lpDmiLength = *((LPWORD)(pBuffer + 6));
|
||||
*lpDmiBase = *((LPDWORD)(pBuffer + 8));
|
||||
return;
|
||||
}
|
||||
pBuffer++;
|
||||
}
|
||||
}
|
||||
|
||||
scanAddr += amOemstringScanStep;
|
||||
} while (scanAddr <= amOemstringScanEnd);
|
||||
}
|
||||
|
||||
void amiOemstringStoreString(BYTE type, int stringno, LPSTR string) {
|
||||
if (type == DmiTypeBios) {
|
||||
if (stringno == 1)
|
||||
strncpy_s(amOemstring.m_biosVersion, sizeof amOemstring.m_biosVersion, string, 0xff);
|
||||
if (stringno == 2)
|
||||
strncpy_s(amOemstring.m_biosDate, sizeof amOemstring.m_biosDate, string, 0xff);
|
||||
} else if (type == DmiTypeSystem) {
|
||||
if (stringno == 0)
|
||||
strncpy_s(amOemstring.m_systemManufacturer, sizeof amOemstring.m_systemManufacturer,
|
||||
string, 0xff);
|
||||
|
||||
} else if (type == DmiTypeString) {
|
||||
if (stringno < 5)
|
||||
strncpy_s(amOemstring.m_strings[stringno], sizeof amOemstring.m_strings[stringno],
|
||||
string, 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL amiOemstringLoadStrings(void) {
|
||||
if (amOemstring.m_loaded) return TRUE;
|
||||
ZeroMemory(&amOemstring, sizeof amOemstring);
|
||||
|
||||
BYTE buffer[0x10000];
|
||||
|
||||
HANDLE hColumba = CreateFileW(L"\\\\.\\columba", GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, 0, NULL);
|
||||
if (hColumba == INVALID_HANDLE_VALUE) return FALSE;
|
||||
|
||||
DWORD me = 0;
|
||||
|
||||
DWORD dmiBase = 0;
|
||||
WORD dmiLength = 0;
|
||||
|
||||
amiOemstringLocateDMITable(hColumba, &dmiBase, &dmiLength);
|
||||
if (dmiBase == 0) return FALSE;
|
||||
|
||||
AM_COLUMBA_REQUEST request;
|
||||
request.m_physAddr.QuadPart = dmiBase;
|
||||
request.m_elementSize = 1;
|
||||
|
||||
if (dmiBase + 0x10000 < 0x100001) {
|
||||
request.m_elementCount = 0x10000;
|
||||
} else {
|
||||
request.m_elementCount = 0x100000 - dmiBase;
|
||||
}
|
||||
|
||||
DWORD nBytesReturned;
|
||||
if (!DeviceIoControl(hColumba, IOCTL_COLUMBA_READ, &request, sizeof request, buffer,
|
||||
sizeof buffer, &nBytesReturned, NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nBytesReturned != 0x10000) return FALSE;
|
||||
|
||||
BYTE type_seen[128] = { 0 };
|
||||
|
||||
LPBYTE pBuffer = (LPBYTE)&buffer;
|
||||
while (1) {
|
||||
DMI_SECTION_HEADER* header = (DMI_SECTION_HEADER*)pBuffer;
|
||||
if (header->Length == 0) break;
|
||||
// Avoid reading outside the DMI tables
|
||||
if ((pBuffer - (LPBYTE)&buffer) + header->Length >= dmiLength) break;
|
||||
// Avoid reading outside the buffer!
|
||||
if ((pBuffer - (LPBYTE)&buffer) + header->Length >= sizeof buffer) break;
|
||||
|
||||
BYTE type = header->Type;
|
||||
pBuffer += header->Length;
|
||||
|
||||
int stringno = 0;
|
||||
do {
|
||||
if (!type_seen[type]) amiOemstringStoreString(type, stringno, (LPSTR)pBuffer);
|
||||
stringno++;
|
||||
|
||||
while (pBuffer[0] != '\0') pBuffer++;
|
||||
pBuffer++;
|
||||
} while (pBuffer[0] != '\0');
|
||||
pBuffer++;
|
||||
|
||||
if (type < sizeof type_seen) type_seen[type] = 1;
|
||||
}
|
||||
|
||||
amOemstring.m_loaded = TRUE;
|
||||
CloseHandle(hColumba);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
AM_OEMSTRING_STATUS amOemstringGetManufacturer(LPSTR manufacturer) {
|
||||
if (manufacturer == NULL) return AM_OEMSTRING_STATUS_ERR_INVALID_PARAM;
|
||||
if (amiOemstringLoadStrings() == 0) {
|
||||
manufacturer[0] = '\0';
|
||||
return AM_OEMSTRING_STATUS_ERR_SYS;
|
||||
}
|
||||
strncpy_s(manufacturer, sizeof amOemstring.m_systemManufacturer,
|
||||
amOemstring.m_systemManufacturer, 0xffffffff);
|
||||
return AM_OEMSTRING_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_OEMSTRING_STATUS amOemstringGetSBiosVer(LPSTR biosVersion) {
|
||||
if (biosVersion == NULL) return AM_OEMSTRING_STATUS_ERR_INVALID_PARAM;
|
||||
if (amiOemstringLoadStrings() == 0) {
|
||||
biosVersion[0] = '\0';
|
||||
return AM_OEMSTRING_STATUS_ERR_SYS;
|
||||
}
|
||||
strncpy_s(biosVersion, sizeof amOemstring.m_biosVersion, amOemstring.m_biosVersion, 0xffffffff);
|
||||
return AM_OEMSTRING_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_OEMSTRING_STATUS amOemstringGetSBiosReleaseDate(LPSTR biosDate) {
|
||||
if (biosDate == NULL) return AM_OEMSTRING_STATUS_ERR_INVALID_PARAM;
|
||||
if (amiOemstringLoadStrings() == 0) {
|
||||
biosDate[0] = '\0';
|
||||
return AM_OEMSTRING_STATUS_ERR_SYS;
|
||||
}
|
||||
strncpy_s(biosDate, sizeof amOemstring.m_biosDate, amOemstring.m_biosDate, 0xffffffff);
|
||||
return AM_OEMSTRING_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_OEMSTRING_STATUS amOemstringGetOemstring(LPSTR oemstring, int which) {
|
||||
LPSTR sVal;
|
||||
|
||||
if (oemstring == NULL) return AM_OEMSTRING_STATUS_ERR_INVALID_PARAM;
|
||||
|
||||
switch (which) {
|
||||
case 0:
|
||||
sVal = amOemstring.m_strings[0];
|
||||
break;
|
||||
case 1:
|
||||
sVal = amOemstring.m_strings[1];
|
||||
break;
|
||||
case 2:
|
||||
sVal = amOemstring.m_strings[2];
|
||||
break;
|
||||
case 3:
|
||||
sVal = amOemstring.m_strings[3];
|
||||
break;
|
||||
case 4:
|
||||
sVal = amOemstring.m_strings[4];
|
||||
break;
|
||||
default:
|
||||
sVal = NULL;
|
||||
}
|
||||
|
||||
oemstring[0] = '\0';
|
||||
if (sVal == NULL) return AM_OEMSTRING_STATUS_ERR_INVALID_PARAM;
|
||||
if (amiOemstringLoadStrings() == 0) return AM_OEMSTRING_STATUS_ERR_SYS;
|
||||
strncpy_s(oemstring, sizeof amOemstring.m_strings[0], sVal, 0xffffffff);
|
||||
return AM_OEMSTRING_STATUS_OK;
|
||||
}
|
41
src/micetools/lib/am/amOemstring.h
Normal file
41
src/micetools/lib/am/amOemstring.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amOemstring, AM_OEMSTRING)
|
||||
|
||||
// Much easier than pulling in winddk.h
|
||||
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
||||
typedef struct {
|
||||
PHYSICAL_ADDRESS m_physAddr;
|
||||
DWORD m_elementSize;
|
||||
DWORD m_elementCount;
|
||||
} AM_COLUMBA_REQUEST;
|
||||
|
||||
typedef struct _AM_OEMSTRING {
|
||||
BOOL m_loaded;
|
||||
CHAR m_biosVersion[32];
|
||||
CHAR m_biosDate[11];
|
||||
CHAR m_systemManufacturer[32];
|
||||
CHAR m_strings[5][32];
|
||||
} AM_OEMSTRING;
|
||||
|
||||
|
||||
typedef enum {
|
||||
AM_OEMSTRING_STATUS_OK = 0,
|
||||
AM_OEMSTRING_STATUS_NG = -1,
|
||||
AM_OEMSTRING_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_OEMSTRING_STATUS_ERR_SYS = -3,
|
||||
} AM_OEMSTRING_STATUS;
|
||||
|
||||
|
||||
void amiOemstringLocateDMITable(HANDLE hColumba, LPDWORD lpDmiBase, LPWORD lpDmiLength);
|
||||
void amiOemstringStoreString(BYTE type, int stringno, LPSTR string);
|
||||
BOOL amiOemstringLoadStrings(void);
|
||||
|
||||
AM_OEMSTRING_STATUS amOemstringGetManufacturer(LPSTR manufacturer);
|
||||
AM_OEMSTRING_STATUS amOemstringGetOemstring(LPSTR oemstring, int which);
|
||||
AM_OEMSTRING_STATUS amOemstringGetSBiosVer(LPSTR biosVersion);
|
||||
AM_OEMSTRING_STATUS amOemstringGetSBiosReleaseDate(LPSTR biosDate);
|
239
src/micetools/lib/am/amPlatform.c
Normal file
239
src/micetools/lib/am/amPlatform.c
Normal file
@ -0,0 +1,239 @@
|
||||
#include "amPlatform.h"
|
||||
|
||||
#include "../ami/amiDebug.h"
|
||||
#include "amEeprom.h"
|
||||
#include "amOemstring.h"
|
||||
#include "amSram.h"
|
||||
|
||||
AM_LIB_C_HEADER(amPlatform, AM_PLATFORM)
|
||||
|
||||
#define _amEepromRead (amPlatformRead_t *)&amEepromRead
|
||||
#define _amEepromWrite (amPlatformWrite_t *)&amEepromWrite
|
||||
#define _amSramRead (amPlatformRead_t *)&amSramRead
|
||||
#define _amSramWrite (amPlatformWrite_t *)&amSramWrite
|
||||
|
||||
AM_PLATFORM_NV_DEVICE_CONFIG amPlatformNvDevices[3][4] = {
|
||||
// RingEdge 1
|
||||
{
|
||||
{
|
||||
.m_base = 0x0,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x1000,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0,
|
||||
.m_size = 0x4000,
|
||||
.m_blockSize = 512,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x4000,
|
||||
.m_size = 0x1FC000,
|
||||
.m_blockSize = 512,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
},
|
||||
// RingEdge 2
|
||||
{
|
||||
{
|
||||
.m_base = 0x0,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x1000,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0,
|
||||
.m_size = 0x4000,
|
||||
.m_blockSize = 4,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x4000,
|
||||
.m_size = 0x1FC000,
|
||||
.m_blockSize = 4,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
},
|
||||
// RingWide
|
||||
{
|
||||
{
|
||||
.m_base = 0x0,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x1000,
|
||||
.m_size = 0x1000,
|
||||
.m_blockSize = 1,
|
||||
.m_read = _amEepromRead,
|
||||
.m_write = _amEepromWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0,
|
||||
.m_size = 0x4000,
|
||||
.m_blockSize = 512,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
{
|
||||
.m_base = 0x4000,
|
||||
.m_size = 0x3C000,
|
||||
.m_blockSize = 512,
|
||||
.m_read = _amSramRead,
|
||||
.m_write = _amSramWrite,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
AM_PLATFORM_NV_DEVICE_CONFIG *amPlatformGetNvDevice(AM_PLATFORM_NV_DEVICE device) {
|
||||
if (device > 0 && device < _NUM_AM_PLATFORM_NV_DEVICE) {
|
||||
AM_PLATFORM_BOARD_TYPE boardType;
|
||||
amPlatformGetBoardType(&boardType);
|
||||
switch (boardType) {
|
||||
case AM_PLATFORM_BOARD_TYPE_RINGEDGE:
|
||||
return &(amPlatformNvDevices[0][device]);
|
||||
case AM_PLATFORM_BOARD_TYPE_RW_SPEC_1:
|
||||
case AM_PLATFORM_BOARD_TYPE_RW_SPEC_2:
|
||||
return &(amPlatformNvDevices[2][device]);
|
||||
case AM_PLATFORM_BOARD_TYPE_RINGEDGE2:
|
||||
return &(amPlatformNvDevices[1][device]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AM_PLATFORM_STATUS amPlatformGetPlatformId(AM_PLATFORM_PLATFORM_ID *platformId) {
|
||||
if (platformId == NULL) {
|
||||
if (amPlatformDebugLevel > 0) amiDebugLog("PARAM Error!!");
|
||||
return AM_PLATFORM_STATUS_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
char oemstringPlatform[32];
|
||||
char oemstringManufacturer[32];
|
||||
|
||||
/**
|
||||
* If platform starts with "AAM" (RW) or "AAL" (RE):
|
||||
* copy it into m_platformId verbatim
|
||||
* Otherwise
|
||||
* fetch the manufacturer name
|
||||
* If manufacturer is "NEC"
|
||||
* m_platformId = "AAL" (RE)
|
||||
* If manufacturer if "Supermicro" or "Advantech"
|
||||
* m_platformId = "AAM" (RW)
|
||||
*/
|
||||
|
||||
if (!amPlatform.m_platformIdCached) {
|
||||
if (amOemstringGetOemstring(oemstringPlatform, 2) != AM_OEMSTRING_STATUS_OK) {
|
||||
if (amPlatformDebugLevel > 0)
|
||||
amiDebugLog("amOemstringGetOemstring Error!! (%d)",
|
||||
AM_PLATFORM_STATUS_ERR_SYS);
|
||||
return AM_PLATFORM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
if (strcmp(oemstringPlatform, PLATFORM_RINGEDGE) == 0 ||
|
||||
strcmp(oemstringPlatform, PLATFORM_RINGWIDE) == 0) {
|
||||
strncpy_s(amPlatform.m_platformId.strPlatformId,
|
||||
sizeof amPlatform.m_platformId.strPlatformId, oemstringPlatform, 0xffffffff);
|
||||
} else if (amOemstringGetManufacturer(oemstringManufacturer) == AM_OEMSTRING_STATUS_OK) {
|
||||
if (strcmp(oemstringManufacturer, "NEC") == 0) {
|
||||
strncpy_s(amPlatform.m_platformId.strPlatformId,
|
||||
sizeof amPlatform.m_platformId.strPlatformId, PLATFORM_RINGEDGE,
|
||||
0xffffffff);
|
||||
} else if (strcmp(oemstringManufacturer, "Supermicro") == 0 ||
|
||||
strcmp(oemstringManufacturer, "Advantech") == 0) {
|
||||
strncpy_s(amPlatform.m_platformId.strPlatformId,
|
||||
sizeof amPlatform.m_platformId.strPlatformId, PLATFORM_RINGWIDE,
|
||||
0xffffffff);
|
||||
}
|
||||
}
|
||||
amPlatform.m_platformIdCached = TRUE;
|
||||
}
|
||||
|
||||
memcpy(platformId->strPlatformId, amPlatform.m_platformId.strPlatformId,
|
||||
sizeof amPlatform.m_platformId.strPlatformId);
|
||||
return amPlatform.m_platformIdCached ? AM_PLATFORM_STATUS_OK : AM_PLATFORM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
AM_PLATFORM_STATUS amPlatformGetBoardType(AM_PLATFORM_BOARD_TYPE *boardType) {
|
||||
AM_PLATFORM_PLATFORM_ID platformId;
|
||||
char oemstring4[32];
|
||||
char oemstringManufacturer[32];
|
||||
|
||||
if (boardType == NULL) {
|
||||
if (amPlatformDebugLevel > 0) amiDebugLog("PARAM Error!!");
|
||||
return AM_PLATFORM_STATUS_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (amPlatform.m_boardTypeCached) {
|
||||
*boardType = amPlatform.m_boardType;
|
||||
return AM_PLATFORM_STATUS_OK;
|
||||
}
|
||||
if (amPlatformGetPlatformId(&platformId) != AM_PLATFORM_STATUS_OK ||
|
||||
amOemstringGetManufacturer(oemstringManufacturer) != AM_OEMSTRING_STATUS_OK) {
|
||||
*boardType = amPlatform.m_boardType;
|
||||
return AM_PLATFORM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
if (strcmp(platformId.strPlatformId, PLATFORM_RINGWIDE) == 0) {
|
||||
if (strcmp(oemstringManufacturer, "Supermicro") == 0) {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RW_SPEC_1;
|
||||
} else if (strcmp(oemstringManufacturer, "Advantech") == 0) {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RW_SPEC_2;
|
||||
} else {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
amPlatform.m_boardTypeCached = TRUE;
|
||||
return AM_PLATFORM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (strcmp(platformId.strPlatformId, PLATFORM_RINGEDGE) == 0) {
|
||||
if (strcmp(oemstringManufacturer, "NEC") == 0) {
|
||||
ZeroMemory(oemstring4, sizeof oemstring4);
|
||||
|
||||
if (amOemstringGetOemstring(oemstring4, 4) != AM_OEMSTRING_STATUS_OK) {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_UNKNOWN;
|
||||
return AM_PLATFORM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
if (strcmp(oemstring4, PLATFORM_RINGEDGE2) == 0) {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RINGEDGE2;
|
||||
amPlatform.m_boardTypeCached = TRUE;
|
||||
return AM_PLATFORM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (strcmp(oemstring4, "") == 0 || strcmp(oemstring4, " ") == 0) {
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_RINGEDGE;
|
||||
amPlatform.m_boardTypeCached = TRUE;
|
||||
return AM_PLATFORM_STATUS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*boardType = amPlatform.m_boardType = AM_PLATFORM_BOARD_TYPE_UNKNOWN;
|
||||
amPlatform.m_boardTypeCached = TRUE;
|
||||
return AM_PLATFORM_STATUS_OK;
|
||||
}
|
112
src/micetools/lib/am/amPlatform.h
Normal file
112
src/micetools/lib/am/amPlatform.h
Normal file
@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amPlatform, AM_PLATFORM)
|
||||
|
||||
#define PLATFORM_RINGWIDE "AAM"
|
||||
#define PLATFORM_RINGEDGE "AAL"
|
||||
#define PLATFORM_RINGEDGE2 "AAL2" // Also AAS in places
|
||||
|
||||
typedef struct {
|
||||
char strPlatformId[4];
|
||||
} AM_PLATFORM_PLATFORM_ID;
|
||||
|
||||
typedef enum {
|
||||
AM_PLATFORM_BOARD_TYPE_RINGEDGE = 0,
|
||||
AM_PLATFORM_BOARD_TYPE_RW_SPEC_1 = 1, // Supermicro
|
||||
AM_PLATFORM_BOARD_TYPE_RW_SPEC_2 = 2, // Advantech
|
||||
AM_PLATFORM_BOARD_TYPE_RINGEDGE2 = 3,
|
||||
AM_PLATFORM_BOARD_TYPE_UNKNOWN = 4,
|
||||
} AM_PLATFORM_BOARD_TYPE;
|
||||
|
||||
typedef struct _AM_PLATFORM {
|
||||
BOOL m_boardTypeCached;
|
||||
AM_PLATFORM_BOARD_TYPE m_boardType;
|
||||
BOOL m_platformIdCached;
|
||||
AM_PLATFORM_PLATFORM_ID m_platformId;
|
||||
} AM_PLATFORM;
|
||||
|
||||
typedef struct {
|
||||
char strVendorId[5];
|
||||
char strDeviceId[5];
|
||||
char strSubId[9];
|
||||
} AM_PLATFORM_ID_GROUP;
|
||||
|
||||
typedef enum {
|
||||
AM_PLATFORM_STATUS_OK = 0,
|
||||
AM_PLATFORM_STATUS_NO_INFO = 1,
|
||||
AM_PLATFORM_STATUS_BUSY = 2,
|
||||
AM_PLATFORM_STATUS_NG = -1,
|
||||
AM_PLATFORM_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_PLATFORM_STATUS_ERR_SYS = -3,
|
||||
AM_PLATFORM_STATUS_ERR_NO_OPEN = -4,
|
||||
AM_PLATFORM_STATUS_ERR_ALREADY_OPEN = -5,
|
||||
AM_PLATFORM_STATUS_ERR_NO_REQUEST = -6,
|
||||
AM_PLATFORM_STATUS_ERR_ALREADY_REQUEST = -7,
|
||||
AM_PLATFORM_STATUS_ERR_BUFF_SIZE = -8,
|
||||
AM_PLATFORM_STATUS_ERR_NO_INIT = -9,
|
||||
AM_PLATFORM_STATUS_ERR_ALREADY_INIT = -10,
|
||||
AM_PLATFORM_STATUS_NOT_SUPPORT = -11,
|
||||
} AM_PLATFORM_STATUS;
|
||||
|
||||
typedef enum {
|
||||
AM_PLATFORM_NV_DEVICE_EEPROM = 0,
|
||||
AM_PLATFORM_NV_DEVICE_EEPROM_DUP = 1,
|
||||
AM_PLATFORM_NV_DEVICE_SRAM = 2,
|
||||
AM_PLATFORM_NV_DEVICE_SRAM_DUP = 3,
|
||||
_NUM_AM_PLATFORM_NV_DEVICE,
|
||||
} AM_PLATFORM_NV_DEVICE;
|
||||
|
||||
typedef int(amPlatformRead_t)(WORD addr, LPBYTE buf, DWORD length);
|
||||
typedef int(amPlatformWrite_t)(WORD addr, LPBYTE buf, DWORD length);
|
||||
|
||||
typedef struct {
|
||||
DWORD m_base;
|
||||
DWORD m_size;
|
||||
DWORD m_blockSize;
|
||||
amPlatformRead_t* m_read;
|
||||
amPlatformWrite_t* m_write;
|
||||
} AM_PLATFORM_NV_DEVICE_CONFIG;
|
||||
|
||||
AM_PLATFORM_NV_DEVICE_CONFIG* amPlatformGetNvDevice(AM_PLATFORM_NV_DEVICE device);
|
||||
|
||||
AM_PLATFORM_STATUS amPlatformGetBoardType(AM_PLATFORM_BOARD_TYPE* boardType);
|
||||
AM_PLATFORM_STATUS amPlatformGetPlatformId(AM_PLATFORM_PLATFORM_ID* platformId);
|
||||
|
||||
// TODO:
|
||||
|
||||
void amPlatformAsyncClose(void);
|
||||
void amPlatformAsyncReqUsbDeviceCount(void);
|
||||
void amPlatformAsyncResUsbDeviceCount(void);
|
||||
void amPlatformChangeDisplayModeAmd(void);
|
||||
void amPlatformChangeDisplayModeNvidia(void);
|
||||
void amPlatformChangeDisplayModeNvidiaEx(void);
|
||||
void amPlatformChangeDisplayResolutionAmd(void);
|
||||
void amPlatformChangeDisplayResolutionNvidia(void);
|
||||
void amPlatformChangeDisplayResolutionNvidiaEx(void);
|
||||
void amPlatformChangeDisplayResolutionWinAPI(void);
|
||||
void amPlatformDestroyCheckInterfaceHandle(void);
|
||||
void amPlatformGetAvailableAmdDriver(void);
|
||||
void amPlatformGetAvailableNvidiaDriver(void);
|
||||
void amPlatformGetBiosInfo(void);
|
||||
void amPlatformGetCheckInterfaceHandle(void);
|
||||
void amPlatformGetComInfo(void);
|
||||
void amPlatformGetDevInfo(void);
|
||||
void amPlatformGetGpuPstate(void);
|
||||
void amPlatformGetGraphicInfo(void);
|
||||
void amPlatformGetMemorySize(void);
|
||||
void amPlatformGetOsVersion(void);
|
||||
void amPlatformGetOsVersion(void);
|
||||
void amPlatformGetPartitionInfo(void);
|
||||
void amPlatformGetPlatformIdEx(void);
|
||||
void amPlatformGetPortName(void);
|
||||
void amPlatformGetSearchDevInfo(void);
|
||||
void amPlatformGetSoundInfo(void);
|
||||
void amPlatformGetStorageInfo(void);
|
||||
void amPlatformNvapiInit(void);
|
||||
void amPlatformSetDisplayMode(void);
|
||||
void amPlatformSetDisplayResolution(void);
|
||||
void amPlatformSetDisplayResolutionAndMode(void);
|
10
src/micetools/lib/am/amRtc.h
Normal file
10
src/micetools/lib/am/amRtc.h
Normal file
@ -0,0 +1,10 @@
|
||||
void amRtcConvertStructToTimet(void);
|
||||
void amRtcConvertSystemToTimet(void);
|
||||
void amRtcConvertTimetToStruct(void);
|
||||
void amRtcConvertTimetToSystem(void);
|
||||
void amRtcFinalize(void);
|
||||
void amRtcGetServerTime(void);
|
||||
void amRtcInit(void);
|
||||
void amRtcSetClockAndTimeZone(void);
|
||||
void amRtcSetSysClockSetting(void);
|
||||
void amRtcStartupTimeZone(void);
|
37
src/micetools/lib/am/amSerialId.c
Normal file
37
src/micetools/lib/am/amSerialId.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include "amSerialId.h"
|
||||
|
||||
AM_LIB_C_HEADER(amSerialId, AM_SERIAL_ID)
|
||||
|
||||
BOOL amSerialIdIsValid(char *id_string) {
|
||||
if (id_string == NULL) return FALSE;
|
||||
|
||||
for (int i = 0; i < 15; i++) {
|
||||
char chr = id_string[i];
|
||||
|
||||
if (chr == '\0') return FALSE;
|
||||
if (chr > 0x7f) return FALSE;
|
||||
|
||||
if (i == 4) {
|
||||
if (chr != '-') return FALSE;
|
||||
} else if (i < 8 || i > 15) {
|
||||
if (!isdigit(chr) && !isupper(chr)) return FALSE;
|
||||
|
||||
if (chr == 'I') return FALSE;
|
||||
|
||||
if (chr == 'O') return FALSE;
|
||||
} else {
|
||||
if (!isdigit(chr)) return FALSE;
|
||||
}
|
||||
}
|
||||
return id_string[16] == '\0';
|
||||
}
|
||||
|
||||
BOOL amSerialIdConvert(char *id_string, char *serial_id) {
|
||||
if (id_string == NULL || serial_id == NULL) return FALSE;
|
||||
if (!amSerialIdIsValid(id_string)) return FALSE;
|
||||
|
||||
ZeroMemory(serial_id, 12);
|
||||
memcpy_s(serial_id, 17, id_string, 4);
|
||||
memcpy_s(serial_id + 4, 13, id_string + 5, 7);
|
||||
return TRUE;
|
||||
}
|
14
src/micetools/lib/am/amSerialId.h
Normal file
14
src/micetools/lib/am/amSerialId.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amSerialId, AM_SERIAL_ID)
|
||||
|
||||
typedef struct _AM_SERIAL_ID {
|
||||
unsigned char Rsv00;
|
||||
} AM_SERIAL_ID;
|
||||
|
||||
BOOL amSerialIdIsValid(char *id_string);
|
||||
BOOL amSerialIdConvert(char *id_string, char *serial_id);
|
298
src/micetools/lib/am/amSram.c
Normal file
298
src/micetools/lib/am/amSram.c
Normal file
@ -0,0 +1,298 @@
|
||||
#include "amSram.h"
|
||||
|
||||
#include "../ami/ami.h"
|
||||
#include "../mice/ioctl.h"
|
||||
|
||||
AM_LIB_C_HEADER(amSram, AM_SRAM)
|
||||
|
||||
AM_SRAM_STATUS amSramCreateMutex(AM_SRAM *device) {
|
||||
SECURITY_ATTRIBUTES muxAttrs;
|
||||
SECURITY_DESCRIPTOR securityDescriptor;
|
||||
SID_IDENTIFIER_AUTHORITY idAuth;
|
||||
|
||||
PSID *pSid = &device->m_sid;
|
||||
idAuth.Value[0] = 0;
|
||||
idAuth.Value[1] = 0;
|
||||
idAuth.Value[2] = 0;
|
||||
idAuth.Value[3] = 0;
|
||||
idAuth.Value[4] = 0;
|
||||
idAuth.Value[5] = 1;
|
||||
|
||||
if (!AllocateAndInitializeSid(&idAuth, '\x01', 0, 0, 0, 0, 0, 0, 0, 0, pSid)) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("AllocateAndInitializeSid Error in amSramInit.");
|
||||
*pSid = NULL;
|
||||
goto amSramCreateMutexError;
|
||||
}
|
||||
|
||||
if (!InitializeSecurityDescriptor(&securityDescriptor, 1)) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("InitializeSecurityDescriptor Error in amSramInit.");
|
||||
goto amSramCreateMutexError;
|
||||
}
|
||||
|
||||
if (!SetSecurityDescriptorDacl(&securityDescriptor, TRUE, NULL, FALSE)) {
|
||||
if (amSramDebugLevel > 0) {
|
||||
amiDebugLog("amSramCreateMutex", 0x43a,
|
||||
"SetSecurityDescriptorDacl Error in amSramInit.\n");
|
||||
}
|
||||
goto amSramCreateMutexError;
|
||||
}
|
||||
|
||||
muxAttrs.lpSecurityDescriptor = &securityDescriptor;
|
||||
muxAttrs.nLength = 12;
|
||||
muxAttrs.bInheritHandle = FALSE;
|
||||
if ((device->m_mutex = CreateMutexA(&muxAttrs, FALSE, "Global\\AM_SRAM_MUTEX")) != NULL) {
|
||||
return AM_SRAM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amSramDebugLevel > 0) amiDebugLog("CreateMutexA Error(%ld).", GetLastError());
|
||||
|
||||
amSramCreateMutexError:
|
||||
if (device->m_mutex != NULL) {
|
||||
CloseHandle(device->m_mutex);
|
||||
device->m_mutex = NULL;
|
||||
}
|
||||
if (*pSid != NULL) {
|
||||
FreeSid(*pSid);
|
||||
*pSid = NULL;
|
||||
}
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramInit(void) {
|
||||
if (amSram.m_init) return AM_SRAM_STATUS_ERR_ALREADY_INIT;
|
||||
|
||||
amSram.m_readTimeout = -1;
|
||||
amSram.m_writeTimeout = -1;
|
||||
amSram.Unk20 = -1;
|
||||
|
||||
AM_SRAM_STATUS status = amSramCreateMutex(&amSram);
|
||||
if (status != AM_SRAM_STATUS_OK) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("amSramCreateMutex Error!! Error Code is %ld!!", status);
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
amSram.m_handle = CreateFileW(L"\\\\.\\mxsram", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_SUPPORTS_REPARSE_POINTS, NULL);
|
||||
if (amSram.m_handle == INVALID_HANDLE_VALUE) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("CreateFileW Error!! Error Code is %ld!!", GetLastError());
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
DWORD bytesReturned;
|
||||
DWORD version;
|
||||
BOOL s = DeviceIoControl(amSram.m_handle, IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version,
|
||||
&bytesReturned, NULL);
|
||||
if (!s || bytesReturned != sizeof version) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("DeviceIoControl Error!! Error Code is %ld!!", GetLastError());
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
if ((version & 0xffff) != 1) {
|
||||
if (amSramDebugLevel > 0) {
|
||||
amiDebugLog(
|
||||
"Sram Driver Protocol Mismatched. Detected Driver Version "
|
||||
": 0x%08lx. Pl ease Update Sram Driver or User Program.\n",
|
||||
version);
|
||||
}
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
DISK_GEOMETRY driveGeometry;
|
||||
s = DeviceIoControl(amSram.m_handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &driveGeometry,
|
||||
sizeof driveGeometry, &bytesReturned, NULL);
|
||||
if (!s || bytesReturned != sizeof driveGeometry) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("DeviceIoControl Error!! Error Code is %ld!!", GetLastError());
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
amSram.m_sectorSize = driveGeometry.BytesPerSector;
|
||||
amSram.m_size.QuadPart = driveGeometry.Cylinders.QuadPart * driveGeometry.TracksPerCylinder *
|
||||
driveGeometry.SectorsPerTrack * driveGeometry.BytesPerSector;
|
||||
if (amSram.m_size.QuadPart == 0) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("Get Sram Size Error!!");
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
|
||||
DWORD sectorSize;
|
||||
s = DeviceIoControl(amSram.m_handle, IOCTL_MXSRAM_GET_SECTOR_SIZE, NULL, 0, §orSize,
|
||||
sizeof sectorSize, &bytesReturned, NULL);
|
||||
if (s) {
|
||||
if (bytesReturned != sizeof sectorSize) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("DeviceIoControl Error!! Error Code is %ld!!", GetLastError());
|
||||
goto amSramInitErrorSys;
|
||||
}
|
||||
amSram.m_sectorSize = sectorSize;
|
||||
}
|
||||
|
||||
if (amSram.m_sectorSize <= AM_SRAM_MAX_SECTOR_SIZE) {
|
||||
amSram.m_init = TRUE;
|
||||
return AM_SRAM_STATUS_OK;
|
||||
}
|
||||
|
||||
if (amSramDebugLevel)
|
||||
amiDebugLog("Internal Error. sector size(%d)is too large.", amSram.m_sectorSize);
|
||||
goto amSramInitErrorSys;
|
||||
|
||||
amSramInitErrorSys:
|
||||
amSram.m_init = TRUE;
|
||||
amSramExit();
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramExit(void) {
|
||||
if (!amSram.m_init) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("No Init Error!!");
|
||||
return AM_SRAM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
|
||||
if (amSram.m_handle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(amSram.m_handle);
|
||||
amSram.m_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if (amSram.m_mutex != NULL) {
|
||||
CloseHandle(amSram.m_mutex);
|
||||
amSram.m_mutex = NULL;
|
||||
}
|
||||
if (amSram.m_sid != NULL) {
|
||||
FreeSid(amSram.m_sid);
|
||||
amSram.m_sid = NULL;
|
||||
}
|
||||
amSram.m_init = FALSE;
|
||||
return AM_SRAM_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramReadInternal(AM_SRAM *device, LONG addressLow, LONG addressHigh, LPVOID buffer,
|
||||
DWORD nBytes) {
|
||||
if (SetFilePointer(device->m_handle, addressLow, &addressHigh, 0) == INVALID_SET_FILE_POINTER) {
|
||||
DWORD lastErr = GetLastError();
|
||||
if (lastErr != 0) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("SetFilePointer Error(%d).", lastErr);
|
||||
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD bytesRead;
|
||||
BOOL s = ReadFile(device->m_handle, buffer, nBytes, &bytesRead, NULL);
|
||||
if (!s || nBytes != bytesRead) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("ReadFile Error(%d).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_READ;
|
||||
}
|
||||
|
||||
return AM_SRAM_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramWriteInternal(AM_SRAM *device, LONG addressLow, LONG addressHigh,
|
||||
LPCVOID buffer, DWORD nBytes) {
|
||||
if (SetFilePointer(device->m_handle, addressLow, &addressHigh, 0) == INVALID_SET_FILE_POINTER) {
|
||||
DWORD lastErr = GetLastError();
|
||||
if (lastErr != 0) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("SetFilePointer Error(%d).", lastErr);
|
||||
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD bytesRead;
|
||||
BOOL s = WriteFile(device->m_handle, buffer, nBytes, &bytesRead, NULL);
|
||||
if (!s || nBytes != bytesRead) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("WriteFile Error(%d).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_WRITE;
|
||||
}
|
||||
|
||||
return AM_SRAM_STATUS_OK;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramRead(DWORD src, LPVOID pDst, DWORD size) {
|
||||
if (!amSram.m_init) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("Not initialized.");
|
||||
return AM_SRAM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
|
||||
if (pDst == NULL || !size || size % amSram.m_sectorSize || src % amSram.m_sectorSize) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("Illegal parameter(s). Src=0x%08x pDst=0x%p Size=0x%08x", src, pDst,
|
||||
size);
|
||||
return AM_SRAM_STATUS_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (src > amSram.m_size.QuadPart - amSram.m_sectorSize || src + size > amSram.m_size.QuadPart) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("Address range is invalid. Src=0x%08x Size=0x%08x", src, size);
|
||||
|
||||
return AM_SRAM_STATUS_ERR_DOMAIN;
|
||||
}
|
||||
|
||||
DWORD err = WaitForSingleObject(amSram.m_mutex, amSram.m_readTimeout);
|
||||
if (err == WAIT_FAILED) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
if (err == WAIT_TIMEOUT) return AM_SRAM_STATUS_ERR_GET_MUTEX;
|
||||
|
||||
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(),
|
||||
err);
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS status = amSramReadInternal(&amSram, src, 0, pDst, size);
|
||||
if (!ReleaseMutex(amSram.m_mutex)) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS amSramWrite(LPCVOID pSrc, DWORD dst, DWORD size) {
|
||||
if (!amSram.m_init) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("Not initialized.");
|
||||
return AM_SRAM_STATUS_ERR_NO_INIT;
|
||||
}
|
||||
|
||||
if (pSrc == NULL || !size || size % amSram.m_sectorSize || dst % amSram.m_sectorSize) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("Illegal parameter(s). pSrc=0x%p Dst=0x%08x Size=0x%08x", pSrc, dst,
|
||||
size);
|
||||
return AM_SRAM_STATUS_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (dst > amSram.m_size.QuadPart - amSram.m_sectorSize || dst + size > amSram.m_size.QuadPart) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("Address range is invalid. Dst=0x%08x Size=0x%08x", dst, size);
|
||||
|
||||
return AM_SRAM_STATUS_ERR_DOMAIN;
|
||||
}
|
||||
|
||||
DWORD err = WaitForSingleObject(amSram.m_mutex, amSram.m_readTimeout);
|
||||
if (err == WAIT_FAILED) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
if (err == WAIT_TIMEOUT) return AM_SRAM_STATUS_ERR_GET_MUTEX;
|
||||
|
||||
if (!(err == WAIT_OBJECT_0 || err == WAIT_ABANDONED)) {
|
||||
if (amSramDebugLevel > 0)
|
||||
amiDebugLog("WaitForSingleObject Error(%ld). Return Value is %d.", GetLastError(),
|
||||
err);
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
|
||||
AM_SRAM_STATUS status = amSramWriteInternal(&amSram, dst, 0, pSrc, size);
|
||||
if (!ReleaseMutex(amSram.m_mutex)) {
|
||||
if (amSramDebugLevel > 0) amiDebugLog("ReleaseMutex Error(%ld).", GetLastError());
|
||||
return AM_SRAM_STATUS_ERR_SYS;
|
||||
}
|
||||
return status;
|
||||
}
|
56
src/micetools/lib/am/amSram.h
Normal file
56
src/micetools/lib/am/amSram.h
Normal file
@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amSram, AM_SRAM)
|
||||
|
||||
typedef struct _AM_SRAM {
|
||||
DWORD m_init;
|
||||
HANDLE m_handle;
|
||||
LARGE_INTEGER m_size;
|
||||
DWORD m_sectorSize;
|
||||
HANDLE m_mutex;
|
||||
int m_readTimeout;
|
||||
int m_writeTimeout;
|
||||
int Unk20;
|
||||
PSID m_sid;
|
||||
} AM_SRAM;
|
||||
|
||||
typedef enum {
|
||||
AM_SRAM_STATUS_OK = 0,
|
||||
AM_SRAM_STATUS_NG = -1,
|
||||
AM_SRAM_STATUS_ERR_INVALID_PARAM = -2,
|
||||
AM_SRAM_STATUS_ERR_NO_INIT = -3,
|
||||
AM_SRAM_STATUS_ERR_ALREADY_INIT = -4,
|
||||
AM_SRAM_STATUS_ERR_PROTOCOL_VER = -5,
|
||||
AM_SRAM_STATUS_ERR_SYS = -6,
|
||||
AM_SRAM_STATUS_ERR_READ = -7,
|
||||
AM_SRAM_STATUS_ERR_WRITE = -8,
|
||||
AM_SRAM_STATUS_ERR_COPY = -9,
|
||||
AM_SRAM_STATUS_ERR_DOMAIN = -10,
|
||||
AM_SRAM_STATUS_ERR_GET_MUTEX = -11,
|
||||
AM_SRAM_STATUS_ERR_NOT_SUPPORT = -12,
|
||||
} AM_SRAM_STATUS;
|
||||
|
||||
#define AM_SRAM_MAX_SECTOR_SIZE 0x800
|
||||
|
||||
AM_SRAM_STATUS amSramCreateMutex(AM_SRAM *device);
|
||||
AM_SRAM_STATUS amSramInit(void);
|
||||
AM_SRAM_STATUS amSramExit(void);
|
||||
|
||||
AM_SRAM_STATUS amSramReadInternal(AM_SRAM *device, LONG addressLow, LONG addressHigh, LPVOID buffer,
|
||||
DWORD nBytes);
|
||||
AM_SRAM_STATUS amSramWriteInternal(AM_SRAM *device, LONG addressLow, LONG addressHigh,
|
||||
LPCVOID buffer, DWORD nBytes);
|
||||
|
||||
AM_SRAM_STATUS amSramRead(DWORD src, LPVOID pDst, DWORD size);
|
||||
AM_SRAM_STATUS amSramWrite(LPCVOID pSrc, DWORD dst, DWORD size);
|
||||
|
||||
// TODO:
|
||||
|
||||
void amSramCopy(void);
|
||||
void amSramGetSectorSize(void);
|
||||
void amSramGetSize(void);
|
||||
void amSramSetTimeout(void);
|
25
src/micetools/lib/am/amStorage.h
Normal file
25
src/micetools/lib/am/amStorage.h
Normal file
@ -0,0 +1,25 @@
|
||||
void amStorageBsGetCount(void);
|
||||
void amStorageBsGetIdentify(void);
|
||||
void amStorageBsGetSmartData(void);
|
||||
void amStorageBsIsBuStarage(void);
|
||||
void amStorageBsRequestHwReset(void);
|
||||
void amStorageBsRequestUnlock(void);
|
||||
void amStorageBusy(void);
|
||||
void amStorageGetDriveLetter(void);
|
||||
void amStorageGetStorageCount(void);
|
||||
void amStorageGetStorageInfo(void);
|
||||
void amStorageGetVolume(void);
|
||||
void amStorageInit(void);
|
||||
void amStorageOpenBinary(void);
|
||||
void amStorageOpenEx(void);
|
||||
void amStorageRequestCheck(void);
|
||||
void amStorageRequestFormat(void);
|
||||
void amStorageRequestMount(void);
|
||||
void amStorageRequestUnmountByDriveLetter(void);
|
||||
void amStorageRequestUnmountByStorageId(void);
|
||||
void amStorageResponseCheck(void);
|
||||
void amStorageSendAndRecvEx(void);
|
||||
void amStorageSendRequest(void);
|
||||
void amStorageSetVolume(void);
|
||||
void amStorageTaskRequest(void);
|
||||
void amStorageWaitReady(void);
|
12
src/micetools/lib/am/amSysData.h
Normal file
12
src/micetools/lib/am/amSysData.h
Normal file
@ -0,0 +1,12 @@
|
||||
typedef struct {
|
||||
unsigned short m_Year;
|
||||
unsigned char m_Month;
|
||||
unsigned char m_Day;
|
||||
unsigned char m_Hour;
|
||||
unsigned char m_Minute;
|
||||
unsigned char m_Second;
|
||||
unsigned char Rsv07[1];
|
||||
} AM_SYSDATA_TIMESTAMP;
|
||||
|
||||
void amSysDataGetDotClockTiming(void);
|
||||
void amSysDataGetOsVersionString(void);
|
@ -1,19 +0,0 @@
|
||||
#include <amTimer.h>
|
||||
|
||||
int frequency_loaded = 0;
|
||||
LARGE_INTEGER frequency;
|
||||
|
||||
amtime_t* amiTimerGet(amtime_t* time) {
|
||||
LARGE_INTEGER counter;
|
||||
|
||||
if (time == NULL) return NULL;
|
||||
|
||||
if (frequency_loaded == 0) {
|
||||
QueryPerformanceFrequency(&frequency);
|
||||
frequency_loaded = 1;
|
||||
}
|
||||
QueryPerformanceCounter(&counter);
|
||||
time->microseconds = (unsigned int)((counter.QuadPart * 1000000) / frequency.QuadPart);
|
||||
time->seconds = (unsigned int)(counter.QuadPart / frequency.QuadPart);
|
||||
return time;
|
||||
}
|
@ -1,10 +1,70 @@
|
||||
amlib = static_library(
|
||||
'am',
|
||||
amOemstring = static_library(
|
||||
'amOemstring',
|
||||
sources: [
|
||||
'amOemstring.c',
|
||||
],
|
||||
)
|
||||
|
||||
amEeprom = static_library(
|
||||
'amEeprom',
|
||||
sources: [
|
||||
'amTimer.c',
|
||||
'amEeprom.c',
|
||||
],
|
||||
link_with: [
|
||||
mice_lib
|
||||
amiDebug,
|
||||
amiCrc,
|
||||
],
|
||||
)
|
||||
|
||||
amSram = static_library(
|
||||
'amSram',
|
||||
sources: [
|
||||
'amSram.c',
|
||||
],
|
||||
link_with: [
|
||||
amiDebug,
|
||||
],
|
||||
)
|
||||
|
||||
amPlatform = static_library(
|
||||
'amPlatform',
|
||||
sources: [
|
||||
'amPlatform.c',
|
||||
],
|
||||
link_with: [
|
||||
amiDebug,
|
||||
amSram,
|
||||
amEeprom,
|
||||
],
|
||||
)
|
||||
|
||||
amDongle = static_library(
|
||||
'amDongle',
|
||||
sources: [
|
||||
'amDongle.c',
|
||||
],
|
||||
link_with: [
|
||||
amiDebug,
|
||||
util_lib,
|
||||
libpcp,
|
||||
],
|
||||
)
|
||||
|
||||
amSerialId = static_library(
|
||||
'amSerialId',
|
||||
sources: [
|
||||
'amSerialId.c',
|
||||
],
|
||||
)
|
||||
|
||||
amInstall = static_library(
|
||||
'amInstall',
|
||||
sources: [
|
||||
'amInstall.c',
|
||||
],
|
||||
link_with: [
|
||||
amiDebug,
|
||||
util_lib,
|
||||
libpcp,
|
||||
],
|
||||
)
|
||||
|
5
src/micetools/lib/ami/ami.h
Normal file
5
src/micetools/lib/ami/ami.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "amiCrc.h"
|
||||
#include "amiDebug.h"
|
||||
#include "amiTimer.h"
|
30
src/micetools/lib/ami/amiCrc.c
Normal file
30
src/micetools/lib/ami/amiCrc.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "amiCrc.h"
|
||||
|
||||
#define CRC32_POLYNOMIAL 0xedb88320
|
||||
|
||||
AM_LIB_C_HEADER(amiCrc, AMI_CRC)
|
||||
|
||||
void amiCrc32RCreateTable(unsigned int *table) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
unsigned int value = (~i & 1) - 1 & CRC32_POLYNOMIAL;
|
||||
value = ((i >> 1 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 2 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 3 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 4 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 5 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = ((i >> 6 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
table[0] = ((i >> 7 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
table++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
|
||||
unsigned int initial) {
|
||||
unsigned int value = ~initial;
|
||||
while (length > 0) {
|
||||
value = value >> 8 ^ table[(data[0] ^ value) & 0xff];
|
||||
length += -1;
|
||||
data++;
|
||||
}
|
||||
return ~value;
|
||||
}
|
24
src/micetools/lib/ami/amiCrc.h
Normal file
24
src/micetools/lib/ami/amiCrc.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "../_am.h"
|
||||
|
||||
AM_LIB_H_HEADER(amiCrc, AMI_CRC)
|
||||
|
||||
typedef struct _AMI_CRC {
|
||||
unsigned int m_init;
|
||||
unsigned int m_table[256];
|
||||
} AMI_CRC;
|
||||
|
||||
void amiCrc32RCreateTable(unsigned int *table);
|
||||
unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data,
|
||||
unsigned int initial);
|
||||
|
||||
#define amCrc32RCreateTable() \
|
||||
do { \
|
||||
if (!amiCrc.m_init) { \
|
||||
amiCrc32RCreateTable(amiCrc.m_table); \
|
||||
amiCrc.m_init = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
#define amCrc32RGet(length, data, initial) \
|
||||
amiCrc32RGet(amiCrc.m_table, (length), (data), (initial))
|
0
src/micetools/lib/ami/amiCri.h
Normal file
0
src/micetools/lib/ami/amiCri.h
Normal file
54
src/micetools/lib/ami/amiDebug.c
Normal file
54
src/micetools/lib/ami/amiDebug.c
Normal file
@ -0,0 +1,54 @@
|
||||
#include "amiDebug.h"
|
||||
|
||||
#include "../mice/mice.h"
|
||||
|
||||
AM_LIB_C_HEADER(amiDebug, AM_DEBUG)
|
||||
|
||||
FILE* amiDebugFile;
|
||||
amiDebugCallback_t* amiDebugCallback;
|
||||
|
||||
int amiDebugVprintf(LPCSTR format, va_list args) {
|
||||
if (amiDebugCallback == NULL) {
|
||||
return vfprintf_s(amiDebugFile ? amiDebugFile : stderr, format, args);
|
||||
}
|
||||
|
||||
char buffer[1024];
|
||||
vsnprintf_s(buffer, sizeof buffer, sizeof buffer - 1, format, args);
|
||||
return (*amiDebugCallback)(buffer);
|
||||
}
|
||||
|
||||
int amiDebugPrintf(LPCSTR format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = amiDebugVprintf(format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int amiDebugVprintfEx(LPCSTR caller, DWORD line, LPCSTR format, va_list args) {
|
||||
char buf[1024];
|
||||
|
||||
int prefixLength = _snprintf_s(buf, sizeof buf, sizeof buf - 1, "%s: Line%d ", caller, line);
|
||||
if (amiDebugCallback == NULL) {
|
||||
FILE* file = amiDebugFile ? amiDebugFile : stderr;
|
||||
if (-1 < fprintf_s(file, "%s", buf)) {
|
||||
return vfprintf_s(file, format, args);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
vsnprintf_s(buf + prefixLength, sizeof buf - prefixLength, (sizeof buf - 1) - prefixLength,
|
||||
format, args);
|
||||
return (*amiDebugCallback)(buf);
|
||||
}
|
||||
|
||||
int amiDebugPrintfEx(LPCSTR caller, DWORD line, LPCSTR format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = amiDebugVprintfEx(caller, line, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amiDebugSetFile(FILE* file) { amiDebugFile = file; }
|
||||
void amiDebugSetCallback(amiDebugCallback_t* callback) { amiDebugCallback = callback; }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user