Compare commits

..

40 Commits
v5.29 ... 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
icex2
ff2a4b9a2c Changelog 5.30 update 2020-04-27 21:59:33 +02:00
Will Xyen
10bddd4905 d3d9ex: add cursor confining (ported from sdvxhook1) 2020-04-27 12:52:07 -07:00
Will Xyen
ad5fbc1f5b sdvxhook2: Add option to force headphone detection on 2020-04-27 10:19:29 -07:00
Will Xyen
25413bcba8 dinput/asio: drop hook suffix 2020-04-05 02:18:24 -07:00
Will Xyen
937290f93d asiohook: add config 2020-04-05 01:44:42 -07:00
Will Xyen
d04598a570 dinputhook: Adds dinput stub hook for later use
Thanks to felix for the original di8_stub_device.
2020-04-05 01:44:42 -07:00
Will Xyen
bd382e5509 asiohook: Adds asio reghook for later use 2020-04-05 01:44:41 -07:00
Will Xyen
0d3fa54316 launcher: Add before-hook support
Required to hook certain things that happen on module load / avs boot:
 - network adapter hooking for avs
 - envvar setting

Note: the logging facilities are NOT setup yet at this point
so these hooks cannot use avs for logging
2020-04-05 01:42:08 -07:00
6d16ce71d2cb7fb29ef6c9b6fd0f0943018cd3d0
e8943edff6 Add light support for SMX gen 4 pads
The old set lights API doesn't support gen 4 pads. Replace the call to SMX_SetLights with SMX_SetLights2 which adds support for gen 4 pads while maintaining backwards compatibility.
2020-03-22 21:18:38 +01:00
Will Xyen
61f3eb44d2 hooklib: fix warning in adapter.c 2020-02-05 01:26:41 -05:00
icex2
5aa1e27a31 Bump version to 5.30 2020-02-01 11:15:51 +01:00
77 changed files with 1860 additions and 252 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:
- build
- test
- release
- create-release-package
- releasetag
build:
stage: build
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:
- make
- make build-docker
artifacts:
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
paths:
@@ -20,31 +28,17 @@ build:
refs:
- master
test:
allow_failure: true
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
create-release-package:
stage: create-release-package
variables:
GIT_STRATEGY: none
dependencies:
- build
before_script:
- apt-get update && apt-get -qq install zip > /dev/null
- apk update && apk add zip > /dev/null
script:
- mv build/bemanitools.zip ./bemanitools.zip
- mv build/docker/bemanitools.zip ./bemanitools.zip
- rm -r build
- find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete
- unzip bemanitools.zip
- rm bemanitools.zip
@@ -55,12 +49,12 @@ release:
only:
refs:
- master
releasetag:
stage: releasetag
dependencies: []
before_script:
- apt-get update && apt-get -qq install curl > /dev/null
- apk update && apk add curl > /dev/null
script:
- |
curl --silent --show-error \

View File

@@ -1,4 +1,19 @@
# 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
* SDVX: sdvxhook2 headphone force and cursor confining config options
* DDR: Add light support for SMX gen 4 pads
## 5.29
* SDVX: Add option for monitor rotation
* SDVX: Add option to allow overriding network adapter IP

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
#
depdir := $(BUILDDIR)/dep
objdir := $(BUILDDIR)/obj
bindir := $(BUILDDIR)/bin
builddir_docker := $(BUILDDIR)/docker
toolchain_32 := i686-w64-mingw32-
toolchain_64 := x86_64-w64-mingw32-
docker_container_name := "bemanitools-build"
docker_image_name := "bemanitools:build"
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
depdir := $(BUILDDIR)/dep
objdir := $(BUILDDIR)/obj
bindir := $(BUILDDIR)/bin
toolchain_32 := i686-w64-mingw32-
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.
@@ -33,6 +38,7 @@ ldflags := -Wl,--gc-sections -static-libgcc
all: build
.PHONY: \
build-docker \
clean \
code-format \
print-building \
@@ -74,6 +80,16 @@ run-tests:
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
#

View File

@@ -77,6 +77,7 @@ imps += avs avs-ea3
include src/main/aciodrv/Module.mk
include src/main/acioemu/Module.mk
include src/main/aciotest/Module.mk
include src/main/asio/Module.mk
include src/main/bio2emu/Module.mk
include src/main/bsthook/Module.mk
include src/main/bstio/Module.mk
@@ -88,6 +89,7 @@ include src/main/ddrhook/Module.mk
include src/main/ddrio/Module.mk
include src/main/ddrio-smx/Module.mk
include src/main/ddrio-mm/Module.mk
include src/main/dinput/Module.mk
include src/main/eamio/Module.mk
include src/main/eamio-icca/Module.mk
include src/main/eamiotest/Module.mk
@@ -181,6 +183,7 @@ $(zipdir)/tools.zip: \
$(V)zip -j $@ $^
$(zipdir)/tools-x64.zip: \
build/bin/indep-64/aciotest.exe \
build/bin/indep-64/eamiotest.exe \
build/bin/indep-64/iidxiotest.exe \
build/bin/indep-64/iidx-ezusb-exit-hook.dll \
@@ -189,10 +192,6 @@ $(zipdir)/tools-x64.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/src.zip: .git/HEAD $(zipdir)/
$(V)echo ... $@
$(V)git archive -o $@ HEAD
$(zipdir)/iidx-09-to-12.zip: \
build/bin/indep-32/iidxhook1.dll \
build/bin/indep-32/config.exe \
@@ -471,6 +470,22 @@ $(zipdir)/ddr-12-to-16.zip: \
$(V)echo ... $@
$(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: \
build/bin/avs2_1603-64/bsthook.dll \
build/bin/avs2_1603-64/launcher.exe \
@@ -523,6 +538,7 @@ $(BUILDDIR)/tests.zip: \
$(BUILDDIR)/bemanitools.zip: \
$(zipdir)/bst.zip \
$(zipdir)/ddr-12-to-16.zip \
$(zipdir)/ddr-16-x64.zip \
$(zipdir)/doc.zip \
$(zipdir)/iidx-09-to-12.zip \
$(zipdir)/iidx-13.zip \
@@ -535,7 +551,6 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-01.zip \
$(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \
$(zipdir)/src.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-cn.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
Version: 5.29</br>
Version: 5.32</br>
[Release history](CHANGELOG.md)
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).
# Development
## Building
See the [development document](doc/development).
## Architecture
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.
@@ -88,10 +91,6 @@ important aspects you should know before you get started with development.
## API
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
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.

View File

@@ -7,12 +7,18 @@ io.disable_bio2_emu=false
# Disables the poll limiter, warning very high CPU usage may arise
io.disable_poll_limiter=false
# Forces game to think headphones are attached
io.force_headphones=false
# Run the game in a framed window (requires windowed option)
gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Confine mouse coursor to window
gfx.confined=false
# Windowed width, -1 for default size
gfx.window_width=1080

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
```
## 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
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.

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
*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.
* 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.
* 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
IO board won't work (e.g. lights).

View File

@@ -61,14 +61,24 @@ SMX_EXTERN_C SMX_API void SMX_GetInfo(int pad, struct SMXInfo *info);
// Get a mask of the currently pressed panels.
SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// Update the lights. Both pads are always updated together. lightsData is a
// list of 8-bit RGB colors, one for each LED. Each panel has lights in the
// following order:
// (deprecated) Equivalent to SMX_SetLights2(lightsData, 864).
SMX_API void SMX_SetLights(const char lightData[864]);
// Update the lights. Both pads are always updated together. lightData is a list of 8-bit RGB
// colors, one for each LED.
//
// 0123
// 4567
// 89AB
// CDEF
// lightDataSize is the number of bytes in lightsData. This should be 1350 (2 pads * 9 panels *
// 25 lights * 3 RGB colors). For backwards-compatibility, this can also be 864.
//
// Each panel has lights in the following order:
//
// 00 01 02 03
// 16 17 18
// 04 05 06 07
// 19 20 21
// 08 09 10 11
// 22 23 24
// 12 13 14 15
//
// Panels are in the following order:
//
@@ -76,17 +86,17 @@ SMX_EXTERN_C SMX_API uint16_t SMX_GetInputState(int pad);
// 345 CDE
// 678 F01
//
// With 18 panels, 16 LEDs per panel and 3 bytes per LED, each light update has
// 864 bytes of data.
// With 18 panels, 25 LEDs per panel and 3 bytes per LED, each light update has 1350 bytes of data.
//
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a
// best effort will be made to send the most recent lights data available, but
// the panels won't update more quickly.
// Lights will update at up to 30 FPS. If lights data is sent more quickly, a best effort will be
// made to send the most recent lights data available, but the panels won't update more quickly.
//
// The panels will return to automatic lighting if no lights are received for a
// while, so applications controlling lights should send light updates
// continually, even if the lights aren't changing.
SMX_EXTERN_C SMX_API void SMX_SetLights(const char lightsData[864]);
// The panels will return to automatic lighting if no lights are received for a while, so applications
// controlling lights should send light updates continually, even if the lights aren't changing.
//
// For backwards compatibility, if lightDataSize is 864, the old 4x4-only order is used,
// which simply omits lights 16-24.
SMX_API void SMX_SetLights2(const char *lightData, int lightDataSize);
// By default, the panels light automatically when stepped on. If a lights
// command is sent by the application, this stops happening to allow the

View File

@@ -7,6 +7,7 @@ EXPORTS
SMX_GetInfo
SMX_GetInputState
SMX_SetLights
SMX_SetLights2
SMX_ReenableAutoLights
SMX_GetConfig
SMX_SetConfig

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 <stdlib.h>
#include "acio/hdxs.h"
#include "acio/icca.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_out kfca_poll_out;
struct ac_io_hdxs_output hdxs_output;
};
} 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_BEGIN_KEYPAD = 0x013A,
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 {

View File

@@ -19,6 +19,7 @@ static char aviodrv_device_node_products[16][4];
static bool aciodrv_device_init(void)
{
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 */
int read = 0;
@@ -27,17 +28,20 @@ static bool aciodrv_device_init(void)
return false;
}
read = aciodrv_port_read(init_seq, sizeof(init_seq));
} while (read == 0);
read = aciodrv_port_read(read_buff, sizeof(read_buff));
} while ((read <= 0) || (read_buff[0] != init_seq[0]));
if (read > 0) {
log_warning("Obtained SOF, clearing out buffer now");
/* empty buffer by reading all data */
while (read > 0) {
read = aciodrv_port_read(init_seq, sizeof(init_seq));
}
log_warning("Cleared buffer, init done");
return read == 0;
} else {
log_warning("Read failure when trying to clear device state");
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)
{
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(
(uint8_t *) msg,
offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes) <= 0) {
#ifdef AC_IO_MSG_LOG
log_info("Beginning send on %d: %04x (%d b)", msg->addr, msg->cmd.code, send_size);
#endif
if (aciodrv_device_send((uint8_t *) msg, send_size) <= 0) {
return false;
}
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) {
return false;
}

View File

@@ -1,5 +1,6 @@
#define LOG_MODULE "acioemu-hdxs"
#include "acio/hdxs.h"
#include "acio/acio.h"
#include "acioemu/emu.h"
@@ -18,12 +19,20 @@ static void ac_io_emu_hdxs_send_status(
const struct ac_io_message *req,
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(emu != NULL);
if (lights_dispatcher == NULL) {
log_warning("NULL lights_dispatcher, HDXS light output won't work");
}
hdxs->emu = emu;
hdxs->lights_dispatcher = lights_dispatcher;
}
void ac_io_emu_hdxs_dispatch_request(
@@ -51,9 +60,19 @@ void ac_io_emu_hdxs_dispatch_request(
case AC_IO_CMD_CLEAR:
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 0x112:
case 0x128:
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.flag = 0x00;
resp.cmd.version.major = 0x01;
resp.cmd.version.minor = 0x06;
resp.cmd.version.revision = 0x00;
resp.cmd.version.minor = 0x00;
resp.cmd.version.revision = 0x01;
memcpy(
resp.cmd.version.product_code,
"HDXS",
"HDXB",
sizeof(resp.cmd.version.product_code));
strncpy(resp.cmd.version.date, __DATE__, sizeof(resp.cmd.version.date));
strncpy(resp.cmd.version.time, __TIME__, sizeof(resp.cmd.version.time));

View File

@@ -5,12 +5,21 @@
#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 *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(
struct ac_io_emu_hdxs *hdxs, const struct ac_io_message *req);

View File

@@ -14,6 +14,7 @@
#include "bemanitools/eamio.h"
#include "util/crc.h"
#include "util/time.h"
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(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us);
uint64_t delay_us,
bool encrypted);
static void ac_io_emu_icca_send_empty(
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,
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(
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;
// queue must be started
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(
@@ -123,7 +140,7 @@ void ac_io_emu_icca_dispatch_request(
break;
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;
@@ -174,6 +191,7 @@ void ac_io_emu_icca_dispatch_request(
break;
}
case AC_IO_ICCA_CMD_POLL_ENCRYPTED:
case AC_IO_ICCA_CMD_POLL:
delay_us = time_get_elapsed_us(
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();
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;
case AC_IO_ICCA_CMD_POLL_FELICA:
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;
@@ -215,10 +246,27 @@ static void ac_io_emu_icca_cmd_send_version(
resp.cmd.seq_no = req->cmd.seq_no;
resp.cmd.nbytes = sizeof(resp.cmd.version);
resp.cmd.version.type = ac_io_u32(AC_IO_NODE_TYPE_ICCA);
resp.cmd.version.flag = 0x00;
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;
memcpy(
resp.cmd.version.product_code,
"ICCA",
@@ -261,7 +309,8 @@ static void ac_io_emu_icca_send_status(
static void ac_io_emu_icca_send_state(
struct ac_io_emu_icca *icca,
const struct ac_io_message *req,
uint64_t delay_us)
uint64_t delay_us,
bool encrypted)
{
struct ac_io_message resp;
struct ac_io_icca_state *body;
@@ -319,7 +368,10 @@ static void ac_io_emu_icca_send_state(
} else if (card_full_insert) {
body->status_code = AC_IO_ICCA_STATUS_GOT_UID;
} 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;
} else {
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;
}
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);
}
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"
enum ac_io_emu_icca_version {
v150 = 0x5,
v160 = 0x6,
v170 = 0x7,
};
struct ac_io_emu_icca {
struct ac_io_emu *emu;
uint8_t unit_no;
@@ -20,11 +26,19 @@ struct ac_io_emu_icca {
bool keypad_started;
bool polling_started;
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(
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(
struct ac_io_emu_icca *icca, const struct ac_io_message *req);

10
src/main/asio/Module.mk Normal file
View File

@@ -0,0 +1,10 @@
libs += asio
libs_asio := \
hook \
hooklib \
util \
src_asio := \
asio-reghook.c \
config-asio.c \

View File

@@ -0,0 +1,199 @@
#define LOG_MODULE "asio-reghook"
// clang-format off
// Don't format because the order is important here
#include <windows.h>
#include <initguid.h>
// clang-format on
#include <winreg.h>
#include <stdio.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "asio/asio-reghook.h"
#include "util/defs.h"
#include "util/log.h"
#include "util/str.h"
#include "util/time.h"
// MAXDRVNAMELEN
#define ASIO_NAME_STRING_SIZE 128
static char asio_expected_name[ASIO_NAME_STRING_SIZE] = "XONAR SOUND CARD(64)";
static char asio_target_name[ASIO_NAME_STRING_SIZE] = "XONAR SOUND CARD(64)";
static HKEY asio_root_key;
static HKEY asio_sub_key;
LSTATUS my_RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
LSTATUS my_RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName);
LSTATUS my_RegOpenKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult);
LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData);
LSTATUS my_RegCloseKey(HKEY hKey);
LSTATUS (*real_RegOpenKeyA)(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult);
LSTATUS (*real_RegEnumKeyA)
(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName);
LSTATUS (*real_RegOpenKeyExA)
(HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult);
LSTATUS (*real_RegQueryValueExA)
(HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData);
LSTATUS (*real_RegCloseKey)(HKEY hKey);
static const struct hook_symbol asio_reghook_advapi32_syms[] = {
{.name = "RegOpenKeyA",
.patch = my_RegOpenKeyA,
.link = (void **) &real_RegOpenKeyA},
{.name = "RegEnumKeyA",
.patch = my_RegEnumKeyA,
.link = (void **) &real_RegEnumKeyA},
{.name = "RegOpenKeyExA",
.patch = my_RegOpenKeyExA,
.link = (void **) &real_RegOpenKeyExA},
{.name = "RegQueryValueExA",
.patch = my_RegQueryValueExA,
.link = (void **) &real_RegQueryValueExA},
{.name = "RegCloseKey",
.patch = my_RegCloseKey,
.link = (void **) &real_RegCloseKey},
};
LSTATUS my_RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
{
LSTATUS result = real_RegOpenKeyA(hKey, lpSubKey, phkResult);
if (!strcmp("software\\asio", lpSubKey)) {
log_info("ASIO root key found");
asio_root_key = *phkResult;
}
return result;
}
LSTATUS my_RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cchName)
{
LSTATUS result = real_RegEnumKeyA(hKey, dwIndex, lpName, cchName);
if (hKey == asio_root_key) {
if (!strcmp(asio_target_name, lpName)) {
log_info(
"Replacing key [%s] with [%s]",
asio_target_name,
asio_expected_name);
strncpy(lpName, asio_expected_name, cchName);
}
}
return result;
}
LSTATUS my_RegOpenKeyExA(
HKEY hKey,
LPCSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult)
{
if (hKey == asio_root_key) {
if (!strcmp(asio_expected_name, lpSubKey)) {
// swap to the real one so the call succeeds
LSTATUS result = real_RegOpenKeyExA(
hKey, asio_target_name, ulOptions, samDesired, phkResult);
asio_sub_key = *phkResult;
log_info("ASIO device key found");
return result;
}
}
return real_RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult);
}
LSTATUS my_RegQueryValueExA(
HKEY hKey,
LPCSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData)
{
DWORD lpcbData_orig = *lpcbData;
LSTATUS result = real_RegQueryValueExA(
hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
if (result == ERROR_SUCCESS) {
if (hKey == asio_sub_key) {
if (!strcmp("description", lpValueName)) {
log_info(
"Replacing description [%s] with [%s]",
lpData,
asio_expected_name);
strncpy((char *) lpData, asio_expected_name, lpcbData_orig);
}
}
}
return result;
}
LSTATUS my_RegCloseKey(HKEY hKey)
{
if (hKey == asio_root_key) {
asio_root_key = NULL;
}
if (hKey == asio_sub_key) {
asio_sub_key = NULL;
}
return real_RegCloseKey(hKey);
}
void asio_reghook_init(const char *expected_name, const char *target_name)
{
strncpy(asio_expected_name, expected_name, ASIO_NAME_STRING_SIZE - 1);
strncpy(asio_target_name, target_name, ASIO_NAME_STRING_SIZE - 1);
asio_expected_name[ASIO_NAME_STRING_SIZE - 1] = '\0';
asio_target_name[ASIO_NAME_STRING_SIZE - 1] = '\0';
hook_table_apply(
NULL,
"Advapi32.dll",
asio_reghook_advapi32_syms,
lengthof(asio_reghook_advapi32_syms));
log_info("Inserted reg hooks for ASIO override");
}

View File

@@ -0,0 +1,6 @@
#ifndef IASIO_REG_HOOK_H
#define IASIO_REG_HOOK_H
void asio_reghook_init(const char *expected_name, const char *target_name);
#endif

View File

@@ -0,0 +1,56 @@
#include "cconfig/cconfig-util.h"
#include "asio/config-asio.h"
#include "util/log.h"
#define ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY "asio.force_asio"
#define ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY "asio.device_name"
#define ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE false
#define ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE \
"XONAR SOUND CARD(64)"
void asiohook_config_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE,
"Force ASIO audio mode/device");
cconfig_util_set_str(
config,
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE,
"The ASIO device name to use");
}
void asiohook_config_asio_get(
struct asiohook_config_asio *config_asio, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
&config_asio->force_asio,
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
ASIOHOOK_CONFIG_IO_FORCE_ASIO_KEY,
ASIOHOOK_CONFIG_IO_DEFAULT_FORCE_ASIO_VALUE);
}
if (!cconfig_util_get_str(
config,
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
config_asio->replacement_name,
sizeof(config_asio->replacement_name) - 1,
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
ASIOHOOK_CONFIG_IO_ASIO_DEVICE_NAME_KEY,
ASIOHOOK_CONFIG_IO_DEFAULT_ASIO_DEVICE_NAME_VALUE);
}
}

View File

@@ -0,0 +1,18 @@
#ifndef ASIOHOOK_CONFIG_IO_H
#define ASIOHOOK_CONFIG_IO_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct asiohook_config_asio {
bool force_asio;
char replacement_name[128];
};
void asiohook_config_init(struct cconfig *config);
void asiohook_config_asio_get(
struct asiohook_config_asio *config_asio, struct cconfig *config);
#endif

View File

@@ -32,8 +32,7 @@ enum ddr_pad_bit {
DDR_P1_MENU_DOWN = 0x01,
};
/* p3io controls menu btn and marquee lights
extio controls neons and stage lights. */
// see the functions below for more information
enum p3io_light_bit {
LIGHT_P1_MENU = 0x00,
@@ -41,7 +40,32 @@ enum p3io_light_bit {
LIGHT_P2_LOWER_LAMP = 0x04,
LIGHT_P2_UPPER_LAMP = 0x05,
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 {
@@ -81,9 +105,26 @@ bool ddr_io_init(
thread_join_t thread_join,
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);
/* 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);
/* used to set SD panel lights, and HD spot 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);
#endif

View File

@@ -256,13 +256,33 @@ STRINGTABLE
IDS_DDR_P2_DOWN "P2 Down"
IDS_DDR_P2_LEFT "P2 Left"
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_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_BOTTOM_LIGHT "P2 Marquee Bottom Light"
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_BTN1 "Button 1"
IDS_PNM_BTN2 "Button 2"
@@ -273,6 +293,15 @@ STRINGTABLE
IDS_PNM_BTN7 "Button 7"
IDS_PNM_BTN8 "Button 8"
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_PANEL1 "Panel 1"
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_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)) {
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_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));

View File

@@ -243,3 +243,32 @@
#define IDS_IIDX_PANEL_S3 40200
#define IDS_IIDX_PANEL_S4 40201
#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"
static const struct action_def dm_actions[] = {{0x01, IDS_GENERIC_TEST},
{0x00, IDS_GENERIC_SERVICE},
static const struct action_def dm_actions[] = {
{0x01, IDS_GENERIC_TEST},
{0x00, IDS_GENERIC_SERVICE},
{0x08, IDS_DM_START},
{0x0F, IDS_DM_MENU_LEFT},
{0x11, IDS_DM_MENU_RIGHT},
{0x08, IDS_DM_START},
{0x0F, IDS_DM_MENU_LEFT},
{0x11, IDS_DM_MENU_RIGHT},
{0x0A, IDS_DM_HI_HAT},
{0x0C, IDS_DM_SNARE},
{0x0E, IDS_DM_HIGH_TOM},
{0x10, IDS_DM_LOW_TOM},
{0x12, IDS_DM_CYMBAL},
{0x16, IDS_DM_BASS}};
{0x0A, IDS_DM_HI_HAT},
{0x0C, IDS_DM_SNARE},
{0x0E, IDS_DM_HIGH_TOM},
{0x10, IDS_DM_LOW_TOM},
{0x12, IDS_DM_CYMBAL},
{0x16, IDS_DM_BASS}};
static const struct light_def dm_lights[] = {{0x00, IDS_DM_HI_HAT},
{0x01, IDS_DM_SNARE},
{0x02, IDS_DM_HIGH_TOM},
{0x03, IDS_DM_LOW_TOM},
{0x04, IDS_DM_CYMBAL},
{0x09, IDS_DM_BASS},
{0x0A, IDS_DM_SPEAKER_LIGHT},
{0x08, IDS_DM_SPOT_LIGHT},
{0x06, IDS_DM_START_LIGHT},
{0x07, IDS_DM_MENU_LIGHT}};
static const struct light_def dm_lights[] = {
{0x00, IDS_DM_HI_HAT},
{0x01, IDS_DM_SNARE},
{0x02, IDS_DM_HIGH_TOM},
{0x03, IDS_DM_LOW_TOM},
{0x04, IDS_DM_CYMBAL},
{0x09, IDS_DM_BASS},
{0x0A, IDS_DM_SPEAKER_LIGHT},
{0x08, IDS_DM_SPOT_LIGHT},
{0x06, IDS_DM_START_LIGHT},
{0x07, IDS_DM_MENU_LIGHT}};
static const struct action_def gf_actions[] = {
{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},
{0x17, IDS_GF_P2_BLUE}};
static const struct light_def gf_lights[] = {{0x08, IDS_GF_P1_SPOT_LIGHT},
{0x09, IDS_GF_P2_SPOT_LIGHT},
{0x0A, IDS_GF_P1_START},
{0x0B, IDS_GF_P2_START}};
static const struct light_def gf_lights[] = {
{0x08, IDS_GF_P1_SPOT_LIGHT},
{0x09, IDS_GF_P2_SPOT_LIGHT},
{0x0A, IDS_GF_P1_START},
{0x0B, IDS_GF_P2_START}};
static const struct action_def iidx_actions[] = {
{0x1C, IDS_GENERIC_TEST}, {0x1D, IDS_GENERIC_SERVICE},
@@ -101,8 +104,8 @@ static const struct light_def iidx_lights[] = {
{0x1F, IDS_IIDX_NEON_LIGHT}};
static const struct analog_def iidx_analogs[] = {{0, IDS_IIDX_P1_TT},
{1, IDS_IIDX_P2_TT}};
static const struct analog_def iidx_analogs[] = {
{0, IDS_IIDX_P1_TT}, {1, IDS_IIDX_P2_TT}};
static const struct action_def ddr_actions[] = {
{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[] = {
/* These are split between non-overlapping P3IO and EXTIO state words */
// P3IO: SD
{0x00, IDS_DDR_P1_MENU_LIGHT},
{0x07, IDS_DDR_P1_TOP_LIGHT},
{0x07, 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},
{0x06, IDS_DDR_P1_BOTTOM_LIGHT},
{0x01, IDS_DDR_P2_MENU_LIGHT},
{0x05, IDS_DDR_P2_TOP_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},
{0x15, IDS_DDR_P2_DOWN},
{0x14, IDS_DDR_P2_LEFT},
@@ -142,18 +174,19 @@ static const struct light_def ddr_lights[] = {
{0x0E, IDS_DDR_BASS_LIGHT}};
static const struct action_def pnm_actions[] = {{0x07, IDS_GENERIC_TEST},
{0x06, IDS_GENERIC_SERVICE},
static const struct action_def pnm_actions[] = {
{0x07, IDS_GENERIC_TEST},
{0x06, IDS_GENERIC_SERVICE},
{0x08, IDS_PNM_BTN1},
{0x09, IDS_PNM_BTN2},
{0x0A, IDS_PNM_BTN3},
{0x0B, IDS_PNM_BTN4},
{0x0C, IDS_PNM_BTN5},
{0x0D, IDS_PNM_BTN6},
{0x0E, IDS_PNM_BTN7},
{0x0F, IDS_PNM_BTN8},
{0x10, IDS_PNM_BTN9}};
{0x08, IDS_PNM_BTN1},
{0x09, IDS_PNM_BTN2},
{0x0A, IDS_PNM_BTN3},
{0x0B, IDS_PNM_BTN4},
{0x0C, IDS_PNM_BTN5},
{0x0D, IDS_PNM_BTN6},
{0x0E, IDS_PNM_BTN7},
{0x0F, IDS_PNM_BTN8},
{0x10, IDS_PNM_BTN9}};
static const struct light_def pnm_lights[] = {
{0x17, IDS_PNM_BTN1},
@@ -165,27 +198,37 @@ static const struct light_def pnm_lights[] = {
{0x1D, IDS_PNM_BTN7},
{0x1E, IDS_PNM_BTN8},
{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},
{0x11, IDS_GENERIC_SERVICE},
static const struct action_def jb_actions[] = {
{0x10, IDS_GENERIC_TEST},
{0x11, IDS_GENERIC_SERVICE},
{0x00, IDS_JB_PANEL1},
{0x01, IDS_JB_PANEL2},
{0x02, IDS_JB_PANEL3},
{0x03, IDS_JB_PANEL4},
{0x04, IDS_JB_PANEL5},
{0x05, IDS_JB_PANEL6},
{0x06, IDS_JB_PANEL7},
{0x07, IDS_JB_PANEL8},
{0x08, IDS_JB_PANEL9},
{0x09, IDS_JB_PANEL10},
{0x0A, IDS_JB_PANEL11},
{0x0B, IDS_JB_PANEL12},
{0x0C, IDS_JB_PANEL13},
{0x0D, IDS_JB_PANEL14},
{0x0E, IDS_JB_PANEL15},
{0x0F, IDS_JB_PANEL16}};
{0x00, IDS_JB_PANEL1},
{0x01, IDS_JB_PANEL2},
{0x02, IDS_JB_PANEL3},
{0x03, IDS_JB_PANEL4},
{0x04, IDS_JB_PANEL5},
{0x05, IDS_JB_PANEL6},
{0x06, IDS_JB_PANEL7},
{0x07, IDS_JB_PANEL8},
{0x08, IDS_JB_PANEL9},
{0x09, IDS_JB_PANEL10},
{0x0A, IDS_JB_PANEL11},
{0x0B, IDS_JB_PANEL12},
{0x0C, IDS_JB_PANEL13},
{0x0D, IDS_JB_PANEL14},
{0x0E, IDS_JB_PANEL15},
{0x0F, IDS_JB_PANEL16}};
static const struct light_def jb_lights[] = {
{0x00, IDS_JB_RGB_FRONT_R},
@@ -208,15 +251,16 @@ static const struct light_def jb_lights[] = {
{0x11, IDS_JB_RGB_WOOFER_B},
};
static const struct action_def sdvx_actions[] = {{0x05, IDS_GENERIC_TEST},
{0x04, IDS_GENERIC_SERVICE},
{0x0B, IDS_SDVX_START},
{0x0A, IDS_SDVX_BTN_A},
{0x09, IDS_SDVX_BTN_B},
{0x08, IDS_SDVX_BTN_C},
{0x15, IDS_SDVX_BTN_D},
{0x14, IDS_SDVX_FX_L},
{0x13, IDS_SDVX_FX_R}};
static const struct action_def sdvx_actions[] = {
{0x05, IDS_GENERIC_TEST},
{0x04, IDS_GENERIC_SERVICE},
{0x0B, IDS_SDVX_START},
{0x0A, IDS_SDVX_BTN_A},
{0x09, IDS_SDVX_BTN_B},
{0x08, IDS_SDVX_BTN_C},
{0x15, IDS_SDVX_BTN_D},
{0x14, IDS_SDVX_FX_L},
{0x13, IDS_SDVX_FX_R}};
static const struct light_def sdvx_lights[] = {
{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},
{0x21, IDS_SDVX_RGB6_B}};
static const struct analog_def sdvx_analogs[] = {{0, IDS_SDVX_VOL_L},
{1, IDS_SDVX_VOL_R}};
static const struct analog_def sdvx_analogs[] = {
{0, IDS_SDVX_VOL_L}, {1, IDS_SDVX_VOL_R}};
static const struct action_def rb_actions[] = {{0x00, IDS_GENERIC_TEST},
{0x01, IDS_GENERIC_SERVICE}};
static const struct action_def rb_actions[] = {
{0x00, IDS_GENERIC_TEST}, {0x01, IDS_GENERIC_SERVICE}};
static const struct action_def bst_actions[] = {
{0x05, IDS_GENERIC_TEST},
{0x04, IDS_GENERIC_SERVICE},
};
static const struct eam_unit_def schema_eam_unit_defs[] = {{IDS_READER_P1, 0},
{IDS_READER_P2, 1}};
static const struct eam_unit_def schema_eam_unit_defs[] = {
{IDS_READER_P1, 0}, {IDS_READER_P2, 1}};
const struct schema schemas[] = {
{"iidx",

View File

@@ -10,6 +10,7 @@
#define D3D9EXHOOK_CONFIG_GFX_FRAMED_KEY "gfx.framed"
#define D3D9EXHOOK_CONFIG_GFX_WINDOWED_KEY "gfx.windowed"
#define D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY "gfx.confined"
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY "gfx.window_width"
#define D3D9EXHOOK_CONFIG_GFX_WINDOW_HEIGHT_KEY "gfx.window_height"
#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
@@ -18,6 +19,7 @@
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE false
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_WIDTH_VALUE -1
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOW_HEIGHT_VALUE -1
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
@@ -38,6 +40,12 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE,
"Run the game windowed");
cconfig_util_set_bool(
config,
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE,
"Confine mouse coursor to window");
cconfig_util_set_int(
config,
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,
@@ -99,6 +107,18 @@ void d3d9exhook_config_gfx_get(
D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE);
}
if (!cconfig_util_get_bool(
config,
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
&config_gfx->confined,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY,
D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE);
}
if (!cconfig_util_get_int(
config,
D3D9EXHOOK_CONFIG_GFX_WINDOW_WIDTH_KEY,

View File

@@ -12,6 +12,7 @@
struct d3d9exhook_config_gfx {
bool framed;
bool windowed;
bool confined;
int32_t window_width;
int32_t window_height;
int32_t forced_refresh_rate;

View File

@@ -47,6 +47,8 @@ static HRESULT STDCALL my_CreateDeviceEx(
static HRESULT STDCALL my_Direct3DCreate9Ex(UINT sdk_ver, IDirect3D9Ex **api);
static WNDPROC real_WndProc;
static BOOL STDCALL my_EnumDisplayDevicesA(
const char *dev_name, DWORD dev_num, DISPLAY_DEVICEA *info, DWORD flags);
@@ -82,6 +84,7 @@ static BOOL(STDCALL *real_MoveWindow)(
/* ------------------------------------------------------------------------- */
static bool d3d9ex_windowed;
static bool d3d9ex_confined;
static int32_t d3d9ex_force_refresh_rate = -1;
static int32_t d3d9ex_window_width = -1;
static int32_t d3d9ex_window_height = -1;
@@ -183,6 +186,52 @@ my_MoveWindow(HWND hWnd, int X, int Y, int nWidth, int nHeight, BOOL bRepaint)
return result;
}
static LRESULT gfx_confine(HWND hwnd)
{
POINT p;
RECT r;
log_misc("Confining mouse (ALT-TAB to release)");
p.x = 0;
p.y = 0;
ClientToScreen(hwnd, &p);
r.left = p.x;
r.top = p.y;
r.right = p.x + 100;
r.bottom = p.y + 100;
ClipCursor(&r);
return TRUE;
}
static LRESULT gfx_unconfine(HWND hwnd)
{
log_misc("Un-confining mouse");
ClipCursor(NULL);
return TRUE;
}
static LRESULT CALLBACK
my_WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) {
case WM_SETFOCUS:
return gfx_confine(hwnd);
case WM_KILLFOCUS:
return gfx_unconfine(hwnd);
default:
return CallWindowProc(real_WndProc, hwnd, msg, wparam, lparam);
}
}
static HRESULT STDCALL my_CreateDeviceEx(
IDirect3D9Ex *self,
UINT adapter,
@@ -268,6 +317,12 @@ static HRESULT STDCALL my_CreateDeviceEx(
hr = IDirect3D9Ex_CreateDeviceEx(
real, adapter, type, hwnd, flags, pp, fdm, pdev);
if (SUCCEEDED(hr) && d3d9ex_confined) {
real_WndProc = (void *) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (uintptr_t) my_WndProc);
}
return hr;
}
@@ -319,6 +374,7 @@ void d3d9ex_hook_init(void)
void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config)
{
d3d9ex_windowed = gfx_config->windowed;
d3d9ex_confined = gfx_config->confined;
d3d9ex_window_framed = gfx_config->framed;
d3d9ex_window_width = gfx_config->window_width;
d3d9ex_window_height = gfx_config->window_height;

View File

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

View File

@@ -11,10 +11,14 @@
#include <string.h>
#include <wchar.h>
#include "acio/hdxs.h"
#include "acioemu/addr.h"
#include "acioemu/hdxs.h"
#include "acioemu/icca.h"
#include "bemanitools/ddrio.h"
#include "ddrhook/_com4.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_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)
{
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_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++) {
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 _15khz;
static const irp_handler_t ddrhook_handlers[] = {
static const irp_handler_t ddrhook_com4_handlers[] = {
p3io_emu_dispatch_irp,
extio_dispatch_irp,
spike_dispatch_irp,
@@ -40,15 +40,27 @@ static const irp_handler_t ddrhook_handlers[] = {
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)
{
int argc;
char **argv;
bool com4;
bool ok;
int i;
log_info("--- Begin ddrhook dll_entry_init ---");
com4 = true;
args_recover(&argc, &argv);
for (i = 1; i < argc; i++) {
@@ -65,13 +77,25 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
case 'w':
gfx_set_windowed();
break;
case 'u':
/* Don't emulate P3IO COM4 and its downstream devices, use the
Windows COM4 port instead. */
com4 = false;
break;
}
}
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();
master_insert_hooks(NULL);
@@ -92,15 +116,17 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
return false;
}
log_info("Initializing card reader backend");
if (com4) {
log_info("Initializing card reader backend");
eam_io_set_loggers(
log_body_misc, log_body_info, log_body_warning, log_body_fatal);
eam_io_set_loggers(
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) {
return false;
if (!ok) {
return false;
}
}
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)
{
/* 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);
}

View File

@@ -7,3 +7,5 @@ EXPORTS
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

View File

@@ -207,6 +207,21 @@ void ddr_io_set_lights_p3io(uint32_t p3io_lights)
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)
{
if (initted) {

View File

@@ -7,3 +7,5 @@ EXPORTS
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

View File

@@ -41,24 +41,28 @@ static const struct ddr_io_smx_pad_map ddr_io_smx_pad_map[] = {
{1, 1 << 7, 1 << DDR_P2_DOWN},
};
#define DDR_IO_SMX_LIGHT_VALUES_PER_PANEL 75
#define DDR_IO_SMX_NUMBER_OF_PANELS 18
#define DDR_IO_SMX_TOTAL_LIGHT_VALUES DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * DDR_IO_SMX_NUMBER_OF_PANELS
static const struct ddr_io_smx_light_map ddr_io_smx_light_map[] = {
/* Light L/R blue and U/D red to match DDR pad color scheme */
{1 << LIGHT_P1_UP, 48 * 1, 0xFF, 0x00, 0x00},
{1 << LIGHT_P1_LEFT, 48 * 3, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_RIGHT, 48 * 5, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_DOWN, 48 * 7, 0xFF, 0x00, 0x00},
{1 << LIGHT_P1_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 1, 0xFF, 0x00, 0x00},
{1 << LIGHT_P1_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 3, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 5, 0x00, 0x00, 0xFF},
{1 << LIGHT_P1_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 7, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_UP, 48 * 10, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_LEFT, 48 * 12, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_RIGHT, 48 * 14, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_DOWN, 48 * 16, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_UP, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 10, 0xFF, 0x00, 0x00},
{1 << LIGHT_P2_LEFT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 12, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_RIGHT, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 14, 0x00, 0x00, 0xFF},
{1 << LIGHT_P2_DOWN, DDR_IO_SMX_LIGHT_VALUES_PER_PANEL * 16, 0xFF, 0x00, 0x00},
};
static _Atomic uint32_t ddr_io_smx_pad_state[2];
static CRITICAL_SECTION ddr_io_smx_lights_lock;
static uint8_t ddr_io_smx_lights_counter;
static char ddr_io_smx_lights[864];
static char ddr_io_smx_lights[DDR_IO_SMX_TOTAL_LIGHT_VALUES];
void ddr_io_set_loggers(
log_formatter_t misc,
@@ -109,7 +113,7 @@ uint32_t ddr_io_read_pad(void)
EnterCriticalSection(&ddr_io_smx_lights_lock);
if (ddr_io_smx_lights_counter == 0) {
SMX_SetLights(ddr_io_smx_lights);
SMX_SetLights2(ddr_io_smx_lights, lengthof(ddr_io_smx_lights));
}
ddr_io_smx_lights_counter++;
@@ -149,7 +153,7 @@ void ddr_io_set_lights_extio(uint32_t lights)
if (lights & map->extio_bit) {
offset = map->smx_light_offset;
for (j = 0; j < 48; j += 3) {
for (j = 0; j < DDR_IO_SMX_LIGHT_VALUES_PER_PANEL; j += 3) {
ddr_io_smx_lights[offset + j] = map->r;
ddr_io_smx_lights[offset + j + 1] = map->g;
ddr_io_smx_lights[offset + j + 2] = map->b;
@@ -164,11 +168,30 @@ void ddr_io_set_lights_p3io(uint32_t lights)
{
uint8_t i;
for (i = 0x0E; i <= 0x1E; i++) {
for (i = 0x00; i <= 0x07; i++) {
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)
{
log_info("Stopping SMX.DLL");

View File

@@ -43,7 +43,7 @@ void ddr_io_set_lights_extio(uint32_t lights)
{
uint8_t i;
for (i = 0x00; i <= 0x07; i++) {
for (i = 0x0E; i <= 0x1E; i++) {
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;
for (i = 0x0E; i <= 0x1E; i++) {
for (i = 0x00; i <= 0x07; i++) {
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)
{
input_fini();

View File

@@ -7,3 +7,5 @@ EXPORTS
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

10
src/main/dinput/Module.mk Normal file
View File

@@ -0,0 +1,10 @@
libs += dinput
libs_dinput := \
hook \
hooklib \
util \
src_dinput := \
dinput.c \
device_dinput8.c \

View File

@@ -0,0 +1,307 @@
#include "dinput/device_dinput8.h"
static ULONG REF_COUNT = 0;
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_QueryInterface(
IDirectInputDevice8W FAR *This, REFIID riid, void **ppvObj)
{
if (ppvObj == NULL) {
return E_POINTER;
}
if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectInputDeviceA) ||
IsEqualGUID(riid, &IID_IDirectInputDeviceW) ||
IsEqualGUID(riid, &IID_IDirectInputDevice2A) ||
IsEqualGUID(riid, &IID_IDirectInputDevice2W) ||
IsEqualGUID(riid, &IID_IDirectInputDevice7A) ||
IsEqualGUID(riid, &IID_IDirectInputDevice7W) ||
IsEqualGUID(riid, &IID_IDirectInputDevice8A) ||
IsEqualGUID(riid, &IID_IDirectInputDevice8W)) {
This->lpVtbl->AddRef(This);
*ppvObj = This;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG STDMETHODCALLTYPE
IDirectInputDevice8W_AddRef(IDirectInputDevice8W FAR *This)
{
return ++REF_COUNT;
}
static ULONG STDMETHODCALLTYPE
IDirectInputDevice8W_Release(IDirectInputDevice8W FAR *This)
{
return --REF_COUNT;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetCapabilities(
IDirectInputDevice8W FAR *This, LPDIDEVCAPS lpDIDevCaps)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumObjects(
IDirectInputDevice8W FAR *This,
LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetProperty(
IDirectInputDevice8W FAR *This, REFGUID rguidProp, LPDIPROPHEADER pdiph)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetProperty(
IDirectInputDevice8W FAR *This, REFGUID rguidProp, LPCDIPROPHEADER pdiph)
{
return DI_OK;
}
static HRESULT STDMETHODCALLTYPE
IDirectInputDevice8W_Acquire(IDirectInputDevice8W FAR *This)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE
IDirectInputDevice8W_Unacquire(IDirectInputDevice8W FAR *This)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceState(
IDirectInputDevice8W FAR *This, DWORD cbData, LPVOID lpvData)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceData(
IDirectInputDevice8W FAR *This,
DWORD cbObjectData,
LPDIDEVICEOBJECTDATA rgdod,
LPDWORD pdwInOut,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetDataFormat(
IDirectInputDevice8W FAR *This, LPCDIDATAFORMAT lpdf)
{
return DI_OK;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetEventNotification(
IDirectInputDevice8W FAR *This, HANDLE hEvent)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetCooperativeLevel(
IDirectInputDevice8W FAR *This, HWND hWnd, DWORD dwFlags)
{
return DI_OK;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetObjectInfo(
IDirectInputDevice8W FAR *This,
LPDIDEVICEOBJECTINSTANCEW pdidoi,
DWORD dwObj,
DWORD dwHow)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetDeviceInfo(
IDirectInputDevice8W FAR *This, LPDIDEVICEINSTANCEW pdidi)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_RunControlPanel(
IDirectInputDevice8W FAR *This, HWND hwndOwner, DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_Initialize(
IDirectInputDevice8W FAR *This,
HINSTANCE hinst,
DWORD dwVersion,
REFGUID rguid)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_CreateEffect(
IDirectInputDevice8W FAR *This,
REFGUID rguid,
LPCDIEFFECT lpeff,
LPDIRECTINPUTEFFECT *ppdeff,
LPUNKNOWN punkOuter)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumEffects(
IDirectInputDevice8W FAR *This,
LPDIENUMEFFECTSCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwEffType)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetEffectInfo(
IDirectInputDevice8W FAR *This, LPDIEFFECTINFOW pdei, REFGUID rguid)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetForceFeedbackState(
IDirectInputDevice8W FAR *This, LPDWORD pdwOut)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SendForceFeedbackCommand(
IDirectInputDevice8W FAR *This, DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumCreatedEffectObjects(
IDirectInputDevice8W FAR *This,
LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
LPVOID pvRef,
DWORD fl)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE
IDirectInputDevice8W_Escape(IDirectInputDevice8W FAR *This, LPDIEFFESCAPE pesc)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE
IDirectInputDevice8W_Poll(IDirectInputDevice8W FAR *This)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SendDeviceData(
IDirectInputDevice8W FAR *This,
DWORD cbObjectData,
LPCDIDEVICEOBJECTDATA rgdod,
LPDWORD pdwInOut,
DWORD fl)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_EnumEffectsInFile(
IDirectInputDevice8W FAR *This,
LPCWSTR lpszFileName,
LPDIENUMEFFECTSINFILECALLBACK pec,
LPVOID pvRef,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_WriteEffectToFile(
IDirectInputDevice8W FAR *This,
LPCWSTR lpszFileName,
DWORD dwEntries,
LPDIFILEEFFECT rgDiFileEft,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_BuildActionMap(
IDirectInputDevice8W FAR *This,
LPDIACTIONFORMATW lpdiaf,
LPCWSTR lpszUserName,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_SetActionMap(
IDirectInputDevice8W FAR *This,
LPDIACTIONFORMATW lpdiaf,
LPCWSTR lpszUserName,
DWORD dwFlags)
{
return DIERR_INVALIDPARAM;
}
static HRESULT STDMETHODCALLTYPE IDirectInputDevice8W_GetImageInfo(
IDirectInputDevice8W FAR *This,
LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
{
return DIERR_INVALIDPARAM;
}
static IDirectInputDevice8WVtbl stub_device_vtbl = {
// IUnknown
.QueryInterface = IDirectInputDevice8W_QueryInterface,
.AddRef = IDirectInputDevice8W_AddRef,
.Release = IDirectInputDevice8W_Release,
// IDirectInputDeviceW
.GetCapabilities = IDirectInputDevice8W_GetCapabilities,
.EnumObjects = IDirectInputDevice8W_EnumObjects,
.GetProperty = IDirectInputDevice8W_GetProperty,
.SetProperty = IDirectInputDevice8W_SetProperty,
.Acquire = IDirectInputDevice8W_Acquire,
.Unacquire = IDirectInputDevice8W_Unacquire,
.GetDeviceState = IDirectInputDevice8W_GetDeviceState,
.GetDeviceData = IDirectInputDevice8W_GetDeviceData,
.SetDataFormat = IDirectInputDevice8W_SetDataFormat,
.SetEventNotification = IDirectInputDevice8W_SetEventNotification,
.SetCooperativeLevel = IDirectInputDevice8W_SetCooperativeLevel,
.GetObjectInfo = IDirectInputDevice8W_GetObjectInfo,
.GetDeviceInfo = IDirectInputDevice8W_GetDeviceInfo,
.RunControlPanel = IDirectInputDevice8W_RunControlPanel,
.Initialize = IDirectInputDevice8W_Initialize,
// IDirectInputDevice2W
.CreateEffect = IDirectInputDevice8W_CreateEffect,
.EnumEffects = IDirectInputDevice8W_EnumEffects,
.GetEffectInfo = IDirectInputDevice8W_GetEffectInfo,
.GetForceFeedbackState = IDirectInputDevice8W_GetForceFeedbackState,
.SendForceFeedbackCommand = IDirectInputDevice8W_SendForceFeedbackCommand,
.EnumCreatedEffectObjects = IDirectInputDevice8W_EnumCreatedEffectObjects,
.Escape = IDirectInputDevice8W_Escape,
.Poll = IDirectInputDevice8W_Poll,
.SendDeviceData = IDirectInputDevice8W_SendDeviceData,
// IDirectInputDevice7W
.EnumEffectsInFile = IDirectInputDevice8W_EnumEffectsInFile,
.WriteEffectToFile = IDirectInputDevice8W_WriteEffectToFile,
// IDirectInputDevice8W
.BuildActionMap = IDirectInputDevice8W_BuildActionMap,
.SetActionMap = IDirectInputDevice8W_SetActionMap,
.GetImageInfo = IDirectInputDevice8W_GetImageInfo,
};
static IDirectInputDevice8W stub_device_object = {
.lpVtbl = &stub_device_vtbl,
};
IDirectInputDevice8W *di8_stub_device = &stub_device_object;

View File

@@ -0,0 +1,10 @@
#ifndef DINPUTHOOK_DEVICES_DINPUT8_H
#define DINPUTHOOK_DEVICES_DINPUT8_H
#include <initguid.h>
#include <dinput.h>
extern IDirectInputDevice8W *di8_stub_device;
#endif

114
src/main/dinput/dinput.c Normal file
View File

@@ -0,0 +1,114 @@
#include <windows.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include "dinput/device_dinput8.h"
#include "dinput/dinput.h"
#include <stdbool.h>
#include "hook/com-proxy.h"
#include "hook/pe.h"
#include "hook/table.h"
#include "util/defs.h"
#include "util/log.h"
static HRESULT STDCALL my_DirectInput8Create(
HINSTANCE hinst,
DWORD dwVersion,
REFIID riidltf,
LPVOID *ppvOut,
LPVOID punkOuter);
static HRESULT(STDCALL *real_DirectInput8Create)(
HINSTANCE hinst,
DWORD dwVersion,
REFIID riidltf,
LPVOID *ppvOut,
LPVOID punkOuter);
static const struct hook_symbol dinput_syms[] = {
{
.name = "DirectInput8Create",
.patch = my_DirectInput8Create,
.link = (void **) &real_DirectInput8Create,
},
};
static HRESULT STDCALL my_CreateDevice(
IDirectInput8W *self,
REFGUID rguid,
LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice,
LPUNKNOWN pUnkOuter)
{
log_misc("IDirectInput8::CreateDevice hook hit");
if (lplpDirectInputDevice == NULL) {
return DIERR_INVALIDPARAM;
}
if (IsEqualGUID(rguid, &GUID_SysKeyboard) ||
IsEqualGUID(rguid, &GUID_SysMouse)) {
log_misc("Returning stub device");
*lplpDirectInputDevice = di8_stub_device;
di8_stub_device->lpVtbl->AddRef(di8_stub_device);
return DI_OK;
}
return DIERR_NOINTERFACE;
}
static HRESULT STDCALL my_EnumDevices(
IDirectInput8W *self,
DWORD dwDevType,
LPDIENUMDEVICESCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwFlags)
{
log_misc("IDirectInput8::EnumDevices hook hit");
return DI_OK;
}
static HRESULT STDCALL my_DirectInput8Create(
HINSTANCE hinst,
DWORD dwVersion,
REFIID riidltf,
LPVOID *ppvOut,
LPVOID punkOuter)
{
IDirectInput8W *api;
IDirectInput8WVtbl *api_vtbl;
struct com_proxy *api_proxy;
HRESULT res;
log_info("DirectInput8Create hook hit");
res = real_DirectInput8Create(
hinst, dwVersion, riidltf, (LPVOID *) &api, punkOuter);
if (res != DI_OK) {
return res;
}
api_proxy = com_proxy_wrap(api, sizeof(*api->lpVtbl));
api_vtbl = api_proxy->vptr;
api_vtbl->EnumDevices = my_EnumDevices;
api_vtbl->CreateDevice = my_CreateDevice;
*(IDirectInput8W **) ppvOut = (IDirectInput8W *) api_proxy;
return res;
}
void dinput_init(void)
{
hook_table_apply(NULL, "dinput8.dll", dinput_syms, lengthof(dinput_syms));
log_info("Inserted dinput hooks");
}

10
src/main/dinput/dinput.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef DINPUTHOOK_DINPUT_H
#define DINPUTHOOK_DINPUT_H
#include <windows.h>
// This is to stub out the dinput device
// Such that rawinput can still poll keyboards
void dinput_init(void);
#endif

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 */
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);
return S_OK;

View File

@@ -59,7 +59,9 @@ struct ezusb_iidx_msg_interrupt_read_packet {
1: Not used
2: 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
6: usb mute?
7: Not used

View File

@@ -36,6 +36,8 @@ EXPORTS
mapper_get_analog_map
mapper_get_analog_sensitivity
mapper_get_npages
mapper_get_nanalogs
mapper_get_nlights
mapper_is_analog_absolute
mapper_iterate_lights
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);
int32_t mapper_get_analog_sensitivity(uint8_t analog);
uint8_t mapper_get_nanalogs(void);
uint8_t mapper_get_nlights(void);
uint8_t mapper_get_npages(void);
bool mapper_is_analog_absolute(uint8_t analog);
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);
}
uint8_t mapper_get_nlights(void)
{
return mapper_impl_get_nlights(mapper_inst);
}
uint8_t mapper_get_npages(void)
{
return mapper_impl_get_npages(mapper_inst);

View File

@@ -124,7 +124,7 @@ void adapter_hook_override(const char *adapter_address)
// but in case it gets called multiple times, set it anyways
use_address_override = false;
if (adapter_address == NULL || *adapter_address == NULL) {
if (adapter_address == NULL || *adapter_address == '\0') {
// empty, do nothing
return;
}

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)
{
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)

View File

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

View File

@@ -10,6 +10,7 @@
#include "hook/iohook.h"
#include "hooklib/adapter.h"
#include "hooklib/app.h"
#include "hooklib/rs232.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);
iohook_init(jbhook_handlers, lengthof(jbhook_handlers));
if (!options.disable_adapteremu) {
adapter_hook_init();
}
if (!options.disable_cardemu) {
rs232_hook_init();
}

View File

@@ -37,6 +37,7 @@ void options_init(struct options *options)
options->window_framed = false;
options->disable_p4ioemu = false;
options->disable_cardemu = false;
options->disable_adapteremu = false;
}
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;
}
case 'a': {
options->disable_adapteremu = true;
break;
}
case 'c': {
options->disable_cardemu = true;
break;
@@ -90,6 +96,7 @@ void options_print_usage(void)
" -h Print this usage message\n"
" -w Run the game windowed\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 "
"real cab)\n"
" -p Disable p4io emulation (e.g. when running on a "

View File

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

View File

@@ -97,13 +97,29 @@ bool ea3_ident_invoke_module_init(
ident->rev,
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);
if (!ok) {
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);
ident->dest[0] = sidcode_short[3];
@@ -111,7 +127,7 @@ bool ea3_ident_invoke_module_init(
ident->rev[0] = sidcode_short[5];
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(
sidcode_long,

View File

@@ -93,10 +93,34 @@ static AVS_LOG_WRITER(log_callback, chars, nchars, ctx)
free(utf16);
}
static void load_hook_dlls(struct array* hook_dlls) {
const char *hook_dll;
for (size_t i = 0; i < hook_dlls->nitems; i++) {
hook_dll = *array_item(char *, hook_dlls, i);
if (LoadLibraryA(hook_dll) == NULL) {
LPSTR buffer;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer,
0,
NULL);
log_fatal("%s: Failed to load hook DLL: %s", hook_dll, buffer);
LocalFree(buffer);
}
}
}
int main(int argc, const char **argv)
{
int i;
const char *hook_dll;
bool ok;
HANDLE logfile;
@@ -170,6 +194,8 @@ int main(int argc, const char **argv)
log_fatal("%s: /config missing", options.avs_config_path);
}
load_hook_dlls(&options.before_hook_dlls);
avs_context_init(
avs_config_root,
options.avs_heap_size,
@@ -188,27 +214,7 @@ int main(int argc, const char **argv)
/* Load hook DLLs */
for (i = 0; i < options.hook_dlls.nitems; i++) {
hook_dll = *array_item(char *, &options.hook_dlls, i);
if (LoadLibraryA(hook_dll) == NULL) {
LPSTR buffer;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer,
0,
NULL);
log_fatal("%s: Failed to load hook DLL: %s", hook_dll, buffer);
LocalFree(buffer);
}
}
load_hook_dlls(&options.hook_dlls);
/* Inject GetModuleHandle hooks */

View File

@@ -17,17 +17,23 @@ void module_context_init(struct module_context *module, const char *path)
if (module->dll == NULL) {
LPSTR buffer;
DWORD err = GetLastError();
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR) &buffer,
0,
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);
LocalFree(buffer);

View File

@@ -23,6 +23,7 @@ void options_init(struct options *options)
options->logfile = NULL;
options->remote_debugger = false;
array_init(&options->hook_dlls);
array_init(&options->before_hook_dlls);
}
bool options_read_cmdline(struct options *options, int argc, const char **argv)
@@ -115,6 +116,16 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
break;
case 'B':
if (i + 1 >= argc) {
return false;
}
*array_append(const char *, &options->before_hook_dlls) =
argv[++i];
break;
case 'Y':
if (i + 1 >= argc) {
return false;
@@ -170,6 +181,8 @@ void options_print_usage(void)
" -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
" -K [filename] Load hook DLL (can be specified multiple "
"times)\n"
" -B [filename] Load pre-hook DLL loaded before avs boot "
"(can be specified multiple times)\n"
" -Y [filename] Log to a file in addition to the console\n"
" -D Halt the launcher before bootstrapping AVS "
"until a"
@@ -179,4 +192,5 @@ void options_print_usage(void)
void options_fini(struct options *options)
{
array_fini(&options->hook_dlls);
array_fini(&options->before_hook_dlls);
}

View File

@@ -17,6 +17,7 @@ struct options {
const char *module;
const char *logfile;
struct array hook_dlls;
struct array before_hook_dlls;
bool remote_debugger;
};

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) {
switch (type) {
case P3IO_CAB_TYPE_SD:
log_misc("%s: Returning cab type SD", __func__);
resp->status = 1;
break;
case P3IO_CAB_TYPE_HD:
log_misc("%s: Returning cab type HD", __func__);
resp->status = 2;
break;

View File

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

View File

@@ -25,8 +25,10 @@ kfca_amp_control(struct ac_io_emu *emu, const struct ac_io_message *req);
static bool poll_delay;
static bool force_headphones_on;
void bio2_emu_bi2a_init(
struct bio2emu_port *bio2_emu, bool disable_poll_limiter)
struct bio2emu_port *bio2_emu, bool disable_poll_limiter, bool force_headphones)
{
bio2emu_port_init(bio2_emu);
@@ -35,6 +37,8 @@ void bio2_emu_bi2a_init(
if (!poll_delay) {
log_warning("bio2_emu_bi2a_init: poll_delay has been disabled");
}
force_headphones_on = force_headphones;
}
void bio2_emu_bi2a_dispatch_request(
@@ -240,6 +244,9 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
pin->buttons_1.b_start = check_pin(gpio0, SDVX_IO_IN_GPIO_0_START);
pin->buttons_1.b_headphone = check_pin(gpio0, SDVX_IO_IN_GPIO_0_HEADPHONE);
if (force_headphones_on) {
pin->buttons_1.b_headphone = 1;
}
pin->buttons_1.b_a = check_pin(gpio0, SDVX_IO_IN_GPIO_0_A);
pin->buttons_1.b_b = check_pin(gpio0, SDVX_IO_IN_GPIO_0_B);
pin->buttons_1.b_c = check_pin(gpio0, SDVX_IO_IN_GPIO_0_C);

View File

@@ -83,7 +83,7 @@ _Static_assert(
"bio2_bi2a_state_out is the wrong size");
#pragma pack(pop)
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter);
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter, bool force_headphones);
void bio2_emu_bi2a_dispatch_request(
struct bio2emu_port *bio2port, const struct ac_io_message *req);

View File

@@ -8,10 +8,12 @@
"io.disable_card_reader_emu"
#define SDVXHOOK2_CONFIG_IO_DISABLE_BIO2_EMU_KEY "io.disable_bio2_emu"
#define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter"
#define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones"
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false
#define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false
void sdvxhook2_config_io_init(struct cconfig *config)
{
@@ -33,6 +35,12 @@ void sdvxhook2_config_io_init(struct cconfig *config)
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE,
"Disables the poll limiter, warning very high CPU usage may arise");
cconfig_util_set_bool(
config,
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE,
"Forces game to think headphones are attached");
}
void sdvxhook2_config_io_get(
@@ -73,4 +81,16 @@ void sdvxhook2_config_io_get(
SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE);
}
if (!cconfig_util_get_bool(
config,
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
&config_io->force_headphones,
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY,
SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE);
}
}

View File

@@ -9,6 +9,7 @@ struct sdvxhook2_config_io {
bool disable_card_reader_emu;
bool disable_bio2_emu;
bool disable_poll_limiter;
bool force_headphones;
};
void sdvxhook2_config_io_init(struct cconfig *config);

View File

@@ -121,7 +121,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
if (!config_io.disable_bio2_emu) {
bio2emu_init();
bio2_emu_bi2a_init(&bio2_emu, config_io.disable_poll_limiter);
bio2_emu_bi2a_init(&bio2_emu, config_io.disable_poll_limiter, config_io.force_headphones);
}
if (!config_io.disable_card_reader_emu) {

View File

@@ -1,6 +1,8 @@
#include <stddef.h>
#include <stdint.h>
#include "util/log.h"
uint8_t crc8(const void *ptr, size_t nbytes, uint8_t in)
{
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 j;
// log_assert(ptr != NULL);
log_assert(ptr != NULL);
bytes = ptr;
crc = ~in;
@@ -35,7 +37,7 @@ uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in)
size_t i;
size_t j;
// log_assert(ptr != NULL);
log_assert(ptr != NULL);
bytes = ptr;
crc = ~in;
@@ -55,6 +57,33 @@ uint16_t crc16(const void *ptr, size_t nbytes, uint16_t in)
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)
{
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 j;
// log_assert(ptr != NULL);
log_assert(ptr != NULL);
bytes = ptr;
crc = ~in;

View File

@@ -6,6 +6,7 @@
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_msb(const void *ptr, size_t nbytes, uint16_t in);
uint32_t crc32(const void *ptr, size_t nbytes, uint32_t in);
#endif

View File

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

View File

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