Compare commits

...

29 Commits
5.30 ... 5.32

Author SHA1 Message Date
icex2
e0cfc8c948 Bump to version 5.32 and update changelog 2020-08-13 13:14:54 +02:00
icex2
93cfb591b7 iidxio-ezusb: Update documentation 2020-08-12 18:01:22 +00:00
icex2
3396c09fbf ezusb-iidx: Add macro to enable D01 board emulation
Used for dumping firmware, only. C02 and D01 boards only differ
in the FPGA firmware written to the board on boot up. This doesn't
matter for emulation, but when using a real IO board with
iidxio-ezusb.dll, a different FPGA firmware is required to be
flashed in order to get working turntables, top unit lights etc
2020-08-12 18:01:22 +00:00
icex2
bd8dc18b30 iidxio-ezusb: Support coin mech input 2020-08-11 22:05:46 +02:00
Will Xyen
8e9abf9906 launcher: Set soft_id_code before calling init as some games use it then 2020-07-24 08:47:25 -07:00
Will Xyen
62bb717582 hdxs: Is really an HDXB 1.0.1 apparently
Also update enum hdxs_rgb_light_idx to start from 0 since that's what the function does
2020-07-10 11:06:13 -07:00
Will Xyen
4816fb809d launcher: Use more descriptive error message for ERROR_MOD_NOT_FOUND 2020-07-06 18:03:25 +00:00
Tau
2a2c77f255 Add ddrhook "COM4" passthrough mode 2020-07-01 21:03:47 +02:00
icex2
55513bac41 Update changelog for 5.31 release 2020-07-01 20:33:35 +02:00
Will Xyen
9c37ef71ba ddrio: add some more comments 2020-06-29 11:23:01 -07:00
Will Xyen
a0a1dea397 ddrhook: Add HDXS acio device + emu 2020-06-29 06:52:07 -07:00
Will Xyen
3c26a3f315 ddrio: Add hdxs output functions
Also fixes IDS_DDR_P1_BOTTOM_LIGHT schema being incorrectly mapped (on SD)
2020-06-29 06:51:25 -07:00
Will Xyen
b408cd9687 config: fix number of lights being loaded wrong if config is outdated 2020-06-29 06:49:22 -07:00
Will Xyen
be4df516fd ddrio: Fix p3io and extio lighting output being swapped with one another
the header, mm and smx modules had it right

also fixes p3io responses being the wrong size in 2 cases
2020-06-29 06:47:31 -07:00
Will Xyen
d1080905e5 ddrhook: Adds 64 bit ddr build and related dependencies 2020-06-29 06:43:29 -07:00
Tau
f87a51bbe4 Silence cabinet type spam under DDR A 2020-06-28 22:10:27 -07:00
635e512cccf1256559f0c600d8185deae60a6840
2a4d3e2865 Moved location of ddrio-smx.md to doc/ddrhook/ddrio-smx.md, fixed some formatting, clarified joystick config. 2020-06-28 15:37:29 -04:00
635e512cccf1256559f0c600d8185deae60a6840
6697ff7df1 Included SMX md file with step-by-step instructions and additional info. 2020-06-28 14:47:51 -04:00
Will Xyen
682fe8aa1b crc: forgot an include 2020-06-24 19:25:46 -07:00
Will Xyen
7d533f60cb acioemu: add support for 1.7.0 and encrypted polls 2020-06-25 00:57:59 +00:00
233596621999a3accb78d883a9ab4d1f3460d772
e5331fbc7c jbhook: add adapter hook 2020-06-14 02:22:07 +02:00
10f2d26b708e9205de6ce889920e36b5596f4908
77527e346b popn hid lights 2020-06-08 11:17:22 +02:00
Will Xyen
1d0a96fa20 aciodrv: Make init more consistent by reading until we actually get a 0xAA
(reboots / command interruptions will cause incorrect state on device side)
2020-05-27 08:51:16 -07:00
icex2
63e19aaaf6 Remove src.zip from distribution package
No need to include the source code with the repository being public.
2020-05-11 00:27:11 +02:00
icex2
4c59f16d46 Update gitlab-ci, build project with Dockerfile 2020-05-11 00:27:09 +02:00
icex2
7157fdedb7 Update readme/development doc about docker building 2020-05-11 00:24:21 +02:00
icex2
13d29cb62e Add Dockerfile for building bemanitools with docker 2020-05-11 00:23:53 +02:00
icex2
bf48715466 test: Fix compiler warning 2020-05-11 00:23:29 +02:00
icex2
24b490e36b Bump version to 5.31 2020-04-27 22:00:50 +02:00
52 changed files with 913 additions and 198 deletions

View File

@@ -1,17 +1,25 @@
image: debian image: docker:stable
variables:
DOCKER_TLS_CERTDIR: "/certs"
services:
- docker:19.03.8-dind
before_script:
- docker info
stages: stages:
- build - build
- test - create-release-package
- release
- releasetag - releasetag
build: build:
stage: build stage: build
before_script: before_script:
- apt-get update && apt-get -qq install clang mingw-w64 git make zip > /dev/null - apk update && apk add make > /dev/null
script: script:
- make - make build-docker
artifacts: artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME" name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths: paths:
@@ -20,31 +28,17 @@ build:
refs: refs:
- master - master
test: create-release-package:
allow_failure: true stage: create-release-package
stage: test
dependencies:
- build
before_script:
- apt-get update && apt-get -qq install make wine unzip > /dev/null
- dpkg --add-architecture i386 && apt-get update && apt-get -qq install wine32 > /dev/null
script:
- ls
- make run-tests
only:
refs:
- master
release:
stage: release
variables: variables:
GIT_STRATEGY: none GIT_STRATEGY: none
dependencies: dependencies:
- build - build
before_script: before_script:
- apt-get update && apt-get -qq install zip > /dev/null - apk update && apk add zip > /dev/null
script: script:
- mv build/bemanitools.zip ./bemanitools.zip - mv build/docker/bemanitools.zip ./bemanitools.zip
- rm -r build
- find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete - find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete
- unzip bemanitools.zip - unzip bemanitools.zip
- rm bemanitools.zip - rm bemanitools.zip
@@ -55,12 +49,12 @@ release:
only: only:
refs: refs:
- master - master
releasetag: releasetag:
stage: releasetag stage: releasetag
dependencies: [] dependencies: []
before_script: before_script:
- apt-get update && apt-get -qq install curl > /dev/null - apk update && apk add curl > /dev/null
script: script:
- | - |
curl --silent --show-error \ curl --silent --show-error \

View File

@@ -1,4 +1,15 @@
# Release history # Release history
## 5.32
* Various bugfixes
## 5.31
* DDR: Fix p3io and extio lights not working / being swapped when using geninput
* DDR: Add HDXS light support
* DDR: Add 64 bit support
* DDR: Add option to use COM4 as the p3io rs232 port instead of emulating (for use with acrealio etc.)
* Jubeat: Add network adapter hook
* Misc: Fix aciodrv sometimes hanging on boot (eamio-icca and sdvxio-kfca)
## 5.30 ## 5.30
* SDVX: sdvxhook2 headphone force and cursor confining config options * SDVX: sdvxhook2 headphone force and cursor confining config options
* DDR: Add light support for SMX gen 4 pads * DDR: Add light support for SMX gen 4 pads

32
Dockerfile Normal file
View File

@@ -0,0 +1,32 @@
FROM fedora:31
LABEL description="Build environment for bemanitools"
RUN yum -y install \
git \
make \
zip \
clang \
mingw64-gcc.x86_64 \
mingw32-gcc.x86_64 \
wine.x86_64
RUN mkdir /bemanitools
WORKDIR /bemanitools
# Order optimized for docker layer caching
COPY run-tests-wine.sh run-tests-wine.sh
COPY CHANGELOG.md CHANGELOG.md
COPY CONTRIBUTING.md CONTRIBUTING.md
COPY LICENSE LICENSE
COPY GNUmakefile GNUmakefile
COPY Module.mk Module.mk
COPY README.md README.md
COPY doc doc
COPY dist dist
COPY src src
# .git folder required or building fails when version is generated
COPY .git .git
# Building
RUN make

View File

@@ -11,19 +11,24 @@ BUILDDIR ?= build
# Internal variables # Internal variables
# #
depdir := $(BUILDDIR)/dep builddir_docker := $(BUILDDIR)/docker
objdir := $(BUILDDIR)/obj
bindir := $(BUILDDIR)/bin
toolchain_32 := i686-w64-mingw32- docker_container_name := "bemanitools-build"
toolchain_64 := x86_64-w64-mingw32- docker_image_name := "bemanitools:build"
gitrev := $(shell git rev-parse HEAD) depdir := $(BUILDDIR)/dep
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev) objdir := $(BUILDDIR)/obj
cflags := -O2 -pipe -ffunction-sections -fdata-sections \ bindir := $(BUILDDIR)/bin
-Wall -std=c99
cflags_release := -Werror toolchain_32 := i686-w64-mingw32-
ldflags := -Wl,--gc-sections -static-libgcc toolchain_64 := x86_64-w64-mingw32-
gitrev := $(shell git rev-parse HEAD)
cppflags := -I src -I src/main -I src/test -DGITREV=$(gitrev)
cflags := -O2 -pipe -ffunction-sections -fdata-sections \
-Wall -std=c99
cflags_release := -Werror
ldflags := -Wl,--gc-sections -static-libgcc
# #
# The first target that GNU Make encounters becomes the default target. # The first target that GNU Make encounters becomes the default target.
@@ -33,6 +38,7 @@ ldflags := -Wl,--gc-sections -static-libgcc
all: build all: build
.PHONY: \ .PHONY: \
build-docker \
clean \ clean \
code-format \ code-format \
print-building \ print-building \
@@ -74,6 +80,16 @@ run-tests:
version: version:
@echo "$(gitrev)" > version @echo "$(gitrev)" > version
build-docker:
$(V)docker rm -f $(docker_container_name) 2> /dev/null || true
$(V)docker build -t $(docker_image_name) -f Dockerfile .
$(V)docker create --name $(docker_container_name) $(docker_image_name)
$(V)rm -rf $(builddir_docker)
$(V)mkdir -p $(builddir_docker)
$(V)docker cp $(docker_container_name):/bemanitools/build $(builddir_docker)
$(V)mv $(builddir_docker)/build/* $(builddir_docker)
$(V)rm -r $(builddir_docker)/build
# #
# Pull in module definitions # Pull in module definitions
# #

View File

@@ -183,6 +183,7 @@ $(zipdir)/tools.zip: \
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/tools-x64.zip: \ $(zipdir)/tools-x64.zip: \
build/bin/indep-64/aciotest.exe \
build/bin/indep-64/eamiotest.exe \ build/bin/indep-64/eamiotest.exe \
build/bin/indep-64/iidxiotest.exe \ build/bin/indep-64/iidxiotest.exe \
build/bin/indep-64/iidx-ezusb-exit-hook.dll \ build/bin/indep-64/iidx-ezusb-exit-hook.dll \
@@ -191,10 +192,6 @@ $(zipdir)/tools-x64.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/src.zip: .git/HEAD $(zipdir)/
$(V)echo ... $@
$(V)git archive -o $@ HEAD
$(zipdir)/iidx-09-to-12.zip: \ $(zipdir)/iidx-09-to-12.zip: \
build/bin/indep-32/iidxhook1.dll \ build/bin/indep-32/iidxhook1.dll \
build/bin/indep-32/config.exe \ build/bin/indep-32/config.exe \
@@ -473,6 +470,22 @@ $(zipdir)/ddr-12-to-16.zip: \
$(V)echo ... $@ $(V)echo ... $@
$(V)zip -j $@ $^ $(V)zip -j $@ $^
$(zipdir)/ddr-16-x64.zip: \
build/bin/avs2_1603-64/launcher.exe \
build/bin/avs2_1603-64/ddrhook.dll \
build/bin/avs2_1603-64/unicorntail.dll \
build/bin/indep-64/config.exe \
build/bin/indep-64/ddrio.dll \
build/bin/indep-64/ddrio-mm.dll \
build/bin/indep-64/ddrio-smx.dll \
build/bin/indep-64/eamio.dll \
build/bin/indep-64/geninput.dll \
dist/ddr/config.bat \
dist/ddr/gamestart-16.bat \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/bst.zip: \ $(zipdir)/bst.zip: \
build/bin/avs2_1603-64/bsthook.dll \ build/bin/avs2_1603-64/bsthook.dll \
build/bin/avs2_1603-64/launcher.exe \ build/bin/avs2_1603-64/launcher.exe \
@@ -525,6 +538,7 @@ $(BUILDDIR)/tests.zip: \
$(BUILDDIR)/bemanitools.zip: \ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/bst.zip \ $(zipdir)/bst.zip \
$(zipdir)/ddr-12-to-16.zip \ $(zipdir)/ddr-12-to-16.zip \
$(zipdir)/ddr-16-x64.zip \
$(zipdir)/doc.zip \ $(zipdir)/doc.zip \
$(zipdir)/iidx-09-to-12.zip \ $(zipdir)/iidx-09-to-12.zip \
$(zipdir)/iidx-13.zip \ $(zipdir)/iidx-13.zip \
@@ -537,7 +551,6 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-01.zip \ $(zipdir)/jb-01.zip \
$(zipdir)/jb-05-to-07.zip \ $(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \ $(zipdir)/jb-08.zip \
$(zipdir)/src.zip \
$(zipdir)/sdvx-01-to-04.zip \ $(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \ $(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-cn.zip \ $(zipdir)/sdvx-05-cn.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5 # Bemanitools 5
[![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master) [![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
Version: 5.30</br> Version: 5.32</br>
[Release history](CHANGELOG.md) [Release history](CHANGELOG.md)
A collection of tools to run [various Bemani arcade games](#list-of-supported-games). A collection of tools to run [various Bemani arcade games](#list-of-supported-games).
@@ -81,6 +81,9 @@ should cover most if not all of the games so far
Please refer to the [dedicated documentation](CONTRIBUTING.md). Please refer to the [dedicated documentation](CONTRIBUTING.md).
# Development # Development
## Building
See the [development document](doc/development).
## Architecture ## Architecture
A dedicate [architecture document](doc/architecture.md) outlines the architecture of Bemanitools and points out the most A dedicate [architecture document](doc/architecture.md) outlines the architecture of Bemanitools and points out the most
important aspects you should know before you get started with development. important aspects you should know before you get started with development.
@@ -88,10 +91,6 @@ important aspects you should know before you get started with development.
## API ## API
Please refer to the [API documentation](doc/api.md). Please refer to the [API documentation](doc/api.md).
## Source Code
The source code is included with this distribution package (src.zip). Please refer to the
[development document](doc/development.md) for further details.
# License # License
Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the
[LICENSE file](LICENSE) included with the source code. [LICENSE file](LICENSE) included with the source code.

14
doc/ddrhook/ddrio-smx.md Normal file
View File

@@ -0,0 +1,14 @@
# Using SMX pads with BemaniTools (DDR Ace and higher)
If you are looking to use StepManiaX pads with DDR, these are supported **natively** for Gen 1 through Gen 5.(And theoretically beyond!) Steps and info below
## Step-by-Step
1. Ensure that you have the latest `SMX.dll` copied to your contents folder. The easiest way to get this is to download and install the latest SMX Config program on [StepManiaX.com](https://data.stepmaniax.com/docs/SMXConfigInstaller-2020-04-03-01.exe). `SMX.dll`'s default install location is `C:\Program Files (x86)\SMXConfig`
2. After bemanitools has been copied to your contents folder, rename the regular `ddrio.dll` to something like `ddrio-orig.dll`.
3. Rename `ddrio-smx.dll` to `ddrio.dll`.
4. Use the config tool to set up the usual stuff.(cards, network, etc.) Be sure to map menu, test, service, and start buttons to your keyboard or other controllers. You **cannot** map SMX panels as joystick inputs.
5. Start the game. If everything works properly, the game will boot and your panels will light up when stepped on during gameplay and song selection.
## Important Things
* Pad panel inputs (UDLR on P1 and P2) are mapped automatically. If you've purchased a single pad from StepManiaX, this jumper is installed and will set your pad to P2 by default. If you want to change to P1, you'll need to open up your pads and remove this jumper in the [MCU box](https://data.stepmaniax.com/docs/Stage%20-%20Gen%205%20Manual%20Rev1.pdf).
* Panel colors set in the SMX config tool are not used. Colors are set internally by Bemanitools.
* If you get a warning about setlights2 when starting the game, your `SMX.dll` is likely out of date. Make sure you've downloaded the latest version of the StepManiaX config tool from stepmaniax.com and have copied the `SMX.dll` to your contents folder.

View File

@@ -58,6 +58,18 @@ command:
make release make release
``` ```
## Building with docker
You can also build bemanitools using docker which avoids having to setup a full development
environment if you are just interested in building binaries for the latest changes. Naturally, this
requires you to have the docker daemon installed. Then, run the following command from the root
folder of the project:
```bash
make build-docker
```
Once completed successfully, the build output is located in the `build/docker` sub-folder.
## Creating releases ## Creating releases
For developers to create official releases with major and minor versioning: For developers to create official releases with major and minor versioning:
1. Ensure that all everything you want to have for this release is merged into master. 1. Ensure that all everything you want to have for this release is merged into master.

View File

@@ -1,4 +1,4 @@
This library drives a "legacy" ezusb IO board, also known as C02 IO, and This library drives a "legacy" ezusb IO board, also known as C02/D01 IO, and
implements the iidxio API of BT5. Thus, it allows you to use this IO board with implements the iidxio API of BT5. Thus, it allows you to use this IO board with
*any* version of IIDX that is supported by BT5. *any* version of IIDX that is supported by BT5.
@@ -24,5 +24,7 @@ the status LEDs on the side of the board should show a blinking pattern.
dump to the FPGA. dump to the FPGA.
* There is a script called ezusb-boot.bat which combines the two steps above * There is a script called ezusb-boot.bat which combines the two steps above
and can be integrated into the startup process of a dedicated setup. and can be integrated into the startup process of a dedicated setup.
* If you are using a D01 IO board, use the `fpga-d01.bin` file instead of the
`fpga.bin` file.
* If you ignore these steps, you will either run into errors or parts of the * If you ignore these steps, you will either run into errors or parts of the
IO board won't work (e.g. lights). IO board won't work (e.g. lights).

View File

@@ -0,0 +1,18 @@
LIBRARY SMX
EXPORTS
SMX_Start
SMX_Stop
SMX_SetLogCallback
SMX_GetInfo
SMX_GetInputState
SMX_SetLights
SMX_SetLights2
SMX_ReenableAutoLights
SMX_GetConfig
SMX_SetConfig
SMX_FactoryReset
SMX_ForceRecalibration
SMX_SetTestMode
SMX_GetTestData
SMX_Version

View File

@@ -5,6 +5,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "acio/hdxs.h"
#include "acio/icca.h" #include "acio/icca.h"
#include "acio/kfca.h" #include "acio/kfca.h"
@@ -71,6 +72,8 @@ struct ac_io_message {
struct ac_io_kfca_poll_in kfca_poll_in; struct ac_io_kfca_poll_in kfca_poll_in;
struct ac_io_kfca_poll_out kfca_poll_out; struct ac_io_kfca_poll_out kfca_poll_out;
struct ac_io_hdxs_output hdxs_output;
}; };
} cmd; } cmd;

48
src/main/acio/hdxs.h Normal file
View File

@@ -0,0 +1,48 @@
#ifndef ACIO_HDXS_H
#define ACIO_HDXS_H
#include <stdint.h>
enum ac_io_hdxs_cmd {
AC_IO_HDXS_CMD_SET_OUTPUTS = 0x0112,
};
#pragma pack(push, 1)
struct ac_io_hdxs_light {
uint8_t analog : 7; // rgb component
uint8_t bit : 1; // buttons
};
struct ac_io_hdxs_output {
uint8_t empty;
struct ac_io_hdxs_light lights[12];
};
enum ac_io_hdxs_front_panel_lights {
AC_IO_HDXS_OUT_P1_START = 0,
AC_IO_HDXS_OUT_P1_UP_DOWN = 1,
AC_IO_HDXS_OUT_P1_LEFT_RIGHT = 2,
AC_IO_HDXS_OUT_P2_START = 3,
AC_IO_HDXS_OUT_P2_UP_DOWN = 4,
AC_IO_HDXS_OUT_P2_LEFT_RIGHT = 5,
};
enum ac_io_hdxs_grb_layout {
AC_IO_HDXS_GREEN = 0,
AC_IO_HDXS_RED = 1,
AC_IO_HDXS_BLUE = 2,
};
enum ac_io_hdxs_speaker_lights {
AC_IO_HDXS_OUT_P1_SPEAKER_F = 0,
AC_IO_HDXS_OUT_P2_SPEAKER_F = 1,
AC_IO_HDXS_OUT_P1_SPEAKER_W = 2,
AC_IO_HDXS_OUT_P2_SPEAKER_W = 3,
};
_Static_assert(
sizeof(struct ac_io_hdxs_output) == 13,
"ac_io_hdxs_output is the wrong size");
#pragma pack(pop)
#endif

View File

@@ -12,6 +12,8 @@ enum ac_io_icca_cmd {
AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135, AC_IO_ICCA_CMD_SET_SLOT_STATE = 0x0135,
AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A, AC_IO_ICCA_CMD_BEGIN_KEYPAD = 0x013A,
AC_IO_ICCA_CMD_POLL_FELICA = 0x0161, AC_IO_ICCA_CMD_POLL_FELICA = 0x0161,
AC_IO_ICCA_CMD_KEY_EXCHANGE = 0x0160,
AC_IO_ICCA_CMD_POLL_ENCRYPTED = 0x0164,
}; };
enum ac_io_icca_slot_state { enum ac_io_icca_slot_state {

View File

@@ -19,6 +19,7 @@ static char aviodrv_device_node_products[16][4];
static bool aciodrv_device_init(void) static bool aciodrv_device_init(void)
{ {
uint8_t init_seq[1] = {AC_IO_SOF}; uint8_t init_seq[1] = {AC_IO_SOF};
uint8_t read_buff[1] = {0x00};
/* init/reset the device by sending 0xAA until 0xAA is returned */ /* init/reset the device by sending 0xAA until 0xAA is returned */
int read = 0; int read = 0;
@@ -27,17 +28,20 @@ static bool aciodrv_device_init(void)
return false; return false;
} }
read = aciodrv_port_read(init_seq, sizeof(init_seq)); read = aciodrv_port_read(read_buff, sizeof(read_buff));
} while (read == 0); } while ((read <= 0) || (read_buff[0] != init_seq[0]));
if (read > 0) { if (read > 0) {
log_warning("Obtained SOF, clearing out buffer now");
/* empty buffer by reading all data */ /* empty buffer by reading all data */
while (read > 0) { while (read > 0) {
read = aciodrv_port_read(init_seq, sizeof(init_seq)); read = aciodrv_port_read(init_seq, sizeof(init_seq));
} }
log_warning("Cleared buffer, init done");
return read == 0; return read == 0;
} else { } else {
log_warning("Read failure when trying to clear device state");
return false; return false;
} }
} }
@@ -314,15 +318,20 @@ bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4])
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size) bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
{ {
msg->cmd.seq_no = aciodrv_device_msg_counter++; msg->cmd.seq_no = aciodrv_device_msg_counter++;
int send_size = offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes;
if (aciodrv_device_send( #ifdef AC_IO_MSG_LOG
(uint8_t *) msg, log_info("Beginning send on %d: %04x (%d b)", msg->addr, msg->cmd.code, send_size);
offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes) <= 0) { #endif
if (aciodrv_device_send((uint8_t *) msg, send_size) <= 0) {
return false; return false;
} }
uint16_t req_code = msg->cmd.code; uint16_t req_code = msg->cmd.code;
#ifdef AC_IO_MSG_LOG
log_info("Beginning recv: (%d b)", resp_size);
#endif
if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) { if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) {
return false; return false;
} }

View File

@@ -1,5 +1,6 @@
#define LOG_MODULE "acioemu-hdxs" #define LOG_MODULE "acioemu-hdxs"
#include "acio/hdxs.h"
#include "acio/acio.h" #include "acio/acio.h"
#include "acioemu/emu.h" #include "acioemu/emu.h"
@@ -18,12 +19,20 @@ static void ac_io_emu_hdxs_send_status(
const struct ac_io_message *req, const struct ac_io_message *req,
uint8_t status); uint8_t status);
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu) void ac_io_emu_hdxs_init(
struct ac_io_emu_hdxs *hdxs,
struct ac_io_emu *emu,
acio_hdxs_dispatcher lights_dispatcher)
{ {
log_assert(hdxs != NULL); log_assert(hdxs != NULL);
log_assert(emu != NULL); log_assert(emu != NULL);
if (lights_dispatcher == NULL) {
log_warning("NULL lights_dispatcher, HDXS light output won't work");
}
hdxs->emu = emu; hdxs->emu = emu;
hdxs->lights_dispatcher = lights_dispatcher;
} }
void ac_io_emu_hdxs_dispatch_request( void ac_io_emu_hdxs_dispatch_request(
@@ -51,9 +60,19 @@ void ac_io_emu_hdxs_dispatch_request(
case AC_IO_CMD_CLEAR: case AC_IO_CMD_CLEAR:
log_misc("AC_IO_CMD_CLEAR(%d)", req->addr); log_misc("AC_IO_CMD_CLEAR(%d)", req->addr);
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
break;
case AC_IO_HDXS_CMD_SET_OUTPUTS:
if (hdxs->lights_dispatcher != NULL) {
hdxs->lights_dispatcher(hdxs, req);
}
ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
break;
case 0x110: case 0x110:
case 0x112:
case 0x128: case 0x128:
ac_io_emu_hdxs_send_status(hdxs, req, 0x00); ac_io_emu_hdxs_send_status(hdxs, req, 0x00);
@@ -86,11 +105,11 @@ static void ac_io_emu_hdxs_cmd_send_version(
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_LED_STRIP); resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_LED_STRIP);
resp.cmd.version.flag = 0x00; resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01; resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x06; resp.cmd.version.minor = 0x00;
resp.cmd.version.revision = 0x00; resp.cmd.version.revision = 0x01;
memcpy( memcpy(
resp.cmd.version.product_code, resp.cmd.version.product_code,
"HDXS", "HDXB",
sizeof(resp.cmd.version.product_code)); sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date)); strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time)); strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));

View File

@@ -5,12 +5,21 @@
#include "acioemu/emu.h" #include "acioemu/emu.h"
struct ac_io_emu_hdxs;
struct ac_io_message;
typedef void (*acio_hdxs_dispatcher)(
struct ac_io_emu_hdxs *emu, const struct ac_io_message *req);
struct ac_io_emu_hdxs { struct ac_io_emu_hdxs {
struct ac_io_emu *emu; struct ac_io_emu *emu;
// TODO ops vtbl acio_hdxs_dispatcher lights_dispatcher;
}; };
void ac_io_emu_hdxs_init(struct ac_io_emu_hdxs *hdxs, struct ac_io_emu *emu); void ac_io_emu_hdxs_init(
struct ac_io_emu_hdxs *hdxs,
struct ac_io_emu *emu,
acio_hdxs_dispatcher lights_dispatcher);
void ac_io_emu_hdxs_dispatch_request( void ac_io_emu_hdxs_dispatch_request(
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req); struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);

View File

@@ -14,6 +14,7 @@
#include "bemanitools/eamio.h" #include "bemanitools/eamio.h"
#include "util/crc.h"
#include "util/time.h" #include "util/time.h"
enum ac_io_icca_subcmd { enum ac_io_icca_subcmd {
@@ -41,7 +42,8 @@ static void ac_io_emu_icca_cmd_send_version(
static void ac_io_emu_icca_send_state( static void ac_io_emu_icca_send_state(
struct ac_io_emu_icca *icca, struct ac_io_emu_icca *icca,
const struct ac_io_message *req, const struct ac_io_message *req,
uint64_t delay_us); uint64_t delay_us,
bool encrypted);
static void ac_io_emu_icca_send_empty( static void ac_io_emu_icca_send_empty(
struct ac_io_emu_icca *icca, const struct ac_io_message *req); struct ac_io_emu_icca *icca, const struct ac_io_message *req);
@@ -51,6 +53,12 @@ static void ac_io_emu_icca_send_status(
const struct ac_io_message *req, const struct ac_io_message *req,
uint8_t status); uint8_t status);
static void ac_io_emu_icca_cipher(
struct ac_io_emu_icca *icca, uint8_t *data, size_t length);
static void ac_io_emu_icca_cipher_set_key(
struct ac_io_emu_icca *icca, const struct ac_io_message *req);
void ac_io_emu_icca_init( void ac_io_emu_icca_init(
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no) struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no)
{ {
@@ -59,6 +67,15 @@ void ac_io_emu_icca_init(
icca->unit_no = unit_no; icca->unit_no = unit_no;
// queue must be started // queue must be started
icca->fault = true; icca->fault = true;
// default to 1.6.0
icca->version = v160;
}
void ac_io_emu_icca_set_version(
struct ac_io_emu_icca *icca, enum ac_io_emu_icca_version version)
{
icca->version = version;
} }
void ac_io_emu_icca_dispatch_request( void ac_io_emu_icca_dispatch_request(
@@ -123,7 +140,7 @@ void ac_io_emu_icca_dispatch_request(
break; break;
case AC_IO_ICCA_CMD_ENGAGE: case AC_IO_ICCA_CMD_ENGAGE:
ac_io_emu_icca_send_state(icca, req, 0); ac_io_emu_icca_send_state(icca, req, 0, false);
break; break;
@@ -174,6 +191,7 @@ void ac_io_emu_icca_dispatch_request(
break; break;
} }
case AC_IO_ICCA_CMD_POLL_ENCRYPTED:
case AC_IO_ICCA_CMD_POLL: case AC_IO_ICCA_CMD_POLL:
delay_us = time_get_elapsed_us( delay_us = time_get_elapsed_us(
time_get_counter() - icca->time_counter_last_poll); time_get_counter() - icca->time_counter_last_poll);
@@ -185,13 +203,26 @@ void ac_io_emu_icca_dispatch_request(
} }
icca->time_counter_last_poll = time_get_counter(); icca->time_counter_last_poll = time_get_counter();
ac_io_emu_icca_send_state(icca, req, delay_us); bool encrypted = cmd_code == AC_IO_ICCA_CMD_POLL_ENCRYPTED;
ac_io_emu_icca_send_state(icca, req, delay_us, encrypted);
break; break;
case AC_IO_ICCA_CMD_POLL_FELICA: case AC_IO_ICCA_CMD_POLL_FELICA:
icca->detected_new_reader = true; icca->detected_new_reader = true;
ac_io_emu_icca_send_status(icca, req, 0x01);
if (icca->version == v170) {
ac_io_emu_icca_send_empty(icca, req);
} else {
ac_io_emu_icca_send_status(icca, req, 0x01);
}
break;
case AC_IO_ICCA_CMD_KEY_EXCHANGE:
icca->detected_new_reader = true;
log_misc("AC_IO_ICCA_CMD_KEY_EXCHANGE(%d)", req->addr);
ac_io_emu_icca_cipher_set_key(icca, req);
break; break;
@@ -215,10 +246,27 @@ static void ac_io_emu_icca_cmd_send_version(
resp.cmd.seq_no = req->cmd.seq_no; resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version); resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_ICCA); resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_ICCA);
resp.cmd.version.flag = 0x00; resp.cmd.version.flag = 0x00;
resp.cmd.version.major = 0x01; resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x06;
if (icca->version == v150) {
log_warning(
"ICCA v1.5.0 emulation requested, please remove this log once implemented");
resp.cmd.version.minor = 0x05;
} else if (icca->version == v160) {
resp.cmd.version.minor = 0x06;
} else if (icca->version == v170) {
resp.cmd.version.minor = 0x07;
} else {
// probably log invalid version here
log_warning(
"Unknown ICCA version: %d emulation requested",
icca->version);
}
resp.cmd.version.revision = 0x00; resp.cmd.version.revision = 0x00;
memcpy( memcpy(
resp.cmd.version.product_code, resp.cmd.version.product_code,
"ICCA", "ICCA",
@@ -261,7 +309,8 @@ static void ac_io_emu_icca_send_status(
static void ac_io_emu_icca_send_state( static void ac_io_emu_icca_send_state(
struct ac_io_emu_icca *icca, struct ac_io_emu_icca *icca,
const struct ac_io_message *req, const struct ac_io_message *req,
uint64_t delay_us) uint64_t delay_us,
bool encrypted)
{ {
struct ac_io_message resp; struct ac_io_message resp;
struct ac_io_icca_state *body; struct ac_io_icca_state *body;
@@ -319,7 +368,10 @@ static void ac_io_emu_icca_send_state(
} else if (card_full_insert) { } else if (card_full_insert) {
body->status_code = AC_IO_ICCA_STATUS_GOT_UID; body->status_code = AC_IO_ICCA_STATUS_GOT_UID;
} else { } else {
if (icca->detected_new_reader) { if (icca->detected_new_reader && icca->version == v170) {
// else we get a power failure?
body->status_code = 0;
} else if (icca->detected_new_reader) {
body->status_code = AC_IO_ICCA_STATUS_IDLE_NEW; body->status_code = AC_IO_ICCA_STATUS_IDLE_NEW;
} else { } else {
body->status_code = AC_IO_ICCA_STATUS_IDLE; body->status_code = AC_IO_ICCA_STATUS_IDLE;
@@ -384,5 +436,88 @@ static void ac_io_emu_icca_send_state(
body->status_code = AC_IO_ICCA_STATUS_FAULT; body->status_code = AC_IO_ICCA_STATUS_FAULT;
} }
if (encrypted) {
size_t base_state_sz = sizeof(struct ac_io_icca_state);
resp.cmd.nbytes = base_state_sz + 2;
if (!icca->cipher_started) {
log_warning("No crypto keys set for unit %d", icca->unit_no);
} else {
uint16_t crc = crc16_msb(resp.cmd.raw, base_state_sz, 0);
resp.cmd.raw[base_state_sz + 0] = (crc >> 8) & 0xFF;
resp.cmd.raw[base_state_sz + 1] = crc & 0xFF;
ac_io_emu_icca_cipher(icca, resp.cmd.raw, 18);
}
}
ac_io_emu_response_push(icca->emu, &resp, delay_us); ac_io_emu_response_push(icca->emu, &resp, delay_us);
} }
static void ac_io_emu_icca_cipher_shift_keys(struct ac_io_emu_icca *icca)
{
uint32_t key4_old = icca->cipher_keys[3];
uint32_t key_new = (key4_old << 11) ^ key4_old;
uint32_t key1_old = icca->cipher_keys[0];
// shift keys up
icca->cipher_keys[3] = icca->cipher_keys[2];
icca->cipher_keys[2] = icca->cipher_keys[1];
icca->cipher_keys[1] = icca->cipher_keys[0];
icca->cipher_keys[0] =
((((key1_old >> 11) ^ key_new) >> 8) ^ key_new ^ key1_old);
}
static void
ac_io_emu_icca_cipher(struct ac_io_emu_icca *icca, uint8_t *data, size_t length)
{
for (size_t i = 0; i < length; i++) {
uint8_t count4 = i % 4;
// shift keys every 4 bytes
if (count4 == 0) {
ac_io_emu_icca_cipher_shift_keys(icca);
}
// process data
data[i] =
(uint8_t)(icca->cipher_keys[0] >> (((3 - count4) << 3)) ^ data[i]);
}
}
static void ac_io_emu_icca_cipher_set_key(
struct ac_io_emu_icca *icca, const struct ac_io_message *req)
{
struct ac_io_message resp;
resp.addr = req->addr | AC_IO_RESPONSE_FLAG;
resp.cmd.code = req->cmd.code;
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = 4; // 4 bytes, uint32_t
uint32_t host_key = 0x00000000;
host_key |= req->cmd.raw[0] << 24;
host_key |= req->cmd.raw[1] << 16;
host_key |= req->cmd.raw[2] << 8;
host_key |= req->cmd.raw[3];
// TODO: should probably RNG this
uint32_t reader_key = 0x14243444;
resp.cmd.raw[0] = (reader_key >> 24) & 0xFF;
resp.cmd.raw[1] = (reader_key >> 16) & 0xFF;
resp.cmd.raw[2] = (reader_key >> 8) & 0xFF;
resp.cmd.raw[3] = (reader_key) & 0xFF;
// so I looked these constants up, this isn't actually a secure key
// generator it's actually Marsaglia's "KISS" algorithm with different
// initial states
icca->cipher_keys[0] = reader_key ^ 0x5491333;
icca->cipher_keys[1] = host_key ^ 0x1F123BB5;
icca->cipher_keys[2] = reader_key ^ 0x159A55E5;
icca->cipher_keys[3] = host_key ^ 0x75BCD15;
log_misc("keys set to: H: %08x R: %08x", host_key, reader_key);
ac_io_emu_response_push(icca->emu, &resp, 0);
icca->cipher_started = true;
}

View File

@@ -6,6 +6,12 @@
#include "acioemu/emu.h" #include "acioemu/emu.h"
enum ac_io_emu_icca_version {
v150 = 0x5,
v160 = 0x6,
v170 = 0x7,
};
struct ac_io_emu_icca { struct ac_io_emu_icca {
struct ac_io_emu *emu; struct ac_io_emu *emu;
uint8_t unit_no; uint8_t unit_no;
@@ -20,11 +26,19 @@ struct ac_io_emu_icca {
bool keypad_started; bool keypad_started;
bool polling_started; bool polling_started;
uint64_t time_counter_last_poll; uint64_t time_counter_last_poll;
enum ac_io_emu_icca_version version;
bool cipher_started;
uint32_t cipher_keys[4];
}; };
void ac_io_emu_icca_init( void ac_io_emu_icca_init(
struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no); struct ac_io_emu_icca *icca, struct ac_io_emu *emu, uint8_t unit_no);
// optional, call after init to override default version
void ac_io_emu_icca_set_version(
struct ac_io_emu_icca *icca, enum ac_io_emu_icca_version version);
void ac_io_emu_icca_dispatch_request( void ac_io_emu_icca_dispatch_request(
struct ac_io_emu_icca *icca, const struct ac_io_message *req); struct ac_io_emu_icca *icca, const struct ac_io_message *req);

View File

@@ -32,8 +32,7 @@ enum ddr_pad_bit {
DDR_P1_MENU_DOWN = 0x01, DDR_P1_MENU_DOWN = 0x01,
}; };
/* p3io controls menu btn and marquee lights // see the functions below for more information
extio controls neons and stage lights. */
enum p3io_light_bit { enum p3io_light_bit {
LIGHT_P1_MENU = 0x00, LIGHT_P1_MENU = 0x00,
@@ -41,7 +40,32 @@ enum p3io_light_bit {
LIGHT_P2_LOWER_LAMP = 0x04, LIGHT_P2_LOWER_LAMP = 0x04,
LIGHT_P2_UPPER_LAMP = 0x05, LIGHT_P2_UPPER_LAMP = 0x05,
LIGHT_P1_LOWER_LAMP = 0x06, LIGHT_P1_LOWER_LAMP = 0x06,
LIGHT_P1_UPPER_LAMP = 0x07 LIGHT_P1_UPPER_LAMP = 0x07,
};
enum hdxs_light_bit {
LIGHT_HD_P1_START = 0x08,
LIGHT_HD_P1_UP_DOWN = 0x09,
LIGHT_HD_P1_LEFT_RIGHT = 0x0A,
LIGHT_HD_P2_START = 0x0B,
LIGHT_HD_P2_UP_DOWN = 0x0C,
LIGHT_HD_P2_LEFT_RIGHT = 0x0D,
};
// the indexing starts from 0x20 if you're looking in geninput
enum hdxs_rgb_light_idx {
LIGHT_HD_P1_SPEAKER_F_R = 0x00,
LIGHT_HD_P1_SPEAKER_F_G = 0x01,
LIGHT_HD_P1_SPEAKER_F_B = 0x02,
LIGHT_HD_P2_SPEAKER_F_R = 0x03,
LIGHT_HD_P2_SPEAKER_F_G = 0x04,
LIGHT_HD_P2_SPEAKER_F_B = 0x05,
LIGHT_HD_P1_SPEAKER_W_R = 0x06,
LIGHT_HD_P1_SPEAKER_W_G = 0x07,
LIGHT_HD_P1_SPEAKER_W_B = 0x08,
LIGHT_HD_P2_SPEAKER_W_R = 0x09,
LIGHT_HD_P2_SPEAKER_W_G = 0x0A,
LIGHT_HD_P2_SPEAKER_W_B = 0x0B,
}; };
enum extio_light_bit { enum extio_light_bit {
@@ -81,9 +105,26 @@ bool ddr_io_init(
thread_join_t thread_join, thread_join_t thread_join,
thread_destroy_t thread_destroy); thread_destroy_t thread_destroy);
/* used to poll the IO for input, note that this is also where lights are
flushed to the device for geninput */
uint32_t ddr_io_read_pad(void); uint32_t ddr_io_read_pad(void);
/* The following are optional to implement, and allow lights to be set and
emulated as needed */
/* used to set pad lights, as well as the bass neon on SD cabs */
void ddr_io_set_lights_extio(uint32_t extio_lights); void ddr_io_set_lights_extio(uint32_t extio_lights);
/* used to set SD panel lights, and HD spot lights */
void ddr_io_set_lights_p3io(uint32_t p3io_lights); void ddr_io_set_lights_p3io(uint32_t p3io_lights);
/* used to set HD cab front panel lights */
void ddr_io_set_lights_hdxs_panel(uint32_t hdxs_lights);
/* used to set HD cab speaker RGB lights */
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b);
void ddr_io_fini(void); void ddr_io_fini(void);
#endif #endif

View File

@@ -256,13 +256,33 @@ STRINGTABLE
IDS_DDR_P2_DOWN "P2 Down" IDS_DDR_P2_DOWN "P2 Down"
IDS_DDR_P2_LEFT "P2 Left" IDS_DDR_P2_LEFT "P2 Left"
IDS_DDR_P2_RIGHT "P2 Right" IDS_DDR_P2_RIGHT "P2 Right"
IDS_DDR_P1_MENU_LIGHT "P1 Menu Lights" IDS_DDR_P1_MENU_LIGHT "P1 Menu Lights / HD Spot Red Satellite"
IDS_DDR_P1_TOP_LIGHT "P1 Marquee Top Light" IDS_DDR_P1_TOP_LIGHT "P1 Marquee Top Light"
IDS_DDR_P1_BOTTOM_LIGHT "P1 Marquee Bottom Light" IDS_DDR_P1_BOTTOM_LIGHT "P1 Marquee Bottom Light"
IDS_DDR_P2_MENU_LIGHT "P2 Menu Lights" IDS_DDR_P2_MENU_LIGHT "P2 Menu Lights / HD Spot Blue Satellite"
IDS_DDR_P2_TOP_LIGHT "P2 Marquee Top Light" IDS_DDR_P2_TOP_LIGHT "P2 Marquee Top Light"
IDS_DDR_P2_BOTTOM_LIGHT "P2 Marquee Bottom Light" IDS_DDR_P2_BOTTOM_LIGHT "P2 Marquee Bottom Light"
IDS_DDR_BASS_LIGHT "Bass Neons" IDS_DDR_BASS_LIGHT "Bass Neons"
IDS_DDR_HD_P1_START "P1 HD Start"
IDS_DDR_HD_P1_UP_DOWN "P1 HD Up/Down"
IDS_DDR_HD_P1_LEFT_RIGHT "P1 HD Left/Right"
IDS_DDR_HD_P2_START "P2 HD Start"
IDS_DDR_HD_P2_UP_DOWN "P2 HD Up/Down"
IDS_DDR_HD_P2_LEFT_RIGHT "P2 HD Left/Right"
IDS_DDR_HD_P1_SPEAKER_F_R "P1 HD Speaker F R"
IDS_DDR_HD_P1_SPEAKER_F_G "P1 HD Speaker F G"
IDS_DDR_HD_P1_SPEAKER_F_B "P1 HD Speaker F B"
IDS_DDR_HD_P2_SPEAKER_F_R "P2 HD Speaker F R"
IDS_DDR_HD_P2_SPEAKER_F_G "P2 HD Speaker F G"
IDS_DDR_HD_P2_SPEAKER_F_B "P2 HD Speaker F B"
IDS_DDR_HD_P1_SPEAKER_W_R "P1 HD Speaker W R"
IDS_DDR_HD_P1_SPEAKER_W_G "P1 HD Speaker W G"
IDS_DDR_HD_P1_SPEAKER_W_B "P1 HD Speaker W B"
IDS_DDR_HD_P2_SPEAKER_W_R "P2 HD Speaker W R"
IDS_DDR_HD_P2_SPEAKER_W_G "P2 HD Speaker W G"
IDS_DDR_HD_P2_SPEAKER_W_B "P2 HD Speaker W B"
IDS_DDR_HD_SPOT_RED_TOP "HD Spot Red Top"
IDS_DDR_HD_SPOT_BLUE_TOP "HD Spot Blue Top"
IDS_PNM_SCHEMA "pop'n music" IDS_PNM_SCHEMA "pop'n music"
IDS_PNM_BTN1 "Button 1" IDS_PNM_BTN1 "Button 1"
IDS_PNM_BTN2 "Button 2" IDS_PNM_BTN2 "Button 2"
@@ -273,6 +293,15 @@ STRINGTABLE
IDS_PNM_BTN7 "Button 7" IDS_PNM_BTN7 "Button 7"
IDS_PNM_BTN8 "Button 8" IDS_PNM_BTN8 "Button 8"
IDS_PNM_BTN9 "Button 9" IDS_PNM_BTN9 "Button 9"
IDS_PNM_TOP1 "Top neon 1 (topmost red)"
IDS_PNM_TOP2 "Top neon 2 (orange)"
IDS_PNM_TOP3 "Top neon 3 (green)"
IDS_PNM_TOP4 "Top neon 4 (green)"
IDS_PNM_TOP5 "Top neon 5 (bottom green)"
IDS_PNM_LB "Left lamp (blue)"
IDS_PNM_LR "Left lamp (red)"
IDS_PNM_RB "Right lamp (blue)"
IDS_PNM_RR "Right lamp (red)"
IDS_JB_SCHEMA "Jubeat" IDS_JB_SCHEMA "Jubeat"
IDS_JB_PANEL1 "Panel 1" IDS_JB_PANEL1 "Panel 1"
IDS_JB_PANEL2 "Panel 2" IDS_JB_PANEL2 "Panel 2"

View File

@@ -105,19 +105,32 @@ int main(int argc, char **argv)
eam_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy); eam_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy);
eam_io_config_api = eam_io_get_config_api(); eam_io_config_api = eam_io_get_config_api();
// calculate these and check against the loaded config
max_light = -1;
for (i = 0; i < schema->nlights; i++) {
if (max_light < schema->lights[i].bit) {
max_light = schema->lights[i].bit;
}
}
if (!mapper_config_load(schema->name)) { if (!mapper_config_load(schema->name)) {
log_info("Initializing empty config for %s", schema->name); log_info("Initializing empty config for %s", schema->name);
max_light = -1;
for (i = 0; i < schema->nlights; i++) {
if (max_light < schema->lights[i].bit) {
max_light = schema->lights[i].bit;
}
}
mapper_set_nlights((uint8_t)(max_light + 1)); mapper_set_nlights((uint8_t)(max_light + 1));
mapper_set_nanalogs((uint8_t) schema->nanalogs); mapper_set_nanalogs((uint8_t) schema->nanalogs);
} else {
// make sure that these are right
if (mapper_get_nlights() != (max_light + 1)) {
log_info("Updating nlights for %s", schema->name);
mapper_set_nlights((uint8_t)(max_light + 1));
}
if (mapper_get_nanalogs() != schema->nanalogs) {
log_info("Updating nanalogs for %s", schema->name);
mapper_set_nanalogs((uint8_t) schema->nanalogs);
}
} }
memset(&psh, 0, sizeof(psh)); memset(&psh, 0, sizeof(psh));

View File

@@ -243,3 +243,32 @@
#define IDS_IIDX_PANEL_S3 40200 #define IDS_IIDX_PANEL_S3 40200
#define IDS_IIDX_PANEL_S4 40201 #define IDS_IIDX_PANEL_S4 40201
#define IDS_IIDX_PANEL_S5 40202 #define IDS_IIDX_PANEL_S5 40202
#define IDS_PNM_TOP1 40203
#define IDS_PNM_TOP2 40204
#define IDS_PNM_TOP3 40205
#define IDS_PNM_TOP4 40206
#define IDS_PNM_TOP5 40207
#define IDS_PNM_LB 40208
#define IDS_PNM_LR 40209
#define IDS_PNM_RB 40210
#define IDS_PNM_RR 40211
#define IDS_DDR_HD_P1_START 40212
#define IDS_DDR_HD_P1_UP_DOWN 40213
#define IDS_DDR_HD_P1_LEFT_RIGHT 40214
#define IDS_DDR_HD_P2_START 40215
#define IDS_DDR_HD_P2_UP_DOWN 40216
#define IDS_DDR_HD_P2_LEFT_RIGHT 40217
#define IDS_DDR_HD_P1_SPEAKER_F_R 40218
#define IDS_DDR_HD_P1_SPEAKER_F_G 40219
#define IDS_DDR_HD_P1_SPEAKER_F_B 40220
#define IDS_DDR_HD_P2_SPEAKER_F_R 40221
#define IDS_DDR_HD_P2_SPEAKER_F_G 40222
#define IDS_DDR_HD_P2_SPEAKER_F_B 40223
#define IDS_DDR_HD_P1_SPEAKER_W_R 40224
#define IDS_DDR_HD_P1_SPEAKER_W_G 40225
#define IDS_DDR_HD_P1_SPEAKER_W_B 40226
#define IDS_DDR_HD_P2_SPEAKER_W_R 40227
#define IDS_DDR_HD_P2_SPEAKER_W_G 40228
#define IDS_DDR_HD_P2_SPEAKER_W_B 40229
#define IDS_DDR_HD_SPOT_RED_TOP 40230
#define IDS_DDR_HD_SPOT_BLUE_TOP 40231

View File

@@ -3,30 +3,32 @@
#include "util/defs.h" #include "util/defs.h"
static const struct action_def dm_actions[] = {{0x01, IDS_GENERIC_TEST}, static const struct action_def dm_actions[] = {
{0x00, IDS_GENERIC_SERVICE}, {0x01, IDS_GENERIC_TEST},
{0x00, IDS_GENERIC_SERVICE},
{0x08, IDS_DM_START}, {0x08, IDS_DM_START},
{0x0F, IDS_DM_MENU_LEFT}, {0x0F, IDS_DM_MENU_LEFT},
{0x11, IDS_DM_MENU_RIGHT}, {0x11, IDS_DM_MENU_RIGHT},
{0x0A, IDS_DM_HI_HAT}, {0x0A, IDS_DM_HI_HAT},
{0x0C, IDS_DM_SNARE}, {0x0C, IDS_DM_SNARE},
{0x0E, IDS_DM_HIGH_TOM}, {0x0E, IDS_DM_HIGH_TOM},
{0x10, IDS_DM_LOW_TOM}, {0x10, IDS_DM_LOW_TOM},
{0x12, IDS_DM_CYMBAL}, {0x12, IDS_DM_CYMBAL},
{0x16, IDS_DM_BASS}}; {0x16, IDS_DM_BASS}};
static const struct light_def dm_lights[] = {{0x00, IDS_DM_HI_HAT}, static const struct light_def dm_lights[] = {
{0x01, IDS_DM_SNARE}, {0x00, IDS_DM_HI_HAT},
{0x02, IDS_DM_HIGH_TOM}, {0x01, IDS_DM_SNARE},
{0x03, IDS_DM_LOW_TOM}, {0x02, IDS_DM_HIGH_TOM},
{0x04, IDS_DM_CYMBAL}, {0x03, IDS_DM_LOW_TOM},
{0x09, IDS_DM_BASS}, {0x04, IDS_DM_CYMBAL},
{0x0A, IDS_DM_SPEAKER_LIGHT}, {0x09, IDS_DM_BASS},
{0x08, IDS_DM_SPOT_LIGHT}, {0x0A, IDS_DM_SPEAKER_LIGHT},
{0x06, IDS_DM_START_LIGHT}, {0x08, IDS_DM_SPOT_LIGHT},
{0x07, IDS_DM_MENU_LIGHT}}; {0x06, IDS_DM_START_LIGHT},
{0x07, IDS_DM_MENU_LIGHT}};
static const struct action_def gf_actions[] = { static const struct action_def gf_actions[] = {
{0x01, IDS_GENERIC_TEST}, {0x00, IDS_GENERIC_SERVICE}, {0x01, IDS_GENERIC_TEST}, {0x00, IDS_GENERIC_SERVICE},
@@ -43,10 +45,11 @@ static const struct action_def gf_actions[] = {
{0x13, IDS_GF_P2_RED}, {0x15, IDS_GF_P2_GREEN}, {0x13, IDS_GF_P2_RED}, {0x15, IDS_GF_P2_GREEN},
{0x17, IDS_GF_P2_BLUE}}; {0x17, IDS_GF_P2_BLUE}};
static const struct light_def gf_lights[] = {{0x08, IDS_GF_P1_SPOT_LIGHT}, static const struct light_def gf_lights[] = {
{0x09, IDS_GF_P2_SPOT_LIGHT}, {0x08, IDS_GF_P1_SPOT_LIGHT},
{0x0A, IDS_GF_P1_START}, {0x09, IDS_GF_P2_SPOT_LIGHT},
{0x0B, IDS_GF_P2_START}}; {0x0A, IDS_GF_P1_START},
{0x0B, IDS_GF_P2_START}};
static const struct action_def iidx_actions[] = { static const struct action_def iidx_actions[] = {
{0x1C, IDS_GENERIC_TEST}, {0x1D, IDS_GENERIC_SERVICE}, {0x1C, IDS_GENERIC_TEST}, {0x1D, IDS_GENERIC_SERVICE},
@@ -101,8 +104,8 @@ static const struct light_def iidx_lights[] = {
{0x1F, IDS_IIDX_NEON_LIGHT}}; {0x1F, IDS_IIDX_NEON_LIGHT}};
static const struct analog_def iidx_analogs[] = {{0, IDS_IIDX_P1_TT}, static const struct analog_def iidx_analogs[] = {
{1, IDS_IIDX_P2_TT}}; {0, IDS_IIDX_P1_TT}, {1, IDS_IIDX_P2_TT}};
static const struct action_def ddr_actions[] = { static const struct action_def ddr_actions[] = {
{0x04, IDS_GENERIC_TEST}, {0x06, IDS_GENERIC_SERVICE}, {0x04, IDS_GENERIC_TEST}, {0x06, IDS_GENERIC_SERVICE},
@@ -122,19 +125,48 @@ static const struct action_def ddr_actions[] = {
static const struct light_def ddr_lights[] = { static const struct light_def ddr_lights[] = {
/* These are split between non-overlapping P3IO and EXTIO state words */ /* These are split between non-overlapping P3IO and EXTIO state words */
// P3IO: SD
{0x00, IDS_DDR_P1_MENU_LIGHT}, {0x00, IDS_DDR_P1_MENU_LIGHT},
{0x07, IDS_DDR_P1_TOP_LIGHT}, {0x07, IDS_DDR_P1_TOP_LIGHT},
{0x07, IDS_DDR_P1_BOTTOM_LIGHT}, {0x06, IDS_DDR_P1_BOTTOM_LIGHT},
{0x1E, IDS_DDR_P1_UP},
{0x1D, IDS_DDR_P1_DOWN},
{0x1C, IDS_DDR_P1_LEFT},
{0x1B, IDS_DDR_P1_RIGHT},
{0x01, IDS_DDR_P2_MENU_LIGHT}, {0x01, IDS_DDR_P2_MENU_LIGHT},
{0x05, IDS_DDR_P2_TOP_LIGHT}, {0x05, IDS_DDR_P2_TOP_LIGHT},
{0x04, IDS_DDR_P2_BOTTOM_LIGHT}, {0x04, IDS_DDR_P2_BOTTOM_LIGHT},
// P3IO: HD
{0x02, IDS_DDR_HD_SPOT_RED_TOP},
{0x03, IDS_DDR_HD_SPOT_BLUE_TOP},
// P3IO: HDXS
{0x08, IDS_DDR_HD_P1_START},
{0x09, IDS_DDR_HD_P1_UP_DOWN},
{0x0A, IDS_DDR_HD_P1_LEFT_RIGHT},
{0x0B, IDS_DDR_HD_P2_START},
{0x0C, IDS_DDR_HD_P2_UP_DOWN},
{0x0D, IDS_DDR_HD_P2_LEFT_RIGHT},
{0x20, IDS_DDR_HD_P1_SPEAKER_F_R},
{0x21, IDS_DDR_HD_P1_SPEAKER_F_G},
{0x22, IDS_DDR_HD_P1_SPEAKER_F_B},
{0x23, IDS_DDR_HD_P2_SPEAKER_F_R},
{0x24, IDS_DDR_HD_P2_SPEAKER_F_G},
{0x25, IDS_DDR_HD_P2_SPEAKER_F_B},
{0x26, IDS_DDR_HD_P1_SPEAKER_W_R},
{0x27, IDS_DDR_HD_P1_SPEAKER_W_G},
{0x28, IDS_DDR_HD_P1_SPEAKER_W_B},
{0x29, IDS_DDR_HD_P2_SPEAKER_W_R},
{0x2A, IDS_DDR_HD_P2_SPEAKER_W_G},
{0x2B, IDS_DDR_HD_P2_SPEAKER_W_B},
// EXTIO
{0x1E, IDS_DDR_P1_UP},
{0x1D, IDS_DDR_P1_DOWN},
{0x1C, IDS_DDR_P1_LEFT},
{0x1B, IDS_DDR_P1_RIGHT},
{0x16, IDS_DDR_P2_UP}, {0x16, IDS_DDR_P2_UP},
{0x15, IDS_DDR_P2_DOWN}, {0x15, IDS_DDR_P2_DOWN},
{0x14, IDS_DDR_P2_LEFT}, {0x14, IDS_DDR_P2_LEFT},
@@ -142,18 +174,19 @@ static const struct light_def ddr_lights[] = {
{0x0E, IDS_DDR_BASS_LIGHT}}; {0x0E, IDS_DDR_BASS_LIGHT}};
static const struct action_def pnm_actions[] = {{0x07, IDS_GENERIC_TEST}, static const struct action_def pnm_actions[] = {
{0x06, IDS_GENERIC_SERVICE}, {0x07, IDS_GENERIC_TEST},
{0x06, IDS_GENERIC_SERVICE},
{0x08, IDS_PNM_BTN1}, {0x08, IDS_PNM_BTN1},
{0x09, IDS_PNM_BTN2}, {0x09, IDS_PNM_BTN2},
{0x0A, IDS_PNM_BTN3}, {0x0A, IDS_PNM_BTN3},
{0x0B, IDS_PNM_BTN4}, {0x0B, IDS_PNM_BTN4},
{0x0C, IDS_PNM_BTN5}, {0x0C, IDS_PNM_BTN5},
{0x0D, IDS_PNM_BTN6}, {0x0D, IDS_PNM_BTN6},
{0x0E, IDS_PNM_BTN7}, {0x0E, IDS_PNM_BTN7},
{0x0F, IDS_PNM_BTN8}, {0x0F, IDS_PNM_BTN8},
{0x10, IDS_PNM_BTN9}}; {0x10, IDS_PNM_BTN9}};
static const struct light_def pnm_lights[] = { static const struct light_def pnm_lights[] = {
{0x17, IDS_PNM_BTN1}, {0x17, IDS_PNM_BTN1},
@@ -165,27 +198,37 @@ static const struct light_def pnm_lights[] = {
{0x1D, IDS_PNM_BTN7}, {0x1D, IDS_PNM_BTN7},
{0x1E, IDS_PNM_BTN8}, {0x1E, IDS_PNM_BTN8},
{0x1F, IDS_PNM_BTN9}, {0x1F, IDS_PNM_BTN9},
{0x20, IDS_PNM_TOP1},
{0x21, IDS_PNM_TOP2},
{0x22, IDS_PNM_TOP3},
{0x23, IDS_PNM_TOP4},
{0x24, IDS_PNM_TOP5},
{0x25, IDS_PNM_LB},
{0x26, IDS_PNM_LR},
{0x27, IDS_PNM_RB},
{0x28, IDS_PNM_RR},
}; };
static const struct action_def jb_actions[] = {{0x10, IDS_GENERIC_TEST}, static const struct action_def jb_actions[] = {
{0x11, IDS_GENERIC_SERVICE}, {0x10, IDS_GENERIC_TEST},
{0x11, IDS_GENERIC_SERVICE},
{0x00, IDS_JB_PANEL1}, {0x00, IDS_JB_PANEL1},
{0x01, IDS_JB_PANEL2}, {0x01, IDS_JB_PANEL2},
{0x02, IDS_JB_PANEL3}, {0x02, IDS_JB_PANEL3},
{0x03, IDS_JB_PANEL4}, {0x03, IDS_JB_PANEL4},
{0x04, IDS_JB_PANEL5}, {0x04, IDS_JB_PANEL5},
{0x05, IDS_JB_PANEL6}, {0x05, IDS_JB_PANEL6},
{0x06, IDS_JB_PANEL7}, {0x06, IDS_JB_PANEL7},
{0x07, IDS_JB_PANEL8}, {0x07, IDS_JB_PANEL8},
{0x08, IDS_JB_PANEL9}, {0x08, IDS_JB_PANEL9},
{0x09, IDS_JB_PANEL10}, {0x09, IDS_JB_PANEL10},
{0x0A, IDS_JB_PANEL11}, {0x0A, IDS_JB_PANEL11},
{0x0B, IDS_JB_PANEL12}, {0x0B, IDS_JB_PANEL12},
{0x0C, IDS_JB_PANEL13}, {0x0C, IDS_JB_PANEL13},
{0x0D, IDS_JB_PANEL14}, {0x0D, IDS_JB_PANEL14},
{0x0E, IDS_JB_PANEL15}, {0x0E, IDS_JB_PANEL15},
{0x0F, IDS_JB_PANEL16}}; {0x0F, IDS_JB_PANEL16}};
static const struct light_def jb_lights[] = { static const struct light_def jb_lights[] = {
{0x00, IDS_JB_RGB_FRONT_R}, {0x00, IDS_JB_RGB_FRONT_R},
@@ -208,15 +251,16 @@ static const struct light_def jb_lights[] = {
{0x11, IDS_JB_RGB_WOOFER_B}, {0x11, IDS_JB_RGB_WOOFER_B},
}; };
static const struct action_def sdvx_actions[] = {{0x05, IDS_GENERIC_TEST}, static const struct action_def sdvx_actions[] = {
{0x04, IDS_GENERIC_SERVICE}, {0x05, IDS_GENERIC_TEST},
{0x0B, IDS_SDVX_START}, {0x04, IDS_GENERIC_SERVICE},
{0x0A, IDS_SDVX_BTN_A}, {0x0B, IDS_SDVX_START},
{0x09, IDS_SDVX_BTN_B}, {0x0A, IDS_SDVX_BTN_A},
{0x08, IDS_SDVX_BTN_C}, {0x09, IDS_SDVX_BTN_B},
{0x15, IDS_SDVX_BTN_D}, {0x08, IDS_SDVX_BTN_C},
{0x14, IDS_SDVX_FX_L}, {0x15, IDS_SDVX_BTN_D},
{0x13, IDS_SDVX_FX_R}}; {0x14, IDS_SDVX_FX_L},
{0x13, IDS_SDVX_FX_R}};
static const struct light_def sdvx_lights[] = { static const struct light_def sdvx_lights[] = {
{0x0D, IDS_SDVX_BTN_A}, {0x0E, IDS_SDVX_BTN_B}, {0x0F, IDS_SDVX_BTN_C}, {0x0D, IDS_SDVX_BTN_A}, {0x0E, IDS_SDVX_BTN_B}, {0x0F, IDS_SDVX_BTN_C},
@@ -229,19 +273,19 @@ static const struct light_def sdvx_lights[] = {
{0x1E, IDS_SDVX_RGB5_B}, {0x1F, IDS_SDVX_RGB6_R}, {0x20, IDS_SDVX_RGB6_G}, {0x1E, IDS_SDVX_RGB5_B}, {0x1F, IDS_SDVX_RGB6_R}, {0x20, IDS_SDVX_RGB6_G},
{0x21, IDS_SDVX_RGB6_B}}; {0x21, IDS_SDVX_RGB6_B}};
static const struct analog_def sdvx_analogs[] = {{0, IDS_SDVX_VOL_L}, static const struct analog_def sdvx_analogs[] = {
{1, IDS_SDVX_VOL_R}}; {0, IDS_SDVX_VOL_L}, {1, IDS_SDVX_VOL_R}};
static const struct action_def rb_actions[] = {{0x00, IDS_GENERIC_TEST}, static const struct action_def rb_actions[] = {
{0x01, IDS_GENERIC_SERVICE}}; {0x00, IDS_GENERIC_TEST}, {0x01, IDS_GENERIC_SERVICE}};
static const struct action_def bst_actions[] = { static const struct action_def bst_actions[] = {
{0x05, IDS_GENERIC_TEST}, {0x05, IDS_GENERIC_TEST},
{0x04, IDS_GENERIC_SERVICE}, {0x04, IDS_GENERIC_SERVICE},
}; };
static const struct eam_unit_def schema_eam_unit_defs[] = {{IDS_READER_P1, 0}, static const struct eam_unit_def schema_eam_unit_defs[] = {
{IDS_READER_P2, 1}}; {IDS_READER_P1, 0}, {IDS_READER_P2, 1}};
const struct schema schemas[] = { const struct schema schemas[] = {
{"iidx", {"iidx",

View File

@@ -9,7 +9,6 @@ libs_ddrhook := \
p3io \ p3io \
hook \ hook \
hooklib \ hooklib \
security \
util \ util \
eamio \ eamio \
ddrio \ ddrio \

View File

@@ -11,10 +11,14 @@
#include <string.h> #include <string.h>
#include <wchar.h> #include <wchar.h>
#include "acio/hdxs.h"
#include "acioemu/addr.h" #include "acioemu/addr.h"
#include "acioemu/hdxs.h" #include "acioemu/hdxs.h"
#include "acioemu/icca.h" #include "acioemu/icca.h"
#include "bemanitools/ddrio.h"
#include "ddrhook/_com4.h" #include "ddrhook/_com4.h"
#include "hook/iohook.h" #include "hook/iohook.h"
@@ -29,16 +33,60 @@ static struct ac_io_emu com4_ac_io_emu;
static struct ac_io_emu_hdxs com4_hdxs; static struct ac_io_emu_hdxs com4_hdxs;
static struct ac_io_emu_icca com4_icca[2]; static struct ac_io_emu_icca com4_icca[2];
static uint32_t check_panel_light(
const struct ac_io_hdxs_output *output,
uint8_t panel_idx,
uint8_t out_idx)
{
if (output->lights[panel_idx].bit) {
return 1 << out_idx;
} else {
return 0;
}
}
static uint8_t upscale_light(uint8_t in_7bit) {
if (in_7bit < 0x10) {
return in_7bit * 2;
} else {
// so we can actually reach 0xFF
return (in_7bit * 2) + 1;
}
}
static void lights_dispatcher(
struct ac_io_emu_hdxs *emu, const struct ac_io_message *req)
{
const struct ac_io_hdxs_output *output = &req->cmd.hdxs_output;
uint32_t lights = 0;
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_START, LIGHT_HD_P1_START);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_UP_DOWN, LIGHT_HD_P1_UP_DOWN);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P1_LEFT_RIGHT, LIGHT_HD_P1_LEFT_RIGHT);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_START, LIGHT_HD_P2_START);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_UP_DOWN, LIGHT_HD_P2_UP_DOWN);
lights |= check_panel_light(output, AC_IO_HDXS_OUT_P2_LEFT_RIGHT, LIGHT_HD_P2_LEFT_RIGHT);
ddr_io_set_lights_hdxs_panel(lights);
for (uint8_t i = 0; i < 4; ++i) {
size_t light_idx = i * 3;
// these are 7 bit, upscale them to 8 bit
uint8_t r = upscale_light(output->lights[light_idx + AC_IO_HDXS_RED].analog);
uint8_t g = upscale_light(output->lights[light_idx + AC_IO_HDXS_GREEN].analog);
uint8_t b = upscale_light(output->lights[light_idx + AC_IO_HDXS_BLUE].analog);
ddr_io_set_lights_hdxs_rgb(i, r, g, b);
}
}
void com4_init(void) void com4_init(void)
{ {
uint8_t i; uint8_t i;
/* This isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we intercept them. */
p3io_uart_set_path(0, L"COM4");
ac_io_emu_init(&com4_ac_io_emu, L"COM4"); ac_io_emu_init(&com4_ac_io_emu, L"COM4");
ac_io_emu_hdxs_init(&com4_hdxs, &com4_ac_io_emu); ac_io_emu_hdxs_init(&com4_hdxs, &com4_ac_io_emu, lights_dispatcher);
for (i = 0; i < lengthof(com4_icca); i++) { for (i = 0; i < lengthof(com4_icca); i++) {
ac_io_emu_icca_init(&com4_icca[i], &com4_ac_io_emu, i); ac_io_emu_icca_init(&com4_icca[i], &com4_ac_io_emu, i);

View File

@@ -32,7 +32,7 @@ static bool my_dll_entry_main(void);
bool standard_def; bool standard_def;
bool _15khz; bool _15khz;
static const irp_handler_t ddrhook_handlers[] = { static const irp_handler_t ddrhook_com4_handlers[] = {
p3io_emu_dispatch_irp, p3io_emu_dispatch_irp,
extio_dispatch_irp, extio_dispatch_irp,
spike_dispatch_irp, spike_dispatch_irp,
@@ -40,15 +40,27 @@ static const irp_handler_t ddrhook_handlers[] = {
com4_dispatch_irp, com4_dispatch_irp,
}; };
static const irp_handler_t ddrhook_handlers[] = {
/* Same as above, but without COM4 emulation.
See ddrhook/p3io.c for details. */
p3io_emu_dispatch_irp,
extio_dispatch_irp,
spike_dispatch_irp,
usbmem_dispatch_irp,
};
static bool my_dll_entry_init(char *sidcode, struct property_node *param) static bool my_dll_entry_init(char *sidcode, struct property_node *param)
{ {
int argc; int argc;
char **argv; char **argv;
bool com4;
bool ok; bool ok;
int i; int i;
log_info("--- Begin ddrhook dll_entry_init ---"); log_info("--- Begin ddrhook dll_entry_init ---");
com4 = true;
args_recover(&argc, &argv); args_recover(&argc, &argv);
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
@@ -65,13 +77,25 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
case 'w': case 'w':
gfx_set_windowed(); gfx_set_windowed();
break;
case 'u':
/* Don't emulate P3IO COM4 and its downstream devices, use the
Windows COM4 port instead. */
com4 = false;
break; break;
} }
} }
args_free(argc, argv); args_free(argc, argv);
iohook_init(ddrhook_handlers, lengthof(ddrhook_handlers)); if (com4) {
iohook_init(ddrhook_com4_handlers, lengthof(ddrhook_com4_handlers));
} else {
iohook_init(ddrhook_handlers, lengthof(ddrhook_handlers));
}
rs232_hook_init(); rs232_hook_init();
master_insert_hooks(NULL); master_insert_hooks(NULL);
@@ -92,15 +116,17 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
return false; return false;
} }
log_info("Initializing card reader backend"); if (com4) {
log_info("Initializing card reader backend");
eam_io_set_loggers( eam_io_set_loggers(
log_body_misc, log_body_info, log_body_warning, log_body_fatal); log_body_misc, log_body_info, log_body_warning, log_body_fatal);
ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy); ok = eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy);
if (!ok) { if (!ok) {
return false; return false;
}
} }
log_info("--- End ddrhook dll_entry_init ---"); log_info("--- End ddrhook dll_entry_init ---");

View File

@@ -29,6 +29,12 @@ static const struct p3io_ops p3io_ddr_ops = {
void p3io_ddr_init(void) void p3io_ddr_init(void)
{ {
/* COM4 isn't a real COM port, we configure the core P3IO emulator code to
generate IRPs addressed to COM4 and then we possibly intercept them in
_com4.c (or possibly don't, in which case the communications will be
sent to the real COM4 on your system) */
p3io_uart_set_path(0, L"COM4");
p3io_emu_init(&p3io_ddr_ops, NULL); p3io_emu_init(&p3io_ddr_ops, NULL);
} }

View File

@@ -7,3 +7,5 @@ EXPORTS
ddr_io_read_pad ddr_io_read_pad
ddr_io_set_lights_extio ddr_io_set_lights_extio
ddr_io_set_lights_p3io ddr_io_set_lights_p3io
ddr_io_set_lights_hdxs_panel
ddr_io_set_lights_hdxs_rgb

View File

@@ -207,6 +207,21 @@ void ddr_io_set_lights_p3io(uint32_t p3io_lights)
atomic_fetch_and(&out.lights, ~clr); atomic_fetch_and(&out.lights, ~clr);
} }
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
(void) lights;
// stubbed
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
(void) idx;
(void) r;
(void) g;
(void) b;
// stubbed
}
void ddr_io_fini(void) void ddr_io_fini(void)
{ {
if (initted) { if (initted) {

View File

@@ -7,3 +7,5 @@ EXPORTS
ddr_io_read_pad ddr_io_read_pad
ddr_io_set_lights_extio ddr_io_set_lights_extio
ddr_io_set_lights_p3io ddr_io_set_lights_p3io
ddr_io_set_lights_hdxs_panel
ddr_io_set_lights_hdxs_rgb

View File

@@ -168,11 +168,30 @@ void ddr_io_set_lights_p3io(uint32_t lights)
{ {
uint8_t i; uint8_t i;
for (i = 0x0E; i <= 0x1E; i++) { for (i = 0x00; i <= 0x07; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0); mapper_write_light(i, lights & (1 << i) ? 255 : 0);
} }
} }
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
uint8_t i;
for (i = 0x08; i <= 0x0D; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0);
}
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
if (idx < 4) {
uint8_t base = 0x20 + idx * 3;
mapper_write_light(base + 0, r);
mapper_write_light(base + 1, g);
mapper_write_light(base + 2, b);
}
}
void ddr_io_fini(void) void ddr_io_fini(void)
{ {
log_info("Stopping SMX.DLL"); log_info("Stopping SMX.DLL");

View File

@@ -43,7 +43,7 @@ void ddr_io_set_lights_extio(uint32_t lights)
{ {
uint8_t i; uint8_t i;
for (i = 0x00; i <= 0x07; i++) { for (i = 0x0E; i <= 0x1E; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0); mapper_write_light(i, lights & (1 << i) ? 255 : 0);
} }
} }
@@ -52,11 +52,30 @@ void ddr_io_set_lights_p3io(uint32_t lights)
{ {
uint8_t i; uint8_t i;
for (i = 0x0E; i <= 0x1E; i++) { for (i = 0x00; i <= 0x07; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0); mapper_write_light(i, lights & (1 << i) ? 255 : 0);
} }
} }
void ddr_io_set_lights_hdxs_panel(uint32_t lights)
{
uint8_t i;
for (i = 0x08; i <= 0x0D; i++) {
mapper_write_light(i, lights & (1 << i) ? 255 : 0);
}
}
void ddr_io_set_lights_hdxs_rgb(uint8_t idx, uint8_t r, uint8_t g, uint8_t b)
{
if (idx < 4) {
uint8_t base = 0x20 + idx * 3;
mapper_write_light(base + 0, r);
mapper_write_light(base + 1, g);
mapper_write_light(base + 2, b);
}
}
void ddr_io_fini(void) void ddr_io_fini(void)
{ {
input_fini(); input_fini();

View File

@@ -7,3 +7,5 @@ EXPORTS
ddr_io_read_pad ddr_io_read_pad
ddr_io_set_lights_extio ddr_io_set_lights_extio
ddr_io_set_lights_p3io ddr_io_set_lights_p3io
ddr_io_set_lights_hdxs_panel
ddr_io_set_lights_hdxs_rgb

View File

@@ -160,6 +160,10 @@ static HRESULT ezusb_iidx_emu_msg_interrupt_read(struct iobuf *read)
otherwise the game's fpga check will fail */ otherwise the game's fpga check will fail */
msg_resp->fpga2_check_flag_unkn = 2; msg_resp->fpga2_check_flag_unkn = 2;
#ifdef EZUSB_IIDX_EMU_D01_BOARD
msg_resp->inverted_pad &= ~(1 << 4);
#endif
read->pos = sizeof(*msg_resp); read->pos = sizeof(*msg_resp);
return S_OK; return S_OK;

View File

@@ -59,7 +59,9 @@ struct ezusb_iidx_msg_interrupt_read_packet {
1: Not used 1: Not used
2: Not used 2: Not used
3: Not used 3: Not used
4: Not used 4: C02/D01 board identifier, 1 = C02, 0 = D01 (on active low). This defines how the game has
to flash the FPGA board since D01 needs a different firmware (see result of FPGA CHECK on
game bootup)
5: Not used 5: Not used
6: usb mute? 6: usb mute?
7: Not used 7: Not used

View File

@@ -36,6 +36,8 @@ EXPORTS
mapper_get_analog_map mapper_get_analog_map
mapper_get_analog_sensitivity mapper_get_analog_sensitivity
mapper_get_npages mapper_get_npages
mapper_get_nanalogs
mapper_get_nlights
mapper_is_analog_absolute mapper_is_analog_absolute
mapper_iterate_lights mapper_iterate_lights
mapper_iterate_actions mapper_iterate_actions

View File

@@ -16,6 +16,7 @@ bool mapper_get_action_map(
bool mapper_get_analog_map(uint8_t analog, struct mapped_analog *ma); bool mapper_get_analog_map(uint8_t analog, struct mapped_analog *ma);
int32_t mapper_get_analog_sensitivity(uint8_t analog); int32_t mapper_get_analog_sensitivity(uint8_t analog);
uint8_t mapper_get_nanalogs(void); uint8_t mapper_get_nanalogs(void);
uint8_t mapper_get_nlights(void);
uint8_t mapper_get_npages(void); uint8_t mapper_get_npages(void);
bool mapper_is_analog_absolute(uint8_t analog); bool mapper_is_analog_absolute(uint8_t analog);
action_iter_t mapper_iterate_actions(void); action_iter_t mapper_iterate_actions(void);

View File

@@ -149,6 +149,11 @@ uint8_t mapper_get_nanalogs(void)
return mapper_impl_get_nanalogs(mapper_inst); return mapper_impl_get_nanalogs(mapper_inst);
} }
uint8_t mapper_get_nlights(void)
{
return mapper_impl_get_nlights(mapper_inst);
}
uint8_t mapper_get_npages(void) uint8_t mapper_get_npages(void)
{ {
return mapper_impl_get_npages(mapper_inst); return mapper_impl_get_npages(mapper_inst);

View File

@@ -192,7 +192,8 @@ uint8_t iidx_io_ep2_get_slider(uint8_t slider_no)
uint8_t iidx_io_ep2_get_sys(void) uint8_t iidx_io_ep2_get_sys(void)
{ {
return ((~iidx_io_ezusb_read_packet.inverted_pad) >> 28) & 0x03; return (((~iidx_io_ezusb_read_packet.inverted_pad) >> 28) & 0x03) |
((((~iidx_io_ezusb_read_packet.inverted_pad) >> 22) & 0x01) << 2);
} }
uint8_t iidx_io_ep2_get_panel(void) uint8_t iidx_io_ep2_get_panel(void)

View File

@@ -5,6 +5,7 @@ deplibs_jbhook := \
ldflags_jbhook := \ ldflags_jbhook := \
-lws2_32 \ -lws2_32 \
-liphlpapi \
libs_jbhook := \ libs_jbhook := \
acioemu \ acioemu \

View File

@@ -10,6 +10,7 @@
#include "hook/iohook.h" #include "hook/iohook.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h" #include "hooklib/app.h"
#include "hooklib/rs232.h" #include "hooklib/rs232.h"
#include "hooklib/setupapi.h" #include "hooklib/setupapi.h"
@@ -133,6 +134,10 @@ BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
app_hook_init(my_dll_entry_init, my_dll_entry_main); app_hook_init(my_dll_entry_init, my_dll_entry_main);
iohook_init(jbhook_handlers, lengthof(jbhook_handlers)); iohook_init(jbhook_handlers, lengthof(jbhook_handlers));
if (!options.disable_adapteremu) {
adapter_hook_init();
}
if (!options.disable_cardemu) { if (!options.disable_cardemu) {
rs232_hook_init(); rs232_hook_init();
} }

View File

@@ -37,6 +37,7 @@ void options_init(struct options *options)
options->window_framed = false; options->window_framed = false;
options->disable_p4ioemu = false; options->disable_p4ioemu = false;
options->disable_cardemu = false; options->disable_cardemu = false;
options->disable_adapteremu = false;
} }
bool options_read_cmdline(struct options *options, int argc, const char **argv) bool options_read_cmdline(struct options *options, int argc, const char **argv)
@@ -64,6 +65,11 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break; break;
} }
case 'a': {
options->disable_adapteremu = true;
break;
}
case 'c': { case 'c': {
options->disable_cardemu = true; options->disable_cardemu = true;
break; break;
@@ -90,6 +96,7 @@ void options_print_usage(void)
" -h Print this usage message\n" " -h Print this usage message\n"
" -w Run the game windowed\n" " -w Run the game windowed\n"
" -f Run the game in a framed window (needs -w option)\n" " -f Run the game in a framed window (needs -w option)\n"
" -a Disable adapter hook\n"
" -c Disable card emulation (e.g. when running on a " " -c Disable card emulation (e.g. when running on a "
"real cab)\n" "real cab)\n"
" -p Disable p4io emulation (e.g. when running on a " " -p Disable p4io emulation (e.g. when running on a "

View File

@@ -9,6 +9,7 @@ struct options {
bool window_framed; bool window_framed;
bool disable_p4ioemu; bool disable_p4ioemu;
bool disable_cardemu; bool disable_cardemu;
bool disable_adapteremu;
}; };
void options_init_from_cmdline(struct options *options); void options_init_from_cmdline(struct options *options);

View File

@@ -97,13 +97,29 @@ bool ea3_ident_invoke_module_init(
ident->rev, ident->rev,
ident->ext); ident->ext);
/* Set up long-form sidcode env var */
str_format(
sidcode_long,
lengthof(sidcode_long),
"%s:%s:%s:%s:%s",
ident->model,
ident->dest,
ident->spec,
ident->rev,
ident->ext);
/* Set this up beforehand, as certain games require it in dll_entry_init */
std_setenv("/env/profile/soft_id_code", sidcode_long);
ok = module_context_invoke_init(module, sidcode_short, app_config); ok = module_context_invoke_init(module, sidcode_short, app_config);
if (!ok) { if (!ok) {
return false; return false;
} }
/* Back-propagate sidcode */ /* Back-propagate sidcode, as some games modify it during init */
memcpy(ident->model, sidcode_short + 0, sizeof(ident->model) - 1); memcpy(ident->model, sidcode_short + 0, sizeof(ident->model) - 1);
ident->dest[0] = sidcode_short[3]; ident->dest[0] = sidcode_short[3];
@@ -111,7 +127,7 @@ bool ea3_ident_invoke_module_init(
ident->rev[0] = sidcode_short[5]; ident->rev[0] = sidcode_short[5];
memcpy(ident->ext, sidcode_short + 6, sizeof(ident->ext)); memcpy(ident->ext, sidcode_short + 6, sizeof(ident->ext));
/* Set up long-form sidcode env var */ /* Set up long-form sidcode env var again */
str_format( str_format(
sidcode_long, sidcode_long,

View File

@@ -17,17 +17,23 @@ void module_context_init(struct module_context *module, const char *path)
if (module->dll == NULL) { if (module->dll == NULL) {
LPSTR buffer; LPSTR buffer;
DWORD err = GetLastError();
FormatMessageA( FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, NULL,
GetLastError(), err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer, (LPSTR) &buffer,
0, 0,
NULL); NULL);
if (err == ERROR_MOD_NOT_FOUND) {
log_warning("%s is likely missing dependencies", path);
log_warning("Do you have vcredist/directx runtimes installed?");
}
log_fatal("%s: Failed to load game DLL: %s", path, buffer); log_fatal("%s: Failed to load game DLL: %s", path, buffer);
LocalFree(buffer); LocalFree(buffer);

View File

@@ -1,8 +0,0 @@
LIBRARY ddrio
EXPORTS
ddr_io_fini
ddr_io_init
ddr_io_read_pad
ddr_io_set_lights_extio
ddr_io_set_lights_p3io

View File

@@ -423,12 +423,10 @@ static void p3io_cmd_get_cab_type_or_dipsw(
if (hr == S_OK) { if (hr == S_OK) {
switch (type) { switch (type) {
case P3IO_CAB_TYPE_SD: case P3IO_CAB_TYPE_SD:
log_misc("%s: Returning cab type SD", __func__);
resp->status = 1; resp->status = 1;
break; break;
case P3IO_CAB_TYPE_HD: case P3IO_CAB_TYPE_HD:
log_misc("%s: Returning cab type HD", __func__);
resp->status = 2; resp->status = 2;
break; break;

View File

@@ -104,7 +104,7 @@ void p3io_uart_cmd_open_close(
} }
end: end:
p3io_resp_init(&resp->hdr, sizeof(resp), &req->hdr); p3io_resp_init(&resp->hdr, sizeof(*resp), &req->hdr);
resp->status = 0; resp->status = 0;
resp->u8 = FAILED(hr); resp->u8 = FAILED(hr);
} }
@@ -167,7 +167,7 @@ void p3io_uart_cmd_write(
hr = p3io_uart_write(p3io_uart_fds[req->port_no], &iobuf); hr = p3io_uart_write(p3io_uart_fds[req->port_no], &iobuf);
end: end:
p3io_resp_init(&resp->hdr, sizeof(resp), &req->hdr); p3io_resp_init(&resp->hdr, sizeof(*resp), &req->hdr);
resp->status = FAILED(hr); resp->status = FAILED(hr);
resp->nbytes = iobuf.pos; resp->nbytes = iobuf.pos;
} }

View File

@@ -1,6 +1,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "util/log.h"
uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in) uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in)
{ {
const uint8_t *bytes; const uint8_t *bytes;
@@ -8,7 +10,7 @@ uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in)
size_t i; size_t i;
size_t j; size_t j;
// log_assert(ptr != NULL); log_assert(ptr != NULL);
bytes = ptr; bytes = ptr;
crc = ~in; crc = ~in;
@@ -35,7 +37,7 @@ uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in)
size_t i; size_t i;
size_t j; size_t j;
// log_assert(ptr != NULL); log_assert(ptr != NULL);
bytes = ptr; bytes = ptr;
crc = ~in; crc = ~in;
@@ -55,6 +57,33 @@ uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in)
return ~crc; return ~crc;
} }
uint16_t crc16_msb(const void *ptr, size_t nbytes, uint16_t in)
{
const uint8_t *bytes;
uint16_t crc;
size_t i;
size_t j;
log_assert(ptr != NULL);
bytes = ptr;
crc = in;
for (i = 0; i < nbytes; i++) {
crc ^= bytes[i] << 8;
for (j = 0; j < 8; j++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc = crc << 1;
}
}
}
return crc;
}
uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in) uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in)
{ {
const uint8_t *bytes; const uint8_t *bytes;
@@ -62,7 +91,7 @@ uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in)
size_t i; size_t i;
size_t j; size_t j;
// log_assert(ptr != NULL); log_assert(ptr != NULL);
bytes = ptr; bytes = ptr;
crc = ~in; crc = ~in;

View File

@@ -6,6 +6,7 @@
uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in); uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in);
uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in); uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in);
uint16_t crc16_msb(const void *ptr, size_t nbytes, uint16_t in);
uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in); uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in);
#endif #endif

View File

@@ -16,7 +16,7 @@ void *xcalloc(size_t nbytes)
mem = calloc(nbytes, 1); mem = calloc(nbytes, 1);
if (mem == NULL) { if (mem == NULL) {
log_fatal("xmalloc(%u) failed", (uint32_t) nbytes); log_fatal("xcalloc(%u) failed", (uint32_t) nbytes);
return NULL; return NULL;
} }
@@ -31,7 +31,7 @@ void *xmalloc(size_t nbytes)
mem = malloc(nbytes); mem = malloc(nbytes);
if (mem == NULL) { if (mem == NULL) {
log_fatal("xcalloc(%u) failed", (uint32_t) nbytes); log_fatal("xmalloc(%u) failed", (uint32_t) nbytes);
return NULL; return NULL;
} }

View File

@@ -206,8 +206,8 @@ void _Noreturn check_data_eq_failed(
line, line,
func, func,
"\tIncorrect result: %s\n" "\tIncorrect result: %s\n"
"\tReturn size was: %d\n" "\tReturn size was: %Iu\n"
"\tExected size: %d\n" "\tExected size: %Iu\n"
"\tReturn value was \"%s\"\n" "\tReturn value was \"%s\"\n"
"\tExpected \"%s\"\n\n", "\tExpected \"%s\"\n\n",
expr, expr,