forked from Dniel97/segatools
Merge pull request 'add almost full vfd implementation' (#31) from Haruka/segatools:vfd into develop
Reviewed-on: Dniel97/segatools#31 Reviewed-by: Dniel97 <dniel97@noreply.gitea.tendokyu.moe>
This commit is contained in:
commit
c827b4c212
@ -90,4 +90,6 @@ void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename)
|
|||||||
assert(filename != NULL);
|
assert(filename != NULL);
|
||||||
|
|
||||||
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
|
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);
|
||||||
}
|
}
|
||||||
|
@ -47,5 +47,8 @@ board_lib = static_library(
|
|||||||
'slider-frame.h',
|
'slider-frame.h',
|
||||||
'vfd.c',
|
'vfd.c',
|
||||||
'vfd.h',
|
'vfd.h',
|
||||||
|
'vfd-cmd.h',
|
||||||
|
'vfd-frame.c',
|
||||||
|
'vfd-frame.h',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
123
board/vfd-cmd.h
Normal file
123
board/vfd-cmd.h
Normal file
@ -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];
|
||||||
|
};
|
88
board/vfd-frame.c
Normal file
88
board/vfd-frame.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
20
board/vfd-frame.h
Normal file
20
board/vfd-frame.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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);
|
400
board/vfd.c
400
board/vfd.c
@ -2,17 +2,16 @@
|
|||||||
directly by amdaemon, and it has something to do with displaying the status
|
directly by amdaemon, and it has something to do with displaying the status
|
||||||
of electronic payments.
|
of electronic payments.
|
||||||
|
|
||||||
Part number in schematics is "VFD GP1232A02A FUTABA".
|
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. */
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "board/config.h"
|
||||||
#include "board/vfd.h"
|
#include "board/vfd.h"
|
||||||
|
#include "board/vfd-cmd.h"
|
||||||
|
|
||||||
#include "hook/iohook.h"
|
#include "hook/iohook.h"
|
||||||
|
|
||||||
@ -21,33 +20,101 @@
|
|||||||
#include "util/dprintf.h"
|
#include "util/dprintf.h"
|
||||||
#include "util/dump.h"
|
#include "util/dump.h"
|
||||||
|
|
||||||
|
#define SUPER_VERBOSE 0
|
||||||
|
|
||||||
static HRESULT vfd_handle_irp(struct irp *irp);
|
static HRESULT vfd_handle_irp(struct irp *irp);
|
||||||
|
|
||||||
static struct uart vfd_uart;
|
static struct uart vfd_uart;
|
||||||
static uint8_t vfd_written[512];
|
static uint8_t vfd_written[4096];
|
||||||
static uint8_t vfd_readable[512];
|
static uint8_t vfd_readable[4096];
|
||||||
UINT codepage;
|
|
||||||
|
|
||||||
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;
|
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.bytes = vfd_written;
|
||||||
vfd_uart.written.nbytes = sizeof(vfd_written);
|
vfd_uart.written.nbytes = sizeof(vfd_written);
|
||||||
vfd_uart.readable.bytes = vfd_readable;
|
vfd_uart.readable.bytes = vfd_readable;
|
||||||
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
vfd_uart.readable.nbytes = sizeof(vfd_readable);
|
||||||
|
|
||||||
codepage = GetACP();
|
|
||||||
dprintf("VFD: hook enabled.\n");
|
|
||||||
|
|
||||||
return iohook_push_handler(vfd_handle_irp);
|
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)
|
static HRESULT vfd_handle_irp(struct irp *irp)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
@ -58,67 +125,274 @@ static HRESULT vfd_handle_irp(struct irp *irp)
|
|||||||
return iohook_invoke_next(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);
|
hr = uart_handle_irp(&vfd_uart, irp);
|
||||||
|
|
||||||
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t cmd = 0;
|
#if SUPER_VERBOSE
|
||||||
uint8_t str_1[512];
|
dprintf("VFD TX:\n");
|
||||||
uint8_t str_2[512];
|
dump_iobuf(&vfd_uart.written);
|
||||||
uint8_t str_1_len = 0;
|
#endif
|
||||||
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 (str_1_len) {
|
struct const_iobuf reader;
|
||||||
str_1[str_1_len++] = '\0';
|
iobuf_flip(&reader, &vfd_uart.written);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_2_len) {
|
struct iobuf* writer = &vfd_uart.readable;
|
||||||
str_2[str_2_len++] = '\0';
|
for (; reader.pos < reader.nbytes ; ){
|
||||||
if (codepage != 932) {
|
|
||||||
WCHAR buffer[512];
|
if (vfd_frame_sync(&reader)) {
|
||||||
MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len);
|
|
||||||
char str_recode[str_2_len * 3];
|
reader.pos++; // get the sync byte out of the way
|
||||||
WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL);
|
|
||||||
dprintf("VFD: %s\n", str_recode);
|
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 {
|
} else {
|
||||||
dprintf("VFD: %s\n", str_2);
|
dprintf("VFD: Unknown command 0x%x\n", cmd);
|
||||||
|
dump_const_iobuf(&reader);
|
||||||
|
hr = S_FALSE;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// 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;
|
vfd_uart.written.pos = 0;
|
||||||
|
|
||||||
return hr;
|
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;
|
||||||
|
}
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
struct vfd_config {
|
struct vfd_config {
|
||||||
bool enable;
|
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);
|
||||||
|
|
||||||
|
2
dist/chusan/segatools.ini
vendored
2
dist/chusan/segatools.ini
vendored
@ -25,7 +25,7 @@ aimePath=DEVICE\aime.txt
|
|||||||
;highBaud=1
|
;highBaud=1
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/cm/segatools.ini
vendored
2
dist/cm/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/fgo/segatools.ini
vendored
2
dist/fgo/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/mai2/segatools.ini
vendored
2
dist/mai2/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/mercury/segatools.ini
vendored
2
dist/mercury/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/mu3/segatools.ini
vendored
2
dist/mu3/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
2
dist/swdc/segatools.ini
vendored
2
dist/swdc/segatools.ini
vendored
@ -23,7 +23,7 @@ enable=1
|
|||||||
aimePath=DEVICE\aime.txt
|
aimePath=DEVICE\aime.txt
|
||||||
|
|
||||||
[vfd]
|
[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.
|
; GP1232A02A FUTABA assembly.
|
||||||
enable=1
|
enable=1
|
||||||
|
|
||||||
|
@ -92,9 +92,21 @@ Controls emulation of the VFD GP1232A02A FUTABA assembly.
|
|||||||
|
|
||||||
Default: `1`
|
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).
|
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]`
|
## `[amvideo]`
|
||||||
|
|
||||||
Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is
|
Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is
|
||||||
|
Loading…
Reference in New Issue
Block a user