diff --git a/board/config.c b/board/config.c index 9b69b42..c1cd713 100644 --- a/board/config.c +++ b/board/config.c @@ -90,4 +90,6 @@ void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename) assert(filename != NULL); cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename); + cfg->port = GetPrivateProfileIntW(L"vfd", L"portNo", 0, filename); + cfg->utf_conversion = GetPrivateProfileIntW(L"vfd", L"utfConversion", 0, filename); } diff --git a/board/meson.build b/board/meson.build index 0bf4fbc..b26851f 100644 --- a/board/meson.build +++ b/board/meson.build @@ -47,5 +47,8 @@ board_lib = static_library( 'slider-frame.h', 'vfd.c', 'vfd.h', + 'vfd-cmd.h', + 'vfd-frame.c', + 'vfd-frame.h', ], ) diff --git a/board/sg-nfc-cmd.h b/board/sg-nfc-cmd.h index c44586a..604783b 100644 --- a/board/sg-nfc-cmd.h +++ b/board/sg-nfc-cmd.h @@ -5,19 +5,21 @@ #pragma pack(push, 1) enum { - SG_NFC_CMD_GET_FW_VERSION = 0x30, - SG_NFC_CMD_GET_HW_VERSION = 0x32, - SG_NFC_CMD_RADIO_ON = 0x40, - SG_NFC_CMD_RADIO_OFF = 0x41, - SG_NFC_CMD_POLL = 0x42, - SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43, - SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50, - SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52, - SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54, - SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55, /* guess based on time sent */ - SG_NFC_CMD_SEND_HEX_DATA = 0x61, - SG_NFC_CMD_RESET = 0x62, - SG_NFC_CMD_FELICA_ENCAP = 0x71, + SG_NFC_CMD_GET_FW_VERSION = 0x30, + SG_NFC_CMD_GET_HW_VERSION = 0x32, + SG_NFC_CMD_RADIO_ON = 0x40, + SG_NFC_CMD_RADIO_OFF = 0x41, + SG_NFC_CMD_POLL = 0x42, + SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43, + SG_NFC_CMD_MIFARE_SET_KEY_A = 0x50, + SG_NFC_CMD_MIFARE_AUTHENTICATE_A = 0x51, + SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52, + SG_NFC_CMD_MIFARE_SET_KEY_B = 0x54, + SG_NFC_CMD_MIFARE_AUTHENTICATE_B = 0x55, + SG_NFC_CMD_TO_UPDATE_MODE = 0x60, + SG_NFC_CMD_SEND_HEX_DATA = 0x61, + SG_NFC_CMD_RESET = 0x62, + SG_NFC_CMD_FELICA_ENCAP = 0x71, }; struct sg_nfc_res_get_fw_version { @@ -32,7 +34,7 @@ struct sg_nfc_res_get_hw_version { struct sg_nfc_req_mifare_set_key { struct sg_req_header req; - uint8_t key_a[6]; + uint8_t key[6]; }; struct sg_nfc_req_mifare_50 { diff --git a/board/sg-nfc.c b/board/sg-nfc.c index 1f023be..19a6ad6 100644 --- a/board/sg-nfc.c +++ b/board/sg-nfc.c @@ -60,6 +60,11 @@ static HRESULT sg_nfc_cmd_felica_encap( const struct sg_nfc_req_felica_encap *req, struct sg_nfc_res_felica_encap *res); +static HRESULT sg_nfc_cmd_send_hex_data( + struct sg_nfc *nfc, + const struct sg_req_header *req, + struct sg_res_header *res); + static HRESULT sg_nfc_cmd_dummy( struct sg_nfc *nfc, const struct sg_req_header *req, @@ -185,12 +190,15 @@ static HRESULT sg_nfc_dispatch( &res->felica_encap); case SG_NFC_CMD_MIFARE_AUTHENTICATE: + case SG_NFC_CMD_SEND_HEX_DATA: + return sg_nfc_cmd_send_hex_data(nfc, &req->simple, &res->simple); + case SG_NFC_CMD_MIFARE_SELECT_TAG: case SG_NFC_CMD_MIFARE_SET_KEY_AIME: case SG_NFC_CMD_MIFARE_SET_KEY_BANA: case SG_NFC_CMD_RADIO_ON: case SG_NFC_CMD_RADIO_OFF: - case SG_NFC_CMD_SEND_HEX_DATA: // TODO: implement? + case SG_NFC_CMD_TO_UPDATE_MODE: return sg_nfc_cmd_dummy(nfc, &req->simple, &res->simple); default: @@ -442,6 +450,22 @@ static HRESULT sg_nfc_cmd_felica_encap( return S_OK; } +static HRESULT sg_nfc_cmd_send_hex_data( + struct sg_nfc *nfc, + const struct sg_req_header *req, + struct sg_res_header *res) +{ + sg_res_init(res, req, 0); + + /* Firmware checksum length? */ + if (req->payload_len == 0x2b) { + /* The firmware is identical flag? */ + res->status = 0x20; + } + + return S_OK; +} + static HRESULT sg_nfc_cmd_dummy( struct sg_nfc *nfc, const struct sg_req_header *req, diff --git a/board/vfd-cmd.h b/board/vfd-cmd.h new file mode 100644 index 0000000..28bcb16 --- /dev/null +++ b/board/vfd-cmd.h @@ -0,0 +1,123 @@ +#pragma once + +#include "board/vfd-frame.h" + +enum { + VFD_CMD_GET_VERSION = 0x5B, + VFD_CMD_RESET = 0x0B, + VFD_CMD_CLEAR_SCREEN = 0x0C, + VFD_CMD_SET_BRIGHTNESS = 0x20, + VFD_CMD_SET_SCREEN_ON = 0x21, + VFD_CMD_SET_H_SCROLL = 0x22, + VFD_CMD_DRAW_IMAGE = 0x2E, + VFD_CMD_SET_CURSOR = 0x30, + VFD_CMD_SET_ENCODING = 0x32, + VFD_CMD_SET_TEXT_WND = 0x40, + VFD_CMD_SET_TEXT_SPEED = 0x41, + VFD_CMD_WRITE_TEXT = 0x50, + VFD_CMD_ENABLE_SCROLL = 0x51, + VFD_CMD_DISABLE_SCROLL = 0x52, + VFD_CMD_ROTATE = 0x5D, + VFD_CMD_CREATE_CHAR = 0xA3, + VFD_CMD_CREATE_CHAR2 = 0xA4, +}; + +enum { + VFD_ENC_GB2312 = 0, + VFD_ENC_BIG5 = 1, + VFD_ENC_SHIFT_JIS = 2, + VFD_ENC_KSC5601 = 3, + VFD_ENC_MAX = 3, +}; + +struct vfd_req_hdr { + uint8_t sync; + uint8_t cmd; +}; + +struct vfd_req_any { + struct vfd_req_hdr hdr; + uint8_t payload[2054]; +}; + +struct vfd_req_board_info { + struct vfd_req_hdr hdr; + uint8_t unk1; +}; + +struct vfd_resp_board_info { // \x0201.20\x03 + uint8_t unk1; + char version[5]; + uint8_t unk2; +}; + +struct vfd_req_reset { + struct vfd_req_hdr hdr; +}; + +struct vfd_req_cls { + struct vfd_req_hdr hdr; +}; + +struct vfd_req_brightness { + struct vfd_req_hdr hdr; + uint8_t brightness; +}; + +struct vfd_req_power { + struct vfd_req_hdr hdr; + uint8_t power_state; +}; + +struct vfd_req_hscroll { + struct vfd_req_hdr hdr; + uint8_t x_pos; +}; + +struct vfd_req_draw { + struct vfd_req_hdr hdr; + uint16_t x0; + uint8_t y0; + uint16_t x1; + uint8_t y1; + uint8_t image[2048]; +}; + +struct vfd_req_cursor { + struct vfd_req_hdr hdr; + uint16_t x; + uint8_t y; +}; + +struct vfd_req_encoding { + struct vfd_req_hdr hdr; + uint8_t encoding; +}; + +struct vfd_req_wnd { + struct vfd_req_hdr hdr; + uint16_t x0; + uint8_t y0; + uint16_t x1; + uint8_t y1; +}; + +struct vfd_req_speed { + struct vfd_req_hdr hdr; + uint8_t encoding; +}; + +struct vfd_req_scroll { + struct vfd_req_hdr hdr; +}; + +struct vfd_req_rotate { + struct vfd_req_hdr hdr; + uint8_t unk1; +}; + +struct vfd_req_create_char { + struct vfd_req_hdr hdr; + uint8_t type; + uint8_t pixels[32]; +}; diff --git a/board/vfd-frame.c b/board/vfd-frame.c new file mode 100644 index 0000000..05fe302 --- /dev/null +++ b/board/vfd-frame.c @@ -0,0 +1,88 @@ +#include + +#include +#include +#include +#include + +#define SUPER_VERBOSE 1 + +#include "board/vfd-frame.h" + +#include "hook/iobuf.h" + +#include "util/dprintf.h" + +static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte); + +/* Frame structure: + + REQUEST: + [0] Sync byte (0x1A or 0x1B) + [1] Packet ID + [2...n-1] Data/payload + + --- OR --- + + if no sync byte is given, plain static text in the currently configured encoding is expected. + + RESPONSE: + This thing never responds, unless it's VFD_CMD_GET_VERSION + */ + +bool vfd_frame_sync(struct const_iobuf *src) { + return src->bytes[src->pos] == VFD_SYNC_BYTE || src->bytes[src->pos] == VFD_SYNC_BYTE2; +} + +HRESULT vfd_frame_encode( + struct iobuf *dest, + const void *ptr, + size_t nbytes) { + const uint8_t *src; + 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; + + if (dest->pos >= dest->nbytes) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + +#if SUPER_VERBOSE + dprintf("VFD: RX Buffer:\n"); +#endif + + for (i = 1; i < nbytes; i++) { + byte = src[i]; +#if SUPER_VERBOSE + dprintf("%02x ", byte); +#endif + + hr = vfd_frame_encode_byte(dest, byte); + + if (FAILED(hr)) { + return hr; + } + } +#if SUPER_VERBOSE + dprintf("\n"); +#endif + + return hr; +} + +static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte) { + if (dest->pos + 1 > dest->nbytes) { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + dest->bytes[dest->pos++] = byte; + + return S_OK; +} diff --git a/board/vfd-frame.h b/board/vfd-frame.h new file mode 100644 index 0000000..7055f5b --- /dev/null +++ b/board/vfd-frame.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include +#include + +#include "hook/iobuf.h" + +enum { + VFD_SYNC_BYTE = 0x1B, + VFD_SYNC_BYTE2 = 0x1A, +}; + +bool vfd_frame_sync(struct const_iobuf *src); + +HRESULT vfd_frame_encode( + struct iobuf *dest, + const void *ptr, + size_t nbytes); diff --git a/board/vfd.c b/board/vfd.c index b216706..abc487a 100644 --- a/board/vfd.c +++ b/board/vfd.c @@ -2,17 +2,16 @@ directly by amdaemon, and it has something to do with displaying the status of electronic payments. - Part number in schematics is "VFD GP1232A02A FUTABA". - - Little else about this board is known. Black-holing the RS232 comms that it - receives seems to be sufficient for the time being. */ + Part number in schematics is "VFD GP1232A02A FUTABA". */ #include #include #include +#include "board/config.h" #include "board/vfd.h" +#include "board/vfd-cmd.h" #include "hook/iohook.h" @@ -21,33 +20,101 @@ #include "util/dprintf.h" #include "util/dump.h" +#define SUPER_VERBOSE 0 + static HRESULT vfd_handle_irp(struct irp *irp); static struct uart vfd_uart; -static uint8_t vfd_written[512]; -static uint8_t vfd_readable[512]; -UINT codepage; +static uint8_t vfd_written[4096]; +static uint8_t vfd_readable[4096]; -HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no) +static int encoding = VFD_ENC_SHIFT_JIS; + +HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); +HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart); + +static bool utf_enabled; + +HRESULT vfd_hook_init(struct vfd_config *cfg, int default_port) { - assert(cfg != NULL); - - if (!cfg->enable) { + if (!cfg->enable){ return S_FALSE; } - uart_init(&vfd_uart, port_no); + utf_enabled = cfg->utf_conversion; + + int port = cfg->port; + if (port == 0){ + port = default_port; + } + + dprintf("VFD: enabling (port=%d)\n", port); + uart_init(&vfd_uart, port); vfd_uart.written.bytes = vfd_written; vfd_uart.written.nbytes = sizeof(vfd_written); vfd_uart.readable.bytes = vfd_readable; vfd_uart.readable.nbytes = sizeof(vfd_readable); - codepage = GetACP(); - dprintf("VFD: hook enabled.\n"); - return iohook_push_handler(vfd_handle_irp); } + +const char* get_encoding_name(int b){ + switch (b){ + case 0: return "gb2312"; + case 1: return "big5"; + case 2: return "shift-jis"; + case 3: return "ks_c_5601-1987"; + default: return "unknown"; + } +} + +void print_vfd_text(const char* str, int len){ + + if (utf_enabled){ + + wchar_t encoded[1024]; + memset(encoded, 0, 1024 * sizeof(wchar_t)); + + int codepage = 0; + if (encoding == VFD_ENC_GB2312){ + codepage = 936; + } else if (encoding == VFD_ENC_BIG5){ + codepage = 950; + } else if (encoding == VFD_ENC_SHIFT_JIS){ + codepage = 932; + } else if (encoding == VFD_ENC_KSC5601) { + codepage = 949; + } + + if (!MultiByteToWideChar(codepage, MB_USEGLYPHCHARS, str, len, encoded, 1024)){ + dprintf("VFD: Text conversion failed: %ld", GetLastError()); + return; + } + + dprintf("VFD: Text: %ls\n", encoded); + } else { + + dprintf("VFD: Text: %s\n", str); + + } +} + static HRESULT vfd_handle_irp(struct irp *irp) { HRESULT hr; @@ -58,67 +125,274 @@ static HRESULT vfd_handle_irp(struct irp *irp) return iohook_invoke_next(irp); } + if (irp->op == IRP_OP_OPEN){ + dprintf("VFD: Open\n"); + } else if (irp->op == IRP_OP_CLOSE){ + dprintf("VFD: Close\n"); + } + hr = uart_handle_irp(&vfd_uart, irp); if (FAILED(hr) || irp->op != IRP_OP_WRITE) { return hr; } - uint8_t cmd = 0; - uint8_t str_1[512]; - uint8_t str_2[512]; - uint8_t str_1_len = 0; - uint8_t str_2_len = 0; - for (size_t i = 0; i < vfd_uart.written.pos; i++) { - if (vfd_uart.written.bytes[i] == 0x1B) { - i++; - cmd = vfd_uart.written.bytes[i]; - if (cmd == 0x30) { - i += 3; - } - else if (cmd == 0x50) { - i++; - } - continue; - } - if (cmd == 0x30) { - str_1[str_1_len++] = vfd_uart.written.bytes[i]; - } - else if (cmd == 0x50) { - str_2[str_2_len++] = vfd_uart.written.bytes[i]; - } - } +#if SUPER_VERBOSE + dprintf("VFD TX:\n"); + dump_iobuf(&vfd_uart.written); +#endif - if (str_1_len) { - str_1[str_1_len++] = '\0'; - if (codepage != 932) { - WCHAR buffer[512]; - MultiByteToWideChar(932, 0, (LPCSTR)str_1, str_1_len, buffer, str_1_len); - char str_recode[str_1_len * 3]; - WideCharToMultiByte(codepage, 0, buffer, str_1_len, str_recode, str_1_len * 3, NULL, NULL); - dprintf("VFD: %s\n", str_recode); - } - else { - dprintf("VFD: %s\n", str_1); - } - } + struct const_iobuf reader; + iobuf_flip(&reader, &vfd_uart.written); - if (str_2_len) { - str_2[str_2_len++] = '\0'; - if (codepage != 932) { - WCHAR buffer[512]; - MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len); - char str_recode[str_2_len * 3]; - WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL); - dprintf("VFD: %s\n", str_recode); + struct iobuf* writer = &vfd_uart.readable; + for (; reader.pos < reader.nbytes ; ){ + + if (vfd_frame_sync(&reader)) { + + reader.pos++; // get the sync byte out of the way + + uint8_t cmd; + iobuf_read_8(&reader, &cmd); + + if (cmd == VFD_CMD_GET_VERSION) { + hr = vfd_handle_get_version(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_RESET) { + hr = vfd_handle_reset(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_CLEAR_SCREEN) { + hr = vfd_handle_clear_screen(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_BRIGHTNESS) { + hr = vfd_handle_set_brightness(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_SCREEN_ON) { + hr = vfd_handle_set_screen_on(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_H_SCROLL) { + hr = vfd_handle_set_h_scroll(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_DRAW_IMAGE) { + hr = vfd_handle_draw_image(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_CURSOR) { + hr = vfd_handle_set_cursor(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_ENCODING) { + hr = vfd_handle_set_encoding(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_TEXT_WND) { + hr = vfd_handle_set_text_wnd(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_SET_TEXT_SPEED) { + hr = vfd_handle_set_text_speed(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_WRITE_TEXT) { + hr = vfd_handle_write_text(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_ENABLE_SCROLL) { + hr = vfd_handle_enable_scroll(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_DISABLE_SCROLL) { + hr = vfd_handle_disable_scroll(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_ROTATE) { + hr = vfd_handle_rotate(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_CREATE_CHAR) { + hr = vfd_handle_create_char(&reader, writer, &vfd_uart); + } else if (cmd == VFD_CMD_CREATE_CHAR2) { + hr = vfd_handle_create_char2(&reader, writer, &vfd_uart); + } else { + dprintf("VFD: Unknown command 0x%x\n", cmd); + dump_const_iobuf(&reader); + hr = S_FALSE; + } } else { - dprintf("VFD: %s\n", str_2); + + // if no sync byte is sent, we are just getting plain text... + + if (reader.pos < reader.nbytes){ + int len = 0; + + // read chars until we hit a new sync byte or the data ends + while (reader.pos + len + 1 < reader.nbytes && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE2){ + len++; + } + + char* str = malloc(len); + memset(str, 0, len); + iobuf_read(&reader, str, len); + print_vfd_text(str, len); + free(str); + + reader.pos += len; + } + } + + if (!SUCCEEDED(hr)){ + return hr; + } + } - // dprintf("VFD TX:\n"); - // dump_iobuf(&vfd_uart.written); vfd_uart.written.pos = 0; return hr; } + +HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + dprintf("VFD: Get Version\n"); + + struct vfd_resp_board_info resp; + + memset(&resp, 0, sizeof(resp)); + resp.unk1 = 2; + strcpy(resp.version, "01.20"); + resp.unk2 = 1; + + return vfd_frame_encode(writer, &resp, sizeof(resp)); +} +HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + dprintf("VFD: Reset\n"); + + encoding = VFD_ENC_SHIFT_JIS; + + return S_FALSE; +} +HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + dprintf("VFD: Clear Screen\n"); + + return S_FALSE; +} +HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + + if (b > 4){ + dprintf("VFD: Brightness, invalid argument\n"); + return E_FAIL; + } + + dprintf("VFD: Brightness, %d\n", b); + + return S_FALSE; +} +HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + + if (b > 1){ + dprintf("VFD: Screen Power, invalid argument\n"); + return E_FAIL; + } + + dprintf("VFD: Screen Power, %d\n", b); + return S_FALSE; +} +HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t x; + iobuf_read_8(reader, &x); + + dprintf("VFD: Horizontal Scroll, X=%d\n", x); + return S_FALSE; +} +HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + int w, h; + uint16_t x0, x1; + uint8_t y0, y1; + uint8_t image[2048]; + + iobuf_read_be16(reader, &x0); + iobuf_read_8(reader, &y0); + iobuf_read_be16(reader, &x1); + iobuf_read_8(reader, &y1); + w = x1 - x0; + h = y1 - y0; + iobuf_read(reader, image, w*h); + + dprintf("VFD: Draw image, %dx%d\n", w, h); + return S_FALSE; +} + +HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint16_t x; + uint8_t y; + + iobuf_read_be16(reader, &x); + iobuf_read_8(reader, &y); + + dprintf("VFD: Set Cursor, x=%d,y=%d\n", x, y); + + return S_FALSE; +} + +HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + + dprintf("VFD: Set Encoding, %d (%s)\n", b, get_encoding_name(b)); + + if (b < 0 || b > VFD_ENC_MAX){ + dprintf("Invalid encoding specified\n"); + return E_FAIL; + } + + encoding = b; + + return S_FALSE; +} +HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint16_t x0, x1; + uint8_t y0, y1; + + iobuf_read_be16(reader, &x0); + iobuf_read_8(reader, &y0); + iobuf_read_be16(reader, &x1); + iobuf_read_8(reader, &y1); + + dprintf("VFD: Set Text Window, p0:%d,%d, p1:%d,%d\n", x0, y0, x1, y1); + return S_FALSE; +} +HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + + dprintf("VFD: Set Text Speed, %d\n", b); + return S_FALSE; +} +HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t len; + iobuf_read_8(reader, &len); + + char* str = malloc(len); + iobuf_read(reader, str, len); + + print_vfd_text(str, len); + free(str); + + return S_FALSE; +} +HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + dprintf("VFD: Enable Scrolling\n"); + return S_FALSE; +} +HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + dprintf("VFD: Disable Scrolling\n"); + return S_FALSE; +} +HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + + dprintf("VFD: Rotate, %d\n", b); + return S_FALSE; +} +HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b; + iobuf_read_8(reader, &b); + char buf[32]; + + iobuf_read(reader, buf, 32); + + dprintf("VFD: Create character, %d\n", b); + return S_FALSE; +} +HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){ + uint8_t b, b2; + iobuf_read_8(reader, &b); + iobuf_read_8(reader, &b2); + char buf[16]; + + iobuf_read(reader, buf, 16); + + dprintf("VFD: Create character, %d, %d\n", b, b2); + return S_FALSE; +} diff --git a/board/vfd.h b/board/vfd.h index e37386f..3e67061 100644 --- a/board/vfd.h +++ b/board/vfd.h @@ -4,7 +4,10 @@ struct vfd_config { bool enable; + int port; + bool utf_conversion; }; -HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no); +HRESULT vfd_hook_init(struct vfd_config *cfg, int default_port); + diff --git a/dist/chusan/segatools.ini b/dist/chusan/segatools.ini index 556df02..ee3af18 100644 --- a/dist/chusan/segatools.ini +++ b/dist/chusan/segatools.ini @@ -25,7 +25,7 @@ aimePath=DEVICE\aime.txt ;highBaud=1 [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/dist/cm/segatools.ini b/dist/cm/segatools.ini index 2cd86b0..cd42cd6 100644 --- a/dist/cm/segatools.ini +++ b/dist/cm/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/dist/fgo/segatools.ini b/dist/fgo/segatools.ini index 945f9a1..790de88 100644 --- a/dist/fgo/segatools.ini +++ b/dist/fgo/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/dist/mai2/segatools.ini b/dist/mai2/segatools.ini index 71dbf15..c253334 100644 --- a/dist/mai2/segatools.ini +++ b/dist/mai2/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/dist/mercury/segatools.ini b/dist/mercury/segatools.ini index 891c4d8..0755bac 100644 --- a/dist/mercury/segatools.ini +++ b/dist/mercury/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/dist/mu3/segatools.ini b/dist/mu3/segatools.ini index 182e1d8..59ec0d2 100644 --- a/dist/mu3/segatools.ini +++ b/dist/mu3/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 @@ -190,7 +190,7 @@ leftSide=0x01 ; Mouse Left rightSide=0x02 ; Mouse Right right1=0x4A ; J -right1=0x4B ; K +right2=0x4B ; K right3=0x4C ; L leftMenu=0x55 ; U diff --git a/dist/swdc/segatools.ini b/dist/swdc/segatools.ini index 6fdee71..72ea69d 100644 --- a/dist/swdc/segatools.ini +++ b/dist/swdc/segatools.ini @@ -23,7 +23,7 @@ enable=1 aimePath=DEVICE\aime.txt [vfd] -; Enable VFD emulation (currently just stubbed). Disable to use a real VFD +; Enable VFD emulation. Disable to use a real VFD ; GP1232A02A FUTABA assembly. enable=1 diff --git a/doc/config/common.md b/doc/config/common.md index ad9e348..e778a8a 100644 --- a/doc/config/common.md +++ b/doc/config/common.md @@ -92,9 +92,21 @@ Controls emulation of the VFD GP1232A02A FUTABA assembly. Default: `1` -Enable VFD emulation (currently just stubbed). Disable to use a real VFD +Enable VFD emulation. Disable to use a real VFD GP1232A02A FUTABA assembly (COM port number varies by game). +### `portNo` + +Default: (game specific) + +Sets the COM port to use for the VFD. + +### `utfConversion` + +Default: `0` + +Converts the strings from the VFD from their respective encoding to UTF, so console output will display as it should on non-Japanese locales. + ## `[amvideo]` Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is