diff --git a/Module.mk b/Module.mk index 31741fa..173246d 100644 --- a/Module.mk +++ b/Module.mk @@ -104,6 +104,7 @@ include src/main/d3d9exhook/Module.mk include src/main/ddrhook-util/Module.mk include src/main/ddrhook1/Module.mk include src/main/ddrhook2/Module.mk +include src/main/ddrio-p3io/Module.mk include src/main/ddrio-mm/Module.mk include src/main/ddrio-smx/Module.mk include src/main/ddrio/Module.mk diff --git a/src/main/ddrio-p3io/Module.mk b/src/main/ddrio-p3io/Module.mk new file mode 100644 index 0000000..43e0fd0 --- /dev/null +++ b/src/main/ddrio-p3io/Module.mk @@ -0,0 +1,16 @@ +dlls += ddrio-p3io + +ldflags_ddrio-p3io:= \ + -lsetupapi \ + +libs_ddrio-p3io := \ + cconfig \ + extio \ + extiodrv \ + p3io \ + p3iodrv \ + util \ + +src_ddrio-p3io := \ + config.c \ + ddrio.c \ diff --git a/src/main/ddrio-p3io/config.c b/src/main/ddrio-p3io/config.c new file mode 100644 index 0000000..c45254e --- /dev/null +++ b/src/main/ddrio-p3io/config.c @@ -0,0 +1,35 @@ +#include "cconfig/cconfig-util.h" + +#include "util/log.h" + +#include "config.h" + +#define DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY "ddrio.p3io.extio_port" + +#define DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE "COM1" + +void ddrio_p3io_config_init(struct cconfig *config) +{ + cconfig_util_set_str( + config, + DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, + DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE, + "COM port the EXTIO is connected to, default COM1"); +} + +void ddrio_p3io_config_get( + struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config) +{ + if (!cconfig_util_get_str( + config, + DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, + config_ddrio_p3io->extio_port, + sizeof(config_ddrio_p3io->extio_port) - 1, + DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%s'", + DDRIO_P3IO_CONFIG_EXTIO_PORT_KEY, + DDRIO_P3IO_CONFIG_EXTIO_PORT_VALUE); + } +} diff --git a/src/main/ddrio-p3io/config.h b/src/main/ddrio-p3io/config.h new file mode 100644 index 0000000..784782f --- /dev/null +++ b/src/main/ddrio-p3io/config.h @@ -0,0 +1,17 @@ +#ifndef DDRIO_P3IO_CONFIG_H +#define DDRIO_P3IO_CONFIG_H + +#include + +#include "cconfig/cconfig.h" + +struct ddrio_p3io_config { + char extio_port[12]; +}; + +void ddrio_p3io_config_init(struct cconfig *config); + +void ddrio_p3io_config_get( + struct ddrio_p3io_config *config_ddrio_p3io, struct cconfig *config); + +#endif \ No newline at end of file diff --git a/src/main/ddrio-p3io/ddrio-p3io.def b/src/main/ddrio-p3io/ddrio-p3io.def new file mode 100644 index 0000000..f6e9fbb --- /dev/null +++ b/src/main/ddrio-p3io/ddrio-p3io.def @@ -0,0 +1,11 @@ +LIBRARY ddrio-p3io + +EXPORTS + ddr_io_set_loggers + ddr_io_fini + ddr_io_init + ddr_io_read_pad + ddr_io_set_lights_extio + ddr_io_set_lights_p3io + ddr_io_set_lights_hdxs_panel + ddr_io_set_lights_hdxs_rgb diff --git a/src/main/ddrio-p3io/ddrio.c b/src/main/ddrio-p3io/ddrio.c new file mode 100644 index 0000000..a38ce09 --- /dev/null +++ b/src/main/ddrio-p3io/ddrio.c @@ -0,0 +1,427 @@ +#define LOG_MODULE "ddrio-p3io" + +#include + +#include +#include +#include + +#include "bemanitools/ddrio.h" + +#include "cconfig/cconfig-main.h" + +#include "extiodrv/device.h" +#include "extiodrv/extio.h" + +#include "p3iodrv/ddr.h" +#include "p3iodrv/device.h" + +#include "util/log.h" +#include "util/thread.h" + +#include "config.h" + +static struct ddrio_p3io_config _ddr_io_p3io_config; +static HANDLE _ddr_io_p3io_handle; +static HANDLE _ddr_io_extio_handle; + +static HRESULT _ddr_io_p3io_scan_and_open(HANDLE *handle) +{ + HRESULT hr; + char path[MAX_PATH]; + + log_info("Scanning for p3io..."); + + hr = p3iodrv_device_scan(path); + + if (FAILED(hr)) { + log_warning("Cannot find a connected p3io: %lX", hr); + return hr; + } + + log_info("Opening p3io: %s", path); + + hr = p3iodrv_device_open(path, handle); + + if (FAILED(hr)) { + log_warning("Opening p3io failed: %lX", hr); + return hr; + } + + return hr; +} + +static HRESULT _ddr_io_p3io_print_version(HANDLE handle) +{ + HRESULT hr; + char version[P3IODRV_VERSION_MAX_LEN]; + + memset(version, 0, P3IODRV_VERSION_MAX_LEN); + + hr = p3iodrv_device_read_version(handle, version); + + if (FAILED(hr)) { + log_warning("Getting p3io version failed: %lX", hr); + return hr; + } + + log_info("P3IO version: %s", version); + + return hr; +} + +static HRESULT _ddr_io_ddr_p3io_print_version(HANDLE handle) +{ + HRESULT hr; + char str[4]; + uint32_t major; + uint32_t minor; + uint32_t patch; + + hr = p3iodrv_ddr_get_version(handle, str, &major, &minor, &patch); + + if (FAILED(hr)) { + log_warning("Getting version failed: %lX", hr); + return hr; + } + + log_info("DDR version: %s %d.%d.%d", str, major, minor, patch); + + return hr; +} + +static HRESULT _ddr_io_ddr_p3io_print_cabinet_type(HANDLE handle) +{ + HRESULT hr; + enum p3io_cab_type type; + + hr = p3iodrv_ddr_get_cab_type(handle, &type); + + if (FAILED(hr)) { + log_warning("Getting cab type failed: %lX", hr); + return hr; + } + + log_info("Cabinet type: %d", type); + + return hr; +} + +static HRESULT _ddr_io_ddr_p3io_print_dip_switches(HANDLE handle) +{ + HRESULT hr; + uint8_t dip_sw; + + hr = p3iodrv_ddr_get_dipsw(handle, &dip_sw); + + if (FAILED(hr)) { + log_warning("Getting dip switches failed"); + return hr; + } + + log_info("Dip switches: 0x%X", dip_sw); + + return hr; +} + +static HRESULT _ddr_io_ddr_p3io_print_video_freq(HANDLE handle) +{ + HRESULT hr; + enum p3io_video_freq video_freq; + + hr = p3iodrv_ddr_get_video_freq(handle, &video_freq); + + if (FAILED(hr)) { + log_warning("Getting video freq failed"); + return hr; + } + + log_info("Video freq: 0x%X", video_freq); + + return hr; +} + +static HRESULT _ddr_io_ddr_p3io_print_debug_info(HANDLE handle) +{ + return _ddr_io_p3io_print_version(handle) && + _ddr_io_ddr_p3io_print_version(handle) && + _ddr_io_ddr_p3io_print_cabinet_type(handle) && + _ddr_io_ddr_p3io_print_dip_switches(handle) && + _ddr_io_ddr_p3io_print_video_freq(handle); +} + +static HRESULT _ddr_io_p3io_init(HANDLE *handle) +{ + HRESULT hr; + + log_info("Initializing DDR P3IO..."); + + hr = _ddr_io_p3io_scan_and_open(handle); + + if (FAILED(hr)) { + return hr; + } + + hr = p3iodrv_ddr_init(*handle); + + if (FAILED(hr)) { + return hr; + } + + hr = _ddr_io_ddr_p3io_print_debug_info(*handle); + + if (FAILED(hr)) { + return hr; + } + + return hr; +} + +static HRESULT _ddr_io_p3io_close(HANDLE *handle) +{ + HRESULT hr; + + log_info("Closing p3io..."); + + hr = p3iodrv_device_close(handle); + + if (FAILED(hr)) { + log_warning("Closing p3io failed: %lX", hr); + return hr; + } + + return hr; +} + +static HRESULT _ddr_io_extio_init(HANDLE *handle) +{ + log_info("Initializing EXTIO..."); + + return extiodrv_device_open(_ddr_io_p3io_config.extio_port, handle); +} + +static HRESULT _ddr_io_extio_close(HANDLE *handle) +{ + log_info("Closing EXTIO..."); + + return extiodrv_device_close(handle); +} + +static HRESULT _ddr_io_flush_and_reset(HANDLE p3io_handle, HANDLE extio_handle) +{ + HRESULT hr; + struct p3io_ddr_jamma jamma; + struct p3io_ddr_output output; + struct extiodrv_extio_pad_lights pad_lights[2]; + bool neons; + + log_assert(p3io_handle != INVALID_HANDLE_VALUE); + log_assert(extio_handle != INVALID_HANDLE_VALUE); + + log_info("Flushing inputs and outputs"); + + memset(&output, 0, sizeof(output)); + memset(&pad_lights, 0, sizeof(pad_lights)); + neons = false; + + hr = p3iodrv_ddr_get_jamma(p3io_handle, &jamma); + + if (FAILED(hr)) { + log_warning("Reading jamma failed"); + return hr; + } + + hr = p3iodrv_ddr_set_outputs(p3io_handle, &output); + + if (FAILED(hr)) { + log_warning("Settings outputs failed"); + return hr; + } + + hr = extiodrv_extio_transfer( + extio_handle, EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL, pad_lights, neons); + + if (FAILED(hr)) { + log_warning("EXTIO transfer failed"); + return hr; + } + + return hr; +} + +void ddr_io_set_loggers( + log_formatter_t misc, + log_formatter_t info, + log_formatter_t warning, + log_formatter_t fatal) +{ + log_to_external(misc, info, warning, fatal); +} + +static void _ddr_io_config_init(struct ddrio_p3io_config *config_ddrio_p3io) +{ + struct cconfig *config; + + config = cconfig_init(); + + ddrio_p3io_config_init(config); + + if (!cconfig_main_config_init( + config, + "--ddrio-p3io-config", + "ddrio-p3io.conf", + "--help", + "-h", + "ddrio-p3io", + CCONFIG_CMD_USAGE_OUT_STDOUT)) { + cconfig_finit(config); + exit(EXIT_FAILURE); + } + + ddrio_p3io_config_get(config_ddrio_p3io, config); + + cconfig_finit(config); +} + +bool ddr_io_init( + thread_create_t thread_create, + thread_join_t thread_join, + thread_destroy_t thread_destroy) +{ + HRESULT hr; + + _ddr_io_config_init(&_ddr_io_p3io_config); + + hr = _ddr_io_p3io_init(&_ddr_io_p3io_handle); + + if (FAILED(hr)) { + return false; + } + + hr = _ddr_io_extio_init(&_ddr_io_extio_handle); + + if (FAILED(hr)) { + return false; + } + + hr = _ddr_io_flush_and_reset(_ddr_io_p3io_handle, _ddr_io_extio_handle); + + if (FAILED(hr)) { + return false; + } + + return true; +} + +uint32_t ddr_io_read_pad(void) +{ + HRESULT hr; + struct p3io_ddr_jamma jamma; + + hr = p3iodrv_ddr_get_jamma(_ddr_io_p3io_handle, &jamma); + + if (FAILED(hr)) { + log_warning("Reading jamma failed"); + return 0; + } + + return _byteswap_ulong(*((uint32_t *) &jamma)); +} + +void ddr_io_set_lights_extio(uint32_t extio_lights) +{ + HRESULT hr; + struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS]; + bool neons; + + pad_lights[0].up = (extio_lights & (1 << LIGHT_P1_UP)) > 0; + pad_lights[0].down = (extio_lights & (1 << LIGHT_P1_DOWN)) > 0; + pad_lights[0].left = (extio_lights & (1 << LIGHT_P1_LEFT)) > 0; + pad_lights[0].right = (extio_lights & (1 << LIGHT_P1_RIGHT)) > 0; + + pad_lights[1].up = (extio_lights & (1 << LIGHT_P2_UP)) > 0; + pad_lights[1].down = (extio_lights & (1 << LIGHT_P2_DOWN)) > 0; + pad_lights[1].left = (extio_lights & (1 << LIGHT_P2_LEFT)) > 0; + pad_lights[1].right = (extio_lights & (1 << LIGHT_P2_RIGHT)) > 0; + + neons = (extio_lights & (1 << LIGHT_NEONS)) > 0; + + hr = extiodrv_extio_transfer( + _ddr_io_extio_handle, + EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL, + pad_lights, + neons); + + if (FAILED(hr)) { + log_warning("EXTIO transfer failed: %lX", hr); + } +} + +void ddr_io_set_lights_p3io(uint32_t p3io_lights) +{ + HRESULT hr; + struct p3io_ddr_output output; + + output.cabinet.top_p1_lower = + (p3io_lights & (1 << LIGHT_P1_LOWER_LAMP)) > 0 ? 1 : 0; + output.cabinet.top_p1_upper = + (p3io_lights & (1 << LIGHT_P1_UPPER_LAMP)) > 0 ? 1 : 0; + output.cabinet.top_p2_lower = + (p3io_lights & (1 << LIGHT_P2_LOWER_LAMP)) > 0 ? 1 : 0; + output.cabinet.top_p2_upper = + (p3io_lights & (1 << LIGHT_P2_UPPER_LAMP)) > 0 ? 1 : 0; + + output.cabinet.p1_menu_buttons = + (p3io_lights & (1 << LIGHT_P1_MENU)) > 0 ? 1 : 0; + output.cabinet.p2_menu_buttons = + (p3io_lights & (1 << LIGHT_P2_MENU)) > 0 ? 1 : 0; + + hr = p3iodrv_ddr_set_outputs(_ddr_io_p3io_handle, &output); + + if (FAILED(hr)) { + log_warning("Settings outputs failed: %lX", hr); + } +} + +void ddr_io_set_lights_hdxs_panel(uint32_t lights) +{ + // Unused + + (void) lights; +} + +void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b) +{ + // Unused + + (void) idx; + (void) r; + (void) g; + (void) b; +} + +void ddr_io_fini(void) +{ + HRESULT hr; + + hr = _ddr_io_flush_and_reset(_ddr_io_p3io_handle, _ddr_io_extio_handle); + + if (FAILED(hr)) { + log_warning("Flusing IO failed: %lX", hr); + return; + } + + hr = _ddr_io_p3io_close(&_ddr_io_p3io_handle); + + if (FAILED(hr)) { + log_warning("Closing P3IO failed: %lX", hr); + // continue + } + + hr = _ddr_io_extio_close(&_ddr_io_extio_handle); + + if (FAILED(hr)) { + log_warning("Closing EXTIO failed: %lX", hr); + // continue + } +}