proto parsing + weirdness highlight
This commit is contained in:
parent
5815df6c16
commit
03ad2693ce
4
Makefile
4
Makefile
|
@ -3,8 +3,8 @@ all: libftfake.so dumpee libsqfake.so ftdidrv
|
|||
libsqfake.so: libsqfake.c
|
||||
$(CC) -shared -fPIC -Wall -Wextra -Wno-unused-parameter -std=gnu11 -pipe -o $@ $<
|
||||
|
||||
libftfake.so: libftfake.c
|
||||
$(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra
|
||||
libftfake.so: libftfake.c libftfake_hl.h
|
||||
$(CC) -shared -fPIC -o "$@" "$<" -I. -ldl -Wall -Wextra -lm
|
||||
|
||||
dumpee: dumpee.c
|
||||
$(CC) -o "$@" "$<" -L../build/ -I. -lftd2xx -Wl,-rpath=../build -Wall -Wextra
|
||||
|
|
34
libftfake.c
34
libftfake.c
|
@ -8,6 +8,9 @@
|
|||
|
||||
#include "ftd2xx.h"
|
||||
|
||||
#define HIGHLEVEL
|
||||
#include "libftfake_hl.h"
|
||||
|
||||
static void* libftd2xx;
|
||||
static void lib_open(void) {
|
||||
static bool opened = false;
|
||||
|
@ -74,7 +77,9 @@ FT_STATUS FT_GetBitMode(FT_HANDLE ftHandle, PUCHAR pucMode) {
|
|||
FT_STATUS FT_GetQueueStatus(FT_HANDLE ftHandle, DWORD* dwRxBytes) {
|
||||
bind(FT_STATUS, (FT_HANDLE, DWORD*), ftHandle, dwRxBytes);
|
||||
// responsible for lots of spam
|
||||
#ifndef HIGHLEVEL
|
||||
printf("FT_GetSqueueStatus(%p, &0x%x) = %d\n", ftHandle, *dwRxBytes, rv);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -84,6 +89,7 @@ FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) {
|
|||
// * fn(nulterm array to strings, &numdevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER)
|
||||
// * fn(null??, charbuf, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER);
|
||||
// * fn(numdev, NULL, FT_LIST_NUMBER_ONLY);
|
||||
#ifndef HIGHLEVEL
|
||||
printf("FT_ListDevices(%p, %p, 0x%08x) = %d\n", pArg1, pArg2, flags, rv);
|
||||
if (flags & FT_LIST_NUMBER_ONLY) {
|
||||
if (pArg2) printf(" W! pArg2 != null!\n");
|
||||
|
@ -102,6 +108,7 @@ FT_STATUS FT_ListDevices(PVOID pArg1, PVOID pArg2, DWORD flags) {
|
|||
} else if (flags & FT_LIST_BY_INDEX) {
|
||||
printf(" W! FT_LIST_BY_INDEX not impl\n");
|
||||
} else printf(" W! unk flags!\n");
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -120,9 +127,21 @@ FT_STATUS FT_OpenEx(PVOID pArg1, DWORD flags, FT_HANDLE* pHandle) {
|
|||
FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpBytesReturned) {
|
||||
bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD),
|
||||
ftHandle, lpBuffer, dwBytesToRead, lpBytesReturned);
|
||||
printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv);
|
||||
if (dwBytesToRead != *lpBytesReturned) printf("\tW: AAAAAAAAAA size mismatch\n");
|
||||
size_t nb = *lpBytesReturned;
|
||||
if (nb < 0x100) {
|
||||
#ifndef HIGHLEVEL
|
||||
printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv);
|
||||
#endif
|
||||
if (nb <
|
||||
#ifndef HIGHLEVEL
|
||||
0x100
|
||||
#else
|
||||
0x10
|
||||
#endif
|
||||
) {
|
||||
#ifdef HIGHLEVEL
|
||||
printf("FT_Read(%p, %p, 0x%x, &0x%x) = %d\n", ftHandle, lpBuffer, dwBytesToRead, *lpBytesReturned, rv);
|
||||
#endif
|
||||
printf(" ");
|
||||
size_t i;
|
||||
for (i = 0; i < nb; ++i) {
|
||||
|
@ -132,6 +151,9 @@ FT_STATUS FT_Read(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDW
|
|||
}
|
||||
if ((i & 15)) printf("\n");
|
||||
}
|
||||
#ifdef HIGHLEVEL
|
||||
ftfake_cb(lpBuffer, nb);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -161,13 +183,16 @@ FT_STATUS FT_SetUSBParameters(FT_HANDLE ftHandle, ULONG inxfersz, ULONG outxfers
|
|||
|
||||
FT_STATUS FT_SetVIDPID(DWORD dwVid, DWORD dwPid) {
|
||||
bind(FT_STATUS, (DWORD, DWORD), dwVid, dwPid);
|
||||
#ifndef HIGHLEVEL
|
||||
printf("FT_SetVIDPID(0x%04x, 0x%04x) = %d\n", dwVid, dwPid, rv);
|
||||
#endif
|
||||
return rv;
|
||||
}
|
||||
|
||||
FT_STATUS FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD len, LPDWORD written) {
|
||||
bind(FT_STATUS, (FT_HANDLE, LPVOID, DWORD, LPDWORD), ftHandle, lpBuffer, len, written);
|
||||
printf("FT_Write(%p, %p, 0x%x, &0x%0x) = %d\n", ftHandle, lpBuffer, len, *written, rv);
|
||||
if (*written != len) printf("\tW: AAAAAAAAAAAAAAAA size mismatch\n");
|
||||
size_t nb = *written;
|
||||
if (nb < 0x100) {
|
||||
printf(" ");
|
||||
|
@ -179,6 +204,11 @@ FT_STATUS FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD len, LPDWORD writt
|
|||
}
|
||||
if ((i & 15)) printf("\n");
|
||||
}
|
||||
|
||||
#ifdef HIGHLEVEL
|
||||
ftfake_parsehl(lpBuffer, nb);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
|
||||
#ifndef LIBFTFAKE_HL_H_
|
||||
#define LIBFTFAKE_HL_H_
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define WARNSTR "\x1b[1;31mW:\x1b[0m "
|
||||
|
||||
__attribute__((__packed__))
|
||||
struct settings {
|
||||
uint8_t norm_or_pwIsMicrosec;
|
||||
uint8_t clockfreq[2];
|
||||
uint8_t pw_trigscale[2];
|
||||
uint8_t ms1[3];
|
||||
uint8_t ms2[3];
|
||||
uint8_t ms3_ioflg[3];
|
||||
uint8_t unk00;
|
||||
uint8_t ntrigsteps;
|
||||
uint8_t unkf0;
|
||||
uint8_t unk0f;
|
||||
uint8_t capgenchans;
|
||||
uint8_t voltage[2];
|
||||
uint8_t unk32;
|
||||
uint8_t nabort;
|
||||
uint8_t abort;
|
||||
};
|
||||
|
||||
struct trigstep_nice {
|
||||
bool ch_ignore[4];
|
||||
bool use_max_pw, use_min_pw;
|
||||
bool ch_hiri1_lofa0[4];
|
||||
bool level1_edge0;
|
||||
uint16_t pw_min, pw_max;
|
||||
bool unkB2b3, unkB2b4, unkB3b6; // bit index: bytevalofsinglebit = 1<<bitindex
|
||||
};
|
||||
|
||||
enum state {
|
||||
normal,
|
||||
incapreadout,
|
||||
ingenupload,
|
||||
scwftres3,
|
||||
scwftres1
|
||||
};
|
||||
|
||||
static enum state state = normal;
|
||||
static size_t capsize = 0, gensize = 0;
|
||||
|
||||
static void state_tonorm(void) {
|
||||
state = normal;
|
||||
capsize = 0;
|
||||
gensize = 0;
|
||||
}
|
||||
|
||||
static void ftfake_parsehl(void* buf_, size_t len) {
|
||||
uint8_t* buf = (uint8_t*)buf_;
|
||||
|
||||
if (state == incapreadout) {
|
||||
printf("\tcapture size: 0x%zx\n", capsize);
|
||||
state_tonorm();
|
||||
} else if (state == ingenupload) {
|
||||
if (len > 0x20) {
|
||||
gensize += len;
|
||||
return;
|
||||
} else {
|
||||
printf("\tgenerate size: 0x%zx\n", gensize);
|
||||
state_tonorm();
|
||||
}
|
||||
}
|
||||
|
||||
switch (buf[0]) {
|
||||
case 0x93:printf("\t->application\n");break;
|
||||
case 0x94:printf("\t->bootloader\n");break;
|
||||
case 0xf0:
|
||||
switch (buf[1]) {
|
||||
case 0x00:printf("\tcapture reset\n");break;
|
||||
case 0x01:
|
||||
printf("\tstart capt/WFT\n");
|
||||
state = scwftres3;
|
||||
break;
|
||||
case 0x02:printf("\tsiggen start repeat\n");break;
|
||||
case 0x03:
|
||||
printf("\tmixed-mode sfc/wft\n");
|
||||
state=scwftres3;
|
||||
break;
|
||||
case 0x05:
|
||||
printf("\tstart gendata dl\n");
|
||||
if (buf[2]!=0xf3)printf("\t" WARNSTR "unk arg2 0x%02x\n", buf[2]);
|
||||
state = ingenupload;
|
||||
gensize = 0;
|
||||
break;
|
||||
case 0x06:
|
||||
printf("\tstart read\n");
|
||||
state = incapreadout;
|
||||
capsize = 0;
|
||||
break;
|
||||
case 0x07:printf("\tsiggen start once\n");break;
|
||||
default:printf("\t" WARNSTR "unk 0xf0 arg 0x%02x!\n", buf[1]);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 0xf1:
|
||||
if (len == 27) {
|
||||
printf("\teep magic 0x%02x 0x%02x 0x%02x\n",
|
||||
buf[1],buf[2],buf[3]);
|
||||
} else if (len == 25) {
|
||||
struct settings sett = *(struct settings*)&buf[1]; // hacks
|
||||
bool weird = sett.unk00 != 0x00 || sett.unkf0 != 0xf0 || sett.unk0f != 0x0f
|
||||
|| sett.unk32 != 0x32 || sett.nabort != 0x01 || sett.abort != 0x00
|
||||
|| (sett.capgenchans&0xf)!=0xf
|
||||
|| (sett.norm_or_pwIsMicrosec != 0x09 && sett.norm_or_pwIsMicrosec != 0x01);
|
||||
uint8_t ioflg = sett.ms3_ioflg[2] & 0xf0; // MSB high nibble ORed with the inverse of nibble M at loc 0x12
|
||||
if (((uint8_t)ioflg ^ (uint8_t)(sett.capgenchans & 0xf0)) != 0xf0)
|
||||
weird = true;
|
||||
float freq = 100000.0f / *(uint16_t*)&sett.clockfreq[0];
|
||||
char normpw = '?';
|
||||
if (sett.norm_or_pwIsMicrosec == 0x09) normpw = 'P';
|
||||
if (sett.norm_or_pwIsMicrosec == 0x01) normpw = 'n';
|
||||
uint32_t ms1 = *(uint32_t*)&sett.ms1[0] & 0x00ffffff;
|
||||
uint32_t ms2 = *(uint32_t*)&sett.ms2[0] & 0x00ffffff;
|
||||
uint32_t ms3 = *(uint32_t*)&sett.ms3_ioflg[0] & 0x000fffff;
|
||||
printf("\t%ssettings:\n", weird ? WARNSTR : "");
|
||||
printf("\t freq=%d kHz #tsteps=%hhu trigscale=0x%04x pwmicro=%c genmap=%c%c%c%c:%x(%x)\n",
|
||||
(int)freq, sett.ntrigsteps, *(uint16_t*)&sett.pw_trigscale[0], normpw,
|
||||
(sett.capgenchans & 0x10)?'1':'-',
|
||||
(sett.capgenchans & 0x20)?'2':'-',
|
||||
(sett.capgenchans & 0x40)?'3':'-',
|
||||
(sett.capgenchans & 0x80)?'4':'-',
|
||||
sett.capgenchans&0xf,ioflg>>4
|
||||
);
|
||||
printf("\t ms1=0x%06x ms2=0x%06x ms3=0x%06x\n", ms1, ms2, ms3);
|
||||
float volt = 0.1f*roundf((sett.voltage[0] / 39.2f) * 10.0f);
|
||||
printf("\t voltage=%.1f unk00=%x unkf0=%02x unk0f=%02x unk32=%02x nabort=%x abort=%x\n",
|
||||
volt, sett.unk00, sett.unkf0, sett.unk0f, sett.unk32, sett.nabort, sett.abort);
|
||||
} else {
|
||||
printf("\t" WARNSTR "0xF1 formatting unknown!\n");
|
||||
} break;
|
||||
case 0xf4: {
|
||||
size_t nst = (len - 1) >> 2;
|
||||
printf("\ttrigger: %zu steps\n", nst);
|
||||
for (size_t i = 0; i < nst; ++i) {
|
||||
size_t ind = 1 + i * 4;
|
||||
|
||||
struct trigstep_nice step;
|
||||
step.ch_ignore[0] = buf[ind+0] & 0x40;
|
||||
step.ch_ignore[1] = buf[ind+0] & 0x80;
|
||||
step.ch_ignore[2] = buf[ind+1] & 0x01;
|
||||
step.ch_ignore[3] = buf[ind+1] & 0x02;
|
||||
|
||||
step.use_max_pw = !(buf[ind+0] & 0x20);
|
||||
step.use_min_pw = !(buf[ind+0] & 0x10);
|
||||
|
||||
step.ch_hiri1_lofa0[0] = buf[ind+0] & 0x01;
|
||||
step.ch_hiri1_lofa0[1] = buf[ind+0] & 0x02;
|
||||
step.ch_hiri1_lofa0[2] = buf[ind+0] & 0x04;
|
||||
step.ch_hiri1_lofa0[3] = buf[ind+0] & 0x08;
|
||||
|
||||
step.pw_min = ((buf[ind+1] & 0xf8) >> 3) | ((uint16_t)(buf[ind+2] & 0x07) << 5);
|
||||
step.pw_max = ((buf[ind+2] & 0xe0) >> 5) | ((uint16_t)(buf[ind+3] & 0x3f) << 3);
|
||||
|
||||
step.level1_edge0 = buf[ind+3] & 0x80;
|
||||
|
||||
step.unkB2b3 = buf[ind+2] & (1<<3);
|
||||
step.unkB2b4 = buf[ind+2] & (1<<4);
|
||||
step.unkB3b6 = buf[ind+3] & (1<<6);
|
||||
|
||||
printf("\t");
|
||||
if (step.unkB2b3 || step.unkB2b4 || step.unkB3b6) printf(WARNSTR);
|
||||
printf(" chans %c%c%c%c :: %s %s %s %s %s minpw=%d maxpw=%d",
|
||||
(step.ch_ignore[0]?'-':'1'),
|
||||
(step.ch_ignore[1]?'-':'2'),
|
||||
(step.ch_ignore[2]?'-':'3'),
|
||||
(step.ch_ignore[3]?'-':'4'),
|
||||
|
||||
(step.ch_ignore[0]?"-":(step.ch_hiri1_lofa0[0]?"hiri":"lofa")),
|
||||
(step.ch_ignore[1]?"-":(step.ch_hiri1_lofa0[1]?"hiri":"lofa")),
|
||||
(step.ch_ignore[2]?"-":(step.ch_hiri1_lofa0[2]?"hiri":"lofa")),
|
||||
(step.ch_ignore[3]?"-":(step.ch_hiri1_lofa0[3]?"hiri":"lofa")),
|
||||
|
||||
step.level1_edge0 ? "level" : "edge",
|
||||
step.use_min_pw ? (int)step.pw_min : (-1),
|
||||
step.use_max_pw ? (int)step.pw_max : (-1)
|
||||
);
|
||||
if (step.unkB2b3) printf(" uB2b3!");
|
||||
if (step.unkB2b4) printf(" uB2b4!");
|
||||
if (step.unkB3b6) printf(" uB3b6!");
|
||||
printf("\n");
|
||||
}
|
||||
} break;
|
||||
case 0xfd:printf("\techo status\n");break;
|
||||
default:
|
||||
printf("\t" WARNSTR "unknown command 0x%02x!\n", buf[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ftfake_cb(void* buf_, size_t len) {
|
||||
uint8_t* buf = (uint8_t*)buf_;
|
||||
|
||||
switch (state) {
|
||||
case incapreadout:
|
||||
capsize += len;
|
||||
break;
|
||||
/*case ingenupload:
|
||||
gensize += len;
|
||||
break;*/
|
||||
case scwftres3: {
|
||||
uint32_t trig_instant = (uint32_t)buf[0] | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2]<<16);
|
||||
printf("\ttrig_instant=0x%06x\n", trig_instant);
|
||||
++state; // to scfwres1
|
||||
} break;
|
||||
case scwftres1:
|
||||
printf("\t%sscwftres = 0x%02x\n", (buf[0] == 0xdd ? "" : WARNSTR), buf[0]);
|
||||
state_tonorm();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue