diff --git a/.vscode/settings.json b/.vscode/settings.json index e92bb91..db4aa61 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,6 +29,14 @@ "hidclass.h": "c", "winusb.h": "c", "setupapi.h": "c", - "table.h": "c" + "table.h": "c", + "k9101258.h": "c", + "iobuf.h": "c", + "spike.h": "c", + "dvd.h": "c", + "hoshi-dll.h": "c", + "usbio.h": "c", + "iohook.h": "c", + "jvs-cmd.h": "c" } } \ No newline at end of file diff --git a/Package.mk b/Package.mk index ef9cf3c..d101d16 100644 --- a/Package.mk +++ b/Package.mk @@ -10,8 +10,7 @@ $(BUILD_DIR_ZIP)/siva.zip: $(BUILD_DIR_ZIP)/siva $(V)mv $(BUILD_DIR_ZIP)/siva/iDmacDrv.dll \ $(BUILD_DIR_ZIP)/siva/iDmacDrv64.dll - $(V)cp pki/client.cer \ - pki/client.p12 \ + $(V)cp pki/client.p12 \ $(BUILD_DIR_ZIP)/siva $(V)strip $(BUILD_DIR_ZIP)/siva/*.{exe,dll} $(V)cd $(BUILD_DIR_ZIP)/siva ; zip -r ../siva.zip * diff --git a/board/io3.c b/board/io3.c index 648d1da..91bd632 100644 --- a/board/io3.c +++ b/board/io3.c @@ -220,7 +220,7 @@ static HRESULT io3_cmd( case JVS_CMD_READ_ANALOGS: return io3_cmd_read_analogs(io3, req, resp); - case JVS_CMD_WRITE_GPIO: + case JVS_CMD_WRITE_GPIO1: return io3_cmd_write_gpio(io3, req, resp); case JVS_CMD_RESET: diff --git a/board/j9100628a.c b/board/j9100628a.c deleted file mode 100644 index 9385be6..0000000 --- a/board/j9100628a.c +++ /dev/null @@ -1,487 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "board/j9100628a.h" - -#include "jvs/jvs-bus.h" -#include "jvs/jvs-cmd.h" -#include "jvs/jvs-util.h" - -#include "util/dprintf.h" -#include "util/dump.h" - -// JVS card reader - -static const uint8_t j9100628a_ident[] = "taito;JVS-Reader;Ver1.00;JPN,Multipurpose"; - -static uint8_t j9100628a_features[] = { - /* Feature : 0x01 : Players and switches - Param1 : 1 : Number of players - Param2 : 18 : Number of switches per player - Param3 : 0 : N/A */ - - 0x01, - 0x01, - 0x18, - 0x00, - - /* Feature : 0x02 : Coin slots - Param1 : 2 : Number of coin slots - Param2 : 0 : N/A - Param3 : 0 : N/A */ - - 0x02, - 0x00, - 0x00, - 0x00, - - /* Feature : 0x03 : Analog inputs - Param1 : 8 : Number of ADC channels - Param2 : 10 : Effective bits of resolution per ADC - Param3 : 0 : N/A */ - - 0x03, - 0x00, - 0x00, - 0x00, - - /* Feature : 0x04 : Rotary Input - Param1 : 4 : Number of Rotary channels - Param2 : 0 : N/A - Param3 : 0 : N/A */ - - 0x04, - 0x00, - 0x00, - 0x00, - - /* Feature : 0x12 : GPIO outputs - Param1 : 3 : Number of ports (8 bits per port) - Param2 : 0 : N/A - Param3 : 0 : N/A - */ - - 0x12, - 0x00, - 0x00, - 0x00, - - /* Feature : 0x13 : Analog outputs - Param1 : 2 : Number of channels - Param2 : 0 : N/A - Param3 : 0 : N/A - */ - - 0x13, - 0x00, - 0x00, - 0x00, - - /* Feature : 0x14 : Character Output - Param1 : 0x50 : Width - Param2 : 0x19 : Height - Param3 : 0 : Type - */ - 0x14, - 0x50, - 0x19, - 0x00, - - /* Feature : 0x00 : End of capabilities */ - - 0x00, -}; - -static void j9100628a_transact( - struct jvs_node *node, - const void *bytes, - size_t nbytes, - struct iobuf *resp); - -static bool j9100628a_sense(struct jvs_node *node); - -static HRESULT j9100628a_cmd( - void *ctx, - struct const_iobuf *req, - struct iobuf *resp); - -static HRESULT j9100628a_cmd_reset(struct j9100628a *j9100628a, struct const_iobuf *req_buf); -static HRESULT j9100628a_cmd_assign_addr(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_read_id(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_get_cmd_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_get_jvs_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_get_comm_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_get_features(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_read_misc_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_read_dip_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); -static HRESULT j9100628a_cmd_write_gpio(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf); - -void j9100628a_init( - struct j9100628a *j9100628a, - struct jvs_node *next, - const struct j9100628a_ops *ops, - void *ops_ctx) -{ - assert(j9100628a != NULL); - assert(ops != NULL); - - j9100628a->jvs.next = next; - j9100628a->jvs.transact = j9100628a_transact; - j9100628a->jvs.sense = j9100628a_sense; - j9100628a->jvs.sense_out = true; - j9100628a->addr = 0xFF; - j9100628a->ops = ops; - j9100628a->ops_ctx = ops_ctx; -} - -struct jvs_node *j9100628a_to_jvs_node(struct j9100628a *j9100628a) -{ - assert(j9100628a != NULL); - - return &j9100628a->jvs; -} - -static void j9100628a_transact( - struct jvs_node *node, - const void *bytes, - size_t nbytes, - struct iobuf *resp) -{ - struct j9100628a *j9100628a; - - assert(node != NULL); - assert(bytes != NULL); - assert(resp != NULL); - - j9100628a = CONTAINING_RECORD(node, struct j9100628a, jvs); - - jvs_crack_request(bytes, nbytes, resp, j9100628a->addr, j9100628a_cmd, j9100628a); -} - -static bool j9100628a_sense(struct jvs_node *node) -{ - struct j9100628a *j9100628a; - - assert(node != NULL); - - j9100628a = CONTAINING_RECORD(node, struct j9100628a, jvs); - - return j9100628a->addr == 0xFF; -} - -static HRESULT j9100628a_cmd( - void *ctx, - struct const_iobuf *req, - struct iobuf *resp) -{ - struct j9100628a *j9100628a; - - j9100628a = ctx; - - switch (req->bytes[req->pos]) { - case JVS_CMD_RESET: - return j9100628a_cmd_reset(j9100628a, req); - - case JVS_CMD_ASSIGN_ADDR: - return j9100628a_cmd_assign_addr(j9100628a, req, resp); - - case JVS_CMD_READ_ID: - return j9100628a_cmd_read_id(j9100628a, req, resp); - - case JVS_CMD_GET_CMD_VERSION: - return j9100628a_cmd_get_cmd_version(j9100628a, req, resp); - - case JVS_CMD_GET_JVS_VERSION: - return j9100628a_cmd_get_jvs_version(j9100628a, req, resp); - - case JVS_CMD_GET_COMM_VERSION: - return j9100628a_cmd_get_comm_version(j9100628a, req, resp); - - case JVS_CMD_GET_FEATURES: - return j9100628a_cmd_get_features(j9100628a, req, resp); - - case JVS_CMD_READ_MISC_SWITCHES: - return j9100628a_cmd_read_misc_switches(j9100628a, req, resp); - - case JVS_CMD_TYPEX_READ_DIPSW: - return j9100628a_cmd_read_dip_switches(j9100628a, req, resp); - - case JVS_CMD_TYPEX_POLL_AMIC: - // FIXME: seperate func - return j9100628a_cmd_read_dip_switches(j9100628a, req, resp); - - case JVS_CMD_WRITE_GPIO: - return j9100628a_cmd_write_gpio(j9100628a, req, resp); - - default: - dprintf("J9100628A: Node %02x: Unhandled command byte %02x\n", - j9100628a->addr, - req->bytes[req->pos]); - - return E_NOTIMPL; - } - - return S_OK; -} - -static HRESULT j9100628a_cmd_reset(struct j9100628a *j9100628a, struct const_iobuf *req_buf) -{ - struct jvs_req_reset req; - HRESULT hr; - - hr = iobuf_read(req_buf, &req, sizeof(req)); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Reset (param %02x)\n", req.unknown); - j9100628a->addr = 0xFF; - j9100628a->jvs.sense_out = false; // ? - - if (j9100628a->ops->reset != NULL) { - j9100628a->ops->reset(j9100628a->ops_ctx); - } - - /* No ack for this since it really is addressed to everybody */ - - return S_OK; -} - -static HRESULT j9100628a_cmd_assign_addr( - struct j9100628a *j9100628a, - struct const_iobuf *req_buf, - struct iobuf *resp_buf) -{ - struct jvs_req_assign_addr req; - bool sense; - HRESULT hr; - - hr = iobuf_read(req_buf, &req, sizeof(req)); - - if (FAILED(hr)) { - return hr; - } - - sense = jvs_node_sense(j9100628a->jvs.next); - dprintf("J9100628A: Assign addr %02x sense %i\n", req.addr, sense); - - if (sense) { - /* That address is for somebody else */ - return S_OK; - } - - j9100628a->addr = req.addr; - j9100628a->jvs.sense_out = true; - - return iobuf_write_8(resp_buf, 0x01); -} - -static HRESULT j9100628a_cmd_read_id(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Read ID\n"); - - /* Write report byte */ - - hr = iobuf_write_8(resp_buf, 0x01); - - if (FAILED(hr)) { - return hr; - } - - /* Write the identification string. The NUL terminator at the end of this C - string is also sent, and it naturally terminates the response chunk. */ - - return iobuf_write(resp_buf, j9100628a_ident, sizeof(j9100628a_ident)); -} - -static HRESULT j9100628a_cmd_get_cmd_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Get command format version\n"); - resp[0] = 0x01; /* Report byte */ - resp[1] = 0x13; /* Command format version BCD */ - - return iobuf_write(resp_buf, resp, sizeof(resp)); -} - -static HRESULT j9100628a_cmd_get_jvs_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Get JVS format version\n"); - resp[0] = 0x01; /* Report byte */ - resp[1] = 0x30; /* JVS format version BCD */ - - return iobuf_write(resp_buf, resp, sizeof(resp)); -} - -static HRESULT j9100628a_cmd_get_comm_version(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Get COMM format version\n"); - resp[0] = 0x01; /* Report byte */ - resp[1] = 0x10; /* COMM format version BCD */ - - return iobuf_write(resp_buf, resp, sizeof(resp)); -} - -static HRESULT j9100628a_cmd_get_features(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - dprintf("J9100628A: Get reader features\n"); - - hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */ - - if (FAILED(hr)) { - return hr; - } - - return iobuf_write(resp_buf, j9100628a_features, sizeof(j9100628a_features)); -} - -static HRESULT j9100628a_cmd_read_misc_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */ - - if (FAILED(hr)) { - return hr; - } - - return iobuf_write_8(resp_buf, 0x00); /* Write switch byte */ -} - -static HRESULT j9100628a_cmd_read_dip_switches(struct j9100628a *j9100628a, struct const_iobuf *req_buf, struct iobuf *resp_buf) -{ - uint8_t req; - uint8_t resp[2]; - HRESULT hr; - - hr = iobuf_read_8(req_buf, &req); - - if (FAILED(hr)) { - return hr; - } - - hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */ - - if (FAILED(hr)) { - return hr; - } - - return iobuf_write_8(resp_buf, 0x00); /* Write switch byte */ -} - -static HRESULT j9100628a_cmd_write_gpio( - struct j9100628a *j9100628a, - struct const_iobuf *req_buf, - struct iobuf *resp_buf) -{ - uint8_t cmd; - uint8_t nbytes; - uint8_t bytes[3]; - HRESULT hr; - - /* Read request header */ - - hr = iobuf_read_8(req_buf, &cmd); - - if (FAILED(hr)) { - return hr; - } - - hr = iobuf_read_8(req_buf, &nbytes); - - if (FAILED(hr)) { - return hr; - } - - if (nbytes > 3) { - dprintf("J9100628A: Invalid GPIO write size %i\n", nbytes); - hr = iobuf_write_8(resp_buf, 0x02); - - if (FAILED(hr)) { - return hr; - } - - return E_FAIL; - } - - /* Read payload */ - - memset(bytes, 0, sizeof(bytes)); - hr = iobuf_read(req_buf, bytes, nbytes); - - if (FAILED(hr)) { - return hr; - } - - if (j9100628a->ops->write_led != NULL) { - j9100628a->ops->write_led( - j9100628a->ops_ctx, - bytes[0] | (bytes[1] << 8) | (bytes[2] << 16)); - } - - /* Write report byte */ - - return iobuf_write_8(resp_buf, 0x01); -} diff --git a/board/j9100647a.h b/board/j9100647a.h deleted file mode 100644 index 847c119..0000000 --- a/board/j9100647a.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include -#include - -#pragma pack(push,1) - -// needs to handle digital and analog reads and writes, coin stuff, and -// having an ad-on device (usually a card reader) and maybe an SD card?? - -// Mayhaps move this to a seperate thing in the event a second USB IO -// providor is needed? -//struct usbio_dev { - // TODO: populate with handler functions for various commands that - // come in via winusb - // It might also just do a mass bulk update, in which case we need - // a struct that encompases all the digital and analog I/O pins and - // their states. -//}; - -#pragma pack(pop) - -HRESULT usbio_hook_init(); diff --git a/board/j9100647a.c b/board/k9101258.c similarity index 53% rename from board/j9100647a.c rename to board/k9101258.c index d175307..424c4e3 100644 --- a/board/j9100647a.c +++ b/board/k9101258.c @@ -9,7 +9,7 @@ #include #include "board/guid.h" -#include "board/j9100647a.h" +#include "board/k9101258.h" #include "hook/iobuf.h" #include "hook/iohook.h" @@ -18,7 +18,20 @@ #include "util/dprintf.h" -// USB IO +// USB IO, A/B/C variants + +static const uint8_t base_bfr[64] = { + 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // 6: gamebtns, 7: door sw, 4: game/opt btns + 0xFF, 0xFF, 0xFF, 0x00, 0x35, 0x00, 0x00, 0x00, // 12 - coin count, 13 - coin jam (64) + //0xF0, 0xCA, 0x79, 0xE0, 0x08, 0xE3, 0x70, 0xE2, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 - 31 possibly analog in? + //0x7C, 0xEB, 0x3C, 0xDB, 0x84, 0xDE, 0xF0, 0xD9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 38/39 system buttons? + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reader stuff? + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; static HRESULT winusb_handle_irp(struct irp *irp); static void read_pipe(void *ctx, uint8_t *bfr, uint32_t bfr_len, uint32_t *len_tx); @@ -29,7 +42,7 @@ static const wchar_t usbio_path[] = L"$usbio"; static HANDLE usbio_fd; static void *usbio_ops_ctx; -HRESULT usbio_hook_init() +HRESULT k9101258_hook_init() { HRESULT hr; @@ -43,16 +56,16 @@ HRESULT usbio_hook_init() struct _USB_DEVICE_DESCRIPTOR desc = { .bLength = sizeof(USB_DEVICE_DESCRIPTOR), .bDescriptorType = USB_DEVICE_DESCRIPTOR_TYPE, - .bcdUSB = 301, // USB 3.01 spec (BCD makes no sense) - .bDeviceClass = 0x03, // HID - .bDeviceSubClass = 0x00, // ?? - .bDeviceProtocol = 0x00, // ?? + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, .bMaxPacketSize0 = 64, .idVendor = 0x0AE4, .idProduct = 0x0901, - .bcdDevice = 0x32, // Needs to be 32 after some processing by the game - .iManufacturer = 0, - .iProduct = 0, + .bcdDevice = 0x32, // Needs to be hex 32 (the game turns it to decimal and expects 32) + .iManufacturer = 1, + .iProduct = 2, .iSerialNumber = 0, .bNumConfigurations = 1, }; @@ -71,17 +84,25 @@ HRESULT usbio_hook_init() return hr; } - dprintf("USBIO: Init\n"); + dprintf("K9101258: Init\n"); return S_OK; } static void read_pipe(void *ctx, uint8_t *bfr, uint32_t bfr_len, uint32_t *len_tx) { - + memcpy_s(bfr, bfr_len, base_bfr, sizeof(base_bfr)); + *len_tx = 64; } static void write_pipe(void *ctx, uint8_t *bfr, uint32_t bfr_len, uint32_t *len_tx) { - + *len_tx = 64; +#if 0 + dprintf("K9101258: Write Pipe -"); + for (int i = 0; i < bfr_len; i++) { + dprintf(" %02X",bfr[i]); + } + dprintf("\n"); +#endif } diff --git a/board/k9101258.h b/board/k9101258.h new file mode 100644 index 0000000..e63bc06 --- /dev/null +++ b/board/k9101258.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include + +#pragma pack(push,1) + +// needs to handle digital and analog reads and writes, coin stuff, and +// having an ad-on device (usually a card reader) and maybe an SD card?? + +// Mayhaps move this to a seperate thing in the event a second USB IO +// providor is needed? +struct usbio_ops { + void (*digital_in)(void *ctx, uint32_t *out); + void (*digital_out)(void *ctx); // TODO: digital outputs + void (*analog_in)(void *ctx, uint16_t out[8]); + bool (*is_coin_pressed)(void *ctx); + void (*reader_poll)(void *ctx); // TODO: reader struct? + void (*reader_led_out)(void *ctx); // TODO: reader struct? +}; + +#pragma pack(pop) + +HRESULT k9101258_hook_init(); diff --git a/board/k92x0249.c b/board/k92x0249.c new file mode 100644 index 0000000..6b11ebf --- /dev/null +++ b/board/k92x0249.c @@ -0,0 +1,422 @@ +#include + +#include +#include +#include +#include +#include + +#include "board/k92x0249.h" + +#include "jvs/jvs-bus.h" +#include "jvs/jvs-cmd.h" +#include "jvs/jvs-util.h" + +#include "util/dprintf.h" +#include "util/dump.h" + +// JVS card reader, A/B/C vairants + +static const uint8_t k92x0249_ident[] = "TAITO CORP.;JVS Reader;Ver1.00;0000.00.00"; +//static const uint8_t k92x0249_ident[] = "TAITO CORP.;JVS Reader;Ver0.20;0000.00.00"; + +static uint8_t k92x0249_features[] = { + /* Feature : 0x01 : Players and switches + Param1 : 1 : Number of players + Param2 : 18 : Number of switches per player + Param3 : 0 : N/A */ + + 0x01, + 0x01, + 0x18, + 0x00, + + /* Feature : 0x02 : Coin slots + Param1 : 2 : Number of coin slots + Param2 : 0 : N/A + Param3 : 0 : N/A */ + + 0x02, + 0x00, + 0x00, + 0x00, + + /* Feature : 0x03 : Analog inputs + Param1 : 8 : Number of ADC channels + Param2 : 10 : Effective bits of resolution per ADC + Param3 : 0 : N/A */ + + 0x03, + 0x00, + 0x00, + 0x00, + + /* Feature : 0x04 : Rotary Input + Param1 : 4 : Number of Rotary channels + Param2 : 0 : N/A + Param3 : 0 : N/A */ + + 0x04, + 0x00, + 0x00, + 0x00, + + /* Feature : 0x12 : GPIO outputs + Param1 : 3 : Number of ports (8 bits per port) + Param2 : 0 : N/A + Param3 : 0 : N/A + */ + + 0x12, + 0x00, + 0x00, + 0x00, + + /* Feature : 0x13 : Analog outputs + Param1 : 2 : Number of channels + Param2 : 0 : N/A + Param3 : 0 : N/A + */ + + 0x13, + 0x00, + 0x00, + 0x00, + + /* Feature : 0x14 : Character Output + Param1 : 0x50 : Width + Param2 : 0x19 : Height + Param3 : 0 : Type + */ + 0x14, + 0x50, + 0x19, + 0x00, + + /* Feature : 0x00 : End of capabilities */ + + 0x00, +}; + +static void k92x0249_transact( + struct jvs_node *node, + const void *bytes, + size_t nbytes, + struct iobuf *resp); + +static bool k92x0249_sense(struct jvs_node *node); + +static HRESULT k92x0249_cmd( + void *ctx, + struct const_iobuf *req, + struct iobuf *resp); + +static HRESULT k92x0249_cmd_reset(struct k92x0249 *k92x0249, struct const_iobuf *req_buf); +static HRESULT k92x0249_cmd_assign_addr(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_read_id(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_get_cmd_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_get_jvs_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_get_comm_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_get_features(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf); +static HRESULT k92x0249_cmd_read_misc_switches(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, uint8_t req_len, struct iobuf *resp_buf); + +void k92x0249_init( + struct k92x0249 *k92x0249, + struct jvs_node *next, + const struct k92x0249_ops *ops, + void *ops_ctx) +{ + assert(k92x0249 != NULL); + assert(ops != NULL); + + k92x0249->jvs.next = next; + k92x0249->jvs.transact = k92x0249_transact; + k92x0249->jvs.sense = k92x0249_sense; + k92x0249->jvs.sense_out = true; + k92x0249->addr = 0xFF; + k92x0249->ops = ops; + k92x0249->ops_ctx = ops_ctx; +} + +struct jvs_node *k92x0249_to_jvs_node(struct k92x0249 *k92x0249) +{ + assert(k92x0249 != NULL); + + return &k92x0249->jvs; +} + +static void k92x0249_transact( + struct jvs_node *node, + const void *bytes, + size_t nbytes, + struct iobuf *resp) +{ + struct k92x0249 *k92x0249; + + assert(node != NULL); + assert(bytes != NULL); + assert(resp != NULL); + + k92x0249 = CONTAINING_RECORD(node, struct k92x0249, jvs); + + jvs_crack_request(bytes, nbytes, resp, k92x0249->addr, k92x0249_cmd, k92x0249); +} + +static bool k92x0249_sense(struct jvs_node *node) +{ + struct k92x0249 *k92x0249; + + assert(node != NULL); + + k92x0249 = CONTAINING_RECORD(node, struct k92x0249, jvs); + + return k92x0249->addr == 0xFF; +} + +static HRESULT k92x0249_cmd( + void *ctx, + struct const_iobuf *req, + struct iobuf *resp) +{ + struct k92x0249 *k92x0249; + uint8_t req_len; + + iobuf_read_8(req, &req_len); // Read the length for variable-length commands + + k92x0249 = ctx; + + switch (req->bytes[req->pos]) { + case JVS_CMD_RESET: + return k92x0249_cmd_reset(k92x0249, req); + + case JVS_CMD_ASSIGN_ADDR: + return k92x0249_cmd_assign_addr(k92x0249, req, resp); + + case JVS_CMD_READ_ID: + return k92x0249_cmd_read_id(k92x0249, req, resp); + + case JVS_CMD_GET_CMD_VERSION: + return k92x0249_cmd_get_cmd_version(k92x0249, req, resp); + + case JVS_CMD_GET_JVS_VERSION: + return k92x0249_cmd_get_jvs_version(k92x0249, req, resp); + + case JVS_CMD_GET_COMM_VERSION: + return k92x0249_cmd_get_comm_version(k92x0249, req, resp); + + case JVS_CMD_GET_FEATURES: + return k92x0249_cmd_get_features(k92x0249, req, resp); + + case JVS_CMD_READ_MISC_SWITCHES: + return k92x0249_cmd_read_misc_switches(k92x0249, req, req_len, resp); + + default: + dprintf("K92X0249: Node %02x: Unhandled command byte %02x\n", + k92x0249->addr, + req->bytes[req->pos]); + + return E_NOTIMPL; + } + + return S_OK; +} + +static HRESULT k92x0249_cmd_reset(struct k92x0249 *k92x0249, struct const_iobuf *req_buf) +{ + struct jvs_req_reset req; + HRESULT hr; + + hr = iobuf_read(req_buf, &req, sizeof(req)); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Reset (param %02x)\n", req.unknown); + k92x0249->addr = 0xFF; + k92x0249->jvs.sense_out = false; // ? + + if (k92x0249->ops->reset != NULL) { + k92x0249->ops->reset(k92x0249->ops_ctx); + } + + /* No ack for this since it really is addressed to everybody */ + + return S_OK; +} + +static HRESULT k92x0249_cmd_assign_addr( + struct k92x0249 *k92x0249, + struct const_iobuf *req_buf, + struct iobuf *resp_buf) +{ + struct jvs_req_assign_addr req; + bool sense; + HRESULT hr; + + hr = iobuf_read(req_buf, &req, sizeof(req)); + + if (FAILED(hr)) { + return hr; + } + + sense = jvs_node_sense(k92x0249->jvs.next); + dprintf("K92X0249: Assign addr %02x sense %i\n", req.addr, sense); + + if (sense) { + /* That address is for somebody else */ + return S_OK; + } + + k92x0249->addr = req.addr; + k92x0249->jvs.sense_out = true; + + return iobuf_write_8(resp_buf, 0x01); +} + +static HRESULT k92x0249_cmd_read_id(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) +{ + uint8_t req; + HRESULT hr; + + hr = iobuf_read_8(req_buf, &req); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Read ID\n"); + + /* Write report byte */ + + hr = iobuf_write_8(resp_buf, 0x01); + + if (FAILED(hr)) { + return hr; + } + + /* Write the identification string. The NUL terminator at the end of this C + string is also sent, and it naturally terminates the response chunk. */ + + return iobuf_write(resp_buf, k92x0249_ident, sizeof(k92x0249_ident)); +} + +static HRESULT k92x0249_cmd_get_cmd_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) +{ + uint8_t req; + uint8_t resp[2]; + HRESULT hr; + + hr = iobuf_read_8(req_buf, &req); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Get command format version\n"); + resp[0] = 0x01; /* Report byte */ + resp[1] = 0x13; /* Command format version BCD */ + + return iobuf_write(resp_buf, resp, sizeof(resp)); +} + +static HRESULT k92x0249_cmd_get_jvs_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) +{ + uint8_t req; + uint8_t resp[2]; + HRESULT hr; + + hr = iobuf_read_8(req_buf, &req); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Get JVS format version\n"); + resp[0] = 0x01; /* Report byte */ + resp[1] = 0x30; /* JVS format version BCD */ + + return iobuf_write(resp_buf, resp, sizeof(resp)); +} + +static HRESULT k92x0249_cmd_get_comm_version(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) +{ + uint8_t req; + uint8_t resp[2]; + HRESULT hr; + + hr = iobuf_read_8(req_buf, &req); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Get COMM format version\n"); + resp[0] = 0x01; /* Report byte */ + resp[1] = 0x10; /* COMM format version BCD */ + + return iobuf_write(resp_buf, resp, sizeof(resp)); +} + +static HRESULT k92x0249_cmd_get_features(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, struct iobuf *resp_buf) +{ + uint8_t req; + uint8_t resp[2]; + HRESULT hr; + + hr = iobuf_read_8(req_buf, &req); + + if (FAILED(hr)) { + return hr; + } + + dprintf("K92X0249: Get reader features\n"); + + hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */ + + if (FAILED(hr)) { + return hr; + } + + return iobuf_write(resp_buf, k92x0249_features, sizeof(k92x0249_features)); +} + +static HRESULT k92x0249_cmd_read_misc_switches(struct k92x0249 *k92x0249, struct const_iobuf *req_buf, uint8_t req_len, struct iobuf *resp_buf) +{ + uint8_t req[255]; + HRESULT hr; + +#if 0 + dprintf("K92X0249: Read misc switches\n"); + dump_const_iobuf(req_buf); +#endif + // data bytes: 01 61 32 01 80 + + hr = iobuf_read(req_buf, &req, req_len - 1); // duno what these bytes mean... + + if (FAILED(hr)) { + return hr; + } + + hr = iobuf_write_8(resp_buf, 0x01); /* Write report byte */ + + if (FAILED(hr)) { + return hr; + } + + return iobuf_write_8(resp_buf, 0x00); /* Write switch byte */ + // Below will trip a card request with blank info + // hr = iobuf_write(resp_buf, (uint8_t *)"7020000000000000", 16); /* Nesica ID */ + + // if (FAILED(hr)) { + // return hr; + // } + + // hr = iobuf_write(resp_buf, (uint8_t *)"00000000000000000000", 20); /* Access Code */ + + // if (FAILED(hr)) { + // return hr; + // } + + // return iobuf_write_8(resp_buf, 0x01); /* is AICC */ +} diff --git a/board/j9100628a.h b/board/k92x0249.h similarity index 56% rename from board/j9100628a.h rename to board/k92x0249.h index cf887bb..af34d8a 100644 --- a/board/j9100628a.h +++ b/board/k92x0249.h @@ -3,23 +3,23 @@ #include "jvs/jvs-bus.h" -struct j9100628a_ops { +struct k92x0249_ops { void (*reset)(void *ctx); void (*write_led)(void *ctx, uint32_t state); void (*poll_card)(void *ctx, char *serial); }; -struct j9100628a { +struct k92x0249 { struct jvs_node jvs; uint8_t addr; - const struct j9100628a_ops *ops; + const struct k92x0249_ops *ops; void *ops_ctx; }; -void j9100628a_init( - struct j9100628a *j9100628a, +void k92x0249_init( + struct k92x0249 *k92x0249, struct jvs_node *next, - const struct j9100628a_ops *ops, + const struct k92x0249_ops *ops, void *ops_ctx); -struct jvs_node *j9100628a_to_jvs_node(struct j9100628a *j9100628a); +struct jvs_node *k92x0249_to_jvs_node(struct k92x0249 *k92x0249); diff --git a/board/meson.build b/board/meson.build index 12132a9..7b87bdb 100644 --- a/board/meson.build +++ b/board/meson.build @@ -16,10 +16,10 @@ board_lib = static_library( 'guid.h', 'io3.c', 'io3.h', - 'j9100628a.c', - 'j9100628a.h', - 'j9100647a.c', - 'j9100647a.h', + 'k92x0249.c', + 'k92x0249.h', + 'k9101258.c', + 'k9101258.h', 'io4.c', 'io4.h', 'sg-cmd.c', diff --git a/dist/ll3/start.bat b/dist/ll3/start.bat index 0d50837..99e4a64 100644 --- a/dist/ll3/start.bat +++ b/dist/ll3/start.bat @@ -2,7 +2,6 @@ pushd %~dp0 -REM chcp 932 start inject.exe -d -k ll3hook.dll d_drive\Service\NesysService.exe -app inject.exe -d -k ll3hook.dll ll3.exe -singlemonitor -windowmode -highquality REM Comment above and uncomment below for terminal mode diff --git a/dist/ll3/taitools.ini b/dist/ll3/taitools.ini index fe5e484..09d5cab 100644 --- a/dist/ll3/taitools.ini +++ b/dist/ll3/taitools.ini @@ -3,3 +3,12 @@ d_drive=d_drive [netenv] enable=1 + +[syscfg] +log_level=0 + +[dns] +default=localhost + +[cert] +path=client.p12 \ No newline at end of file diff --git a/dist/siva/taitools.ini b/dist/siva/taitools.ini index fe5e484..c39d9bb 100644 --- a/dist/siva/taitools.ini +++ b/dist/siva/taitools.ini @@ -3,3 +3,12 @@ d_drive=d_drive [netenv] enable=1 + +[gfx] +enable=0 + +[dns] +default=localhost + +[cert] +path=client.p12 diff --git a/doc/config/common.md b/doc/config/common.md index 9603e00..d520b33 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -6,59 +6,7 @@ all games. Keyboard binding settings use [Virtual-Key Codes](https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). -## `[aimeio]` - -Controls the card reader driver. - -### `path` - -Specify a path for a third-party card reader driver DLL. Default is empty -(use built-in emulation based on text files and keyboard input). - -In previous versions of Taitools this was accomplished by replacing the -AIMEIO.DLL file that came with Taitools. Taitools no longer ships with a -separate AIMEIO.DLL file (its functionality is now built into the various hook -DLLs). - -## `[aime]` - -Controls emulation of the Aime card reader assembly. - -### `enable` - -Default: `1` - -Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime -reader (COM port number varies by game). - -### `aimePath` - -Default: `DEVICE\aime.txt` - -Path to a text file containing a classic Nesica IC card ID. **This does not -currently work**. - -### `felicaPath` - -Default: `DEVICE\felica.txt` - -Path to a text file containing a FeliCa e-cash card IDm serial number. - -### `felicaGen` - -Default: `1` - -Whether to generate a random FeliCa ID if the file at `felicaPath` does not -exist. - -### `scan` - -Default: `0x0D` (`VK_RETURN`) - -Virtual-key code. If this button is **held** then the emulated IC card reader -emulates an IC card in its proximity. A variety of different IC cards can be -emulated; the exact choice of card that is emulated depends on the presence or -absence of the configured card ID files. +For Raw Input, you're on your own for now. ## `[clock]` @@ -110,34 +58,25 @@ Default: Empty string (i.e. use value from `default` setting) Overrides the target of the `tenporouter.loc` and `bbrouter.loc` hostname lookups. -### `startup` - -Default: Empty string (i.e. use value from `default` setting) - -Overrides the target of the `naominet.jp` host lookup. - -### `billing` - -Default: Empty string (i.e. use value from `default` setting) - -Overrides the target of the `ib.naominet.jp` host lookup. - -### `aimedb` - -Default: Empty string (i.e. use value from `default` setting) - -Overrides the target of the `aime.naominet.jp` host lookup. - - ## `[jvs]` -Configure emulation of the AMEX PCIe JVS *controller* (not IO board!) +Configure emulation of the iDMAC JVS port (usually the reader, NOT IO! For IO, see the FastIO section) ### `enable` Default `1` -Enable JVS port emulation. Disable to use the JVS port on a real AMEX. +Enable JVS port emulation. Disable to use the JVS port on a real iDMAC card. + +## `[fastio]` + +Configure emulation of the iDMAC FastIO ports + +### `enable` + +Default `1` + +Enable FastIO port emulation. Disable to use the JVS port on a real iDMAC card. ## `[netenv]` @@ -243,5 +182,6 @@ If 1, hooks functions related to server and client certificate processing. Default: `` -Path to a cert file (base64 with headers) that contains the client cert to be used for mTLS. -Leave this blank to disable mTLS, if the server you're connecting to supports it. +Path to a certificate file in either PEM or P12/PFX format that contains the client cert +to be used for mTLS. Leave this blank to disable mTLS, if the server you're connecting +to supports it. diff --git a/doc/config/theatrhythm.md b/doc/config/theatrhythm.md new file mode 100644 index 0000000..f2c2a76 --- /dev/null +++ b/doc/config/theatrhythm.md @@ -0,0 +1,69 @@ +# Theatrhythm (sivahook) configuration settings + +Config options specific to Theatrhythm. Note that the system buttons +in the fastio section are only mapped to the keyboard via `GetAsyncKeyState`, +and are not exposed via Raw Input. + +## `[fastio]` + +### `test` + +Default `0x24`(VK_HOME) + +IO board "test" system button. + +### `service` + +Default `0x2E`(VK_DELETE) + +IO board "service" system button. + +### `select` + +Default `0x23`(VK_END) + +IO board "select" system button. + +### `enter` + +Default `0xA1`(VK_RSHIFT) + +IO board "enter" system button. + +### `coin` + +Default `0x2D`(VK_INSERT) + +Coin switch, adds a coin if you're not in free play + +## `[deck]` + +### `input_type` + +Default `0` + +0 for the legacy `GetAsyncKeyState` method of input polling, +1 for newer Raw Input polling. See above note for system buttons in +the `[fastio]` section. + +### `device_num` + +Default `0` + +Index of the device on the list of Raw Input devices. Note that this value +may change as devices are connected and disconnected, and between system +reboots. + +### `left_button` + +Default `67`(C) + +Left button on the control deck. + +### `right_button` + +Default `78`(N) + +Right button on the control deck. + +### TODO: the rest of the inputs. See [sivaio/config.c](../../sivaio/config.c) in the mean time. diff --git a/hooklib/config.c b/hooklib/config.c index 5fc9383..c94df03 100644 --- a/hooklib/config.c +++ b/hooklib/config.c @@ -1,11 +1,13 @@ #include #include +#include #include #include #include "hooklib/config.h" #include "hooklib/dvd.h" +#include "hooklib/printer.h" void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) { @@ -14,3 +16,62 @@ void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename) cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename); } + +void printer_config_load(struct printer_config *cfg, const wchar_t *filename) +{ + assert(cfg != NULL); + assert(filename != NULL); + + wchar_t tmpstr[16]; + + cfg->enable = GetPrivateProfileIntW(L"printer", L"enable", 0, filename); + cfg->rotate_180 = GetPrivateProfileIntW(L"printer", L"rotate180", 0, filename); + + GetPrivateProfileStringW( + L"printer", + L"serial_no", + L"5A-A123", + tmpstr, + _countof(tmpstr), + filename); + + size_t n = wcstombs(cfg->serial_no, tmpstr, sizeof(cfg->serial_no)); + for (int i = n; i < sizeof(cfg->serial_no); i++) + { + cfg->serial_no[i] = '\0'; + } + + GetPrivateProfileStringW( + L"printer", + L"mainFwPath", + L"d_drive\\printer_main_fw.bin", + cfg->main_fw_path, + _countof(cfg->main_fw_path), + filename); + + GetPrivateProfileStringW( + L"printer", + L"dspFwPath", + L"d_drive\\printer_dsp_fw.bin", + cfg->dsp_fw_path, + _countof(cfg->dsp_fw_path), + filename); + + GetPrivateProfileStringW( + L"printer", + L"paramFwPath", + L"d_drive\\printer_param_fw.bin", + cfg->param_fw_path, + _countof(cfg->param_fw_path), + filename); + + GetPrivateProfileStringW( + L"printer", + L"printerOutPath", + L"d_drive\\print", + cfg->printer_out_path, + _countof(cfg->printer_out_path), + filename); + + cfg->wait_time = GetPrivateProfileIntW(L"printer", L"waitTime", 0, filename); +} diff --git a/hooklib/config.h b/hooklib/config.h index 5da045d..f826e92 100644 --- a/hooklib/config.h +++ b/hooklib/config.h @@ -3,5 +3,7 @@ #include #include "hooklib/dvd.h" +#include "hooklib/printer.h" void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename); +void printer_config_load(struct printer_config *cfg, const wchar_t *filename); diff --git a/hooklib/cursor.c b/hooklib/cursor.c index 44ed25b..f4dc619 100644 --- a/hooklib/cursor.c +++ b/hooklib/cursor.c @@ -20,16 +20,16 @@ static const struct hook_symbol cursor_syms[] = { .name = "SetCursor", .patch = my_SetCursor, .link = (void **) &next_SetCursor - },/*{ + }, { .name = "SetCursorPos", .patch = my_SetCursorPos, - },*/ { + }, { .name = "SetPhysicalCursorPos", .patch = my_SetPhysicalCursorPos - }, /*{ + }, { .name = "ShowCursor", .patch = my_ShowCursor - }*/ + } }; void cursor_hook_init() @@ -45,13 +45,13 @@ void cursor_hook_init() static BOOL my_SetCursorPos(int x, int y) { - dprintf("my_SetCursorPos Hit! x %d y %d\n", x, y); + //dprintf("my_SetCursorPos Hit! x %d y %d\n", x, y); return true; } static BOOL my_SetPhysicalCursorPos(int x, int y) { - dprintf("my_SetPhysicalCursorPos Hit! x %d y %d\n", x, y); + //dprintf("my_SetPhysicalCursorPos Hit! x %d y %d\n", x, y); return true; } @@ -63,7 +63,7 @@ static int my_ShowCursor(BOOL bShow) static HCURSOR my_SetCursor(HCURSOR hCursor) { - dprintf("my_SetCursor Hit!\n"); + //dprintf("my_SetCursor Hit!\n"); HCURSOR fake_cursor; if ( hCursor ) diff --git a/hooklib/meson.build b/hooklib/meson.build index 401c38f..17f3f82 100644 --- a/hooklib/meson.build +++ b/hooklib/meson.build @@ -23,6 +23,8 @@ hooklib_lib = static_library( 'fdshark.h', 'path.c', 'path.h', + 'printer.c', + 'printer.h', 'reg.c', 'reg.h', 'setupapi.c', diff --git a/hooklib/printer.c b/hooklib/printer.c new file mode 100644 index 0000000..638dc86 --- /dev/null +++ b/hooklib/printer.c @@ -0,0 +1,3472 @@ +/* + Sinfonia CHC-C3XX Printer emulator + + Credits: + + c310emu (rakisaionji) + taitools-kancolle (OLEG) + c310emu (doremi) + chc (emihiok) +*/ + +#include "hooklib/printer.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "hook/table.h" +#include "hook/procaddr.h" +#include "hooklib/dll.h" +#include "hooklib/uart.h" +#include "util/dprintf.h" +#include "util/dump.h" + +// #define IMAGE_SIZE 0x24FC00 +#define IMAGE_SIZE 0x1F0800 +#define HOLO_SIZE 0xC5400 + +static const int8_t idNumber = 0x01; +static uint64_t serialNo = 0x333231412D4135; + +static uint16_t WIDTH = 0; +static uint16_t HEIGHT = 0; + +static bool rotate180 = false; +static uint8_t cardRFID[0xC] = {0}; +static uint8_t cardDataBuffer[0x20] = {0}; +static bool awaitingCardExit = false; +static wchar_t printer_out_path[MAX_PATH]; + +/* Firmware data */ + +static uint8_t mainFirmware[0x40] = {0}; +static uint8_t dspFirmware[0x40] = {0}; +static uint8_t paramFirmware[0x40] = {0}; + +/* printerInfo variables */ + +static int32_t PAPERINFO[10]; +static int32_t CURVE[3][3]; +static uint8_t POLISH[2]; +static int32_t MTF[9]; + +/* Printer status */ + +static uint8_t STATUS = 0; +static ULONGLONG finishTime = 0; + +/* C3XXFWDLusb API hooks */ + +int WINAPI fwdlusb_open(uint16_t *rResult); +void WINAPI fwdlusb_close(); +int WINAPI fwdlusb_listupPrinter(uint8_t *rIdArray); +int WINAPI fwdlusb_listupPrinterSN(uint64_t *rSerialArray); +int WINAPI fwdlusb_selectPrinter(uint8_t printerId, uint16_t *rResult); +int WINAPI fwdlusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult); +int WINAPI fwdlusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen); +int WINAPI fwdlusb_status(uint16_t *rResult); +int WINAPI fwdlusb_statusAll(uint8_t *idArray, uint16_t *rResultArray); +int WINAPI fwdlusb_resetPrinter(uint16_t *rResult); +int WINAPI fwdlusb_updateFirmware(uint8_t update, LPCSTR filename, uint16_t *rResult); +int WINAPI fwdlusb_getFirmwareInfo(uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult); +int WINAPI fwdlusb_MakeThread(uint16_t maxCount); +int WINAPI fwdlusb_ReleaseThread(uint16_t *rResult); +int WINAPI fwdlusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount); +int WINAPI fwdlusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult); + +/* C3XXusb API hooks */ + +int WINAPI chcusb_MakeThread(uint16_t maxCount); +int WINAPI chcusb_open(uint16_t *rResult); +void WINAPI chcusb_close(); +int WINAPI chcusb_ReleaseThread(uint16_t *rResult); +int WINAPI chcusb_listupPrinter(uint8_t *rIdArray); +int WINAPI chcusb_listupPrinterSN(uint64_t *rSerialArray); +int WINAPI chcusb_selectPrinter(uint8_t printerId, uint16_t *rResult); +int WINAPI chcusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult); +int WINAPI chcusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen); +int WINAPI chcusb_imageformat(uint16_t format, uint16_t ncomp, uint16_t depth, uint16_t width, uint16_t height, uint8_t * image, uint16_t* rResult); +int WINAPI chcusb_imageformat_330( + uint16_t format, + uint16_t ncomp, + uint16_t depth, + uint16_t width, + uint16_t height, + uint16_t *rResult); +int __fastcall chcusb_setmtf(int32_t *mtf); +int WINAPI chcusb_makeGamma(uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB); +int WINAPI chcusb_setIcctable( + LPCSTR icc1, + LPCSTR icc2, + uint16_t intents, + uint8_t *intoneR, + uint8_t *intoneG, + uint8_t *intoneB, + uint8_t *outtoneR, + uint8_t *outtoneG, + uint8_t *outtoneB, + uint16_t *rResult); +int WINAPI chcusb_copies(uint16_t copies, uint16_t *rResult); +int WINAPI chcusb_status(uint16_t *rResult); +int WINAPI chcusb_statusAll(uint8_t *idArray, uint16_t *rResultArray); +int WINAPI chcusb_startpage(uint16_t postCardState, uint16_t *pageId, uint16_t *rResult); +int WINAPI chcusb_startpage_300(uint16_t postCardState, uint16_t *rResult); +int WINAPI chcusb_endpage(uint16_t *rResult); +int WINAPI chcusb_write(uint8_t *data, uint32_t *writeSize, uint16_t *rResult); +int WINAPI chcusb_writeLaminate(uint8_t *data, uint32_t *writeSize, uint16_t *rResult); +int WINAPI chcusb_writeHolo(uint8_t *data, uint32_t *writeSize, uint16_t *rResult); +int WINAPI chcusb_setPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult); +int WINAPI chcusb_getGamma(LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult); +int WINAPI chcusb_getMtf(LPCSTR filename, int32_t *mtf, uint16_t *rResult); +int WINAPI chcusb_cancelCopies(uint16_t pageId, uint16_t *rResult); +int WINAPI chcusb_setPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult); +int WINAPI chcusb_getPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult); +int WINAPI chcusb_blinkLED(uint16_t *rResult); +int WINAPI chcusb_resetPrinter(uint16_t *rResult); +int WINAPI chcusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount); +int WINAPI chcusb_getPrintIDStatus(uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult); +int WINAPI chcusb_setPrintStandby(uint16_t position, uint16_t *rResult); +int WINAPI chcusb_setPrintStandby_300(uint16_t *rResult); +int WINAPI chcusb_testCardFeed(uint16_t mode, uint16_t times, uint16_t *rResult); +int WINAPI chcusb_exitCard(uint16_t *rResult); +int WINAPI chcusb_getCardRfidTID(uint8_t *rCardTID, uint16_t *rResult); +int WINAPI chcusb_commCardRfidReader(uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult); +int WINAPI chcusb_updateCardRfidReader(uint8_t *data, uint32_t size, uint16_t *rResult); +int WINAPI chcusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult); +int WINAPI chcusb_getErrorStatus(uint16_t *rBuffer); +int WINAPI chcusb_setCutList(uint8_t *rData, uint16_t *rResult); +int WINAPI chcusb_setLaminatePattern(uint16_t index, uint8_t *rData, uint16_t *rResult); +int WINAPI chcusb_color_adjustment(LPCSTR filename, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult); +int WINAPI chcusb_color_adjustmentEx(int32_t a1, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult); +int WINAPI chcusb_getEEPROM(uint8_t index, uint8_t *rData, uint16_t *rResult); +int WINAPI chcusb_setParameter(uint8_t a1, uint32_t a2, uint16_t *rResult); +int WINAPI chcusb_getParameter(uint8_t a1, uint8_t *a2, uint16_t *rResult); +int WINAPI chcusb_universal_command(int32_t a1, uint8_t a2, int32_t a3, uint8_t *a4, uint16_t *rResult); + +/* PrintDLL API hooks */ + +void CFW_close(const void *handle); +int CFW_getFirmwareInfo(const void *handle, uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult); +int CFW_getPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen); +int CFW_init(LPCSTR dllpath); +int CFW_listupPrinter(const void *handle, uint8_t *rIdArray); +int CFW_listupPrinterSN(const void *handle, uint64_t *rSerialArray); +int CFW_open(const void *handle, uint16_t *rResult); +int CFW_resetPrinter(const void *handle, uint16_t *rResult); +int CFW_selectPrinter(const void *handle, uint8_t printerId, uint16_t *rResult); +int CFW_selectPrinterSN(const void *handle, uint64_t printerSN, uint16_t *rResult); +int CFW_status(const void *handle, uint16_t *rResult); +int CFW_statusAll(const void *handle, uint8_t *idArray, uint16_t *rResultArray); +void CFW_term(const void *handle); +int CFW_updateFirmware(const void *handle, uint8_t update, LPCSTR filename, uint16_t *rResult); +int CHCUSB_AttachThreadCount(const void *handle, uint16_t *rCount, uint16_t *rMaxCount); +int CHCUSB_MakeThread(const void *handle, uint16_t maxCount); +int CHCUSB_ReleaseThread(const void *handle, uint16_t *rResult); +int CHCUSB_blinkLED(const void *handle, uint16_t *rResult); +int CHCUSB_cancelCopies(const void *handle, uint16_t pageId, uint16_t *rResult); +void CHCUSB_close(const void *handle); +int CHCUSB_commCardRfidReader(const void *handle, uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult); +int CHCUSB_copies(const void *handle, uint16_t copies, uint16_t *rResult); +int CHCUSB_endpage(const void *handle, uint16_t *rResult); +int CHCUSB_exitCard(const void *handle, uint16_t *rResult); +int CHCUSB_getCardRfidTID(const void *handle, uint8_t *rCardTID, uint16_t *rResult); +int CHCUSB_getErrorLog(const void *handle, uint16_t index, uint8_t *rData, uint16_t *rResult); +int CHCUSB_getErrorStatus(const void *handle, uint16_t *rBuffer); +int CHCUSB_getGamma(const void *handle, LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult); +int CHCUSB_getMtf(const void *handle, LPCSTR filename, int32_t *mtf, uint16_t *rResult); +int CHCUSB_getPrintIDStatus(const void *handle, uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult); +int CHCUSB_getPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen); +int CHCUSB_getPrinterToneCurve(const void *handle, uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult); +int CHCUSB_imageformat(const void *handle, uint16_t format, uint16_t ncomp, uint16_t depth, uint16_t width, uint16_t height, uint8_t *inputImage, uint16_t *rResult); +int CHCUSB_init(LPCSTR dllpath); +int CHCUSB_listupPrinter(const void *handle, uint8_t *rIdArray); +int CHCUSB_listupPrinterSN(const void *handle, uint64_t *rSerialArray); +int CHCUSB_makeGamma(const void *handle, uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB); +int CHCUSB_open(const void *handle, uint16_t *rResult); +int CHCUSB_resetPrinter(const void *handle, uint16_t *rResult); +int CHCUSB_selectPrinter(const void *handle, uint8_t printerId, uint16_t *rResult); +int CHCUSB_selectPrinterSN(const void *handle, uint64_t printerSN, uint16_t *rResult); +int CHCUSB_setIcctable(const void *handle, uint16_t intents, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB, uint8_t *outtoneR, uint8_t *outtoneG, uint8_t *outtoneB, uint16_t *rResult); +int CHCUSB_setIcctableProfile(const void *handle, LPCSTR icc1, LPCSTR icc2, uint16_t intents, uint16_t *rResult); +int CHCUSB_setPrintStandby(const void *handle, uint16_t position, uint16_t *rResult); +int CHCUSB_setPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult); +int CHCUSB_setPrinterToneCurve(const void *handle, uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult); +int CHCUSB_setmtf(const void *handle, int32_t *mtf); +int CHCUSB_startpage(const void *handle, uint16_t postCardState, uint16_t *pageId, uint16_t *rResult); +int CHCUSB_status(const void *handle, uint16_t *rResult); +int CHCUSB_statusAll(const void *handle, uint8_t *idArray, uint16_t *rResultArray); +int CHCUSB_testCardFeed(const void *handle, uint16_t mode, uint16_t times, uint16_t *rResult); +void CHCUSB_term(const void *handle); +int CHCUSB_updateCardRfidReader(const void *handle, uint8_t *data, uint32_t size, uint16_t *rResult); +int CHCUSB_write(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult); +int CHCUSB_writeHolo(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult); +int CHCUSB_writeLaminate(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult); + +/* Bitmap writing utils */ + +DWORD WriteDataToBitmapFile( + LPCWSTR lpFilePath, DWORD dwBitCount, + DWORD dwWidth, DWORD dwHeight, + PBYTE pbInput, DWORD cbInput, + PBYTE pbMetadata, DWORD cbMetadata, + bool pFlip); +DWORD WriteArrayToFile(LPCSTR lpOutputFilePath, LPVOID lpDataTemp, DWORD nDataSize, BOOL isAppend); + +#define MAX_CARDS 36 + +// big thanks to Coburn and Mitsuhide for helping me figure out this thing + +// request format: +// 0xe0 - sync +// 0x?? - command +// 0x?? - payload length +// ... - payload +// 0x?? - checksum (sum of everything except the sync byte) +// +// response format: +// 0xe0 - sync +// 0x?? - command +// 0x?? - status code +// 0x?? - payload length +// ... - payload +// 0x?? - checksum + +enum { + DECK_CMD_RESET = 0x41, + DECK_CMD_GET_BOOT_FW_VERSION = 0x84, + DECK_CMD_GET_BOARD_INFO = 0x85, + DECK_CMD_INIT_UNK1 = 0x81, + DECK_CMD_GET_APP_FW_VERSION = 0x42, + DECK_CMD_READ_DATA = 0x02, + DECK_CMD_WRITE = 0x03, + DECK_CMD_INIT_UNK2 = 0x04, + DECK_CMD_INIT_UNK3 = 0x05, + DECK_CMD_READ = 0x06 +}; + +enum { + DECK_READ_START = 0x81, + DECK_READ_DATA = 0x82, + DECK_READ_END = 0x83 +}; + +struct deck_hdr { + uint8_t sync; + uint8_t cmd; + uint8_t nbytes; +}; + +struct deck_resp_hdr { + uint8_t sync; + uint8_t cmd; + uint8_t status; + uint8_t nbytes; +}; + +struct deck_resp_get_boot_fw_version { + struct deck_resp_hdr hdr; + uint8_t boot_fw_version; +}; + +struct deck_resp_get_app_fw_version { + struct deck_resp_hdr hdr; + uint8_t app_fw_version; +}; + +struct deck_resp_get_board_info { + struct deck_resp_hdr hdr; + uint8_t board[9]; +}; + +struct deck_resp_read_data { + struct deck_resp_hdr hdr; + uint8_t card_data[32]; +}; + +struct deck_resp_read { + struct deck_resp_hdr hdr; + uint8_t card_data[44]; +}; + +union deck_req_any { + struct deck_hdr hdr; + uint8_t bytes[520]; +}; + +static HRESULT deck_handle_irp(struct irp *irp); +static HRESULT deck_handle_irp_locked(struct irp *irp); +static HRESULT deck_req_dispatch(const union deck_req_any *req); +static HRESULT deck_req_get_boot_fw_version(void); +static HRESULT deck_req_get_app_fw_version(void); +static HRESULT deck_req_get_board_info(void); +static HRESULT deck_req_read(void); +static HRESULT deck_req_read_data(void); +static HRESULT deck_req_write(const uint8_t *req_bytes); +static HRESULT deck_req_nop(uint8_t cmd); +static void deck_read_one(void); + +static HRESULT deck_frame_accept(const struct iobuf *dest); +static void deck_frame_sync(struct iobuf *src); +static HRESULT deck_frame_decode(struct iobuf *dest, struct iobuf *src); +static HRESULT deck_frame_encode(struct iobuf *dest, const void *ptr, size_t nbytes); +static HRESULT deck_frame_encode_byte(struct iobuf *dest, uint8_t byte); + +static CRITICAL_SECTION deck_lock; +static struct uart deck_uart; +static uint8_t deck_written_bytes[1024]; +static uint8_t deck_readable_bytes[1024]; +static uint8_t current_card_idx = 0; +static bool read_pending = false; + +/* C3XXFWDLusb hook tbl. The ordinals are required, as some games, for example + Sekito, will import this library by ordinal and not by name. */ + +static const struct hook_symbol C3XXFWDLusb_hooks[] = { + { + .name = "fwdlusb_open", + .ordinal = 0x0001, + .patch = fwdlusb_open, + .link = NULL + }, { + .name = "fwdlusb_close", + .ordinal = 0x0002, + .patch = fwdlusb_close, + .link = NULL + }, { + .name = "fwdlusb_listupPrinter", + .ordinal = 0x0003, + .patch = fwdlusb_listupPrinter, + .link = NULL + }, { + .name = "fwdlusb_listupPrinterSN", + .ordinal = 0x0004, + .patch = fwdlusb_listupPrinterSN, + .link = NULL + }, { + .name = "fwdlusb_selectPrinter", + .ordinal = 0x0005, + .patch = fwdlusb_selectPrinter, + .link = NULL + }, { + .name = "fwdlusb_selectPrinterSN", + .ordinal = 0x0006, + .patch = fwdlusb_selectPrinterSN, + .link = NULL + }, { + .name = "fwdlusb_getPrinterInfo", + .ordinal = 0x0007, + .patch = fwdlusb_getPrinterInfo, + .link = NULL + }, { + .name = "fwdlusb_status", + .ordinal = 0x0008, + .patch = fwdlusb_status, + .link = NULL + }, { + .name = "fwdlusb_statusAll", + .ordinal = 0x0009, + .patch = fwdlusb_statusAll, + .link = NULL + }, { + .name = "fwdlusb_resetPrinter", + .ordinal = 0x000a, + .patch = fwdlusb_resetPrinter, + .link = NULL + }, { + .name = "fwdlusb_updateFirmware", + .ordinal = 0x000b, + .patch = fwdlusb_updateFirmware, + .link = NULL + }, { + .name = "fwdlusb_getFirmwareInfo", + .ordinal = 0x000c, + .patch = fwdlusb_getFirmwareInfo, + .link = NULL + }, { + .name = "fwdlusb_MakeThread", + .ordinal = 0x0065, + .patch = fwdlusb_MakeThread, + .link = NULL + }, { + .name = "fwdlusb_ReleaseThread", + .ordinal = 0x0066, + .patch = fwdlusb_ReleaseThread, + .link = NULL + }, { + .name = "fwdlusb_AttachThreadCount", + .ordinal = 0x0067, + .patch = fwdlusb_AttachThreadCount, + .link = NULL + }, { + .name = "fwdlusb_getErrorLog", + .ordinal = 0x0068, + .patch = fwdlusb_getErrorLog, + .link = NULL + }, +}; + +/* C300usb hook tbl */ + +static const struct hook_symbol C300usb_hooks[] = { + { + .name = "chcusb_MakeThread", + .ordinal = 0x0001, + .patch = chcusb_MakeThread, + .link = NULL + }, { + .name = "chcusb_open", + .ordinal = 0x0002, + .patch = chcusb_open, + .link = NULL + }, { + .name = "chcusb_close", + .ordinal = 0x0003, + .patch = chcusb_close, + .link = NULL + }, { + .name = "chcusb_ReleaseThread", + .ordinal = 0x0004, + .patch = chcusb_ReleaseThread, + .link = NULL + }, { + .name = "chcusb_listupPrinter", + .ordinal = 0x0005, + .patch = chcusb_listupPrinter, + .link = NULL + }, { + .name = "chcusb_listupPrinterSN", + .ordinal = 0x0006, + .patch = chcusb_listupPrinterSN, + .link = NULL + }, { + .name = "chcusb_selectPrinter", + .ordinal = 0x0007, + .patch = chcusb_selectPrinter, + .link = NULL + }, { + .name = "chcusb_selectPrinterSN", + .ordinal = 0x0008, + .patch = chcusb_selectPrinterSN, + .link = NULL + }, { + .name = "chcusb_getPrinterInfo", + .ordinal = 0x0009, + .patch = chcusb_getPrinterInfo, + .link = NULL + }, { + .name = "chcusb_imageformat", + .ordinal = 0x000a, + .patch = chcusb_imageformat, + .link = NULL + }, { + .name = "chcusb_setmtf", + .ordinal = 0x000b, + .patch = chcusb_setmtf, + .link = NULL + }, { + .name = "chcusb_makeGamma", + .ordinal = 0x000c, + .patch = chcusb_makeGamma, + .link = NULL + }, { + .name = "chcusb_setIcctable", + .ordinal = 0x000d, + .patch = chcusb_setIcctable, + .link = NULL + }, { + .name = "chcusb_copies", + .ordinal = 0x000e, + .patch = chcusb_copies, + .link = NULL + }, { + .name = "chcusb_status", + .ordinal = 0x000f, + .patch = chcusb_status, + .link = NULL + }, { + .name = "chcusb_statusAll", + .ordinal = 0x0010, + .patch = chcusb_statusAll, + .link = NULL + }, { + .name = "chcusb_startpage", + .ordinal = 0x0011, + .patch = chcusb_startpage_300, + .link = NULL + }, { + .name = "chcusb_endpage", + .ordinal = 0x0012, + .patch = chcusb_endpage, + .link = NULL + }, { + .name = "chcusb_write", + .ordinal = 0x0013, + .patch = chcusb_write, + .link = NULL + }, { + .name = "chcusb_writeLaminate", + .ordinal = 0x0014, + .patch = chcusb_writeLaminate, + .link = NULL + }, { + .name = "chcusb_setPrinterInfo", + .ordinal = 0x0015, + .patch = chcusb_setPrinterInfo, + .link = NULL + }, { + .name = "chcusb_getGamma", + .ordinal = 0x0016, + .patch = chcusb_getGamma, + .link = NULL + }, { + .name = "chcusb_getMtf", + .ordinal = 0x0017, + .patch = chcusb_getMtf, + .link = NULL + }, { + .name = "chcusb_cancelCopies", + .ordinal = 0x0018, + .patch = chcusb_cancelCopies, + .link = NULL + }, { + .name = "chcusb_setPrinterToneCurve", + .ordinal = 0x0019, + .patch = chcusb_setPrinterToneCurve, + .link = NULL + }, { + .name = "chcusb_getPrinterToneCurve", + .ordinal = 0x001a, + .patch = chcusb_getPrinterToneCurve, + .link = NULL + }, { + .name = "chcusb_blinkLED", + .ordinal = 0x001b, + .patch = chcusb_blinkLED, + .link = NULL + }, { + .name = "chcusb_resetPrinter", + .ordinal = 0x001c, + .patch = chcusb_resetPrinter, + .link = NULL + }, { + .name = "chcusb_AttachThreadCount", + .ordinal = 0x001d, + .patch = chcusb_AttachThreadCount, + .link = NULL + }, { + .name = "chcusb_getPrintIDStatus", + .ordinal = 0x001e, + .patch = chcusb_getPrintIDStatus, + .link = NULL + }, { + .name = "chcusb_setPrintStandby", + .ordinal = 0x001f, + .patch = chcusb_setPrintStandby_300, + .link = NULL + }, { + .name = "chcusb_testCardFeed", + .ordinal = 0x0020, + .patch = chcusb_testCardFeed, + .link = NULL + }, { + .name = "chcusb_setParameter", + .ordinal = 0x0021, + .patch = chcusb_setParameter, + .link = NULL + }, { + .name = "chcusb_getParameter", + .ordinal = 0x0022, + .patch = chcusb_getParameter, + .link = NULL + }, { + .name = "chcusb_getErrorStatus", + .ordinal = 0x0023, + .patch = chcusb_getErrorStatus, + .link = NULL + }, { + .name = "chcusb_setCutList", + .ordinal = 0x0028, + .patch = chcusb_setCutList, + .link = NULL + }, { + .name = "chcusb_setLaminatePattern", + .ordinal = 0x0029, + .patch = chcusb_setLaminatePattern, + .link = NULL + }, { + .name = "chcusb_color_adjustment", + .ordinal = 0x002a, + .patch = chcusb_color_adjustment, + .link = NULL + }, { + .name = "chcusb_color_adjustmentEx", + .ordinal = 0x002b, + .patch = chcusb_color_adjustmentEx, + .link = NULL + }, { + .name = "chcusb_getEEPROM", + .ordinal = 0x003a, + .patch = chcusb_getEEPROM, + .link = NULL + }, { + .name = "chcusb_universal_command", + .ordinal = 0x0049, + .patch = chcusb_universal_command, + .link = NULL + }, +}; + +/* C310A-Busb/C320Ausb/C330Ausb hook tbl. The ordinals are required, as some + games, for example Sekito, will import this library by ordinal and not by + name. */ + +static const struct hook_symbol C3XXusb_hooks[] = { + { + .name = "chcusb_MakeThread", + .ordinal = 0x0001, + .patch = chcusb_MakeThread, + .link = NULL + }, { + .name = "chcusb_open", + .ordinal = 0x0002, + .patch = chcusb_open, + .link = NULL + }, { + .name = "chcusb_close", + .ordinal = 0x0003, + .patch = chcusb_close, + .link = NULL + }, { + .name = "chcusb_ReleaseThread", + .ordinal = 0x0004, + .patch = chcusb_ReleaseThread, + .link = NULL + }, { + .name = "chcusb_listupPrinter", + .ordinal = 0x0005, + .patch = chcusb_listupPrinter, + .link = NULL + }, { + .name = "chcusb_listupPrinterSN", + .ordinal = 0x0006, + .patch = chcusb_listupPrinterSN, + .link = NULL + }, { + .name = "chcusb_selectPrinter", + .ordinal = 0x0007, + .patch = chcusb_selectPrinter, + .link = NULL + }, { + .name = "chcusb_selectPrinterSN", + .ordinal = 0x0008, + .patch = chcusb_selectPrinterSN, + .link = NULL + }, { + .name = "chcusb_getPrinterInfo", + .ordinal = 0x0009, + .patch = chcusb_getPrinterInfo, + .link = NULL + }, { + .name = "chcusb_imageformat", + .ordinal = 0x000a, + .patch = chcusb_imageformat, + .link = NULL + }, { + .name = "chcusb_setmtf", + .ordinal = 0x000b, + .patch = chcusb_setmtf, + .link = NULL + }, { + .name = "chcusb_makeGamma", + .ordinal = 0x000c, + .patch = chcusb_makeGamma, + .link = NULL + }, { + .name = "chcusb_setIcctable", + .ordinal = 0x000d, + .patch = chcusb_setIcctable, + .link = NULL + }, { + .name = "chcusb_copies", + .ordinal = 0x000e, + .patch = chcusb_copies, + .link = NULL + }, { + .name = "chcusb_status", + .ordinal = 0x000f, + .patch = chcusb_status, + .link = NULL + }, { + .name = "chcusb_statusAll", + .ordinal = 0x0010, + .patch = chcusb_statusAll, + .link = NULL + }, { + .name = "chcusb_startpage", + .ordinal = 0x0011, + .patch = chcusb_startpage, + .link = NULL + }, { + .name = "chcusb_endpage", + .ordinal = 0x0012, + .patch = chcusb_endpage, + .link = NULL + }, { + .name = "chcusb_write", + .ordinal = 0x0013, + .patch = chcusb_write, + .link = NULL + }, { + .name = "chcusb_writeLaminate", + .ordinal = 0x0014, + .patch = chcusb_writeLaminate, + .link = NULL + }, { + .name = "chcusb_writeHolo", + .ordinal = 0x0015, + .patch = chcusb_writeHolo, + .link = NULL + }, { + .name = "chcusb_setPrinterInfo", + .ordinal = 0x0016, + .patch = chcusb_setPrinterInfo, + .link = NULL + }, { + .name = "chcusb_getGamma", + .ordinal = 0x0017, + .patch = chcusb_getGamma, + .link = NULL + }, { + .name = "chcusb_getMtf", + .ordinal = 0x0018, + .patch = chcusb_getMtf, + .link = NULL + }, { + .name = "chcusb_cancelCopies", + .ordinal = 0x0019, + .patch = chcusb_cancelCopies, + .link = NULL + }, { + .name = "chcusb_setPrinterToneCurve", + .ordinal = 0x001a, + .patch = chcusb_setPrinterToneCurve, + .link = NULL + }, { + .name = "chcusb_getPrinterToneCurve", + .ordinal = 0x001b, + .patch = chcusb_getPrinterToneCurve, + .link = NULL + }, { + .name = "chcusb_blinkLED", + .ordinal = 0x001c, + .patch = chcusb_blinkLED, + .link = NULL + }, { + .name = "chcusb_resetPrinter", + .ordinal = 0x001d, + .patch = chcusb_resetPrinter, + .link = NULL + }, { + .name = "chcusb_AttachThreadCount", + .ordinal = 0x001e, + .patch = chcusb_AttachThreadCount, + .link = NULL + }, { + .name = "chcusb_getPrintIDStatus", + .ordinal = 0x001f, + .patch = chcusb_getPrintIDStatus, + .link = NULL + }, { + .name = "chcusb_setPrintStandby", + .ordinal = 0x0020, + .patch = chcusb_setPrintStandby, + .link = NULL + }, { + .name = "chcusb_testCardFeed", + .ordinal = 0x0021, + .patch = chcusb_testCardFeed, + .link = NULL + }, { + .name = "chcusb_exitCard", + .ordinal = 0x0022, + .patch = chcusb_exitCard, + .link = NULL + }, { + .name = "chcusb_getCardRfidTID", + .ordinal = 0x0023, + .patch = chcusb_getCardRfidTID, + .link = NULL + }, { + .name = "chcusb_commCardRfidReader", + .ordinal = 0x0024, + .patch = chcusb_commCardRfidReader, + .link = NULL + }, { + .name = "chcusb_updateCardRfidReader", + .ordinal = 0x0025, + .patch = chcusb_updateCardRfidReader, + .link = NULL + }, { + .name = "chcusb_getErrorLog", + .ordinal = 0x0026, + .patch = chcusb_getErrorLog, + .link = NULL + }, { + .name = "chcusb_getErrorStatus", + .ordinal = 0x0027, + .patch = chcusb_getErrorStatus, + .link = NULL + }, { + .name = "chcusb_setCutList", + .ordinal = 0x0028, + .patch = chcusb_setCutList, + .link = NULL + }, { + .name = "chcusb_setLaminatePattern", + .ordinal = 0x0029, + .patch = chcusb_setLaminatePattern, + .link = NULL + }, { + .name = "chcusb_color_adjustment", + .ordinal = 0x002a, + .patch = chcusb_color_adjustment, + .link = NULL + }, { + .name = "chcusb_color_adjustmentEx", + .ordinal = 0x002b, + .patch = chcusb_color_adjustmentEx, + .link = NULL + }, { + .name = "chcusb_getEEPROM", + .ordinal = 0x003a, + .patch = chcusb_getEEPROM, + .link = NULL + }, { + .name = "chcusb_setParameter", + .ordinal = 0x0040, + .patch = chcusb_setParameter, + .link = NULL + }, { + .name = "chcusb_getParameter", + .ordinal = 0x0041, + .patch = chcusb_getParameter, + .link = NULL + }, { + .name = "chcusb_universal_command", + .ordinal = 0x0049, + .patch = chcusb_universal_command, + .link = NULL + }, +}; + +/* S6145-5Husb hook tbl. The ordinals are required, as some games, for example + Sekito, will import this library by ordinal and not by name. */ + +static const struct hook_symbol S6145hub_hooks[] = { + { + .name = "chcusb_MakeThread", + .ordinal = 0x0001, + .patch = chcusb_MakeThread, + .link = NULL + }, { + .name = "chcusb_open", + .ordinal = 0x0002, + .patch = chcusb_open, + .link = NULL + }, { + .name = "chcusb_close", + .ordinal = 0x0003, + .patch = chcusb_close, + .link = NULL + }, { + .name = "chcusb_ReleaseThread", + .ordinal = 0x0004, + .patch = chcusb_ReleaseThread, + .link = NULL + }, { + .name = "chcusb_listupPrinter", + .ordinal = 0x0005, + .patch = chcusb_listupPrinter, + .link = NULL + }, { + .name = "chcusb_listupPrinterSN", + .ordinal = 0x0006, + .patch = chcusb_listupPrinterSN, + .link = NULL + }, { + .name = "chcusb_selectPrinter", + .ordinal = 0x0007, + .patch = chcusb_selectPrinter, + .link = NULL + }, { + .name = "chcusb_selectPrinterSN", + .ordinal = 0x0008, + .patch = chcusb_selectPrinterSN, + .link = NULL + }, { + .name = "chcusb_getPrinterInfo", + .ordinal = 0x0009, + .patch = chcusb_getPrinterInfo, + .link = NULL + }, { + .name = "chcusb_imageformat", + .ordinal = 0x000a, + .patch = chcusb_imageformat, + .link = NULL + }, { + .name = "chcusb_setmtf", + .ordinal = 0x000b, + .patch = chcusb_setmtf, + .link = NULL + }, { + .name = "chcusb_makeGamma", + .ordinal = 0x000c, + .patch = chcusb_makeGamma, + .link = NULL + }, { + .name = "chcusb_setIcctable", + .ordinal = 0x000d, + .patch = chcusb_setIcctable, + .link = NULL + }, { + .name = "chcusb_copies", + .ordinal = 0x000e, + .patch = chcusb_copies, + .link = NULL + }, { + .name = "chcusb_status", + .ordinal = 0x000f, + .patch = chcusb_status, + .link = NULL + }, { + .name = "chcusb_startpage", + .ordinal = 0x0011, + .patch = chcusb_startpage, + .link = NULL + }, { + .name = "chcusb_endpage", + .ordinal = 0x0012, + .patch = chcusb_endpage, + .link = NULL + }, { + .name = "chcusb_write", + .ordinal = 0x0014, + .patch = chcusb_write, + .link = NULL + }, { + .name = "chcusb_setPrinterInfo", + .ordinal = 0x0015, + .patch = chcusb_setPrinterInfo, + .link = NULL + }, { + .name = "chcusb_getMtf", + .ordinal = 0x0017, + .patch = chcusb_getMtf, + .link = NULL + }, { + .name = "chcusb_resetPrinter", + .ordinal = 0x001c, + .patch = chcusb_resetPrinter, + .link = NULL + }, { + .name = "chcusb_getPrintIDStatus", + .ordinal = 0x0020, + .patch = chcusb_getPrintIDStatus, + .link = NULL + }, +}; + +/* PrintDLL hook tbl */ + +static struct hook_symbol printdll_hooks[] = { + { + .name = "CFW_close", + .ordinal = 0x0001, + .patch = CFW_close, + .link = NULL + }, { + .name = "CFW_getFirmwareInfo", + .ordinal = 0x0002, + .patch = CFW_getFirmwareInfo, + .link = NULL + }, { + .name = "CFW_getPrinterInfo", + .ordinal = 0x0003, + .patch = CFW_getPrinterInfo, + .link = NULL + }, { + .name = "CFW_init", + .ordinal = 0x0004, + .patch = CFW_init, + .link = NULL + }, { + .name = "CFW_listupPrinter", + .ordinal = 0x0005, + .patch = CFW_listupPrinter, + .link = NULL + }, { + .name = "CFW_listupPrinterSN", + .ordinal = 0x0006, + .patch = CFW_listupPrinterSN, + .link = NULL + }, { + .name = "CFW_open", + .ordinal = 0x0007, + .patch = CFW_open, + .link = NULL + }, { + .name = "CFW_resetPrinter", + .ordinal = 0x0008, + .patch = CFW_resetPrinter, + .link = NULL + }, { + .name = "CFW_selectPrinter", + .ordinal = 0x0009, + .patch = CFW_selectPrinter, + .link = NULL + }, { + .name = "CFW_selectPrinterSN", + .ordinal = 0x000a, + .patch = CFW_selectPrinterSN, + .link = NULL + }, { + .name = "CFW_status", + .ordinal = 0x000b, + .patch = CFW_status, + .link = NULL + }, { + .name = "CFW_statusAll", + .ordinal = 0x000c, + .patch = CFW_statusAll, + .link = NULL + }, { + .name = "CFW_term", + .ordinal = 0x000d, + .patch = CFW_term, + .link = NULL + }, { + .name = "CFW_updateFirmware", + .ordinal = 0x000e, + .patch = CFW_updateFirmware, + .link = NULL + }, { + .name = "CHCUSB_AttachThreadCount", + .ordinal = 0x000f, + .patch = CHCUSB_AttachThreadCount, + .link = NULL + }, { + .name = "CHCUSB_MakeThread", + .ordinal = 0x0010, + .patch = CHCUSB_MakeThread, + .link = NULL + }, { + .name = "CHCUSB_ReleaseThread", + .ordinal = 0x0011, + .patch = CHCUSB_ReleaseThread, + .link = NULL + }, { + .name = "CHCUSB_blinkLED", + .ordinal = 0x0012, + .patch = CHCUSB_blinkLED, + .link = NULL + }, { + .name = "CHCUSB_cancelCopies", + .ordinal = 0x0013, + .patch = CHCUSB_cancelCopies, + .link = NULL + }, { + .name = "CHCUSB_close", + .ordinal = 0x0014, + .patch = CHCUSB_close, + .link = NULL + }, { + .name = "CHCUSB_commCardRfidReader", + .ordinal = 0x0015, + .patch = CHCUSB_commCardRfidReader, + .link = NULL + }, { + .name = "CHCUSB_copies", + .ordinal = 0x0016, + .patch = CHCUSB_copies, + .link = NULL + }, { + .name = "CHCUSB_endpage", + .ordinal = 0x0017, + .patch = CHCUSB_endpage, + .link = NULL + }, { + .name = "CHCUSB_exitCard", + .ordinal = 0x0018, + .patch = CHCUSB_exitCard, + .link = NULL + }, { + .name = "CHCUSB_getCardRfidTID", + .ordinal = 0x0019, + .patch = CHCUSB_getCardRfidTID, + .link = NULL + }, { + .name = "CHCUSB_getErrorLog", + .ordinal = 0x001a, + .patch = CHCUSB_getErrorLog, + .link = NULL + }, { + .name = "CHCUSB_getErrorStatus", + .ordinal = 0x001b, + .patch = CHCUSB_getErrorStatus, + .link = NULL + }, { + .name = "CHCUSB_getGamma", + .ordinal = 0x001c, + .patch = CHCUSB_getGamma, + .link = NULL + }, { + .name = "CHCUSB_getMtf", + .ordinal = 0x001d, + .patch = CHCUSB_getMtf, + .link = NULL + }, { + .name = "CHCUSB_getPrintIDStatus", + .ordinal = 0x001e, + .patch = CHCUSB_getPrintIDStatus, + .link = NULL + }, { + .name = "CHCUSB_getPrinterInfo", + .ordinal = 0x001f, + .patch = CHCUSB_getPrinterInfo, + .link = NULL + }, { + .name = "CHCUSB_getPrinterToneCurve", + .ordinal = 0x0020, + .patch = CHCUSB_getPrinterToneCurve, + .link = NULL + }, { + .name = "CHCUSB_imageformat", + .ordinal = 0x0021, + .patch = CHCUSB_imageformat, + .link = NULL + }, { + .name = "CHCUSB_init", + .ordinal = 0x0022, + .patch = CHCUSB_init, + .link = NULL + }, { + .name = "CHCUSB_listupPrinter", + .ordinal = 0x0023, + .patch = CHCUSB_listupPrinter, + .link = NULL + }, { + .name = "CHCUSB_listupPrinterSN", + .ordinal = 0x0024, + .patch = CHCUSB_listupPrinterSN, + .link = NULL + }, { + .name = "CHCUSB_makeGamma", + .ordinal = 0x0025, + .patch = CHCUSB_makeGamma, + .link = NULL + }, { + .name = "CHCUSB_open", + .ordinal = 0x0026, + .patch = CHCUSB_open, + .link = NULL + }, { + .name = "CHCUSB_resetPrinter", + .ordinal = 0x0027, + .patch = CHCUSB_resetPrinter, + .link = NULL + }, { + .name = "CHCUSB_selectPrinter", + .ordinal = 0x0028, + .patch = CHCUSB_selectPrinter, + .link = NULL + }, { + .name = "CHCUSB_selectPrinterSN", + .ordinal = 0x0029, + .patch = CHCUSB_selectPrinterSN, + .link = NULL + }, { + .name = "CHCUSB_setIcctable", + .ordinal = 0x002a, + .patch = CHCUSB_setIcctable, + .link = NULL + }, { + .name = "CHCUSB_setIcctableProfile", + .ordinal = 0x002b, + .patch = CHCUSB_setIcctableProfile, + .link = NULL + }, { + .name = "CHCUSB_setPrintStandby", + .ordinal = 0x002c, + .patch = CHCUSB_setPrintStandby, + .link = NULL + }, { + .name = "CHCUSB_setPrinterInfo", + .ordinal = 0x002d, + .patch = CHCUSB_setPrinterInfo, + .link = NULL + }, { + .name = "CHCUSB_setPrinterToneCurve", + .ordinal = 0x0023, + .patch = CHCUSB_setPrinterToneCurve, + .link = NULL + }, { + .name = "CHCUSB_setmtf", + .ordinal = 0x002f, + .patch = CHCUSB_setmtf, + .link = NULL + }, { + .name = "CHCUSB_startpage", + .ordinal = 0x0030, + .patch = CHCUSB_startpage, + .link = NULL + }, { + .name = "CHCUSB_status", + .ordinal = 0x0031, + .patch = CHCUSB_status, + .link = NULL + }, { + .name = "CHCUSB_statusAll", + .ordinal = 0x0032, + .patch = CHCUSB_statusAll, + .link = NULL + }, { + .name = "CHCUSB_term", + .ordinal = 0x0033, + .patch = CHCUSB_term, + .link = NULL + }, { + .name = "CHCUSB_testCardFeed", + .ordinal = 0x0034, + .patch = CHCUSB_testCardFeed, + .link = NULL + }, { + .name = "CHCUSB_updateCardRfidReader", + .ordinal = 0x0035, + .patch = CHCUSB_updateCardRfidReader, + .link = NULL + }, { + .name = "CHCUSB_write", + .ordinal = 0x0036, + .patch = CHCUSB_write, + .link = NULL + }, { + .name = "CHCUSB_writeHolo", + .ordinal = 0x0037, + .patch = CHCUSB_writeHolo, + .link = NULL + }, { + .name = "CHCUSB_writeLaminate", + .ordinal = 0x0038, + .patch = CHCUSB_writeLaminate, + .link = NULL + }, +}; + +static struct printer_config printer_config; + +void printer_hook_init(const struct printer_config *cfg, int rfid_port_no, HINSTANCE self) { + HANDLE fwFile = NULL; + DWORD bytesRead = 0; + + assert(cfg != NULL); + + if (!cfg->enable) { + return; + } + + /* Set serial and rotate cfg */ + + memcpy(&serialNo, cfg->serial_no, sizeof(serialNo)); + _byteswap_uint64(serialNo); + + rotate180 = cfg->rotate_180; + + memcpy(&printer_config, cfg, sizeof(*cfg)); + printer_hook_insert_hooks(NULL); + + /* + if (self != NULL) { + // dll_hook_push(self, L"PrintDLL.dll"); // TODO: This doesn't work. Unity moment + dll_hook_push(self, L"C300usb.dll"); + dll_hook_push(self, L"C300FWDLusb.dll"); + dll_hook_push(self, L"C310Ausb.dll"); + dll_hook_push(self, L"C310Busb.dll"); + dll_hook_push(self, L"C310FWDLusb.dll"); + dll_hook_push(self, L"C310BFWDLusb.dll"); + dll_hook_push(self, L"C320Ausb.dll"); + dll_hook_push(self, L"C320AFWDLusb.dll"); + dll_hook_push(self, L"C330Ausb.dll"); + dll_hook_push(self, L"C330AFWDLusb.dll"); + } + */ + + // Load firmware if has previously been written to + fwFile = CreateFileW(cfg->main_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + ReadFile(fwFile, mainFirmware, sizeof(mainFirmware), &bytesRead, NULL); + CloseHandle(fwFile); + } + + fwFile = CreateFileW(cfg->dsp_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + ReadFile(fwFile, dspFirmware, sizeof(dspFirmware), &bytesRead, NULL); + CloseHandle(fwFile); + } + + fwFile = CreateFileW(cfg->param_fw_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + ReadFile(fwFile, paramFirmware, sizeof(dspFirmware), &bytesRead, NULL); + CloseHandle(fwFile); + } + + CreateDirectoryW(cfg->printer_out_path, NULL); + memcpy(printer_out_path, cfg->printer_out_path, MAX_PATH); + + if (rfid_port_no != 0) { + InitializeCriticalSection(&deck_lock); + + uart_init(&deck_uart, rfid_port_no); + deck_uart.written.bytes = deck_written_bytes; + deck_uart.written.nbytes = sizeof(deck_written_bytes); + deck_uart.readable.bytes = deck_readable_bytes; + deck_uart.readable.nbytes = sizeof(deck_readable_bytes); + + dprintf("Printer: RFID: hook enabled.\n"); + + if (FAILED(iohook_push_handler(deck_handle_irp))) { + dprintf("Printer: RFID: failed to hook IRP handler.\n"); + } + } + + dprintf("Printer: hook enabled.\n"); +} + +void printer_hook_insert_hooks(HMODULE target) { + hook_table_apply(target, "C310Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks)); + hook_table_apply(target, "C310Busb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks)); + hook_table_apply(target, "C310FWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks)); + hook_table_apply(target, "C310BFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks)); + hook_table_apply(target, "C320Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks)); + hook_table_apply(target, "C320AFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks)); + hook_table_apply(target, "C330Ausb.dll", C3XXusb_hooks, _countof(C3XXusb_hooks)); + hook_table_apply(target, "C330AFWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks)); + hook_table_apply(target, "S6145-5Husb.dll", S6145hub_hooks, _countof(S6145hub_hooks)); + + /* Unity workaround */ + proc_addr_table_push(target, "PrintDLL.dll", printdll_hooks, _countof(printdll_hooks)); + proc_addr_table_push(target, "C300usb.dll", C300usb_hooks, _countof(C300usb_hooks)); + proc_addr_table_push(target, "C300FWDLusb.dll", C3XXFWDLusb_hooks, _countof(C3XXFWDLusb_hooks)); +} + +static inline bool check_for_wait_time(){ + return finishTime > 0 && GetTickCount64() < finishTime; +} + +static void generate_rfid(void) { + for (int i = 0; i < sizeof(cardRFID); i++) + cardRFID[i] = rand(); + + dprintf("Printer: New card RFID:\n"); + dump(cardRFID, sizeof(cardRFID)); +} + +static HRESULT deck_handle_irp(struct irp *irp) { + HRESULT hr; + + assert(irp != NULL); + + if (!uart_match_irp(&deck_uart, irp)) { + return iohook_invoke_next(irp); + } + + EnterCriticalSection(&deck_lock); + hr = deck_handle_irp_locked(irp); + LeaveCriticalSection(&deck_lock); + + return hr; +} + +static HRESULT deck_handle_irp_locked(struct irp *irp) { + uint8_t req[1024]; + struct iobuf req_iobuf; + HRESULT hr; + + if (irp->op == IRP_OP_OPEN) { + dprintf("Printer: RFID: Starting backend\n"); + } + + hr = uart_handle_irp(&deck_uart, irp); + + if (SUCCEEDED(hr) && irp->op == IRP_OP_READ && read_pending == true) { + deck_read_one(); + return S_OK; + } + + if (FAILED(hr) || irp->op != IRP_OP_WRITE) { + return hr; + } + + for (;;) { + // if (deck_uart.written.pos != 0) { + // dprintf("Printer: RFID: TX Buffer:\n"); + // dump_iobuf(&deck_uart.written); + // } + + req_iobuf.bytes = req; + req_iobuf.nbytes = sizeof(req); + req_iobuf.pos = 0; + + hr = deck_frame_decode(&req_iobuf, &deck_uart.written); + + if (hr != S_OK) { + if (FAILED(hr)) { + dprintf("Printer: RFID: Deframe error: %x, %d %d\n", (int)hr, (int)req_iobuf.nbytes, (int)req_iobuf.pos); + } + + return hr; + } + + // dprintf("Printer: RFID: Deframe Buffer:\n"); + // dump_iobuf(&req_iobuf); + + hr = deck_req_dispatch((const union deck_req_any *)&req); + + if (FAILED(hr)) { + dprintf("Printer: RFID: Processing error: %x\n", (int)hr); + } + + // dprintf("Printer: RFID: Written bytes:\n"); + // dump_iobuf(&deck_uart.readable); + } +} + +static HRESULT deck_req_dispatch(const union deck_req_any *req) { + switch (req->hdr.cmd) { + case DECK_CMD_RESET: + case DECK_CMD_INIT_UNK1: + case DECK_CMD_INIT_UNK2: + case DECK_CMD_INIT_UNK3: + return deck_req_nop(req->hdr.cmd); + + case DECK_CMD_GET_BOOT_FW_VERSION: + return deck_req_get_boot_fw_version(); + + case DECK_CMD_GET_APP_FW_VERSION: + return deck_req_get_app_fw_version(); + + case DECK_CMD_GET_BOARD_INFO: + return deck_req_get_board_info(); + + case DECK_CMD_READ: + return deck_req_read(); + + case DECK_CMD_READ_DATA: + return deck_req_read_data(); + + case DECK_CMD_WRITE: + return deck_req_write(req->bytes); + + default: + dprintf("Printer: RFID: Unhandled command %#02x\n", req->hdr.cmd); + + return S_OK; + } +} + +static HRESULT deck_req_get_boot_fw_version(void) { + struct deck_resp_get_boot_fw_version resp; + + dprintf("Printer: RFID: Get Boot FW Version\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_GET_BOOT_FW_VERSION; + resp.hdr.status = 0; + resp.hdr.nbytes = 1; + resp.boot_fw_version = 0x90; + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT deck_req_get_app_fw_version(void) { + struct deck_resp_get_app_fw_version resp; + + dprintf("Printer: RFID: Get App FW Version\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_GET_APP_FW_VERSION; + resp.hdr.status = 0; + resp.hdr.nbytes = 1; + resp.app_fw_version = 0x90; + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT deck_req_get_board_info(void) { + struct deck_resp_get_board_info resp; + + dprintf("Printer: RFID: Get Board Info\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_GET_BOARD_INFO; + resp.hdr.status = 0; + resp.hdr.nbytes = 9; + memcpy(resp.board, (void *)"837-15347", 9); + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT deck_req_read(void) { + struct deck_resp_read resp; + + dprintf("Printer: RFID: Read Card\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_READ; + resp.hdr.status = DECK_READ_START; + resp.hdr.nbytes = 0; + + current_card_idx = 0; + read_pending = true; + + return deck_frame_encode(&deck_uart.readable, &resp.hdr, sizeof(resp.hdr)); +} + +static HRESULT deck_req_read_data(void) { + struct deck_resp_read_data resp; + + dprintf("Printer: RFID: Read Card Data\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_READ_DATA; + resp.hdr.status = 0; + resp.hdr.nbytes = 32; + memcpy(resp.card_data, cardDataBuffer, 32); + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static HRESULT deck_req_write(const uint8_t *req_bytes) { + struct deck_resp_hdr resp; + uint8_t off; + + resp.sync = 0xE0; + resp.cmd = DECK_CMD_WRITE; + resp.status = 0; + resp.nbytes = 0; + + off = (req_bytes[5] - 1) * 2; + cardDataBuffer[off] = req_bytes[6]; + cardDataBuffer[off + 1] = req_bytes[7]; + if (req_bytes[5] == 0x10) { + dprintf("Printer: RFID: Card Data Buffer: \n"); + dump(cardDataBuffer, 0x20); + } + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static void deck_read_one(void) { + struct deck_resp_read resp; + + dprintf("Printer: RFID: Read One Card\n"); + + resp.hdr.sync = 0xE0; + resp.hdr.cmd = DECK_CMD_READ; + + if (current_card_idx < 1) { + resp.hdr.status = DECK_READ_DATA; + resp.hdr.nbytes = 44; + memset(resp.card_data, 0, 44); + memcpy(resp.card_data, cardRFID, 0xC); + memcpy(resp.card_data + 0x0C, cardDataBuffer, 0x20); + dump(resp.card_data, 44); + + deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); + current_card_idx++; + } else { + resp.hdr.status = DECK_READ_END; + resp.hdr.nbytes = 0; + deck_frame_encode(&deck_uart.readable, &resp.hdr, sizeof(resp.hdr)); + read_pending = false; + } +} + +static HRESULT deck_req_nop(uint8_t cmd) { + struct deck_resp_hdr resp; + + dprintf("Printer: RFID: No-op cmd %#02x\n", cmd); + + resp.sync = 0xE0; + resp.cmd = cmd; + resp.status = 0; + resp.nbytes = 0; + + return deck_frame_encode(&deck_uart.readable, &resp, sizeof(resp)); +} + +static void deck_frame_sync(struct iobuf *src) { + size_t i; + + for (i = 0; i < src->pos && src->bytes[i] != 0xE0; i++) + ; + + src->pos -= i; + memmove(&src->bytes[0], &src->bytes[i], i); +} + +static HRESULT deck_frame_accept(const struct iobuf *dest) { + if (dest->pos < 2 || dest->pos != dest->bytes[2] + 4) { + return S_FALSE; + } + + return S_OK; +} + +static HRESULT deck_frame_decode(struct iobuf *dest, struct iobuf *src) { + uint8_t byte; + bool escape; + size_t i; + HRESULT hr; + + assert(dest != NULL); + assert(dest->bytes != NULL || dest->nbytes == 0); + assert(dest->pos <= dest->nbytes); + assert(src != NULL); + assert(src->bytes != NULL || src->nbytes == 0); + assert(src->pos <= src->nbytes); + + dest->pos = 0; + escape = false; + + for (i = 0, hr = S_FALSE; i < src->pos && hr == S_FALSE; i++) { + /* Step the FSM to unstuff another byte */ + + byte = src->bytes[i]; + + if (dest->pos >= dest->nbytes) { + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } else if (i == 0) { + dest->bytes[dest->pos++] = byte; + } else if (byte == 0xE0) { + hr = E_FAIL; + } else if (byte == 0xD0) { + if (escape) { + hr = E_FAIL; + } + + escape = true; + } else if (escape) { + dest->bytes[dest->pos++] = byte + 1; + escape = false; + } else { + dest->bytes[dest->pos++] = byte; + } + + /* Try to accept the packet we've built up so far */ + + if (SUCCEEDED(hr)) { + hr = deck_frame_accept(dest); + } + } + + /* Handle FSM terminal state */ + + if (hr != S_FALSE) { + /* Frame was either accepted or rejected, remove it from src */ + memmove(&src->bytes[0], &src->bytes[i], src->pos - i); + src->pos -= i; + } + + return hr; +} + +static HRESULT deck_frame_encode( + struct iobuf *dest, + const void *ptr, + size_t nbytes) { + const uint8_t *src; + uint8_t checksum; + uint8_t byte; + size_t i; + HRESULT hr; + + assert(dest != NULL); + assert(dest->bytes != NULL || dest->nbytes == 0); + assert(dest->pos <= dest->nbytes); + assert(ptr != NULL); + + src = ptr; + + assert(nbytes >= 2 && src[0] == 0xE0 && src[3] + 4 == nbytes); + + if (dest->pos >= dest->nbytes) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dest->bytes[dest->pos++] = 0xE0; + checksum = 0x0; + + for (i = 1; i < nbytes; i++) { + byte = src[i]; + checksum += byte; + + hr = deck_frame_encode_byte(dest, byte); + + if (FAILED(hr)) { + return hr; + } + } + + return deck_frame_encode_byte(dest, checksum); +} + +static HRESULT deck_frame_encode_byte(struct iobuf *dest, uint8_t byte) { + if (byte == 0xD0 || byte == 0xE0) { + if (dest->pos + 2 > dest->nbytes) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dest->bytes[dest->pos++] = 0xD0; + dest->bytes[dest->pos++] = byte - 1; + } else { + if (dest->pos + 1 > dest->nbytes) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dest->bytes[dest->pos++] = byte; + } + + return S_OK; +} + +// C3XXFWDLusb stubs + +int WINAPI fwdlusb_open(uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +void WINAPI fwdlusb_close() {} + +int WINAPI fwdlusb_listupPrinter(uint8_t *rIdArray) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + memset(rIdArray, 0xFF, 0x80); + rIdArray[0] = idNumber; + return 1; +} + +int WINAPI fwdlusb_listupPrinterSN(uint64_t *rSerialArray) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + memset(rSerialArray, 0xFF, 0x400); + rSerialArray[0] = serialNo; + return 1; +} + +int WINAPI fwdlusb_selectPrinter(uint8_t printerId, uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI fwdlusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI fwdlusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + switch (tagNumber) { + case 0: // getPaperInfo + if (*rLen != 0x67) *rLen = 0x67; + if (rBuffer) memset(rBuffer, 0, *rLen); + return 1; + case 3: // getFirmwareVersion + if (*rLen != 0x99) *rLen = 0x99; + if (rBuffer) { + memset(rBuffer, 0, *rLen); + rBuffer[0] = 4; // firmware count + // bootFirmware + int i = 1; + memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware)); + // mainFirmware + i += 0x26; + memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware)); + // printParameterTable + i += 0x26; + memcpy(rBuffer + i, paramFirmware, sizeof(paramFirmware)); + // dspFirmware (C300 only) + i += 0x26; + memcpy(rBuffer + i, dspFirmware, 0x26); + } + return 1; + case 4: // getPrintCountInfo (C300 only) + if (!rBuffer) { + *rLen = 0x1C; + return 1; + } + int32_t bInfoC300[10] = {0}; + uint16_t printCounterC300; + bInfoC300[0] = 22; // printCounter0 + bInfoC300[1] = 23; // printCounter1 + bInfoC300[2] = 33; // feedRollerCount + bInfoC300[3] = 55; // cutterCount + bInfoC300[4] = 88; // headCount + bInfoC300[5] = 999; // ribbonRemain + bInfoC300[6] = 0; // dummy + if (*rLen <= 0x1Cu) { + memcpy(rBuffer, bInfoC300, *rLen); + } else { + bInfoC300[7] = 0; // TODO + if (*rLen > 0x20u) *rLen = 0x20; + memcpy(rBuffer, bInfoC300, *rLen); + } + break; + case 5: // getPrintCountInfo + if (!rBuffer) { + *rLen = 0x28; + return 1; + } + int32_t bInfo[10] = {0}; + bInfo[0] = 22; // printCounter0 + bInfo[1] = 23; // printCounter1 + bInfo[2] = 33; // feedRollerCount + bInfo[3] = 55; // cutterCount + bInfo[4] = 88; // headCount + bInfo[5] = 999; // ribbonRemain + bInfo[6] = 99; // holoHeadCount + if (*rLen <= 0x1Cu) { + memcpy(rBuffer, bInfo, *rLen); + } else { + bInfo[7] = 69; // paperCount + bInfo[8] = 21; // printCounter2 + bInfo[9] = 20; // holoPrintCounter + if (*rLen > 0x28u) *rLen = 0x28; + memcpy(rBuffer, bInfo, *rLen); + } + break; + case 26: // getPrinterSerial + if (*rLen != 8) *rLen = 8; + if (rBuffer) memcpy(rBuffer, &serialNo, 8); + return 1; + default: + dprintf("Printer: %s: Unknown parameter 'tagNumber' value %d.\n", __func__, tagNumber); + break; + } + return 1; +} + +int WINAPI fwdlusb_status(uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI fwdlusb_statusAll(uint8_t *idArray, uint16_t *rResultArray) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + for (int i = 0; *(uint8_t *)(idArray + i) != 255 && i < 128; ++i) { + *(uint16_t *)(rResultArray + 2 * i) = 0; + } + + return 1; +} + +int WINAPI fwdlusb_resetPrinter(uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI fwdlusb_getFirmwareVersion(uint8_t *buffer, int size) { + int8_t a; + uint32_t b = 0; + for (int32_t i = 0; i < size; ++i) { + if (*(int8_t *)(buffer + i) < 0x30 || *(int8_t *)(buffer + i) > 0x39) { + if (*(int8_t *)(buffer + i) < 0x41 || *(int8_t *)(buffer + i) > 0x46) { + if (*(int8_t *)(buffer + i) < 0x61 || *(int8_t *)(buffer + i) > 0x66) { + return 0; + } + a = *(int8_t *)(buffer + i) - 0x57; + } else { + a = *(int8_t *)(buffer + i) - 0x37; + } + } else { + a = *(int8_t *)(buffer + i) - 0x30; + } + b = a + 0x10 * b; + } + return b; +} + +int WINAPI fwdlusb_updateFirmware_main(uint8_t update, LPCSTR filename, uint16_t *rResult) { + DWORD result; + HANDLE fwFile = NULL; + DWORD bytesWritten = 0; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + CloseHandle(hFile); + if (result && read > 0x24) { + uint8_t rBuffer[0x40] = {0}; + + memcpy(rBuffer, buffer + 0x2, 0x8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + *(rBuffer + 0x22) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1A, 0x2); + *(rBuffer + 0x23) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1C, 0x2); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + memcpy(mainFirmware, rBuffer, 0x40); + + fwFile = CreateFileW(printer_config.main_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL); + CloseHandle(fwFile); + } + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_updateFirmware_dsp(uint8_t update, LPCSTR filename, uint16_t *rResult) { + DWORD result; + HANDLE fwFile = NULL; + DWORD bytesWritten = 0; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + CloseHandle(hFile); + if (result && read > 0x24) { + uint8_t rBuffer[0x40] = {0}; + + memcpy(rBuffer, buffer + 0x2, 8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1); + memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + memcpy(dspFirmware, rBuffer, 0x40); + + fwFile = CreateFileW(printer_config.dsp_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL); + CloseHandle(fwFile); + } + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_updateFirmware_param(uint8_t update, LPCSTR filename, uint16_t *rResult) { + DWORD result; + HANDLE fwFile = NULL; + DWORD bytesWritten = 0; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + CloseHandle(hFile); + if (result && read > 0x24) { + uint8_t rBuffer[0x40] = {0}; + + memcpy(rBuffer, buffer + 0x2, 8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1); + memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + memcpy(paramFirmware, rBuffer, 0x40); + + fwFile = CreateFileW(printer_config.param_fw_path, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (fwFile != NULL) { + WriteFile(fwFile, rBuffer, 0x40, &bytesWritten, NULL); + CloseHandle(fwFile); + } + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_updateFirmware(uint8_t update, LPCSTR filename, uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + if (update == 1) { + return fwdlusb_updateFirmware_main(update, filename, rResult); + } else if (update == 2) { + return fwdlusb_updateFirmware_dsp(update, filename, rResult); + } else if (update == 3) { + return fwdlusb_updateFirmware_param(update, filename, rResult); + } else { + *rResult = 0; + return 1; + } +} + +int WINAPI fwdlusb_getFirmwareInfo_main(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) { + DWORD result; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + if (result && read > 0x24) { + memcpy(rBuffer, buffer + 0x2, 0x8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + *(rBuffer + 0x22) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1A, 0x2); + *(rBuffer + 0x23) = (uint8_t)fwdlusb_getFirmwareVersion(buffer + 0x1C, 0x2); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_getFirmwareInfo_dsp(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) { + DWORD result; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + if (result && read > 0x24) { + memcpy(rBuffer, buffer + 0x2, 8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1); + memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_getFirmwareInfo_param(LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) { + DWORD result; + + if (filename) { + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + { + if (rResult) *rResult = 1005; + result = 0; + } + + DWORD read; + uint8_t buffer[0x40]; + result = ReadFile(hFile, buffer, 0x40, &read, NULL); + if (result && read > 0x24) { + memcpy(rBuffer, buffer + 0x2, 8); + memcpy(rBuffer + 0x8, buffer + 0xA, 0x10); + memcpy(rBuffer + 0x18, buffer + 0x20, 0xA); + memcpy(rBuffer + 0x22, buffer + 0x1A, 0x1); + memcpy(rBuffer + 0x23, buffer + 0x1C, 0x1); + memcpy(rBuffer + 0x24, buffer + 0x2A, 0x2); + + if (rResult) *rResult = 0; + result = 1; + } else { + if (rResult) *rResult = 1005; + result = 0; + } + } else { + if (rResult) *rResult = 1006; + result = 0; + } + + return result; +} + +int WINAPI fwdlusb_getFirmwareInfo(uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s(update: %d, filename: %s)\n", __func__, update, filename); + if (!rBuffer) { + *rLen = 38; + return 1; + } + if (*rLen > 38) *rLen = 38; + if (update == 1) { + return fwdlusb_getFirmwareInfo_main(filename, rBuffer, rLen, rResult); + } else if (update == 2) { + return fwdlusb_getFirmwareInfo_dsp(filename, rBuffer, rLen, rResult); + } else if (update == 3) { + return fwdlusb_getFirmwareInfo_param(filename, rBuffer, rLen, rResult); + } else { + if (rResult) *rResult = 0; + return 1; + } +} + +int WINAPI fwdlusb_MakeThread(uint16_t maxCount) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + return 1; +} + +int WINAPI fwdlusb_ReleaseThread(uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI fwdlusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rCount = 0; + *rMaxCount = 1; + return 1; +} + +int WINAPI fwdlusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult) { + dprintf("Printer: C3XXFWDLusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +// C3XXusb stubs + +int WINAPI chcusb_MakeThread(uint16_t maxCount) { + dprintf("Printer: C3XXusb: %s\n", __func__); + return 1; +} + +int WINAPI chcusb_open(uint16_t *rResult) { + // Seed random for card id generation + srand(time(NULL)); + generate_rfid(); + + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +void WINAPI chcusb_close() { + dprintf("Printer: C3XXusb: %s\n", __func__); +} + +int WINAPI chcusb_ReleaseThread(uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + return 1; +} + +int WINAPI chcusb_listupPrinter(uint8_t *rIdArray) { + dprintf("Printer: C3XXusb: %s\n", __func__); + memset(rIdArray, 0xFF, 0x80); + rIdArray[0] = idNumber; + return 1; +} + +int WINAPI chcusb_listupPrinterSN(uint64_t *rSerialArray) { + dprintf("Printer: C3XXusb: %s\n", __func__); + memset(rSerialArray, 0xFF, 0x400); + rSerialArray[0] = serialNo; + return 1; +} + +int WINAPI chcusb_selectPrinter(uint8_t printerId, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_selectPrinterSN(uint64_t printerSN, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) { + // dprintf("Printer: C3XXusb: %s\n", __func__); + + switch (tagNumber) { + // getPaperInfo + case 0: + if (*rLen != 0x67) *rLen = 0x67; + if (rBuffer) memset(rBuffer, 0, *rLen); + break; + + case 3: // getFirmwareVersion + if (*rLen != 0x99) *rLen = 0x99; + if (rBuffer) { + memset(rBuffer, 0, *rLen); + rBuffer[0] = 4; // firmware count + // bootFirmware + int i = 1; + memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware)); + // mainFirmware + i += 0x26; + memcpy(rBuffer + i, mainFirmware, sizeof(mainFirmware)); + // printParameterTable + i += 0x26; + memcpy(rBuffer + i, paramFirmware, sizeof(paramFirmware)); + // dspFirmware (C300 only) + i += 0x26; + memcpy(rBuffer + i, dspFirmware, 0x26); + } + break; + + case 4: // getPrintCountInfo (C300 only) + if (!rBuffer) { + *rLen = 0x1C; + return 1; + } + int32_t bInfoC300[10] = {0}; + bInfoC300[0] = 22; // printCounter0 + bInfoC300[1] = 23; // printCounter1 + bInfoC300[2] = 33; // feedRollerCount + bInfoC300[3] = 55; // cutterCount + bInfoC300[4] = 88; // headCount + bInfoC300[5] = 999; // ribbonRemain + bInfoC300[6] = 0; // dummy + if (*rLen <= 0x1Cu) { + memcpy(rBuffer, bInfoC300, *rLen); + } else { + bInfoC300[7] = 0; // TODO + if (*rLen > 0x20u) *rLen = 0x20; + memcpy(rBuffer, bInfoC300, *rLen); + } + break; + + case 5: // getPrintCountInfo2 (C310A and later) + if (!rBuffer) { + *rLen = 0x28; + return 1; + } + int32_t bInfo[10] = {0}; + bInfo[0] = 22; // printCounter0 + bInfo[1] = 23; // printCounter1 + bInfo[2] = 33; // feedRollerCount + bInfo[3] = 55; // cutterCount + bInfo[4] = 88; // headCount + bInfo[5] = 999; // ribbonRemain + bInfo[6] = 99; // holoHeadCount + if (*rLen <= 0x1Cu) { + memcpy(rBuffer, bInfo, *rLen); + } else { + bInfo[7] = 69; // paperCount + bInfo[8] = 21; // printCounter2 + bInfo[9] = 20; // holoPrintCounter + if (*rLen > 0x28u) *rLen = 0x28; + memcpy(rBuffer, bInfo, *rLen); + } + break; + + case 6: // pageStatusInfo + *rLen = 32; + if (rBuffer) { + memset(rBuffer, 0, 32); + rBuffer[0] = 88; // holoRemain + rBuffer[1] = 0; + rBuffer[2] = 0; + rBuffer[3] = 0; + } + break; + + case 7: // svc + *rLen = 2; + if (rBuffer) { + memset(rBuffer, 0, 2); + rBuffer[0] = 0; // mainError + rBuffer[1] = 0; // subError + } + break; + + case 8: // printStandby + *rLen = 1; + if (awaitingCardExit) + *rBuffer = 0xF0; + else if (STATUS == 1) + *rBuffer = 1; + else + *rBuffer = 0; + break; + + case 16: // memoryInfo + *rLen = 18; + if (rBuffer) memset(rBuffer, 0, 18); + break; + + case 20: // printMode + dprintf("Printer: C3XXusb: Unimpl tagNumber 20\n"); + break; + + case 26: // getPrinterSerial + if (*rLen != 8) *rLen = 8; + if (rBuffer) memcpy(rBuffer, &serialNo, 8); + break; + + case 30: // TODO + dprintf("Printer: C3XXusb: Unimpl tagNumber 30\n"); + break; + + case 31: // TODO, possibly CardRFIDCheck? + *rLen = 1; + if (rBuffer) memset(rBuffer, 0, 1); + break; + + case 40: // temperature + *rLen = 10; + if (rBuffer) { + memset(rBuffer, 0, 10); + rBuffer[0] = 1; + rBuffer[1] = 2; + rBuffer[2] = 3; + } + break; + + case 50: // errHistory + *rLen = 61; + if (rBuffer) memset(rBuffer, 0, 61); + break; + + case 60: // getToneTable + *rLen = 6; + if (rBuffer) memset(rBuffer, 0, 6); + break; + + default: + dprintf("Printer: unknown tagNumber, %d", tagNumber); + break; + } + + return 1; +} + +int WINAPI chcusb_imageformat( + uint16_t format, + uint16_t ncomp, + uint16_t depth, + uint16_t width, + uint16_t height, + uint8_t *image, + uint16_t *rResult) { + return chcusb_imageformat_330(format, ncomp, depth, width, height, rResult); +} + +int WINAPI chcusb_imageformat_330( + uint16_t format, + uint16_t ncomp, + uint16_t depth, + uint16_t width, + uint16_t height, + uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + WIDTH = width; + HEIGHT = height; + + *rResult = 0; + return 1; +} + +int __fastcall chcusb_setmtf(int32_t *mtf) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + memcpy(MTF, mtf, sizeof(MTF)); + return 1; +} + +int WINAPI chcusb_makeGamma(uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + uint8_t tone; + int32_t value; + double power; + + double factor = (double)k / 100.0; + + for (int i = 0; i < 256; ++i) { + power = pow((double)i, factor); + value = (int)(power / pow(255.0, factor) * 255.0); + + if (value > 255) + tone = 255; + if (value >= 0) + tone = value; + else + tone = 0; + + if (intoneR) + *(uint8_t *)(intoneR + i) = tone; + if (intoneG) + *(uint8_t *)(intoneG + i) = tone; + if (intoneB) + *(uint8_t *)(intoneB + i) = tone; + } + + return 1; +} + +int WINAPI chcusb_setIcctable( + LPCSTR icc1, + LPCSTR icc2, + uint16_t intents, + uint8_t *intoneR, + uint8_t *intoneG, + uint8_t *intoneB, + uint8_t *outtoneR, + uint8_t *outtoneG, + uint8_t *outtoneB, + uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + if (intoneR != NULL && intoneG != NULL && intoneB != NULL && outtoneR != NULL && outtoneG != NULL && outtoneB != NULL) { + for (int i = 0; i < 256; ++i) { + intoneR[i] = i; + intoneG[i] = i; + intoneB[i] = i; + outtoneR[i] = i; + outtoneG[i] = i; + outtoneB[i] = i; + } + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_copies(uint16_t copies, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_status(uint16_t *rResult) { + // dprintf("Printer: C3XXusb: %s\n", __func__); + if (check_for_wait_time()) { + *rResult = 2203; + } else { + *rResult = 0; + } + return 1; +} + +int WINAPI chcusb_statusAll(uint8_t *idArray, uint16_t *rResultArray) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + for (int i = 0; *(uint8_t *)(idArray + i) != 255 && i < 128; ++i) { + *(uint16_t *)(rResultArray + 2 * i) = 0; + } + + return 1; +} + +int WINAPI chcusb_startpage(uint16_t postCardState, uint16_t *pageId, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + STATUS = 2; + + *pageId = 1; + *rResult = 0; + return 1; +} + +int WINAPI chcusb_startpage_300(uint16_t postCardState, uint16_t *rResult) { + dprintf("Printer: C300usb: %s\n", __func__); + + STATUS = 2; + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_endpage(uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + if (printer_config.wait_time > 0){ + finishTime = GetTickCount64() + printer_config.wait_time; + dprintf("Printer: Waiting for %dms...\n", printer_config.wait_time); + } + awaitingCardExit = true; + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_write(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) { + SYSTEMTIME t; + GetLocalTime(&t); + + wchar_t dumpPath[MAX_PATH]; + uint8_t metadata[44]; + swprintf_s( + dumpPath, MAX_PATH, + L"%s\\C3XX_%04d%02d%02d_%02d%02d%02d.bmp", + printer_out_path, t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); + + memcpy(metadata, cardRFID, 12); + memcpy(metadata + 12, cardDataBuffer, 32); + + WriteDataToBitmapFile(dumpPath, 24, WIDTH, HEIGHT, data, *writeSize, metadata, 44, rotate180); + // WriteArrayToFile(dumpPath, data, IMAGE_SIZE, FALSE); + dprintf("Printer: C3XXusb: %s\n", __func__); + dwprintf(L"Printer: File written: %s\n", dumpPath); + + *rResult = 0; + + return 1; +} + +int WINAPI chcusb_writeLaminate(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) { + SYSTEMTIME t; + GetLocalTime(&t); + + wchar_t dumpPath[MAX_PATH]; + swprintf_s( + dumpPath, MAX_PATH, + L"%s\\C3XX_%04d%02d%02d_%02d%02d%02d_laminate.bmp", + printer_out_path, t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); + + // WriteDataToBitmapFile(dumpPath, 8, WIDTH, HEIGHT, data, HOLO_SIZE, NULL, 0, rotate180); + dprintf("Printer: C3XXusb: %s\n", __func__); + + // *writeSize = written; + *rResult = 0; + + return 1; +} + +int WINAPI chcusb_writeHolo(uint8_t *data, uint32_t *writeSize, uint16_t *rResult) { + SYSTEMTIME t; + GetLocalTime(&t); + + wchar_t dumpPath[MAX_PATH]; + swprintf_s( + dumpPath, MAX_PATH, + L"%s\\C3XX_%04d%02d%02d_%02d%02d%02d_holo.bmp", + printer_out_path, t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); + + WriteDataToBitmapFile(dumpPath, 8, WIDTH, HEIGHT, data, HOLO_SIZE, NULL, 0, rotate180); + dprintf("Printer: C3XXusb: %s\n", __func__); + + *writeSize = HOLO_SIZE; + *rResult = 0; + + return 1; +} + +int WINAPI chcusb_setPrinterInfo(uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + switch (tagNumber) { + case 0: // setPaperInfo + memcpy(PAPERINFO, rBuffer, sizeof(PAPERINFO)); + break; + case 20: // setPolishInfo + memcpy(POLISH, rBuffer, sizeof(POLISH)); + break; + default: + break; + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getGamma(LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + for (int i = 0; i < 256; ++i) { + r[i] = i; + g[i] = i; + b[i] = i; + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getMtf(LPCSTR filename, int32_t *mtf, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) return 0; + + DWORD read; + uint8_t buffer[0x40]; + BOOL result = ReadFile(hFile, buffer, 0x40, &read, NULL); + if (!result) return 0; + + int a, c; + int b = 1; + int d = c = 0; + + memset(mtf, 0, sizeof(MTF)); + + for (DWORD i = 0; i < read; i++) { + a = buffer[i] - 0x30; + if (a == -3 && c == 0) { + b = -1; + } else if (a >= 0 && a <= 9) { + mtf[d] = mtf[d] * 10 + a; + c++; + } else if (c > 0) { + mtf[d] *= b; + b = 1; + c = 0; + d++; + } + if (d > 9) break; + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_cancelCopies(uint16_t pageId, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_setPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + if ((type > 0 && type < 3) && (number > 0 && number < 3)) { + CURVE[type][number] = *data; + } + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getPrinterToneCurve(uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + if ((type > 0 && type < 3) && (number > 0 && number < 3)) { + *data = CURVE[type][number]; + } + *rResult = 0; + return 1; +} + +int WINAPI chcusb_blinkLED(uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_resetPrinter(uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_AttachThreadCount(uint16_t *rCount, uint16_t *rMaxCount) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rCount = 0; + *rMaxCount = 1; + return 1; +} + +int WINAPI chcusb_getPrintIDStatus(uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult) { + // dprintf("Printer: C3XXusb: %s\n", __func__); + memset(rBuffer, 0, 8); + + if (check_for_wait_time()) { + *((uint16_t*)(rBuffer + 6)) = 2203; + } else if (STATUS > 1) { + STATUS = 0; + *((uint16_t*)(rBuffer + 6)) = 2212; + } else { + *((uint16_t*)(rBuffer + 6)) = 2300; + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_setPrintStandby(uint16_t position, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + if (STATUS == 0) + { + STATUS = 1; + *rResult = 2100; + } + else + { + *rResult = 0; + } + + return 1; +} + +int WINAPI chcusb_setPrintStandby_300(uint16_t *rResult) { + dprintf("Printer: C300usb: %s\n", __func__); + + *rResult = 0; + if (awaitingCardExit){ // 300 does not use exitCard, so reset this for getPrinterInfo. + awaitingCardExit = false; + finishTime = 0; + STATUS = 1; + } + if (STATUS == 0) + { + STATUS = 1; + } + + return 1; +} + +int WINAPI chcusb_testCardFeed(uint16_t mode, uint16_t times, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_exitCard(uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + if (check_for_wait_time()) { + *rResult = 2203; + return 0; + } else { + awaitingCardExit = false; + finishTime = 0; + generate_rfid(); + } + + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getCardRfidTID(uint8_t *rCardTID, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + + memcpy(rCardTID, cardRFID, sizeof(cardRFID)); + *rResult = 2405; + return 1; +} + +int WINAPI chcusb_commCardRfidReader(uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult) { + uint8_t off; + + dprintf("Printer: C3XXusb: %s\n", __func__); + // dprintf("Printer: C3XXusb: commCardRfidReader send buffer: \n"); + // dump(sendData, sendSize); + + *rResult = 0; + + switch (sendData[0]) { + case 0x02: + memset(rRecvData, 0, 35); + rRecvData[0] = 2; + rRecvData[2] = 32; + memcpy(rRecvData + 3, cardDataBuffer, 32); + *rRecvSize = 35; + break; + case 0x03: + off = (sendData[4] - 1) * 2; + cardDataBuffer[off] = sendData[5]; + cardDataBuffer[off + 1] = sendData[6]; + if (sendData[4] == 0x10) { + dprintf("Printer: C3XXusb: commCardRfidReader card data buffer: \n"); + dump(cardDataBuffer, 0x20); + } + memset(rRecvData, 0, 3); + rRecvData[0] = 0x03; + *rRecvSize = 3; + break; + case 0x84: + memset(rRecvData, 0, 4); + rRecvData[0] = 0x84; + rRecvData[2] = 1; + rRecvData[3] = 0x90; + *rRecvSize = 4; + break; + case 0x85: + memset(rRecvData, 0, 12); + rRecvData[0] = 0x85; + rRecvData[2] = 9; + memcpy(rRecvData + 3, (void *)"837-15345", 9); + *rRecvSize = 12; + break; + case 0x42: + memset(rRecvData, 0, 4); + rRecvData[0] = 0x42; + rRecvData[2] = 1; + rRecvData[3] = 0x91; + *rRecvSize = 4; + break; + default: + memset(rRecvData, 0, 3); + rRecvData[0] = sendData[0]; + *rRecvSize = 3; + break; + } + + // dprintf("Printer: C3XXusb: commCardRfidReader recv buffer: \n"); + // dump(rRecvData, *rRecvSize); + + return 1; +} + +int WINAPI chcusb_updateCardRfidReader(uint8_t *data, uint32_t size, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getErrorLog(uint16_t index, uint8_t *rData, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getErrorStatus(uint16_t *rBuffer) { + dprintf("Printer: C3XXusb: %s\n", __func__); + memset(rBuffer, 0, 0x80); + return 1; +} + +int WINAPI chcusb_setCutList(uint8_t *rData, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_setLaminatePattern(uint16_t index, uint8_t *rData, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_color_adjustment(LPCSTR filename, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_color_adjustmentEx(int32_t a1, int32_t a2, int32_t a3, int16_t a4, int16_t a5, int64_t a6, int64_t a7, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getEEPROM(uint8_t index, uint8_t *rData, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_setParameter(uint8_t a1, uint32_t a2, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_getParameter(uint8_t a1, uint8_t *a2, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +int WINAPI chcusb_universal_command(int32_t a1, uint8_t a2, int32_t a3, uint8_t *a4, uint16_t *rResult) { + dprintf("Printer: C3XXusb: %s\n", __func__); + *rResult = 0; + return 1; +} + +/* PrintDll hooks */ + +int CFW_AttachThreadCount(const void *handle, uint16_t *rCount, uint16_t *rMaxCount) +{ + return fwdlusb_AttachThreadCount(rCount, rMaxCount); +} + +void CFW_close(const void *handle) +{ + fwdlusb_close(); +} + +int CFW_getErrorLog(const void *handle, uint16_t index, uint8_t *rData, uint16_t *rResult) +{ + return fwdlusb_getErrorLog(index, rData, rResult); +} + +int CFW_getFirmwareInfo(const void *handle, uint8_t update, LPCSTR filename, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) +{ + return fwdlusb_getFirmwareInfo(update, filename, rBuffer, rLen, rResult); +} + +int CFW_getPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) +{ + return fwdlusb_getPrinterInfo(tagNumber, rBuffer, rLen); +} + +int CFW_init(LPCSTR dllpath) +{ + dprintf("Printer PrintDLL: %s (dllpath: %s)\n", __func__, dllpath); + return 1; +} + +int CFW_listupPrinter(const void *handle, uint8_t *rIdArray) +{ + return fwdlusb_listupPrinter(rIdArray); +} + +int CFW_listupPrinterSN(const void *handle, uint64_t *rSerialArray) +{ + return fwdlusb_listupPrinterSN(rSerialArray); +} + +int CFW_MakeThread(const void *handle, uint16_t maxCount) +{ + return fwdlusb_MakeThread(maxCount); +} + +int CFW_open(const void *handle, uint16_t *rResult) +{ + return fwdlusb_open(rResult); +} + +int CFW_ReleaseThread(const void *handle, uint16_t *rResult) +{ + return fwdlusb_ReleaseThread(rResult); +} + +int CFW_resetPrinter(const void *handle, uint16_t *rResult) +{ + return fwdlusb_resetPrinter(rResult); +} + +int CFW_selectPrinter(const void *handle, uint8_t printerId, uint16_t *rResult) +{ + return fwdlusb_selectPrinter(printerId, rResult); +} + +int CFW_selectPrinterSN(const void *handle, uint64_t printerSN, uint16_t *rResult) +{ + return fwdlusb_selectPrinterSN(printerSN, rResult); +} + +int CFW_status(const void *handle, uint16_t *rResult) +{ + return fwdlusb_status(rResult); +} + +int CFW_statusAll(const void *handle, uint8_t *idArray, uint16_t *rResultArray) +{ + return fwdlusb_statusAll(idArray, rResultArray); +} + +void CFW_term(const void *handle) +{ + dprintf("Printer PrintDLL: %s\n", __func__); +} + +int CFW_updateFirmware(const void *handle, uint8_t update, LPCSTR filename, uint16_t *rResult) +{ + return fwdlusb_updateFirmware(update, filename, rResult); +} + +int CHCUSB_AttachThreadCount(const void *handle, uint16_t *rCount, uint16_t *rMaxCount) +{ + return chcusb_AttachThreadCount(rCount, rMaxCount); +} + +int CHCUSB_MakeThread(const void *handle, uint16_t maxCount) +{ + return chcusb_MakeThread(maxCount); +} + +int CHCUSB_ReleaseThread(const void *handle, uint16_t *rResult) +{ + return chcusb_ReleaseThread(rResult); +} + +int CHCUSB_blinkLED(const void *handle, uint16_t *rResult) +{ + return chcusb_blinkLED(rResult); +} + +int CHCUSB_cancelCopies(const void *handle, uint16_t pageId, uint16_t *rResult) +{ + return chcusb_cancelCopies(pageId, rResult); +} + +void CHCUSB_close(const void *handle) +{ + chcusb_close(); +} + +int CHCUSB_commCardRfidReader(const void *handle, uint8_t *sendData, uint8_t *rRecvData, uint32_t sendSize, uint32_t *rRecvSize, uint16_t *rResult) +{ + return chcusb_commCardRfidReader(sendData, rRecvData, sendSize, rRecvSize, rResult); +} + +int CHCUSB_copies(const void *handle, uint16_t copies, uint16_t *rResult) +{ + return chcusb_copies(copies, rResult); +} + +int CHCUSB_endpage(const void *handle, uint16_t *rResult) +{ + return chcusb_endpage(rResult); +} + +int CHCUSB_exitCard(const void *handle, uint16_t *rResult) +{ + return chcusb_exitCard(rResult); +} + +int CHCUSB_getCardRfidTID(const void *handle, uint8_t *rCardTID, uint16_t *rResult) +{ + return chcusb_getCardRfidTID(rCardTID, rResult); +} + +int CHCUSB_getErrorLog(const void *handle, uint16_t index, uint8_t *rData, uint16_t *rResult) +{ + return chcusb_getErrorLog(index, rData, rResult); +} + +int CHCUSB_getErrorStatus(const void *handle, uint16_t *rBuffer) +{ + return chcusb_getErrorStatus(rBuffer); +} + +int CHCUSB_getGamma(const void *handle, LPCSTR filename, uint8_t *r, uint8_t *g, uint8_t *b, uint16_t *rResult) +{ + return chcusb_getGamma(filename, r, g, b, rResult); +} + +int CHCUSB_getMtf(const void *handle, LPCSTR filename, int32_t *mtf, uint16_t *rResult) +{ + return chcusb_getMtf(filename, mtf, rResult); +} + +int CHCUSB_getPrintIDStatus(const void *handle, uint16_t pageId, uint8_t *rBuffer, uint16_t *rResult) +{ + return chcusb_getPrintIDStatus(pageId, rBuffer, rResult); +} + +int CHCUSB_getPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen) +{ + return chcusb_getPrinterInfo(tagNumber, rBuffer, rLen); +} + +int CHCUSB_getPrinterToneCurve(const void *handle, uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) +{ + return chcusb_getPrinterToneCurve(type, number, data, rResult); +} + +int CHCUSB_imageformat(const void *handle, uint16_t format, uint16_t ncomp, uint16_t depth, uint16_t width, uint16_t height, uint8_t *inputImage, uint16_t *rResult) +{ + return chcusb_imageformat(format, ncomp, depth, width, height, inputImage, rResult); +} + +int CHCUSB_init(LPCSTR dllpath) +{ + dprintf("Printer PrintDLL: %s (dllpath: %s)\n", __func__, dllpath); + return 1; +} + +int CHCUSB_listupPrinter(const void *handle, uint8_t *rIdArray) +{ + return chcusb_listupPrinter(rIdArray); +} + +int CHCUSB_listupPrinterSN(const void *handle, uint64_t *rSerialArray) +{ + return chcusb_listupPrinterSN(rSerialArray); +} + +int CHCUSB_makeGamma(const void *handle, uint16_t k, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB) +{ + return chcusb_makeGamma(k, intoneR, intoneG, intoneB); +} + +int CHCUSB_open(const void *handle, uint16_t *rResult) +{ + return chcusb_open(rResult); +} + +int CHCUSB_resetPrinter(const void *handle, uint16_t *rResult) +{ + return chcusb_resetPrinter(rResult); +} + +int CHCUSB_selectPrinter(const void *handle, uint8_t printerId, uint16_t *rResult) +{ + return chcusb_selectPrinter(printerId, rResult); +} + +int CHCUSB_selectPrinterSN(const void *handle, uint64_t printerSN, uint16_t *rResult) +{ + return chcusb_selectPrinterSN(printerSN, rResult); +} + +int CHCUSB_setIcctableProfile(const void *handle, LPCSTR icc1, LPCSTR icc2, uint16_t intents, uint16_t *rResult) +{ + dprintf("Printer PrintDLL: %s (icc1: %s, icc2: %s)\n", + __func__, icc1, icc2); + *rResult = 0; + return 1; +} + +int CHCUSB_setIcctable(const void *handle, uint16_t intents, uint8_t *intoneR, uint8_t *intoneG, uint8_t *intoneB, uint8_t *outtoneR, uint8_t *outtoneG, uint8_t *outtoneB, uint16_t *rResult) +{ + return chcusb_setIcctable("CFW", "CFW", intents, intoneR, intoneG, intoneB, outtoneR, outtoneG, outtoneB, rResult); +} + +int CHCUSB_setPrintStandby(const void *handle, uint16_t position, uint16_t *rResult) +{ + return chcusb_setPrintStandby(position, rResult); +} + +int CHCUSB_setPrinterInfo(const void *handle, uint16_t tagNumber, uint8_t *rBuffer, uint32_t *rLen, uint16_t *rResult) +{ + return chcusb_setPrinterInfo(tagNumber, rBuffer, rLen, rResult); +} + +int CHCUSB_setPrinterToneCurve(const void *handle, uint16_t type, uint16_t number, uint16_t *data, uint16_t *rResult) +{ + return chcusb_setPrinterToneCurve(type, number, data, rResult); +} + +int CHCUSB_setmtf(const void *handle, int32_t *mtf) +{ + return chcusb_setmtf(mtf); +} + +int CHCUSB_startpage(const void *handle, uint16_t postCardState, uint16_t *pageId, uint16_t *rResult) +{ + return chcusb_startpage(postCardState, pageId, rResult); +} + +int CHCUSB_status(const void *handle, uint16_t *rResult) +{ + return chcusb_status(rResult); +} + +int CHCUSB_statusAll(const void *handle, uint8_t *idArray, uint16_t *rResultArray) +{ + return chcusb_statusAll(idArray, rResultArray); +} + +int CHCUSB_testCardFeed(const void *handle, uint16_t mode, uint16_t times, uint16_t *rResult) +{ + return chcusb_testCardFeed(mode, times, rResult); +} + +void CHCUSB_term(const void *handle) +{ + dprintf("Printer PrintDLL: %s\n", __func__); +} + +int CHCUSB_updateCardRfidReader(const void *handle, uint8_t *data, uint32_t size, uint16_t *rResult) +{ + return chcusb_updateCardRfidReader(data, size, rResult); +} + +int CHCUSB_write(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult) +{ + return chcusb_write(data, writeSize, rResult); +} + +int CHCUSB_writeHolo(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult) +{ + return chcusb_writeHolo(data, writeSize, rResult); +} + +int CHCUSB_writeLaminate(const void *handle, uint8_t *data, uint32_t offset, uint32_t *writeSize, uint16_t *rResult) +{ + return chcusb_writeLaminate(data, writeSize, rResult); +} + +// copy pasted from https://dev.s-ul.net/domeori/c310emu +#define BITMAPHEADERSIZE 0x36 + +DWORD ConvertDataToBitmap( + DWORD dwBitCount, + DWORD dwWidth, DWORD dwHeight, + PBYTE pbInput, DWORD cbInput, + PBYTE pbOutput, DWORD cbOutput, + PDWORD pcbResult, + bool pFlip) { + if (!pbInput || !pbOutput || dwBitCount < 8) return -3; + + if (cbInput < (dwWidth * dwHeight * dwBitCount / 8)) return -3; + + PBYTE pBuffer = (PBYTE)malloc(cbInput); + if (!pBuffer) return -2; + + BYTE dwColors = (BYTE)(dwBitCount / 8); + if (!dwColors) return -1; + + UINT16 cbColors; + RGBQUAD pbColors[256]; + + switch (dwBitCount) { + case 1: + cbColors = 1; + break; + case 2: + cbColors = 4; + break; + case 4: + cbColors = 16; + break; + case 8: + cbColors = 256; + break; + default: + cbColors = 0; + break; + } + + if (cbColors) { + BYTE dwStep = (BYTE)(256 / cbColors); + + for (UINT16 i = 0; i < cbColors; ++i) { + pbColors[i].rgbRed = dwStep * i; + pbColors[i].rgbGreen = dwStep * i; + pbColors[i].rgbBlue = dwStep * i; + pbColors[i].rgbReserved = 0; + } + } + + DWORD dwTable = cbColors * sizeof(RGBQUAD); + DWORD dwOffset = BITMAPHEADERSIZE + dwTable; + + // calculate the padded row size, again + DWORD dwLineSize = (dwWidth * dwBitCount / 8 + 3) & ~3; + + BITMAPFILEHEADER bFile = {0}; + BITMAPINFOHEADER bInfo = {0}; + + bFile.bfType = 0x4D42; // MAGIC + bFile.bfSize = dwOffset + cbInput; + bFile.bfOffBits = dwOffset; + + bInfo.biSize = sizeof(BITMAPINFOHEADER); + bInfo.biWidth = dwWidth; + bInfo.biHeight = dwHeight; + bInfo.biPlanes = 1; + bInfo.biBitCount = (WORD)dwBitCount; + bInfo.biCompression = BI_RGB; + bInfo.biSizeImage = cbInput; + + if (cbOutput < bFile.bfSize) return -1; + + // Flip the image (if necessary) and add padding to each row + if (pFlip) { + for (size_t i = 0; i < dwHeight; i++) { + for (size_t j = 0; j < dwWidth; j++) { + for (size_t k = 0; k < dwColors; k++) { + // Calculate the position in the padded buffer + // Make sure to also flip the colors from RGB to BRG + size_t x = (dwHeight - i - 1) * dwLineSize + (dwWidth - j - 1) * dwColors + (dwColors - k - 1); + size_t y = (dwHeight - i - 1) * dwWidth * dwColors + j * dwColors + k; + *(pBuffer + x) = *(pbInput + y); + } + } + } + } else { + for (size_t i = 0; i < dwHeight; i++) { + for (size_t j = 0; j < dwWidth; j++) { + for (size_t k = 0; k < dwColors; k++) { + // Calculate the position in the padded buffer + size_t x = i * dwLineSize + j * dwColors + (dwColors - k - 1); + size_t y = (dwHeight - i - 1) * dwWidth * dwColors + j * dwColors + k; + *(pBuffer + x) = *(pbInput + y); + } + } + } + } + + memcpy(pbOutput, &bFile, sizeof(BITMAPFILEHEADER)); + memcpy(pbOutput + sizeof(BITMAPFILEHEADER), &bInfo, sizeof(BITMAPINFOHEADER)); + if (cbColors) memcpy(pbOutput + BITMAPHEADERSIZE, pbColors, dwTable); + memcpy(pbOutput + dwOffset, pBuffer, cbInput); + + *pcbResult = bFile.bfSize; + + free(pBuffer); + return 0; +} + +DWORD WriteDataToBitmapFile( + LPCWSTR lpFilePath, DWORD dwBitCount, + DWORD dwWidth, DWORD dwHeight, + PBYTE pbInput, DWORD cbInput, + PBYTE pbMetadata, DWORD cbMetadata, + bool pFlip) { + if (!lpFilePath || !pbInput) return -3; + + HANDLE hFile; + DWORD dwBytesWritten; + + hFile = CreateFileW( + lpFilePath, + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, + NULL); + if (hFile == INVALID_HANDLE_VALUE) return -1; + + // calculate the padded row size and padded image size + DWORD dwLineSize = (dwWidth * dwBitCount / 8 + 3) & ~3; + DWORD dwImageSize = dwLineSize * dwHeight; + + DWORD cbResult; + DWORD cbBuffer = dwImageSize + 0x500; + PBYTE pbBuffer = (PBYTE)calloc(cbBuffer, 1); + if (!pbBuffer) return -2; + + if (ConvertDataToBitmap(dwBitCount, dwWidth, dwHeight, pbInput, dwImageSize, pbBuffer, cbBuffer, &cbResult, pFlip) < 0) { + cbResult = -1; + goto WriteDataToBitmapFile_End; + } + + WriteFile(hFile, pbBuffer, cbResult, &dwBytesWritten, NULL); + + if (pbMetadata) + WriteFile(hFile, pbMetadata, cbMetadata, &dwBytesWritten, NULL); + + CloseHandle(hFile); + + cbResult = dwBytesWritten; + +WriteDataToBitmapFile_End: + free(pbBuffer); + return cbResult; +} + +DWORD WriteArrayToFile(LPCSTR lpOutputFilePath, LPVOID lpDataTemp, DWORD nDataSize, BOOL isAppend) { +#ifdef NDEBUG + + return nDataSize; + +#else + + HANDLE hFile; + DWORD dwBytesWritten; + DWORD dwDesiredAccess; + DWORD dwCreationDisposition; + + if (isAppend) { + dwDesiredAccess = FILE_APPEND_DATA; + dwCreationDisposition = OPEN_ALWAYS; + } else { + dwDesiredAccess = GENERIC_WRITE; + dwCreationDisposition = CREATE_ALWAYS; + } + + hFile = CreateFileA( + lpOutputFilePath, + dwDesiredAccess, + FILE_SHARE_READ, + NULL, + dwCreationDisposition, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, + NULL); + if (hFile == INVALID_HANDLE_VALUE) { + return FALSE; + } + + WriteFile(hFile, lpDataTemp, nDataSize, &dwBytesWritten, NULL); + CloseHandle(hFile); + + return dwBytesWritten; + +#endif +} + +void printer_set_dimensions(int width, int height){ + WIDTH = width; + HEIGHT = height; +} diff --git a/hooklib/printer.h b/hooklib/printer.h new file mode 100644 index 0000000..3e451d1 --- /dev/null +++ b/hooklib/printer.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +struct printer_config { + bool enable; + bool rotate_180; + char serial_no[8]; + wchar_t main_fw_path[MAX_PATH]; + wchar_t dsp_fw_path[MAX_PATH]; + wchar_t param_fw_path[MAX_PATH]; + wchar_t printer_out_path[MAX_PATH]; + uint32_t wait_time; +}; + +void printer_hook_init(const struct printer_config *cfg, int rfid_port_no, HINSTANCE self); +void printer_hook_insert_hooks(HMODULE target); + +void printer_set_dimensions(int width, int height); +int WINAPI fwdlusb_updateFirmware_main(uint8_t update, LPCSTR filename, uint16_t *rResult); +int WINAPI fwdlusb_updateFirmware_dsp(uint8_t update, LPCSTR filename, uint16_t *rResult); +int WINAPI fwdlusb_updateFirmware_param(uint8_t update, LPCSTR filename, uint16_t *rResult); \ No newline at end of file diff --git a/hooklib/winusb.c b/hooklib/winusb.c index f49d349..d1f800a 100644 --- a/hooklib/winusb.c +++ b/hooklib/winusb.c @@ -6,6 +6,7 @@ #include "hook/table.h" #include "hook/iohook.h" +#include "hook/procaddr.h" #include "board/guid.h" #include "hooklib/setupapi.h" @@ -228,6 +229,12 @@ void winusb_hook_insert_hooks(HMODULE target) "WINUSB.dll", winusb_syms, _countof(winusb_syms)); + + proc_addr_table_push( + target, + "WINUSB.dll", + winusb_syms, + _countof(winusb_syms)); } static HRESULT winusb_handle_irp(struct irp *irp) @@ -287,13 +294,11 @@ BOOL my_WinUsb_QueryPipe(WINUSB_INTERFACE_HANDLE InterfaceHandle, UCHAR Alternat if (!this_pipeid) { return false; } - - //PipeInformation = (PWINUSB_PIPE_INFORMATION)malloc(sizeof(WINUSB_PIPE_INFORMATION)); PipeInformation->PipeType = UsbdPipeTypeBulk; PipeInformation->PipeId = this_pipeid; - PipeInformation->Interval = 0xff; // never checked? - PipeInformation->MaximumPacketSize = 128; // never checked? + PipeInformation->Interval = 0x00; // never checked? + PipeInformation->MaximumPacketSize = 0x40; // never checked? return true; } @@ -307,7 +312,16 @@ BOOL my_WinUsb_QueryInterfaceSettings(WINUSB_INTERFACE_HANDLE InterfaceHandle, U return next_WinUsb_QueryInterfaceSettings(InterfaceHandle, AlternateInterfaceNumber, UsbAltInterfaceDescriptor); }*/ + UsbAltInterfaceDescriptor->bLength = 9; + UsbAltInterfaceDescriptor->bDescriptorType = USB_INTERFACE_DESCRIPTOR_TYPE; + UsbAltInterfaceDescriptor->bInterfaceNumber = 0; + UsbAltInterfaceDescriptor->bAlternateSetting = 0; UsbAltInterfaceDescriptor->bNumEndpoints = 2; // nothing else is checked + UsbAltInterfaceDescriptor->bInterfaceClass = 255; + UsbAltInterfaceDescriptor->bInterfaceSubClass = 0; + UsbAltInterfaceDescriptor->bInterfaceProtocol = 0; + UsbAltInterfaceDescriptor->iInterface = 0; + return true; } @@ -371,10 +385,10 @@ BOOL my_WinUsb_WritePipe( Overlapped ); }*/ -#if 1 +#if 0 dprintf("WritePipe %d\t", (int)BufferLength); for (int i = 0; i < BufferLength; i++) { - dprintf("%02X", (char)Buffer[i]); + dprintf("%02X ", (uint8_t)Buffer[i]); } dprintf("\n"); #endif @@ -415,7 +429,7 @@ BOOL my_WinUsb_ReadPipe( Overlapped ); }*/ -#if 1 +#if 0 dprintf("ReadPipe %d\n", (int)BufferLength); #endif winusb_classes[idx].read_pipe(NULL, Buffer, BufferLength, (uint32_t *)LengthTransferred); diff --git a/jvs/jvs-cmd.h b/jvs/jvs-cmd.h index efbb476..19a44f6 100644 --- a/jvs/jvs-cmd.h +++ b/jvs/jvs-cmd.h @@ -1,21 +1,38 @@ #pragma once enum { - JVS_CMD_TYPEX_READ_DIPSW = 0x01, - JVS_CMD_READ_ID = 0x10, - JVS_CMD_GET_CMD_VERSION = 0x11, - JVS_CMD_GET_JVS_VERSION = 0x12, - JVS_CMD_GET_COMM_VERSION = 0x13, - JVS_CMD_GET_FEATURES = 0x14, - JVS_CMD_READ_SWITCHES = 0x20, - JVS_CMD_READ_COIN = 0x21, - JVS_CMD_READ_ANALOGS = 0x22, - JVS_CMD_READ_MISC_SWITCHES = 0x26, - JVS_CMD_WRITE_GPIO = 0x32, - JVS_CMD_TYPEX_POLL_AMIC = 0x61, - JVS_CMD_TYPEX_POLL_CARD = 0x66, - JVS_CMD_RESET = 0xF0, - JVS_CMD_ASSIGN_ADDR = 0xF1, + JVS_CMD_TAITO_READ_DIPSW = 0x01, + + JVS_CMD_READ_ID = 0x10, + JVS_CMD_GET_CMD_VERSION = 0x11, + JVS_CMD_GET_JVS_VERSION = 0x12, + JVS_CMD_GET_COMM_VERSION = 0x13, + JVS_CMD_GET_FEATURES = 0x14, + JVS_CMD_SET_MAIN_ID = 0x15, + + JVS_CMD_READ_SWITCHES = 0x20, + JVS_CMD_READ_COIN = 0x21, + JVS_CMD_READ_ANALOGS = 0x22, + JVS_CMD_READ_ROTARY = 0x23, + JVS_CMD_READ_KEYCODE = 0x24, + JVS_CMD_READ_SCREEN_POS = 0x25, + JVS_CMD_READ_MISC_SWITCHES = 0x26, + + JVS_CMD_WRITE_PAYOUT_REMAIN = 0x2E, + JVS_CMD_DATA_RETRANSMIT = 0x2F, + JVS_CMD_DEC_COIN_CT = 0x30, + JVS_CMD_INC_PAYOUTT = 0x31, + JVS_CMD_WRITE_GPIO1 = 0x32, + JVS_CMD_WRITE_ANALOG_OUT = 0x33, + JVS_CMD_WRITE_CHAR_OUT = 0x34, + JVS_CMD_INC_COIN_CT = 0x35, + JVS_CMD_DEC_PAYOUTT = 0x36, + JVS_CMD_WRITE_GPIO2 = 0x37, + JVS_CMD_WRITE_GPIO3 = 0x38, + + JVS_CMD_RESET = 0xF0, + JVS_CMD_ASSIGN_ADDR = 0xF1, + JVS_CMD_CHANGE_COMM_METHOD = 0xF2, }; #pragma pack(push, 1) diff --git a/jvs/jvs-util.c b/jvs/jvs-util.c index 1bbe10e..f99c3c4 100644 --- a/jvs/jvs-util.c +++ b/jvs/jvs-util.c @@ -10,6 +10,7 @@ #include "jvs/jvs-util.h" #include "util/dprintf.h" +#include "util/dump.h" typedef HRESULT (*jvs_dispatch_fn_t)( void *ctx, @@ -26,6 +27,7 @@ void jvs_crack_request( { uint8_t req_bytes[128]; uint8_t resp_bytes[128]; + uint8_t req_bytenum = 0; struct iobuf decode; struct iobuf encode; struct const_iobuf segments; @@ -56,7 +58,9 @@ void jvs_crack_request( } iobuf_flip(&segments, &decode); - segments.pos = 2; + + //segments.pos = 2; + segments.pos = 1; // We want to pass the length to the dispatch as well encode.bytes = resp_bytes; encode.nbytes = sizeof(resp_bytes); @@ -69,6 +73,11 @@ void jvs_crack_request( while (segments.pos + 1 < segments.nbytes) { hr = dispatch_fn(dispatch_ctx, &segments, &encode); + if (segments.nbytes != segments.pos + 1) { + dprintf("JVS: Unconsumed buffer!\n"); + dump_const_iobuf(&segments); + } + if (FAILED(hr)) { break; } diff --git a/ll3hook/config.c b/ll3hook/config.c index 81fa92a..450b8f9 100644 --- a/ll3hook/config.c +++ b/ll3hook/config.c @@ -32,4 +32,5 @@ void ll3_hook_config_load( platform_config_load(&cfg->platform, filename); ll3_dll_config_load(&cfg->dll, filename); gfx_config_load(&cfg->gfx, filename); + printer_config_load(&cfg->printer, filename); } \ No newline at end of file diff --git a/ll3hook/config.h b/ll3hook/config.h index 6f33ad6..3fb6eaa 100644 --- a/ll3hook/config.h +++ b/ll3hook/config.h @@ -7,11 +7,13 @@ #include "platform/config.h" #include "gfxhook/config.h" #include "board/config.h" +#include "hooklib/config.h" struct ll3_hook_config { struct platform_config platform; struct ll3_dll_config dll; struct gfx_config gfx; + struct printer_config printer; }; void ll3_hook_config_load( diff --git a/ll3hook/dllmain.c b/ll3hook/dllmain.c index e92973f..cd14208 100644 --- a/ll3hook/dllmain.c +++ b/ll3hook/dllmain.c @@ -1,12 +1,13 @@ #include #include -#include "board/j9100647a.h" +#include "board/k9101258.h" #include "hook/process.h" #include "hooklib/serial.h" #include "hooklib/spike.h" +#include "hooklib/printer.h" #include "gfxhook/gfx.h" #include "gfxhook/d3d11.h" @@ -40,7 +41,9 @@ static DWORD CALLBACK ll3_pre_startup(void) gfx_hook_init(&ll3_hook_cfg.gfx); gfx_d3d11_hook_init(&ll3_hook_cfg.gfx, ll3_hook_mod); - hr = usbio_hook_init(); + printer_hook_init(&ll3_hook_cfg.printer, 0, ll3_hook_mod); + + hr = k9101258_hook_init(); if (FAILED(hr)) { goto fail; } diff --git a/ll3hook/ll3-dll.c b/ll3hook/ll3-dll.c index 0fe4665..836e507 100644 --- a/ll3hook/ll3-dll.c +++ b/ll3hook/ll3-dll.c @@ -67,7 +67,7 @@ HRESULT ll3_dll_init(const struct ll3_dll_config *cfg, HINSTANCE self) if (ll3_dll.api_version >= 0x0200) { hr = E_NOTIMPL; dprintf("ll3 IO: Custom IO DLL implements an unsupported " - "API version (%#04x). Please update Segatools.\n", + "API version (%#04x). Please update Taitools.\n", ll3_dll.api_version); goto end; diff --git a/meson.build b/meson.build index 870240d..93b0eca 100644 --- a/meson.build +++ b/meson.build @@ -32,6 +32,11 @@ if meson.get_compiler('c').get_id() != 'msvc' '-static-libgcc', language: 'c', ) +else + add_project_arguments( + '/wd4090', # different 'const' qualifiers + language: 'c', + ) endif cc = meson.get_compiler('c') diff --git a/msvc-build.bat b/msvc-build.bat index ce19537..f0a009c 100644 --- a/msvc-build.bat +++ b/msvc-build.bat @@ -1,4 +1,6 @@ @echo off +setlocal enabledelayedexpansion + set BUILD_DIR=build set BUILD_DIR_32=%BUILD_DIR%\build32 set BUILD_DIR_64=%BUILD_DIR%\build64 @@ -6,11 +8,33 @@ set BUILD_DIR_ZIP=%BUILD_DIR%\zip set DIST_DIR=dist set DOC_DIR=doc -REM Set Your Visual Studio install path if this one was wrong -if "%VS_INSTALLATION%"=="" set VS_INSTALLATION=C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools +REM Set your Visual Studio install path if Visual Studio installation can not be detected +set VS_INSTALLATION=C:\Program Files\Microsoft Visual Studio\2022\Community if /I "%1"=="build" ( - call :build + call :detect-visual-studio + if ERRORLEVEL 2 exit /b + if ERRORLEVEL 1 ( + echo Failed to detect Visual Studio installation path. + echo. + echo If Visual Studio is installed then edit VS_INSTALLATION in this file + echo to manually specify Visual Studio install path. + exit /b + ) + + call :detect-meson + if ERRORLEVEL 1 ( + echo Meson is not installed. + exit /b + ) + + set VSVARSALL=!VSVARSALL! + set MESON=!MESON! + + call :build %2 + + echo. + echo Build done! exit /b ) if /I "%1"=="zip" ( @@ -18,56 +42,94 @@ if /I "%1"=="zip" ( exit /b ) -echo %~nx0 [action] +echo %~nx0 [action] [switch] echo build: Build the for both x86 and x64 +echo /PROJECTONLY: Only create projects +echo. echo zip: Make zip file +echo. exit /b -:build ( - REM Check VC++ - set VSVARALL="%VS_INSTALLATION%\VC\Auxiliary\Build\vcvarsall.bat" - if not exist %VSVARALL% ( - echo Build tools for Microsoft Visual C++ 2022 is not Installed - echo Edit this file to change the VS_INSTALLATION if you are installed the Visual Studio in other path - goto end +rem This should works for Visual Studio 2017+ +:detect-visual-studio ( + rem Fall back to x86 program directory for MSVC standalone if it can't be found in x64, because even though it's x64 compilers, they install in x86 program files for whatever dumb reason + set VSWHERE="%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" + if not exist %VSWHERE% ( + set VSWHERE="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ) - REM Check Meson + if exist %VSWHERE% ( + REM get vcvarsall by using vswhere + set VSVARSALL="" + for /f "tokens=* usebackq" %%i in (`%VSWHERE% -products * -find VC\Auxiliary\Build\vcvarsall.bat`) do set VSVARSALL="%%i" + ) else ( + REM fallback to old method + set VSVARSALL="%VS_INSTALLATION%\VC\Auxiliary\Build\vcvarsall.bat" + ) + + :check-vcvarsall + if /i %VSVARSALL%=="" ( + echo Microsoft Visual C++ Component is not installed + echo Install it from Visual Studio Installer + exit /b 2 + ) + + rem if a path is returned by vswhere, then it's sure that the result path exists + rem if path not exists than it was assumed from VS_INSTALLATION + if not exist %VSVARSALL% ( + echo vsvarsall.bat not exists in VS_INSTALLATION, + echo either Visual C++ Component is not installed + echo or VS_INSTALLATION is wrong. + exit /b 1 + ) + + exit /b 0 +) + +:detect-meson ( + set MESON="" for /f "tokens=* usebackq" %%i in (`where meson`) do set MESON="%%i" if not exist %MESON% ( - echo Meson is not Installed - goto end + exit /b 1 ) + exit /b 0 +) + +:build ( :build_x64 ( - call %VSVARALL% x64 + call %VSVARSALL% x64 if exist %BUILD_DIR_64% ( - %MESON% setup %BUILD_DIR_64% --backend vs --buildtype release --reconfigure + %MESON% setup %BUILD_DIR_64% --buildtype release --reconfigure ) else ( %MESON% setup %BUILD_DIR_64% --backend vs --buildtype release ) - pushd %BUILD_DIR_64% - msbuild /m /p:Configuration=release /p:Platform=x64 taitools.sln - popd + if /I not "%1"=="/PROJECTONLY" ( + pushd %BUILD_DIR_64% + msbuild /m /p:Configuration=release /p:Platform=x64 taitools.sln + popd + ) ) :build_x86 ( - call %VSVARALL% x86 + call %VSVARSALL% x86 if exist %BUILD_DIR_32% ( - %MESON% setup %BUILD_DIR_32% --backend vs --buildtype release --reconfigure + %MESON% setup %BUILD_DIR_32% --buildtype release --reconfigure ) else ( %MESON% setup %BUILD_DIR_32% --backend vs --buildtype release ) - pushd %BUILD_DIR_32% - msbuild /m /p:Configuration=release /p:Platform=Win32 taitools.sln - popd + if /I not "%1"=="/PROJECTONLY" ( + pushd %BUILD_DIR_32% + msbuild /m /p:Configuration=release /p:Platform=Win32 taitools.sln + popd + ) ) :end ( - endlocal + exit /b ) ) diff --git a/platform/cert.c b/platform/cert.c index 04adad0..d65b841 100644 --- a/platform/cert.c +++ b/platform/cert.c @@ -26,10 +26,10 @@ static CRITICAL_SECTION cert_lock; static wchar_t path[MAX_PATH]; -HCERTSTORE p12store; -PCCERT_CONTEXT client_cert_ctx = NULL; +static HCERTSTORE p12store; +static PCCERT_CONTEXT client_cert_ctx = NULL; -PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( +static PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, @@ -38,7 +38,7 @@ PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( PCCERT_CONTEXT pPrevCertContext ); -HCERTSTORE WINAPI my_CertOpenStore( +static HCERTSTORE WINAPI my_CertOpenStore( LPCSTR lpszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv, @@ -53,7 +53,7 @@ static BOOL my_WinHttpSetOption( DWORD dwBufferLength ); -PCCERT_CONTEXT (WINAPI *next_CertFindCertificateInStore)( +static PCCERT_CONTEXT (WINAPI *next_CertFindCertificateInStore)( HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, @@ -62,7 +62,7 @@ PCCERT_CONTEXT (WINAPI *next_CertFindCertificateInStore)( PCCERT_CONTEXT pPrevCertContext ); -HCERTSTORE (WINAPI *next_CertOpenStore)( +static HCERTSTORE (WINAPI *next_CertOpenStore)( LPCSTR lpszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv, @@ -77,7 +77,7 @@ static BOOL (*next_WinHttpSetOption)( DWORD dwBufferLength ); -void ca_error_cb(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength); +static void ca_error_cb(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength); static const struct hook_symbol cert_syms[] = { { @@ -200,7 +200,7 @@ void cert_hook_insert_hooks(HMODULE target) _countof(winhttp_syms)); } -PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( +static PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFindFlags, @@ -239,7 +239,7 @@ PCCERT_CONTEXT WINAPI my_CertFindCertificateInStore( ); } -HCERTSTORE WINAPI my_CertOpenStore( +static HCERTSTORE WINAPI my_CertOpenStore( LPCSTR lpszStoreProvider, DWORD dwEncodingType, HCRYPTPROV_LEGACY hCryptProv, @@ -290,8 +290,12 @@ static BOOL my_WinHttpSetOption( } // Some games don't call WINHTTP_OPTION_SECURITY_FLAGS, so we do it here - int value = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID; - next_WinHttpSetOption(hInternet, WINHTTP_OPTION_SECURITY_FLAGS, &value, dwBufferLength); + int value = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; + next_WinHttpSetOption(hInternet, WINHTTP_OPTION_SECURITY_FLAGS, &value, 4); + + if (p12store == NULL && client_cert_ctx == NULL) { + return next_WinHttpSetOption(hInternet, dwOption, WINHTTP_NO_CLIENT_CERT_CONTEXT, 0); + } } else if (dwOption == WINHTTP_OPTION_SECURITY_FLAGS) { dprintf("Cert: Add all security ignore flags\n"); @@ -303,7 +307,7 @@ static BOOL my_WinHttpSetOption( SetLastError(0); } - int value = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID; // the kitchen sink + int value = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE; // the kitchen sink return next_WinHttpSetOption(hInternet, dwOption, &value, dwBufferLength); } else { dprintf("Cert: my_WinHttpSetOption %p %08X\n", hInternet, (int)dwOption); @@ -312,7 +316,7 @@ static BOOL my_WinHttpSetOption( return next_WinHttpSetOption(hInternet, dwOption, lpBuffer, dwBufferLength); } -void ca_error_cb(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) +static void ca_error_cb(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) { dprintf("Cert: HTTP Secure connection failure: %04lX\n", *(DWORD *)lpvStatusInformation); } diff --git a/ri/ri.c b/ri/ri.c index be164da..3a1e48b 100644 --- a/ri/ri.c +++ b/ri/ri.c @@ -16,10 +16,14 @@ static WNDCLASSEX ri_wndclass; static HANDLE selected_ri_dev = (HANDLE)-1; static uintptr_t ri_thread; +static ri_mouse_cb_t mouse_cb = NULL; +static ri_kb_cb_t kb_cb = NULL; +static ri_hid_cb_t hid_cb = NULL; + LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam); static unsigned int __stdcall ri_thread_proc(void *ctx); -HRESULT ri_init(uint8_t dev_num) +HRESULT ri_init(uint8_t dev_num, ri_mouse_cb_t in_mouse_cb, ri_kb_cb_t in_kb_cb, ri_hid_cb_t in_hid_cb) { wchar_t ri_dev_name[MAX_PATH] = L"\0"; wchar_t hid_prod_name[MAX_PATH] = L"\0"; @@ -28,6 +32,10 @@ HRESULT ri_init(uint8_t dev_num) DWORD err = 0; PRAWINPUTDEVICELIST ri_devs = NULL; + mouse_cb = in_mouse_cb; + kb_cb = in_kb_cb; + hid_cb = in_hid_cb; + if (GetRawInputDeviceList(NULL, &num_ri_devs, sizeof(RAWINPUTDEVICELIST)) != 0) { err = GetLastError(); dprintf("RawInput: GetRawInputDeviceList failed to get number of devices %08lX\n", err); @@ -118,25 +126,25 @@ static unsigned int __stdcall ri_thread_proc(void *ctx) ri_hwnd = CreateWindowExA(0, ri_wndclass.lpszClassName, "Taitools Input", 0, 0, 0, 0, 0, NULL, NULL, ri_wndclass.hInstance, NULL); RAWINPUTDEVICE Rid[4]; - Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC - Rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE - Rid[0].dwFlags = RIDEV_NOLEGACY; // adds mouse and also ignores legacy mouse messages - Rid[0].hwndTarget = ri_hwnd; + Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; + Rid[0].dwFlags = RIDEV_NOLEGACY; // adds mouse and also ignores legacy mouse messages + Rid[0].hwndTarget = ri_hwnd; - Rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC - Rid[1].usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD - Rid[1].dwFlags = RIDEV_NOLEGACY; // adds keyboard and also ignores legacy keyboard messages - Rid[1].hwndTarget = ri_hwnd; + Rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[1].usUsage = HID_USAGE_GENERIC_KEYBOARD; + Rid[1].dwFlags = RIDEV_NOLEGACY; // adds keyboard and also ignores legacy keyboard messages + Rid[1].hwndTarget = ri_hwnd; - Rid[2].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC - Rid[2].usUsage = 0x05; // HID_USAGE_GENERIC_GAMEPAD - Rid[2].dwFlags = 0; // adds game pad - Rid[2].hwndTarget = ri_hwnd; + Rid[2].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[2].usUsage = HID_USAGE_GENERIC_GAMEPAD; + Rid[2].dwFlags = 0; // adds game pad + Rid[2].hwndTarget = ri_hwnd; - Rid[3].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC - Rid[3].usUsage = 0x04; // HID_USAGE_GENERIC_JOYSTICK - Rid[3].dwFlags = 0; // adds joystick - Rid[3].hwndTarget = ri_hwnd; + Rid[3].usUsagePage = HID_USAGE_PAGE_GENERIC; + Rid[3].usUsage = HID_USAGE_GENERIC_JOYSTICK; + Rid[3].dwFlags = 0; // adds joystick + Rid[3].hwndTarget = ri_hwnd; if (!RegisterRawInputDevices(Rid, 4, sizeof(Rid[0]))) { dprintf("RawInput: Failed to register RI devices\n"); @@ -161,7 +169,41 @@ LRESULT CALLBACK ri_win_proc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lParam) switch (msg) { case WM_INPUT: //dprintf("RawInput: Got input\n"); - break; + UINT pdata_size = 0; + if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &pdata_size, sizeof(RAWINPUTHEADER)) != -1 && pdata_size > 0) { + PRAWINPUT ridata = (PRAWINPUT)malloc(pdata_size); + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, ridata, &pdata_size, sizeof(RAWINPUTHEADER)); + + if (ridata->header.hDevice != selected_ri_dev) { + free(ridata); + return (LRESULT)0; + } + + switch (ridata->header.dwType) { + case RIM_TYPEMOUSE: + if (mouse_cb != NULL) { + mouse_cb(&ridata->data.mouse); + } + break; + case RIM_TYPEKEYBOARD: + if (kb_cb != NULL) { + kb_cb(&ridata->data.keyboard); + } + break; + case RIM_TYPEHID: + if (hid_cb != NULL) { + hid_cb(&ridata->data.hid); + } + break; + } + + free(ridata); + } + return (LRESULT)0; + case WM_QUIT: + dprintf("RI: Exit requested\n"); + ExitProcess(0); + return (LRESULT)0; } return DefWindowProc(hWnd, msg, wparam, lParam); diff --git a/ri/ri.h b/ri/ri.h index 6afd6b7..d1e5fad 100644 --- a/ri/ri.h +++ b/ri/ri.h @@ -2,5 +2,9 @@ #include #include -HRESULT ri_init(uint8_t dev_num); +typedef void (*ri_mouse_cb_t)(PRAWMOUSE); +typedef void (*ri_kb_cb_t)(PRAWKEYBOARD); +typedef void (*ri_hid_cb_t)(PRAWHID); + +HRESULT ri_init(uint8_t dev_num, ri_mouse_cb_t in_mouse_cb, ri_kb_cb_t in_kb_cb, ri_hid_cb_t in_hid_cb); void ri_exit(); diff --git a/sivahook/dllmain.c b/sivahook/dllmain.c index 4ff88df..bd8abb8 100644 --- a/sivahook/dllmain.c +++ b/sivahook/dllmain.c @@ -8,6 +8,7 @@ #include "hooklib/serial.h" #include "hooklib/spike.h" +#include "hooklib/cursor.h" #include "idmac/idmac.h" @@ -82,6 +83,7 @@ static DWORD CALLBACK siva_pre_startup(void) } unity_hook_init(); + cursor_hook_init(); /* Initialize debug helpers */ spike_hook_init(L".\\taitools.ini"); diff --git a/sivahook/fastio.c b/sivahook/fastio.c index 7160279..bcdaf61 100644 --- a/sivahook/fastio.c +++ b/sivahook/fastio.c @@ -50,6 +50,54 @@ static void siva_fastio_digital_read(void *ctx, uint32_t *out) if (btn & BTN_SERVICE) { *out |= SIVA_SWITCH_SYS_SERVICE; } + + if (btn & BTN_SELECT) { + *out |= SIVA_SWITCH_SYS_SELECT; + } + + if (btn & BTN_ENTER) { + *out |= SIVA_SWITCH_SYS_ENTER; + } + + if (btn & BTN_LEFT) { + *out |= SIVA_SWITCH_LEFT_BUTTON; + } + + if (btn & BTN_RIGHT) { + *out |= SIVA_SWITCH_RIGHT_BUTTON; + } + + if (stick & STICK_LEFT_UP) { + *out |= SIVA_SWITCH_LEFT_UP; + } + + if (stick & STICK_LEFT_DOWN) { + *out |= SIVA_SWITCH_LEFT_DOWN; + } + + if (stick & STICK_LEFT_LEFT) { + *out |= SIVA_SWITCH_LEFT_LEFT; + } + + if (stick & STICK_LEFT_RIGHT) { + *out |= SIVA_SWITCH_LEFT_RIGHT; + } + + if (stick & STICK_RIGHT_UP) { + *out |= SIVA_SWITCH_RIGHT_UP; + } + + if (stick & STICK_RIGHT_DOWN) { + *out |= SIVA_SWITCH_RIGHT_DOWN; + } + + if (stick & STICK_RIGHT_LEFT) { + *out |= SIVA_SWITCH_RIGHT_LEFT; + } + + if (stick & STICK_RIGHT_RIGHT) { + *out |= SIVA_SWITCH_RIGHT_RIGHT; + } } static void siva_fastio_coin_read(void *ctx, uint8_t slot_no, uint32_t *out) diff --git a/sivahook/reader.c b/sivahook/reader.c index ffe818c..75e1dce 100644 --- a/sivahook/reader.c +++ b/sivahook/reader.c @@ -3,7 +3,7 @@ #include "jvs/jvs-bus.h" #include "idmac/jvs.h" -#include "board/j9100628a.h" +#include "board/k92x0249.h" #include "sivahook/reader.h" #include "sivahook/siva-dll.h" @@ -13,12 +13,12 @@ static void reader_jvs_write_led(void *ctx, uint32_t state); static void reader_jvs_poll_card(void *ctx, char *serial); -static const struct j9100628a_ops siva_jvs_reader_ops = { +static const struct k92x0249_ops siva_jvs_reader_ops = { .write_led = reader_jvs_write_led, .poll_card = reader_jvs_poll_card, }; -static struct j9100628a siva_jvs_reader; +static struct k92x0249 siva_jvs_reader; HRESULT siva_reader_init(struct jvs_node **out) { @@ -28,8 +28,8 @@ HRESULT siva_reader_init(struct jvs_node **out) dprintf("Siva Nesica Reader: Init\n"); - j9100628a_init(&siva_jvs_reader, NULL, &siva_jvs_reader_ops, NULL); - *out = j9100628a_to_jvs_node(&siva_jvs_reader); + k92x0249_init(&siva_jvs_reader, NULL, &siva_jvs_reader_ops, NULL); + *out = k92x0249_to_jvs_node(&siva_jvs_reader); return S_OK; } diff --git a/sivahook/siva-dll.c b/sivahook/siva-dll.c index d001710..6909864 100644 --- a/sivahook/siva-dll.c +++ b/sivahook/siva-dll.c @@ -67,7 +67,7 @@ HRESULT siva_dll_init(const struct siva_dll_config *cfg, HINSTANCE self) if (siva_dll.api_version >= 0x0200) { hr = E_NOTIMPL; dprintf("Siva IO: Custom IO DLL implements an unsupported " - "API version (%#04x). Please update Segatools.\n", + "API version (%#04x). Please update Taitools.\n", siva_dll.api_version); goto end; diff --git a/sivaio/config.c b/sivaio/config.c index 89a94ea..c035ba4 100644 --- a/sivaio/config.c +++ b/sivaio/config.c @@ -8,11 +8,13 @@ void siva_io_config_load(struct siva_input_config *cfg, const wchar_t *filename) { - cfg->test = GetPrivateProfileIntW(L"jvs", L"test", VK_HOME, filename); - cfg->service = GetPrivateProfileIntW(L"jvs", L"service", VK_DELETE, filename); - cfg->coin = GetPrivateProfileIntW(L"jvs", L"coin", VK_INSERT, filename); + cfg->test = GetPrivateProfileIntW(L"fastio", L"test", VK_HOME, filename); + cfg->service = GetPrivateProfileIntW(L"fastio", L"service", VK_DELETE, filename); + cfg->select = GetPrivateProfileIntW(L"fastio", L"select", VK_END, filename); + cfg->enter = GetPrivateProfileIntW(L"fastio", L"enter", VK_RSHIFT, filename); + cfg->coin = GetPrivateProfileIntW(L"fastio", L"coin", VK_INSERT, filename); - cfg->is_ri = GetPrivateProfileIntW(L"deck", L"input_type", 0, filename); // 0 for KB, 1 for RI + cfg->is_ri = GetPrivateProfileIntW(L"deck", L"input_type", 0, filename); // 0 for KB, 1 for RI cfg->device_num = GetPrivateProfileIntW(L"deck", L"device_num", 1, filename); cfg->btn_l = GetPrivateProfileIntW(L"deck", L"left_button", 'C', filename); diff --git a/sivaio/config.h b/sivaio/config.h index ccc3731..0bcb957 100644 --- a/sivaio/config.h +++ b/sivaio/config.h @@ -10,7 +10,10 @@ struct siva_input_config { uint8_t test; uint8_t service; + uint8_t select; + uint8_t enter; uint8_t coin; + uint8_t btn_l; uint8_t btn_r; diff --git a/sivaio/sivaio.c b/sivaio/sivaio.c index 0cba932..0dd8e62 100644 --- a/sivaio/sivaio.c +++ b/sivaio/sivaio.c @@ -16,6 +16,11 @@ static bool siva_io_service = false; static uint16_t siva_coin_ct = 0; static uint16_t siva_service_ct = 0; static struct siva_input_config cfg; +static CRITICAL_SECTION ri_critsec; + +void ri_mouse_input_cb(PRAWMOUSE mouse); +void ri_kb_input_cb(PRAWKEYBOARD kb); +void ri_hid_input_cb(PRAWHID hid); uint16_t siva_io_get_api_version(void) { @@ -28,7 +33,8 @@ HRESULT siva_io_init(void) siva_io_config_load(&cfg, L".\\taitools.ini"); if (cfg.is_ri) { - return ri_init(cfg.device_num); + InitializeCriticalSection(&ri_critsec); + return ri_init(cfg.device_num, ri_mouse_input_cb, ri_kb_input_cb, ri_hid_input_cb); } return S_OK; } @@ -36,9 +42,53 @@ HRESULT siva_io_init(void) void siva_io_get_btns(uint8_t *btn, uint8_t *stick) { - if (GetAsyncKeyState(VK_MENU) && GetAsyncKeyState(VK_F4)) { - ri_exit(); - return; + // if (GetAsyncKeyState(VK_MENU) && GetAsyncKeyState(VK_F4)) { + // ri_exit(); + // return; + // } + + if (cfg.is_ri) { + + } else { + if (GetAsyncKeyState(cfg.btn_l) & 0x8000) { + *btn |= BTN_LEFT; + } + + if (GetAsyncKeyState(cfg.btn_r) & 0x8000) { + *btn |= BTN_RIGHT; + } + + if (GetAsyncKeyState(cfg.stick_l_up) & 0x8000) { + *stick |= STICK_LEFT_UP; + } + + if (GetAsyncKeyState(cfg.stick_l_down) & 0x8000) { + *stick |= STICK_LEFT_DOWN; + } + + if (GetAsyncKeyState(cfg.stick_l_left) & 0x8000) { + *stick |= STICK_LEFT_LEFT; + } + + if (GetAsyncKeyState(cfg.stick_l_right) & 0x8000) { + *stick |= STICK_LEFT_RIGHT; + } + + if (GetAsyncKeyState(cfg.stick_r_up) & 0x8000) { + *stick |= STICK_RIGHT_UP; + } + + if (GetAsyncKeyState(cfg.stick_r_down) & 0x8000) { + *stick |= STICK_RIGHT_DOWN; + } + + if (GetAsyncKeyState(cfg.stick_r_left) & 0x8000) { + *stick |= STICK_RIGHT_LEFT; + } + + if (GetAsyncKeyState(cfg.stick_r_right) & 0x8000) { + *stick |= STICK_RIGHT_RIGHT; + } } if (GetAsyncKeyState(cfg.test) & 0x8000) { @@ -49,6 +99,14 @@ void siva_io_get_btns(uint8_t *btn, uint8_t *stick) *btn |= BTN_SERVICE; } + if (GetAsyncKeyState(cfg.select) & 0x8000) { + *btn |= BTN_SELECT; + } + + if (GetAsyncKeyState(cfg.enter) & 0x8000) { + *btn |= BTN_ENTER; + } + } void siva_io_read_coin_counter(uint16_t *coins, uint16_t *services) @@ -73,4 +131,25 @@ void siva_io_read_coin_counter(uint16_t *coins, uint16_t *services) *coins = siva_coin_ct; *services = siva_service_ct; -} \ No newline at end of file +} + +void ri_mouse_input_cb(PRAWMOUSE mouse) +{ + +} + +void ri_kb_input_cb(PRAWKEYBOARD kb) +{ + +} + +void ri_hid_input_cb(PRAWHID hid) +{ + DWORD bfr_size = hid->dwCount * hid->dwSizeHid; + dprintf("SivaIO: HID input - %d elements * %d bytes per element = %d\n", (int)hid->dwCount, (int)hid->dwSizeHid, (int)bfr_size); + + for (int i = 0; i < bfr_size; i++) { + dprintf(" %02X", hid->bRawData[i]); + } + dprintf("\n"); +} diff --git a/util/env.c b/util/env.c new file mode 100644 index 0000000..5f38beb --- /dev/null +++ b/util/env.c @@ -0,0 +1,10 @@ +#include "env.h" + +const wchar_t* get_config_path() { + static wchar_t path[MAX_PATH]; + if (!GetEnvironmentVariableW(L"TAITOOLS_CONFIG_PATH", path, MAX_PATH)) { + return L".\\taitools.ini"; + } + + return path; +} diff --git a/util/env.h b/util/env.h new file mode 100644 index 0000000..c62194a --- /dev/null +++ b/util/env.h @@ -0,0 +1,4 @@ +#pragma once +#include + +const wchar_t* get_config_path(); diff --git a/util/meson.build b/util/meson.build index 5dfa7bc..37ae9db 100644 --- a/util/meson.build +++ b/util/meson.build @@ -10,6 +10,8 @@ util_lib = static_library( 'async.h', 'crc.c', 'crc.h', + 'env.c', + 'env.h', 'dll-bind.c', 'dll-bind.h', 'dprintf.c',