mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2026-09-15 11:55:10 -05:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec76ba075f | ||
|
|
f438f04f2a | ||
|
|
865980991e | ||
|
|
37384c15ec | ||
|
|
f0d62cc938 | ||
|
|
bf067de633 | ||
|
|
f3b07aeb0a | ||
|
|
a1a67697c4 | ||
|
|
ce5b1b2eac | ||
|
|
3f2aed65e4 | ||
|
|
22f3845609 | ||
|
|
de0d70d808 | ||
|
|
12c52bb0d8 | ||
|
|
279d4de4b3 | ||
|
|
2b52fbe211 | ||
|
|
78e7c05876 | ||
|
|
9a5418f6a3 | ||
|
|
2363498f73 | ||
|
|
edbbe5ae67 | ||
|
|
d799b69d12 | ||
|
|
91f83cd975 | ||
|
|
adeabbea19 | ||
|
|
41187091b0 | ||
|
|
5658658d3a | ||
|
|
79a74b2d2f | ||
|
|
51484b1d3d | ||
|
|
df8f3bc96a | ||
|
|
ec435e7a7b | ||
|
|
f8a01ed92f | ||
|
|
2b1dd866d0 | ||
|
|
7d129a3e63 | ||
|
|
29db89cebe | ||
|
|
f7e1c8b3f9 | ||
|
|
f667ae5601 | ||
|
|
4b061bdf8f | ||
|
|
13600db1d5 | ||
|
|
e4126500ef | ||
|
|
049f1b4564 | ||
|
|
687c000000 | ||
|
|
1b593a8e23 | ||
|
|
24178121f0 | ||
|
|
62ad4e0616 | ||
|
|
c348a41d22 | ||
|
|
ef377f40d8 | ||
|
|
0c88518a1f | ||
|
|
0bc87db8da | ||
|
|
53f8cb3bf3 | ||
|
|
41edfec702 | ||
|
|
c6c3bdb075 | ||
|
|
b3a89012ca | ||
|
|
f0bc87f1d6 | ||
|
|
7508c43119 | ||
|
|
34be731211 | ||
|
|
bac1ce62e5 | ||
|
|
58689bbc30 | ||
|
|
d5e186ffe2 | ||
|
|
34c95561c4 | ||
|
|
81d697d59a | ||
|
|
3bdda4d123 | ||
|
|
ea8842b58a | ||
|
|
e89889806b | ||
|
|
b3b2f8f433 | ||
|
|
1cdf330cbf | ||
|
|
89c3ada28f | ||
|
|
d9cb953b67 | ||
|
|
7ebb80d600 | ||
|
|
e737d60893 | ||
|
|
f39843b41f | ||
|
|
98d0debd05 | ||
|
|
950584f025 | ||
|
|
e4081c057f | ||
|
|
8c3030354a | ||
|
|
9777eddaa0 | ||
|
|
671723febd | ||
|
|
c1f6166e1b | ||
|
|
538650f7ac | ||
|
|
efd243fd9d | ||
|
|
383b301d3c | ||
|
|
a9d201691a | ||
|
|
ebb6f811b4 | ||
|
|
9e96cf074f |
@@ -11,57 +11,45 @@ before_script:
|
||||
|
||||
stages:
|
||||
- build
|
||||
- create-release-package
|
||||
- releasetag
|
||||
- upload-release
|
||||
|
||||
build:
|
||||
build-master:
|
||||
stage: build
|
||||
before_script:
|
||||
- apk update && apk add make > /dev/null
|
||||
script:
|
||||
- make build-docker
|
||||
- mv build/docker/bemanitools.zip bemanitools.zip
|
||||
artifacts:
|
||||
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
||||
paths:
|
||||
- build
|
||||
- bemanitools.zip
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
create-release-package:
|
||||
stage: create-release-package
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
dependencies:
|
||||
- build
|
||||
build-tags:
|
||||
stage: build
|
||||
before_script:
|
||||
- apk update && apk add zip > /dev/null
|
||||
- apk update && apk add make > /dev/null
|
||||
script:
|
||||
- mv build/docker/bemanitools.zip ./bemanitools.zip
|
||||
- rm -r build
|
||||
- find . -mindepth 1 ! -regex '^./bemanitools.zip' -delete
|
||||
- unzip bemanitools.zip
|
||||
- rm bemanitools.zip
|
||||
- make build-docker
|
||||
- mv build/docker/bemanitools.zip bemanitools.zip
|
||||
artifacts:
|
||||
name: "$CI_COMMIT_SHORT_SHA-$CI_JOB_NAME"
|
||||
paths:
|
||||
- ./*
|
||||
- bemanitools.zip
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
|
||||
releasetag:
|
||||
stage: releasetag
|
||||
dependencies: []
|
||||
- tags
|
||||
|
||||
upload-release:
|
||||
stage: upload-release
|
||||
dependencies:
|
||||
- build-tags
|
||||
before_script:
|
||||
- apk update && apk add curl > /dev/null
|
||||
script:
|
||||
- |
|
||||
curl --silent --show-error \
|
||||
--data "{\"tag_name\": \"${CI_COMMIT_TAG}\", \"name\": \"${CI_PROJECT_NAME}-${CI_COMMIT_TAG}\", \"description\": \"${CI_COMMIT_TAG_MESSAGE:-No release notes.}\"}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Private-Token: ${CI_PRIVATE_TOKEN}" \
|
||||
--request POST \
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/releases"
|
||||
- echo "Uploading ${CI_PROJECT_NAME}-${CI_COMMIT_TAG}..."
|
||||
- curl --silent --show-error -F "key=${CI_UPLOAD_KEY}" -F "filename=${CI_PROJECT_NAME}-v${CI_COMMIT_TAG}.zip" -F "file=@./bemanitools.zip" ${CI_UPLOAD_URL}
|
||||
only:
|
||||
- tags
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
<!--- Tell us what happens instead of the expected behavior -->
|
||||
|
||||
## Detailed Description
|
||||
<!--- Provide a detailed description of the issue. Include links to screenshots or videos if necessary -->
|
||||
<!--- Provide a detailed description of the issue. Include links to screenshots or videos if
|
||||
necessary -->
|
||||
|
||||
## Steps to reproduce
|
||||
<!--- Provide a detailed step by step description how to reproduce this issue -->
|
||||
@@ -29,16 +30,43 @@
|
||||
|
||||
### Log output
|
||||
See attachment.
|
||||
<!--- Provide log output as attachment. Make sure to censor sensitive data like PCBIDs or device names if necessary -->
|
||||
<!---
|
||||
Provide FULL log output, e.g. inject.log or launcher.log. Please do not guess which things
|
||||
are relevant or not. Without knowing, you might leave out things that are relevant for the developers. You have to enable log output explicitly if not done already.
|
||||
|
||||
For inject.exe and launcher.exe, add `-Y logfile.log` to the command line args to output to a file, e.g. `gamestart.bat -Y logfile.log`.
|
||||
|
||||
!!!!!!
|
||||
REMOVE ANY SENSITIVE DATA LIKE PCBIDS OR DEVICE NAMES BY REPLACING IT THEM WITH
|
||||
|
||||
[REDACTED]
|
||||
|
||||
BEFORE UPLOADING/POSTING ANY LOG DATA!!!
|
||||
|
||||
Use the search and replace feature of any kind of text editor.
|
||||
!!!!!!
|
||||
-->
|
||||
|
||||
### Configuration files
|
||||
See attachment.
|
||||
<!--- Provide any configuration files that you used, e.g. iidxhook-XX.conf. Make sure to censor sensitive data like
|
||||
PCBIDs -->
|
||||
<!--- Provide any configuration files that you used, e.g. iidxhook-XX.conf. This file is located in
|
||||
the same directory as launcher.exe or inject.exe.
|
||||
|
||||
!!!!!!
|
||||
REMOVE ANY SENSITIVE DATA LIKE PCBIDS OR DEVICE NAMES BY REPLACING IT THEM WITH
|
||||
|
||||
[REDACTED]
|
||||
|
||||
BEFORE UPLOADING/POSTING ANY LOG DATA!!!
|
||||
|
||||
Use the search and replace feature of any kind of text editor.
|
||||
!!!!!!
|
||||
-->
|
||||
|
||||
### Command line arguments
|
||||
<!--- Provide how you run the game from the command line, e.g. which gamestart.bat you used and any additional arguments
|
||||
that you provided to it. Also provide the contents of the gamestart.bat you used if you altered it. -->
|
||||
<!--- Provide how you run the game from the command line, e.g. which gamestart.bat you used and any
|
||||
additional arguments that you provided to it. Also provide the contents of the gamestart.bat you
|
||||
used if you altered it. -->
|
||||
|
||||
### APIs used
|
||||
* <!--- List all APIs you used as a bullet list, e.g. iidxio-keyboard, eamio-keyboard -->
|
||||
|
||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,4 +1,21 @@
|
||||
# Release history
|
||||
## 5.35
|
||||
|
||||
## 5.34
|
||||
* IIDX: Support IO and card reader feature switches to disable emulation in iidxhook4-7
|
||||
* Jubeat: jbio implementation for magicbox hardware
|
||||
* Misc: Various documentation improvements
|
||||
* IIDX: Turntable multiplier (can also be used as inverted) for iidxhook9
|
||||
* IIDX: iidxhook9, add force screen resolution option to fix sometimes wrong auto res detection by
|
||||
iidx27 causing inaccurate/wrong refresh rates on monitor check
|
||||
* IIDX: iidxio BIO2 implementation -> Use BIO2 hardware with any iidxhook or other software
|
||||
supporting BT5's iidxio interface
|
||||
* IIDX: BIO2 exit hook, exit the game pressing Start P1 + Start P2, Effect and VEFX
|
||||
* launcher: Allow overriding service URL from command line
|
||||
* IIDX: vigem-iidxio, tool to allow using iidxio (ezusb, ezusb2 or bio2) to emulate XBOX controllers
|
||||
to play other non arcade games that support xinput, e.g. Lunatic Rave (note: Infinitas does not
|
||||
work with this since it only supports direct input)
|
||||
|
||||
## 5.33
|
||||
* iidxhook9: Support for IIDX27
|
||||
* sdvxio-bio2: Driver for real sdvx5 cabinet IO hardware
|
||||
|
||||
@@ -1,30 +1,83 @@
|
||||
# Contributing
|
||||
Please have a look at the issue board about what's currently going on. If you see an issue that is not assigned yet and
|
||||
that you can and want to work on, please leave a comment to reach out to one of our developers. You can also ask
|
||||
questions and discuss the issue.
|
||||
This document outlines different types of contributions and how YOU can help us to improve the
|
||||
project. Read it, as it provides guidelines that are there to help you and the maintainers.
|
||||
|
||||
# Bug reports
|
||||
Please check if the bug was already reported by searching the existing issues. If it does, feel free to leave a comment
|
||||
that you also have this issue. Add additional information, screenshots, log files etc. The more information and details
|
||||
we have, the easier it might get to solve the issue.
|
||||
## Reporting and discussions: Issues section on gitlab
|
||||
In order to avoid having to manage ongoing discussions and bug reports on different communication
|
||||
channels, e.g. forums, messangers or other closed groups, we ask everyone to treat the issue
|
||||
section on gitlab as the place to open their relevant discussions and bug reports regarding the
|
||||
project.
|
||||
|
||||
When creating new issues, use our template for reporting bugs. It tells you what kind of information we need.
|
||||
The maintainers of the project do not have the time nor motivation to micromanage on the various
|
||||
channels and enter all data here to have it collected. This is a simple task that *ANYONE* can do
|
||||
allowing the maintainers and developers to spend their time on the codebase.
|
||||
|
||||
# Pull requests: bugfixes, new features or other code contributions
|
||||
Pull requests are welcome! May it be a PR to an already known issue or a new feature that you consider as a valuable
|
||||
contribution, please open a PR. If you want to start working on a new feature that was proposed in an issue, yet, it
|
||||
is recommended to reach out to the developers about this, first, to discuss if this contribution is valuable to the
|
||||
project. Otherwise, you might waste your time on implementing something that won't make it into master.
|
||||
## Bug reports
|
||||
Follow these steps when reporting bugs to ensure you provide all information we *always* need and
|
||||
make your report valuable and actionable.
|
||||
|
||||
Please read our [development guidelines](doc/development.md) as they contain valuable information that your contribution
|
||||
meets our standards.
|
||||
1. On the bemanitools repository, go `Issues` on the left-hand sidebar.
|
||||
1. Use the search function to check if there is an already open issue regarding what you want to
|
||||
report
|
||||
1. If that applies, read the open issue to check what's already covered regarding the bug
|
||||
1. Provide additional information or things that are missing. Upload your log files,
|
||||
screenshots, videos etc. Be careful to remove sensitive information like PCBIDs
|
||||
1. Give a thumbs up to the issue to show you are interested/affected as well
|
||||
1. If no existing issue avilable, create a new one
|
||||
1. Come up with a descriptive title
|
||||
1. **USE OUR BUG REPORTING TEMPLATE**: Pick it by selecting `Bug` on the `Description` section
|
||||
1. Follow the sections and their instructions provided by the template and fill them in. All fields
|
||||
are mandatory to provide a comprehensive report if not stated otherwise
|
||||
1. When finished, submit the issue
|
||||
|
||||
Fork the upstream repository and start developing on your personal fork. Make sure to test your changes with games that
|
||||
are affected by them. Pay attention to the target platform/hardware you are testing on! This is valuable information
|
||||
that should be included in the PR.
|
||||
## Pull requests: bugfixes, new features or other code contributions
|
||||
Pull requests are welcome! May it be a merge request to an already known issue or a new feature that
|
||||
you consider as a valuable contribution, please open a MR.
|
||||
|
||||
Once you completed your implementation, open a pull request on the upstream repository to propose your changes. We will review your contribution and get back to you about any changes or when we merge them to our upstream repository. Your changes, once approved, will be included in the next release.
|
||||
**!!! Maintaining documentation by adding new or improving existing documentation is as important as
|
||||
code !!!**
|
||||
|
||||
# Roadmap
|
||||
No concrete roadmap or timeline exists. We want to continue adding support for new games as well as old games (some of
|
||||
the old games supported by BT4 are not supported, yet).
|
||||
If you want to start working on a new feature that was proposed in an issue, yet, it is recommended
|
||||
to reach out to the active developers about this, first, to discuss if this contribution is valuable
|
||||
to the project. Otherwise, you might waste your time on implementing something that won't make it
|
||||
into master.
|
||||
|
||||
Please read our [development guidelines](doc/development.md) as they contain valuable information
|
||||
that your contribution meets our standards. This is not meant to annoy people but ensures
|
||||
consistency that the project stays maintainable for everyone.
|
||||
|
||||
Steps for contributing to the repository using a merge request:
|
||||
1. If you are new to git, take a bit of time to learn the basics which are very simple, e.g. Google
|
||||
for "git tutorial for non-programmers"
|
||||
1. Fork the upstream repository (Fork button on the top right on the main page of the repository)
|
||||
1. You can start editing files like documentation easily inside gitlab which might be the prefered
|
||||
option for many non-coders
|
||||
1. Clone your fork to your local machine and start working on stuff
|
||||
1. Ensure you push your changes to your fork on gitlab
|
||||
1. When done, go to the `Merge Requests` section on the left sidebar of the upstream repository
|
||||
1. Hit the `New merge request` button
|
||||
1. Select the `master` branch as the source branch
|
||||
1. Select whatever branch you worked, likely `master` if you didn't change that, as the target
|
||||
branch
|
||||
1. Hit `Compare branches and continue`
|
||||
1. Provide a descriptive title of what your change is about
|
||||
1. **USE OUR MR TEMPLATES**
|
||||
1. If you submit a bugfix, use the `Bugfix` tempalte and fill in the sections
|
||||
1. If you submit a new feature, use the `Feature` template and fill in the sections
|
||||
1. If you submit some minor fixes or documentation improvements, there is no template for that.
|
||||
Please provide a expressive description what you did and *why* you did that
|
||||
1. If any of your changes are tied to one or multiple issues, link them in the description
|
||||
1. When done, hit `Submit merge request`
|
||||
|
||||
The maintainers will take a look at your submission and provide their feedback. The intention of
|
||||
this process is to ensure the contribution meets the quality standards. Please also see this is
|
||||
a learning opportunity, especially with your first contribution, if a lot of comments and change
|
||||
requests are being made. The maintainers are open to discuss their suggestions/feedback if
|
||||
reasonable feedback is given back to them.
|
||||
|
||||
Once all discussion is resolved and the involved maintainers approved your submission, it will be
|
||||
merged into master and also included in the next release.
|
||||
|
||||
## Roadmap
|
||||
No concrete roadmap or timeline exists. We want to continue adding support for new games as well as
|
||||
old games (some of the old games supported by BT4 are not supported, yet).
|
||||
@@ -256,7 +256,7 @@ impdef_$1_$2_$3 ?= src/imports/import_$1_$2_$3.def
|
||||
|
||||
$$(bindir_$1_$2)/lib$3.a: $$(impdef_$1_$2_$3) | $$(bindir_$1_$2)
|
||||
$(V)echo ... $$@ [dlltool]
|
||||
$(V)$$(toolchain_$1)dlltool -l $$@ -d $$<
|
||||
$(V)$$(toolchain_$1)dlltool --kill-at -l $$@ -d $$<
|
||||
|
||||
endef
|
||||
|
||||
|
||||
48
Module.mk
48
Module.mk
@@ -54,9 +54,11 @@
|
||||
#
|
||||
# 17: Patch 0: beatmania IIDX 25 CANNON BALLERS
|
||||
# beatmania IIDX 26 Rootage
|
||||
# beatmania IIDX 27 HEROIC VERSE
|
||||
#
|
||||
# Patch 3: SOUND VOLTEX VIVID WAVE
|
||||
#
|
||||
#
|
||||
|
||||
cflags += \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
@@ -79,8 +81,8 @@ include src/main/acioemu/Module.mk
|
||||
include src/main/aciotest/Module.mk
|
||||
include src/main/asio/Module.mk
|
||||
include src/main/bio2drv/Module.mk
|
||||
include src/main/bio2emu/Module.mk
|
||||
include src/main/bio2emu-iidx/Module.mk
|
||||
include src/main/bio2emu/Module.mk
|
||||
include src/main/bsthook/Module.mk
|
||||
include src/main/bstio/Module.mk
|
||||
include src/main/camhook/Module.mk
|
||||
@@ -88,29 +90,30 @@ include src/main/cconfig/Module.mk
|
||||
include src/main/config/Module.mk
|
||||
include src/main/d3d9exhook/Module.mk
|
||||
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/ddrio-smx/Module.mk
|
||||
include src/main/ddrio/Module.mk
|
||||
include src/main/dinput/Module.mk
|
||||
include src/main/eamio/Module.mk
|
||||
include src/main/eamio-icca/Module.mk
|
||||
include src/main/eamio/Module.mk
|
||||
include src/main/eamiotest/Module.mk
|
||||
include src/main/ezusb/Module.mk
|
||||
include src/main/ezusb-emu/Module.mk
|
||||
include src/main/ezusb-iidx/Module.mk
|
||||
include src/main/ezusb-iidx-emu/Module.mk
|
||||
include src/main/ezusb-iidx-fpga-flash/Module.mk
|
||||
include src/main/ezusb-iidx-sram-flash/Module.mk
|
||||
include src/main/ezusb-iidx/Module.mk
|
||||
include src/main/ezusb-tool/Module.mk
|
||||
include src/main/ezusb2/Module.mk
|
||||
include src/main/ezusb/Module.mk
|
||||
include src/main/ezusb2-dbg-hook/Module.mk
|
||||
include src/main/ezusb2-emu/Module.mk
|
||||
include src/main/ezusb2-iidx/Module.mk
|
||||
include src/main/ezusb2-iidx-emu/Module.mk
|
||||
include src/main/ezusb2-iidx/Module.mk
|
||||
include src/main/ezusb2-tool/Module.mk
|
||||
include src/main/ezusb-iidx-emu/Module.mk
|
||||
include src/main/ezusb2/Module.mk
|
||||
include src/main/geninput/Module.mk
|
||||
include src/main/hook/Module.mk
|
||||
include src/main/hooklib/Module.mk
|
||||
include src/main/iidx-bio2-exit-hook/Module.mk
|
||||
include src/main/iidx-ezusb-exit-hook/Module.mk
|
||||
include src/main/iidx-ezusb2-exit-hook/Module.mk
|
||||
include src/main/iidx-irbeat-patch/Module.mk
|
||||
@@ -124,15 +127,17 @@ include src/main/iidxhook6/Module.mk
|
||||
include src/main/iidxhook7/Module.mk
|
||||
include src/main/iidxhook8/Module.mk
|
||||
include src/main/iidxhook9/Module.mk
|
||||
include src/main/iidxio/Module.mk
|
||||
include src/main/iidxio-bio2/Module.mk
|
||||
include src/main/iidxio-ezusb/Module.mk
|
||||
include src/main/iidxio-ezusb2/Module.mk
|
||||
include src/main/iidxio/Module.mk
|
||||
include src/main/iidxiotest/Module.mk
|
||||
include src/main/inject/Module.mk
|
||||
include src/main/jbio/Module.mk
|
||||
include src/main/jbiotest/Module.mk
|
||||
include src/main/jbhook/Module.mk
|
||||
include src/main/jbhook1/Module.mk
|
||||
include src/main/jbio-magicbox/Module.mk
|
||||
include src/main/jbio/Module.mk
|
||||
include src/main/jbiotest/Module.mk
|
||||
include src/main/launcher/Module.mk
|
||||
include src/main/mempatch-hook/Module.mk
|
||||
include src/main/mm/Module.mk
|
||||
@@ -141,25 +146,26 @@ include src/main/p3ioemu/Module.mk
|
||||
include src/main/p4ioemu/Module.mk
|
||||
include src/main/pcbidgen/Module.mk
|
||||
include src/main/sdvxhook/Module.mk
|
||||
include src/main/sdvxhook2/Module.mk
|
||||
include src/main/sdvxhook2-cn/Module.mk
|
||||
include src/main/sdvxio/Module.mk
|
||||
include src/main/sdvxio-kfca/Module.mk
|
||||
include src/main/sdvxhook2/Module.mk
|
||||
include src/main/sdvxio-bio2/Module.mk
|
||||
include src/main/sdvxio-kfca/Module.mk
|
||||
include src/main/sdvxio/Module.mk
|
||||
include src/main/security/Module.mk
|
||||
include src/main/unicorntail/Module.mk
|
||||
include src/main/util/Module.mk
|
||||
include src/main/vefxio/Module.mk
|
||||
include src/main/vigem-iidxio/Module.mk
|
||||
include src/main/vigem-sdvxio/Module.mk
|
||||
include src/main/vigemstub/Module.mk
|
||||
|
||||
include src/test/cconfig/Module.mk
|
||||
include src/test/d3d9hook/Module.mk
|
||||
include src/test/iidxhook-util/Module.mk
|
||||
include src/test/iidxhook8/Module.mk
|
||||
include src/test/security/Module.mk
|
||||
include src/test/test/Module.mk
|
||||
include src/test/util/Module.mk
|
||||
include src/test/iidxhook8/Module.mk
|
||||
|
||||
#
|
||||
# Distribution build rules
|
||||
@@ -176,6 +182,7 @@ $(zipdir)/tools.zip: \
|
||||
build/bin/indep-32/ezusb-iidx-fpga-flash.exe \
|
||||
build/bin/indep-32/ezusb-iidx-sram-flash.exe \
|
||||
build/bin/indep-32/iidxiotest.exe \
|
||||
build/bin/indep-32/iidx-bio2-exit-hook.dll \
|
||||
build/bin/indep-32/iidx-ezusb-exit-hook.dll \
|
||||
build/bin/indep-32/iidx-ezusb2-exit-hook.dll \
|
||||
build/bin/indep-32/jbiotest.exe \
|
||||
@@ -194,6 +201,7 @@ $(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-bio2-exit-hook.dll \
|
||||
build/bin/indep-64/iidx-ezusb-exit-hook.dll \
|
||||
build/bin/indep-64/iidx-ezusb2-exit-hook.dll \
|
||||
build/bin/indep-64/jbiotest.exe \
|
||||
@@ -371,16 +379,24 @@ $(zipdir)/iidx-27.zip: \
|
||||
|
||||
$(zipdir)/iidx-hwio-x86.zip: \
|
||||
build/bin/indep-32/eamio-icca.dll \
|
||||
build/bin/indep-32/iidxio-bio2.dll \
|
||||
build/bin/indep-32/iidxio-ezusb.dll \
|
||||
build/bin/indep-32/iidxio-ezusb2.dll \
|
||||
dist/iidx/iidxio-bio2.conf \
|
||||
build/bin/indep-32/vigem-iidxio.exe \
|
||||
dist/iidx/vigem-iidxio.conf \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
$(zipdir)/iidx-hwio-x64.zip: \
|
||||
build/bin/indep-64/eamio-icca.dll \
|
||||
build/bin/indep-64/iidxio-bio2.dll \
|
||||
build/bin/indep-64/iidxio-ezusb.dll \
|
||||
build/bin/indep-64/iidxio-ezusb2.dll \
|
||||
dist/iidx/iidxio-bio2.conf \
|
||||
build/bin/indep-64/vigem-iidxio.exe \
|
||||
dist/iidx/vigem-iidxio.conf \
|
||||
| $(zipdir)/
|
||||
$(V)echo ... $@
|
||||
$(V)zip -j $@ $^
|
||||
|
||||
45
README.md
45
README.md
@@ -1,7 +1,7 @@
|
||||
# Bemanitools 5
|
||||
[](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
|
||||
|
||||
Version: 5.33
|
||||
Version: 5.35
|
||||
|
||||
[Release history](CHANGELOG.md)
|
||||
|
||||
@@ -12,7 +12,21 @@ BT5 uses a cleaner approach than BT4 did; specifically, all input and lighting i
|
||||
spoken by the real IO PCBs, instead of replacing chunks of game code like BT4. The benefits of this approach are a more
|
||||
authentic gameplay experience, and easier support for a broader range of releases from each game series.
|
||||
|
||||
# List of supported games
|
||||
## Documentation
|
||||
Browse our [documentation](doc/README.md) as it might already cover various questions and concerns
|
||||
you are looking for or about to ask.
|
||||
|
||||
## Contributions and bug reporting
|
||||
[Read the dedicated CONTRIBUTING.md documentation](CONTRIBUTING.md).
|
||||
|
||||
The tl;dr version and golden rules of the sections in the document:
|
||||
* **EVERYONE** can contribute, this is **NOT** limited to people coding
|
||||
* [Open an issue on gitlab for discussions, feature requests and bug reports](CONTRIBUTING.md#reporting-and-discussions-issues-section-on-github)
|
||||
* [ALWAYS report bugs as issues and ALWAYS use the available bug template](CONTRIBUTING.md#bug-reports)
|
||||
* [Everyone is allowed to submit changes which are not just limited to code by opening merge requests](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions)
|
||||
* [Documentation improvements can and even should be contributed by non developers](CONTRIBUTING.md#pull-requests-bugfixes-new-features-or-other-code-contributions)
|
||||
|
||||
## List of supported games (hook libraries)
|
||||
* BeatStream
|
||||
* BeatStream (bst.zip) using bsthook
|
||||
* BeatStream アニムトライヴ (bst.zip) using bsthook
|
||||
@@ -55,13 +69,19 @@ authentic gameplay experience, and easier support for a broader range of release
|
||||
* SOUND VOLTEX IV HEAVENLY HAVEN (sdvx-01-to-04.zip) using sdvxhook
|
||||
* SOUND VOLTEX Vivid Wave (sdvx-05.zip) using sdvxhook2
|
||||
|
||||
# Supported platforms
|
||||
## ViGEm clients: Expose BT5 APIs as XBOX game controllers
|
||||
Play your favorite non-bemani arcade games with any hardware, e.g. real cabinet hardware, that
|
||||
implements BT5 APIs.
|
||||
|
||||
See the dedicated [readme](docs/vigem/README.md) for details.
|
||||
|
||||
## Supported platforms
|
||||
Our main platforms are currently Windows XP and Windows 7 which are also the target platforms on the original hardware
|
||||
of those games. However, as it gets more difficult to get and maintain hardware comptible with Windows XP, this might
|
||||
change in the future. Many games also run on very recent Windows 10 builds but bear with us that it's hard to keep up
|
||||
with Windows updates breaking legacy software.
|
||||
|
||||
# Distribution contents
|
||||
## Distribution contents
|
||||
Check the [list of supported games](#list-of-supported-games) to grab the right files for your game. BT5 also includes
|
||||
a *tools* subpackage (tools.zip) as well as the full source code (src.zip).
|
||||
|
||||
@@ -69,7 +89,7 @@ You will find *.md files in various sub-packages that give you further instructi
|
||||
or FAQ. We advice you to read them as your questions and concerns might already be answered by them. If not, let us
|
||||
know if there is any information that you consider helpful or important to know and should be added.
|
||||
|
||||
# Setup and dependencies
|
||||
## Setup and dependencies
|
||||
Most (older generation) games were developed for Windows XP Embedded but should run fine on any
|
||||
consumer version of Windows XP. Newer versions of Windows, e.g. Windows 7, 8 and 10, should be fine
|
||||
as well. Some hooks also include fixes required to run the games on a more recent version.
|
||||
@@ -79,21 +99,18 @@ Depending on the game, you also need the following dependencies installed:
|
||||
* Microsoft Visual C++ Redistributables 2010 **and** 2013: Depends on the game and age but both
|
||||
should cover most if not all of the games so far
|
||||
|
||||
# Contributions
|
||||
Please refer to the [dedicated documentation](CONTRIBUTING.md).
|
||||
## Development
|
||||
### Building
|
||||
See the [development document](doc/development.md).
|
||||
|
||||
# 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
|
||||
important aspects you should know before you get started with development.
|
||||
|
||||
## API
|
||||
### API
|
||||
Please refer to the [API documentation](doc/api.md).
|
||||
|
||||
# License
|
||||
## 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.
|
||||
|
||||
|
||||
6
dist/iidx/iidxhook-18.conf
vendored
6
dist/iidx/iidxhook-18.conf
vendored
@@ -36,3 +36,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-19.conf
vendored
6
dist/iidx/iidxhook-19.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-20.conf
vendored
6
dist/iidx/iidxhook-20.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-21.conf
vendored
6
dist/iidx/iidxhook-21.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-22.conf
vendored
6
dist/iidx/iidxhook-22.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-23.conf
vendored
6
dist/iidx/iidxhook-23.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
6
dist/iidx/iidxhook-24.conf
vendored
6
dist/iidx/iidxhook-24.conf
vendored
@@ -33,3 +33,9 @@ gfx.forced_refresh_rate=-1
|
||||
|
||||
# D3D9 device adapter (monitor), -1 to use default, 0, 1, 2 etc. to use specified adapter
|
||||
gfx.device_adapter=-1
|
||||
|
||||
# Disable card reader emulation and enable usage of real card reader hardware on COM1 (for games supporting slotted/wavepass readers)
|
||||
io.disable_card_reader_emu=false
|
||||
|
||||
# Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware
|
||||
io.disable_io_emu=false
|
||||
9
dist/iidx/iidxhook-27.conf
vendored
9
dist/iidx/iidxhook-27.conf
vendored
@@ -16,6 +16,9 @@ io.disable_cams=false
|
||||
# Disables the built in file hooks, requiring manual file creation
|
||||
io.disable_file_hooks=false
|
||||
|
||||
# Turntable sensitivity multiplier (1.0 is default)
|
||||
io.tt_multiplier=1.0
|
||||
|
||||
# Disables the camera emulation
|
||||
cam.disable_emu=false
|
||||
|
||||
@@ -49,6 +52,12 @@ gfx.device_adapter=-1
|
||||
# Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees
|
||||
gfx.force_orientation=-1
|
||||
|
||||
# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
|
||||
gfx.force_screen_res.width=-1
|
||||
|
||||
# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.
|
||||
gfx.force_screen_res.height=-1
|
||||
|
||||
# IP of adapter to force override with
|
||||
adapter.override_ip=
|
||||
|
||||
|
||||
8
dist/iidx/iidxio-bio2.conf
vendored
Normal file
8
dist/iidx/iidxio-bio2.conf
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Autodetect BIO2 port (default: on)
|
||||
bio2.autodetect=true
|
||||
|
||||
# BIO2 serial port. Optional, if autodetect property is turned on
|
||||
bio2.port=COM4
|
||||
|
||||
# BIO2 bus baudrate (real devices expect 115200)
|
||||
bio2.baud=115200
|
||||
26
dist/iidx/vigem-iidxio.conf
vendored
Normal file
26
dist/iidx/vigem-iidxio.conf
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Use relative mode analog mapping instead of absolute analog values
|
||||
vigem.iidxio.tt.anlog.relative=false
|
||||
|
||||
# Sensitivity value for relative mode (1 to 32767). Tweak if you are having issues with jittering/misfiring/unresponsiveness
|
||||
vigem.iidxio.tt.anlog.relative_sensitivity=1024
|
||||
|
||||
# Button turntable: "debounce" value (1 to 50, recommend 20). Tweak if you are having issues with TT button misfiring/unresponsiveness
|
||||
vigem.iidxio.tt.button.debounce=20
|
||||
|
||||
# Button turntable: minimum ticks required within (debounce * 2) ms to register movement (1 to 4, recommend 2). Tweak if you button input is too (un-) responsive
|
||||
vigem.iidxio.tt.button.threshold=2
|
||||
|
||||
# Print verbose debug output to the console for debugging turntable sensitivity issues
|
||||
vigem.iidxio.tt.debug_output=false
|
||||
|
||||
# Enable input based key lighting
|
||||
vigem.iidxio.cab_light.enable_keylight=true
|
||||
|
||||
# Different cabinet light modes: 0 = off, 1 = neons sequence, 2 = neons flash on TT spin
|
||||
vigem.iidxio.cab_light.light_mode=0
|
||||
|
||||
# Display text on 16seg. If text exceeds 9 char display limit, it will scroll + cycle
|
||||
vigem.iidxio.cab_light.text_16seg=
|
||||
|
||||
# Cycle time/scroll speed for text exceeding 16seg display length (9) to scroll from right
|
||||
vigem.iidxio.cab_light.text_scroll_cycle_time_ms=500
|
||||
2
dist/jb/gamestart.bat
vendored
2
dist/jb/gamestart.bat
vendored
@@ -7,4 +7,4 @@ if not exist dev\nvram\coin.xml copy prop\defaults\coin.xml dev\nvram\coin.xml
|
||||
if not exist dev\nvram\eacoin.xml copy prop\defaults\eacoin.xml dev\nvram\eacoin.xml
|
||||
if not exist dev\raw mkdir dev\raw
|
||||
|
||||
launcher -K jbhook.dll jubeat.dll
|
||||
launcher -H 33554432 -K jbhook.dll jubeat.dll
|
||||
|
||||
21
doc/README.md
Normal file
21
doc/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Bemanitools 5 documentation
|
||||
This folder contains various types of documentation.
|
||||
|
||||
Table of contents:
|
||||
* Key tools
|
||||
* [Inject](inject.md): Readme for one of BT5's key applications, `inject.exe`
|
||||
* [Launcher](launcher.md): Readme for another one of BT5's key applications, `launcher.exe`
|
||||
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
||||
* Game hooks
|
||||
* [ddrhook](ddrhook/README.md): Documentation relevant to `ddrhook` implementations
|
||||
* [iidxhook](iidxhook/README.md): Documentation relevant to `iidxhook` implementations
|
||||
* [jbhook](jbhook/README.md): Documentation relevant to `jbhook` implementations
|
||||
* [sdvxhook](sdvxhook/README.md): Documentation relevant to `sdvxhook` implementations
|
||||
* Development
|
||||
* [API](api.md): Available APIs for BT5 and instructions how to use them
|
||||
* [Architecture](architecture.md): Outline of BT5's architecture, how things are designed and why
|
||||
* [Development](development.md): Development environment, building, releasing, etc.
|
||||
* [Developer documentation](dev/README.md): Various lose documentation/notes by developers
|
||||
* [Tools](tools/README.md): Documentation for additional user and development tooling
|
||||
* Hardware
|
||||
* [Hardware](hardware/README.md): Anything related to hardware, e.g. IO boards
|
||||
@@ -22,12 +22,15 @@ The following implementations are already shipped with BT5.
|
||||
* ddrio-smx.dll: StepManiaX platforms
|
||||
* Beatmania IIDX
|
||||
* iidxio.dll (default): Keyboard, joystick and mouse input
|
||||
* iidxio-ezusb.dll: Ezusb (C02 IO) driver
|
||||
* iidxio-ezusb2.dll: Ezusb FX2 (IO2) driver
|
||||
* [iidxio-bio2.dll](iidxhook/iidxio-bio2.md): BIO2 driver
|
||||
* [iidxio-ezusb.dll](iidxhook/iidxio-ezusb.md): Ezusb (C02 IO) driver
|
||||
* [iidxio-ezusb2.dll](iidxhook/iidxio-ezusb2.md): Ezusb FX2 (IO2) driver
|
||||
* jubeat
|
||||
* jbio.dll (default): Keyboard, joystick and mouse input
|
||||
* SOUND VOLTEX
|
||||
* sdvxio.dll (default): Keyboard, joystick and mouse input
|
||||
* [sdvxio-bio2.dll](sdvxhook/sdvxio-bio2.md): BIO2 driver
|
||||
* [sdvxio-kfca.dll](sdvxhook/sdvxio-kfca.md): KFCA IO board driver
|
||||
|
||||
Eamuse hardware support is implemented separately:
|
||||
* eamio.dll (default): Keyboard and joystick input
|
||||
|
||||
3
doc/dev/README.md
Normal file
3
doc/dev/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Development documentation and notes
|
||||
This folder contains various lose documentation snippets created by the developers. These can be
|
||||
helpful as future reference.
|
||||
192
doc/dev/acio-bio2-iidx-package-dump.md
Normal file
192
doc/dev/acio-bio2-iidx-package-dump.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# ACIO BIO2 IIDX package dump
|
||||
Package dump excerpt of the init sequence of a original Konami IIDX BIO2 with sub IO connected.
|
||||
This was used to identify a missing piece of information that needs to be communicated to the BIO2
|
||||
for IIDX to initialize the sub IO correctly.
|
||||
|
||||
The dump was cut off after two polls as the sequence just keeps on repeating from that point on.
|
||||
|
||||
## Findings for problem to solve
|
||||
With the previous implemention of the BIO2 driver, which was created off references of SDVX KFCA,
|
||||
a BIO2 used with IIDX and the sub IO (to upgrade older C02, IO2 cabinets) connected didn't
|
||||
initialize properly. This resulted in no inputs/outputs other than 14 keys working.
|
||||
|
||||
The problem identified was a different byte, exact meaning not known, that is sent in
|
||||
[exchange 4](#exchange-4-ac-io-cmd-clear). Instead of `0x3B` from the SDVX KFCA based
|
||||
implementation, it needs to be set to `0x2D`.
|
||||
|
||||
## Exchange 1: AC_IO_CMD_ASSIGN_ADDRS
|
||||
### Write
|
||||
```text
|
||||
AA 00 00 01 00 01 00 02
|
||||
|
||||
AA: SOF
|
||||
00: addr
|
||||
0001: AC_IO_CMD_ASSIGN_ADDRS
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
data: 00
|
||||
02: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 00 00 01 00 01 01 03
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
00: addr
|
||||
0001: addr
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
01: data
|
||||
03: checksum
|
||||
```
|
||||
|
||||
## Exchange 2: AC_IO_CMD_GET_VERSION
|
||||
### Write
|
||||
```
|
||||
AA 01 00 02 00 00 03
|
||||
|
||||
AA: SOF
|
||||
01: addr, node 1
|
||||
0002: AC_IO_CMD_GET_VERSION
|
||||
00: seq_no
|
||||
00: nbytes
|
||||
03: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 00 02 00 2C 0D 06 00 00 ...
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
81: Response flag + node 1
|
||||
0002: AC_IO_CMD_GET_VERSION
|
||||
00: seq_no
|
||||
2C: nbytes
|
||||
0D 06 00 00 ...: data
|
||||
XX: checksum
|
||||
```
|
||||
|
||||
## Exchange 3: AC_IO_CMD_START_UP
|
||||
### Write
|
||||
```
|
||||
AA 01 00 03 00 00 04
|
||||
|
||||
AA: SOF
|
||||
01: addr
|
||||
0003: AC_IO_CMD_START_UP
|
||||
00: seq_no
|
||||
00: nbytes
|
||||
04: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 00 03 00 01 00 85
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
81: Response flag + node 1
|
||||
0003: AC_IO_CMD_START_UP
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
00: data
|
||||
85: checksum
|
||||
```
|
||||
|
||||
## Exchange 4: AC_IO_CMD_CLEAR
|
||||
### Write
|
||||
```
|
||||
AA 01 01 00 00 01 2D 30
|
||||
|
||||
AA: SOF
|
||||
01: addr
|
||||
0100: AC_IO_CMD_CLEAR
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
2D: data
|
||||
30: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 01 00 00 01 00 83
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
81: Response flag + node 1
|
||||
0100: AC_IO_CMD_CLEAR
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
00: data
|
||||
83: checksum
|
||||
```
|
||||
|
||||
## Exchange 5: BIO2_BI2A_CMD_WATCHDOG
|
||||
### Write
|
||||
```
|
||||
AA 01 01 20 00 02 00 00 24
|
||||
|
||||
AA: SOF
|
||||
01: addr
|
||||
0120: BIO2_BI2A_CMD_WATCHDOG
|
||||
00: seq_no
|
||||
02: nbytes
|
||||
00 00: data
|
||||
24: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 01 20 00 01 00 A3
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
81: Response flag + node 1
|
||||
0120: BIO2_BI2A_CMD_WATCHDOG
|
||||
00: seq_no
|
||||
01: nbytes
|
||||
00: data
|
||||
A3: checksum
|
||||
```
|
||||
|
||||
## Exchange 6: BIO2_BI2A_CMD_POLL
|
||||
### Write
|
||||
```
|
||||
AA 01 01 52 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84
|
||||
|
||||
AA: SOF
|
||||
01: addr
|
||||
0152: BIO2_BI2A_CMD_POLL
|
||||
00: seq_no
|
||||
30: nbtes
|
||||
...: data
|
||||
84: checksum
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 01 52 00 2E 00 00 B0 00 F0 00 F0 F0 00 00 00 00 00 02 00 5F 11 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F3
|
||||
|
||||
AA: SOF
|
||||
AA: SOF
|
||||
81: Response flag + node 1
|
||||
0152: BIO2_BI2A_CMD_POLL
|
||||
00: seq_no
|
||||
2E: nbytes
|
||||
...: data
|
||||
F3: checksum
|
||||
```
|
||||
|
||||
## Exchange 7: BIO2_BI2A_CMD_POLL
|
||||
### Write
|
||||
```
|
||||
AA 01 01 52 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 84
|
||||
```
|
||||
|
||||
### Read
|
||||
```
|
||||
AA AA 81 01 52 00 2E 00 00 B0 00 F0 00 F0 F0 00 00 00 00 00 02 00 64 11 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F8
|
||||
```
|
||||
54
doc/hardware/bio2-sub-io-turntable-bypass-cable.md
Normal file
54
doc/hardware/bio2-sub-io-turntable-bypass-cable.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# BIO2 sub IO turntable bypass cable
|
||||
If you upgraded a C02/IO2 wired cabinet, the turntables are connected to the
|
||||
sub IO via a serial line that goes to another sub IO behind the front panel
|
||||
next to the 16seg display. This introduces additional latency as the input
|
||||
data needs to pass through multiple systems/PCBs until it reaches the game.
|
||||
|
||||
This can be reduced by using a so-called "bypass" cable, that connects the
|
||||
turntables directly to the BIO2 sub IO board reducing latency significantly.
|
||||
|
||||
This cable could be ordered with any IIDX upgrade kit including the BIO sub IO
|
||||
board but can also be easily created from scratch.
|
||||
|
||||
## Parts
|
||||
* Some wires
|
||||
* [JST HL](https://jst.de/file/download/219/pitch-3-96-mm-wtw-hl2-pdf) 2x4 pin female connector
|
||||
* [JST HVQ](https://jst.de/file/download/637/hvq) 8 pin female connector
|
||||
* Matching terminals for the connectors
|
||||
|
||||
## Pinout
|
||||
```text
|
||||
JST HL 2x4 pin front view connector
|
||||
|
||||
notch at top
|
||||
___
|
||||
|---------|
|
||||
| 1 2 3 4 |
|
||||
| 5 6 7 8 |
|
||||
|---------|
|
||||
```
|
||||
|
||||
```
|
||||
JST HVQ 8 pin front view connector
|
||||
Numbering on connector matches
|
||||
|
||||
notch at top
|
||||
___________________
|
||||
-------------------
|
||||
|-----------------|
|
||||
| 1 2 3 4 5 6 7 8 |
|
||||
|-----------------|
|
||||
|
||||
```
|
||||
|
||||
Pins of the two connectors need to be connected like this:
|
||||
| JST HL 2x4 pin | JST 8 pin |
|
||||
|----------------|-----------|
|
||||
| 1 | 1 |
|
||||
| 2 | 1 |
|
||||
| 3 | 3 |
|
||||
| 4 | 2 |
|
||||
| 5 | 5 |
|
||||
| 6 | 4 |
|
||||
| 7 | 8 |
|
||||
| 8 | 8 |
|
||||
51
doc/hardware/ezusb-iidx-rj45-to-din8-pinout.md
Normal file
51
doc/hardware/ezusb-iidx-rj45-to-din8-pinout.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Ezusb 1/2 RJ45 to DIN8 connector pinout
|
||||
This was created from using the BIO2 sub IO board to connect pre IIDX 25 cabinet hardware to the
|
||||
BIO2 IO board. The two connector types from different generation IO boards, RJ45 on the ezusb FX
|
||||
(C02) board and a round DIN8 connector on the ezusb FX2 (IO2) board are just different connectors to
|
||||
the same hardware on the PCB.
|
||||
|
||||
Therefore, any C02 wired cabinet can be easily upgraded to IO2 wiring and vice versa by building
|
||||
a simple RJ45 -> DIN8 or DIN8 -> RJ45 adapter.
|
||||
|
||||
The following connection information was traced on a original Konami BIO2 sub IO board.
|
||||
|
||||
RJ45 (female) connector, top view:
|
||||
```text
|
||||
plug insert
|
||||
|
|
||||
|
|
||||
v
|
||||
|-----------|
|
||||
| Top view |
|
||||
| |
|
||||
| Pins |
|
||||
| 7 5 3 1 |
|
||||
| 8 6 4 2 |
|
||||
|-----------|
|
||||
```
|
||||
|
||||
DIN8 (female) connector, top view:
|
||||
```text
|
||||
plug insert
|
||||
|
|
||||
|
|
||||
v
|
||||
|-----------|
|
||||
| Top view |
|
||||
| Pins |
|
||||
| 3 1 2 6 |
|
||||
| 7 4 5 8 9 |
|
||||
|-----------|
|
||||
```
|
||||
|
||||
The two connectors are interconnected on the PCB like this:
|
||||
| RJ45 pins | DIN8 pins |
|
||||
|-----------|-----------|
|
||||
| 1 | 1 |
|
||||
| 2 | 7 |
|
||||
| 3 | 4 |
|
||||
| 4 | 6 |
|
||||
| 5 | 5 |
|
||||
| 6 | 3 |
|
||||
| 7 | 2 |
|
||||
| 8 | 1 |
|
||||
@@ -1,5 +1,4 @@
|
||||
# iidxhook
|
||||
|
||||
iidxhook is a collection of hook libraries for BeatmaniaIIDX providing
|
||||
emulation and various patches to run these games on non BemaniPC hardware and
|
||||
newer Windows versions.
|
||||
@@ -9,8 +8,7 @@ The hook libraries must be bootstrapped either using [inject](../inject.md) or
|
||||
instructions are given in dedicated readme files for each iidxhook version
|
||||
(see below).
|
||||
|
||||
# Versions
|
||||
|
||||
## Versions
|
||||
iidxhook comes in a few different flavors. The game and its engine changed over
|
||||
the years. Some game versions might require patches/parameters enabled which
|
||||
others don't need or have different AVS versions. Here is the list of supported
|
||||
@@ -30,8 +28,7 @@ which are ready to be dropped on top of vanilla AC data dumps. We recommend
|
||||
using prestine dumps to avoid any conflicts with other hardcoded hacks or
|
||||
binary patches.
|
||||
|
||||
# How to run
|
||||
|
||||
## How to run
|
||||
To run your game with iidxhook, you have to use the inject tool to inject the
|
||||
DLL to the game process. *dist/iidx* contains bat scripts with all the
|
||||
important parameters configured. Further parameters can be added but might not
|
||||
@@ -39,7 +36,15 @@ be required to run the game with default settings.
|
||||
Further information on how to setup the data for each specific version are
|
||||
elaborated in their dedicated readme files.
|
||||
|
||||
# Command line options
|
||||
|
||||
## Command line options
|
||||
Add the argument *-h* when running inject with iidxhook to print help/usage
|
||||
information with a list of parameters you can apply to tweak various things.
|
||||
|
||||
## iidxio API
|
||||
Available implementations that can be swapped out depending on which kind of
|
||||
IO hardware you want to use:
|
||||
* `iidxio`: Default implementation supporting keyboard, mouse and USB
|
||||
game controllers
|
||||
* [iidxio-bio2](iidxhook/iidxio-bio2.md): Support BIO2 hardware
|
||||
* [iidxio-ezusb](iidxhook/iidxio-ezusb.md): Support C02 ezusb FX hardware
|
||||
* [iidxio-ezusb2](iidxhook/iidxio-ezusb2.md): Support IO2 ezusb FX2 hardware
|
||||
@@ -126,6 +126,16 @@ happens, run the game again.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
|
||||
## The game is running (very) slow in fullscreen mode but is fine in window mode
|
||||
If you are using a AMD GPU, try disabling "GPU scaling" which you can find in AMD
|
||||
settings UI under "Settings" -> "Display".
|
||||
|
||||
This issue only observed on 9th Style so far.
|
||||
|
||||
Use
|
||||
[bemanitool's built in upscaling feature](#over-underscan-bad-image-quality-or-latency-caused-by-my-monitorsTV-upscaler) if the game is not
|
||||
scaled properly in full screen.
|
||||
|
||||
## Window mode or any other gfx related options do not work when changing them in the config file or using cmd args
|
||||
|
||||
See [this](#Use-d3d8to9-wrapper) section.
|
||||
|
||||
@@ -85,17 +85,29 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
## USB IO (ezusb)
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
You have the following options:
|
||||
* Set `io.disable_io_emu=true` in the `iidxhook.conf` file to not hook ezusb
|
||||
IO communication with an emulation layer. The game will directly talk to the IO.
|
||||
The game supports the ezusb (C02) as well as ezusb FX2 (IO2) boards.
|
||||
* Set `io.disable_io_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (slotted readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
@@ -112,7 +124,7 @@ mainboard.
|
||||
# Known bugs
|
||||
## USBIO (FM-DL TIMEOUT)
|
||||
IIDX occasionally fails to boot with a "USBIO (FM-DL TIMEOUT)" error. If this
|
||||
happens, run the game again.
|
||||
happens, run the game again.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
|
||||
|
||||
@@ -85,17 +85,29 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
## USB IO (ezusb)
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
You have the following options:
|
||||
* Set `io.disable_io_emu=true` in the `iidxhook.conf` file to not hook ezusb
|
||||
IO communication with an emulation layer. The game will directly talk to the IO.
|
||||
The game supports the ezusb (C02) as well as ezusb FX2 (IO2) boards.
|
||||
* Set `io.disable_io_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (wave pass readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
|
||||
@@ -96,17 +96,29 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
## USB IO (ezusb)
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
You have the following options:
|
||||
* Set `io.disable_io_emu=true` in the `iidxhook.conf` file to not hook ezusb
|
||||
IO communication with an emulation layer. The game will directly talk to the IO.
|
||||
The game supports the ezusb (C02) as well as ezusb FX2 (IO2) boards.
|
||||
* Set `io.disable_io_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (wave pass readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
|
||||
@@ -101,17 +101,29 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
## USB IO (ezusb)
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
You have the following options:
|
||||
* Set `io.disable_io_emu=true` in the `iidxhook.conf` file to not hook ezusb
|
||||
IO communication with an emulation layer. The game will directly talk to the IO.
|
||||
The game supports the ezusb (C02) as well as ezusb FX2 (IO2) boards.
|
||||
* Set `io.disable_io_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (wave pass readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
|
||||
@@ -97,22 +97,31 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
### BIO2 hardware
|
||||
|
||||
Set the *io.disable_bio2_emu* configuration value to *1* to disable BIO2
|
||||
emulation to run the game using real BIO2 hardware.
|
||||
Set `io.disable_bio2_emu=true` in the `iidxhook.conf` file to not hook the BIO2
|
||||
communication with an emulation layer. The game will directly talk to the IO.
|
||||
In this mode, tthe game supports the BIO2 board only.
|
||||
|
||||
### Ezusb and other
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
Set `io.disable_bio2_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (wave pass readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
@@ -128,6 +137,16 @@ mainboard.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
|
||||
## The monitor check is showing high fps and I am using a monitor with high refresh rate features, e.g. 120/144hz
|
||||
Sync and timing might be screwed up since the game was never meant to run on
|
||||
such refresh rates. Try setting the option `gfx.forced_refresh_rate` to either
|
||||
`59` or `60`.
|
||||
|
||||
Note: Your GPU driver settings must be configured to allow application overrides
|
||||
on vertical sync/refresh rate options.
|
||||
|
||||
On AMD GPUs, set the "V-Sync" option to `On, unless application specifies`.
|
||||
|
||||
## The game does not run "well" (frame drops, drifting offsync etc)
|
||||
This can be related to various issues:
|
||||
* Make sure to run the game as (true) Administrator especially on Windows 7 and
|
||||
|
||||
@@ -92,24 +92,78 @@ cycle the machine (i.e. quit the game and restart it).
|
||||
|
||||
# Real hardware support
|
||||
|
||||
## The game does not go into either 640x480 (SD) or 1280x720 (HD) as expected but rather picks a resolution like 1386x768
|
||||
The graphics backend of the game is auto detecting the resolution and refresh
|
||||
rate based on the supported specs reported by the monitor. Depending on that
|
||||
output, this can lead to the game picking some "odd" resolution like 1386x768
|
||||
even the game is set to HD mode (expecting 1280x720).
|
||||
|
||||
Furthermore, this can lead to different refresh rate values on the automatic
|
||||
monitor check, e.g. compared to previous versions (59.94 on Rootage but 60.02
|
||||
on Heroic Verse). Ultimately, the result can be a very offsync gameplay
|
||||
experience with extremely delayed input.
|
||||
|
||||
If that happens, try forcing the resolution to `1280x720` when the game is
|
||||
set to HD mode in the operator menu. Note: Your monitor must also be capable
|
||||
of handling the resolution.
|
||||
|
||||
iidxhook.conf:
|
||||
```text
|
||||
gfx.force_screen_res.width=1280
|
||||
gfx.force_screen_res.height=720
|
||||
```
|
||||
|
||||
## The monitor check is showing high fps and I am using a monitor with high refresh rate features, e.g. 120/144hz
|
||||
Sync and timing might be screwed up since the game was never meant to run on
|
||||
such refresh rates. Try setting the option `gfx.forced_refresh_rate` to either
|
||||
`59` or `60`.
|
||||
|
||||
Note: Your GPU driver settings must be configured to allow application overrides
|
||||
on vertical sync/refresh rate options.
|
||||
|
||||
On AMD GPUs, set the "V-Sync" option to `On, unless application specifies`.
|
||||
|
||||
### BIO2 hardware
|
||||
|
||||
Set the *io.disable_bio2_emu* configuration value to *1* to disable BIO2
|
||||
emulation to run the game using real BIO2 hardware.
|
||||
Set `io.disable_bio2_emu=true` in the `iidxhook.conf` file to not hook the BIO2
|
||||
communication with an emulation layer. The game will directly talk to the IO.
|
||||
In this mode, the game supports the BIO2 board only.
|
||||
|
||||
## Driver notes
|
||||
You can use the default driver that Windows (7/10) automatically installs once
|
||||
you connect the BIO2 board via USB to your host. However, these drivers will
|
||||
not allow the game to detect the board correctly, throwing an IO error.
|
||||
The drivers will work fine when using the iidxio API implementation
|
||||
[iidxio-bio2](iidxio-bio2.md).
|
||||
|
||||
If you want to use the BIO2 with the game without the emulation layer, as
|
||||
suggested above, you need to install Konami's original driver which is
|
||||
identical to the stock Windows driver except the device name is different
|
||||
(which is the crucial part for the stock game's automatic detection).
|
||||
|
||||
The driver is available in the bemanitools-supplement repository.
|
||||
|
||||
### Ezusb and other
|
||||
|
||||
Use the specific iidxio API implementations, e.g. iidxio-ezusb2.dll to use
|
||||
the IO2 EZUSB board, to run the game on real hardware. Thanks to a common
|
||||
abstraction layer, you can also use custom IO boards or whatever Konami hardware
|
||||
is going to be available in the future. Obviously, someone has to write a
|
||||
driver, first.
|
||||
Set `io.disable_bio2_emu=false` in the `iidxhook.conf` file.
|
||||
Use the specific iidxio API implementations, e.g. `iidxio-ezusb2.dll` to use
|
||||
the IO2 EZUSB board. The common `iidxio` abstraction layer also allows you to
|
||||
use custom IO boards or whatever Konami hardware is going to be available in
|
||||
the future. Obviously, someone has to write an imlementation of the `iidxio`
|
||||
API, first.
|
||||
|
||||
## Slotted/Wave pass card readers
|
||||
|
||||
Replace the default *eamio.dll* with the *eamio-icca.dll* and have either your
|
||||
You have the following options:
|
||||
* Set `io.disable_card_reader_emu=true` in the `iidxhook.conf` file to not hook
|
||||
card reader communication with an emulation layer. The game will directly talk
|
||||
to the real readers though this only supports whatever readers the game
|
||||
directly supports (wave pass readers)
|
||||
* Set `io.disable_card_reader_emu=false` in the `iidxhook.conf` file.
|
||||
Replace the default `eamio.dll` with the `eamio-icca.dll` and have either your
|
||||
slotted (IIDX, DDR Supernova or GF/DM type) or new wave pass card readers
|
||||
conencted and and assigned to *COM1*.
|
||||
conencted and and assigned to `COM1`. Other custom implementations of of the
|
||||
`eamio` API also work.
|
||||
|
||||
### ICCA device settings (device manager)
|
||||
* Port: COM1
|
||||
@@ -124,6 +178,9 @@ stuck, try a USB <-> COM dongle instead of using one of the COM ports of the
|
||||
mainboard.
|
||||
|
||||
# Troubleshooting and FAQ
|
||||
## The turntable input feels laggy/delayed with my BIO2 + sub IO
|
||||
See the [this readme](hardware/bio2-sub-io-turntable-bypass-cable.md) for
|
||||
information about the bypass cable.
|
||||
|
||||
## The game does not run "well" (frame drops, drifting offsync etc)
|
||||
This can be related to various issues:
|
||||
|
||||
21
doc/iidxhook/iidxio-bio2.md
Normal file
21
doc/iidxhook/iidxio-bio2.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# IIDXIO API implementation with BIO2 driver
|
||||
This implementation of BT5's iidxio API allows you to use native BIO2 hardware with anything that
|
||||
supports BT5's iidxio API, e.g. all iidxhooks of BT5. Thus, you can play your favorite old IIDX
|
||||
games with the latest generation of hardware.5.
|
||||
|
||||
## Setup
|
||||
* Have `iidxio-bio2.dll` in the same folder as your `iidxhookX.dll`
|
||||
* Rename `iidxio-bio2.dll` to `iidxio.dll`
|
||||
* Ensure that your `gamestart.bat` actually injects the appropriate iidxhook dll, for example:
|
||||
```bat
|
||||
inject iidxhook3.dll bm2dx.exe ...*
|
||||
```
|
||||
or
|
||||
```bat
|
||||
launcher -K iidxhook4.dll bm2dx.dll ...*
|
||||
```
|
||||
* This assumes that the BIO2 is already flashed to the correct firmware. The firmware perists once
|
||||
flashed and does not need to be re-flashed after a power cycle.
|
||||
|
||||
## Driver notes
|
||||
See [here](iidxhook9.md#driver-notes).
|
||||
13
doc/jbhook/jbio-magicbox.md
Normal file
13
doc/jbhook/jbio-magicbox.md
Normal file
@@ -0,0 +1,13 @@
|
||||
This library talks to a MagicBox cab's IO and implements the jbio API of BT5.
|
||||
Thus, it allows you to use a MagicBox cab with *any* version of jubeat that is supported by BT5.
|
||||
|
||||
# Setup
|
||||
* Rename `jbio-magicbox.dll` to `jbio.dll`.
|
||||
* Make sure `jbio.dll` is in the same folder as both `jbhook.dll` and `jubeat.dll`
|
||||
* Make sure that you have a copy of the `ch341dll.dll` that comes with MagicBox.
|
||||
* Ensure that your `gamestart.bat` actually injects the appropriate jbhook dll
|
||||
for example:
|
||||
```
|
||||
launcher -K jbhook.dll jubeat.dll ...*
|
||||
```
|
||||
or that the application otherwise uses `jbio.dll`
|
||||
38
doc/tools/README.md
Normal file
38
doc/tools/README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Tools
|
||||
Documentation about various additional tooling that is fundamentally not required to run any of
|
||||
BT5's supported games, but provides additional features for users and developers alike.
|
||||
|
||||
## BT5 API
|
||||
Various command line tools for quick and easy testing of BT5 API implementations witohut having
|
||||
to run any target games.
|
||||
|
||||
* [eamiotest](eamiotest.md): `eamio` API
|
||||
* [iidxiotest](iidxiotest.md): `iidxio` API
|
||||
* [jbiotest](jbiotest.md): `jbio` API
|
||||
|
||||
## IO related
|
||||
### ACIO
|
||||
* [aciotest](aciotest.md): Command line tool for quick and easy testing of ACIO devices without
|
||||
having to run a game.
|
||||
|
||||
### Ezusb
|
||||
* [ezusb-iidx-fpga-flash](ezusb-iidx-fpga-flash.md): Tool for flashing the FPGA on ezusb 1 boards.
|
||||
Required if you want to run games without native ezusb support using BT5's iidxio API.
|
||||
* [ezusb-iidx-sram-flash](ezusb-iidx-sram-flash.md): Tool for flashing data to the SRAM of ezusb
|
||||
FX 2 boards. Required if you want to run games without native ezusb FX 2 support using BT5's iidxio
|
||||
API.
|
||||
* [ezusb-tool](ezusb-tool.md): Fundamental tool for flashing the base firmware to ezusb 1/2 boards.
|
||||
Required if you want to run games without native ezusb 1/2 support using BT5's iidxio API.
|
||||
|
||||
### IIDX exit hooks
|
||||
Exit hooks allow you to exit the game using a combination of inputs on native IO hardware.
|
||||
|
||||
Supported IO hardware:
|
||||
* [ezusb](iidx-ezusb-exit-hook.md)
|
||||
* [ezusb 2](iidx-ezusb2-exit-hook.md)
|
||||
* [bio2](iidx-bio2-exit-hook.md)
|
||||
|
||||
## Misc
|
||||
* [mempatch-hook]: Hook library to dynamically apply memory address patches during runtime before
|
||||
your application starts execution. Should be prefered over hardcoded hex-edits if applicable.
|
||||
* [pcbidgen]: Command line tool to generate random PCBIDs
|
||||
17
doc/tools/iidx-bio2-exit-hook.md
Normal file
17
doc/tools/iidx-bio2-exit-hook.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# IIDX BIO2 exit hook
|
||||
A hook library that can be used with BeatmaniaIIDX games that run the BIO2 IO board either natively,
|
||||
e.g. 25+, or using the [iidxio-bio2 backend](../iidxhook/iidx-bio2.md). It allows the player to
|
||||
exit the game by pressing the buttons `Start P1 + Start P2 + VEFX + Effect` simultaneously. This can
|
||||
be useful if you want an option to exit back to your desktop without having a keyboard attached.
|
||||
|
||||
The exit hook lib must be loaded like any other hook lib you are already injecting to the game
|
||||
using either `inject` or `launcher` (depending on the game version). The order for the hook libs is important as they are loaded in the order specified for the inject/launcher call. The entry in the `gamestart.bat` file should look like this for inject:
|
||||
```bat
|
||||
inject iidxhook3.dll -K iidx-bio2-exit-hook.dll bm2dx.exe ...
|
||||
```
|
||||
...and for launcher:
|
||||
```bat
|
||||
launcher -K iidxhook8.dll -K iidx-bio2-exit-hook.dll bm2dx.dll ...
|
||||
```
|
||||
|
||||
Where `iidxhook3.dll` is used for versions 14-15 and `iidxhook8.dll` for versions 25-26.
|
||||
13
doc/vigem/README.md
Normal file
13
doc/vigem/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# ViGEm: Virtual Gamepad Emulation Framework
|
||||
Virtual game controller emulation library. Allows us to create in code emulated XBOX controllers.
|
||||
|
||||
This is used to hook up BT5's various IO API libraries allowing you to use any of their
|
||||
implemtations as a game controller on Windows.
|
||||
|
||||
References:
|
||||
* [ViGEmBus](https://github.com/ViGEm/ViGEmBus)
|
||||
* [ViGEmClient](https://github.com/ViGEm/ViGEmClient)
|
||||
|
||||
Available ViGEm client implementations:
|
||||
* [vigem-iidxio](vigem-iidxio.md): Exposes inputs provided by the iidxio API as three XBOX gamepads
|
||||
* [vigem-sdvxio](vigem-sdvxio.md): Exposes inputs provided by the sdvxio API as one XBOX gamepad
|
||||
62
doc/vigem/vigem-iidxio.md
Normal file
62
doc/vigem/vigem-iidxio.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# ViGEm IIDXIO
|
||||
This application allows you to use any iidxio backend, e.g. `iidxio-ezusb.dll`, `iidxio-ezusb2.dll`
|
||||
or `iidxio-bio2.dll`, to be exposed as three XBOX 360 game controller on Windows.
|
||||
|
||||
Thus, it allows you to use a real cabinet with all its IO with *any* game that supports xinput.
|
||||
|
||||
Note: This will not work with games that require Direct Input (dinput), e.g. IIDX Infinitas.
|
||||
|
||||
## Setup
|
||||
* Install [ViGEmBus](https://github.com/ViGEm/ViGEmBus/releases)
|
||||
* Source for compiled binaries: [bemanitools-supplement](https://dev.s-ul.eu/djhackers/bemanitools-supplement)
|
||||
* Place the following in the same folder as `vigem-iidxio.exe`:
|
||||
* Get a copy of [ViGEmClient.dll](https://bin.jvnv.net/file/ZgMJK/ViGEmClient.zip) (or from bemanitools-supplements)
|
||||
* Rename your corresponding `iidxio-XXX.dll`, e.g. `iidxio-bio2.dll`, to `iidxio.dll`.
|
||||
* Run `vigem-iidxio.exe` so that the config file gets created (on first start)
|
||||
* Edit `vigem-iidxio.conf` if needed. Available options are explained in the file
|
||||
|
||||
## Usage
|
||||
* Depending on the iidxio implementation used, you might have to do some setup, e.g. flashing your
|
||||
IO board for [ezusb](../iidxhook/iidxio-ezusb.md#setup) or
|
||||
[ezusb2](../iidxhook/iidxio-ezusb2.md#setup)
|
||||
* Run `vigem-iidxio.exe` and keep it open/running
|
||||
* To quit the program, hit the `TEST` and `SERVICE` buttons at the same time
|
||||
|
||||
## Input mappings
|
||||
| Cabinet | XBOX Gamepad 1 | XBOX Gamepad 2 | XBOX Gamepad 3 |
|
||||
|------------|--------------------|--------------------|--------------------|
|
||||
| P1 Key 1 | A | | |
|
||||
| P1 Key 2 | B | | |
|
||||
| P1 Key 3 | X | | |
|
||||
| P1 Key 4 | Y | | |
|
||||
| P1 Key 5 | Left shoulder | | |
|
||||
| P1 Key 6 | Rights houlder | | |
|
||||
| P1 Key 7 | Start | | |
|
||||
| P2 Key 1 | | A | |
|
||||
| P2 Key 2 | | B | |
|
||||
| P2 Key 3 | | X | |
|
||||
| P2 Key 4 | | Y | |
|
||||
| P2 Key 5 | | Left shoulder | |
|
||||
| P2 Key 6 | | Rights houlder | |
|
||||
| P2 Key 7 | | Start | |
|
||||
| Start P1 | Back | | |
|
||||
| Start P2 | | Back | |
|
||||
| VEFX | | | B |
|
||||
| Effect | | | A |
|
||||
| Test | | | X |
|
||||
| Service | | | Y |
|
||||
| Coin | | | Start |
|
||||
| TT P1 Up | Thumbstick X axis+ | | |
|
||||
| TT P1 Down | Thumbstick X axis- | | |
|
||||
| TT P2 Up | | Thumbstick X axis+ | |
|
||||
| TT P2 Down | | Thumbstick X axis- | |
|
||||
|
||||
Turntables are either in absolute or relative mode depending on how it's defined in the
|
||||
`vigem-iidxio.conf`.
|
||||
|
||||
## Additional Notes For Cabinets (Running on embedded Windows 7):
|
||||
* Make sure that you follow the instructions exactly from the release page
|
||||
([Prerequisites for Windows 7](https://github.com/ViGEm/ViGEmBus/wiki/Prerequisites-for-Windows-7))
|
||||
* If you get an error while trying to install KB3033929, re-enable windows update
|
||||
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be
|
||||
done once)
|
||||
@@ -36,7 +36,8 @@ enum property_type {
|
||||
PROPERTY_TYPE_S64 = 8,
|
||||
PROPERTY_TYPE_U64 = 9,
|
||||
PROPERTY_TYPE_BIN = 10,
|
||||
PROPERTY_TYPE_STR = 11
|
||||
PROPERTY_TYPE_STR = 11,
|
||||
PROPERTY_TYPE_BOOL = 52
|
||||
};
|
||||
|
||||
struct property;
|
||||
@@ -57,8 +58,6 @@ enum psmap_type {
|
||||
PSMAP_TYPE_S64 = 8,
|
||||
PSMAP_TYPE_U64 = 9,
|
||||
PSMAP_TYPE_STR = 10,
|
||||
/* Used on avs 803 instead of value 10 */
|
||||
PSMAP_TYPE_STR_LEGACY = 11,
|
||||
PSMAP_TYPE_ATTR = 45,
|
||||
PSMAP_TYPE_BOOL = 50,
|
||||
};
|
||||
|
||||
19
src/imports/ch341.h
Normal file
19
src/imports/ch341.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* This is the header for ch341dll.dll, a library for interfacing with the
|
||||
* CH341 USB to serial/parallel port chip. Magic Box uses this for their
|
||||
* proprietary IO, and it provides access to the panel sensors.
|
||||
*
|
||||
* The full .h for this file is floating around online with many more functions
|
||||
* and comments (in Chinese). Only the bare minimum definitions are provided
|
||||
* here for use in jbio-magicbox
|
||||
*/
|
||||
|
||||
#ifndef IMPORTS_CH341_H
|
||||
#define IMPORTS_CH341_H
|
||||
|
||||
HANDLE WINAPI CH341OpenDevice(ULONG iIndex);
|
||||
VOID WINAPI CH341CloseDevice(ULONG iIndex);
|
||||
BOOL WINAPI CH341EppReadData(ULONG iIndex, PVOID oBuffer, PULONG ioLength);
|
||||
BOOL WINAPI CH341EppSetAddr(ULONG iIndex, UCHAR iAddr);
|
||||
|
||||
#endif
|
||||
7
src/imports/import_32_indep_ch341.def
Normal file
7
src/imports/import_32_indep_ch341.def
Normal file
@@ -0,0 +1,7 @@
|
||||
LIBRARY ch341dll
|
||||
|
||||
EXPORTS
|
||||
CH341OpenDevice@4=CH341OpenDevice
|
||||
CH341CloseDevice@4=CH341CloseDevice
|
||||
CH341EppReadData@12=CH341EppReadData
|
||||
CH341EppSetAddr@8=CH341EppSetAddr
|
||||
@@ -66,6 +66,7 @@ struct ac_io_message {
|
||||
uint8_t raw[0xFF];
|
||||
uint8_t count;
|
||||
uint8_t status;
|
||||
uint8_t param;
|
||||
struct ac_io_version version;
|
||||
|
||||
struct ac_io_icca_misc icca_misc;
|
||||
|
||||
@@ -70,6 +70,19 @@ enum iidx_io_panel_light {
|
||||
IIDX_IO_PANEL_LIGHT_EFFECT = 3,
|
||||
};
|
||||
|
||||
/* Bit mapping for the top lamps from left to right when facing cabinet screen */
|
||||
|
||||
enum iidx_io_top_lamp {
|
||||
IIDX_IO_TOP_LAMP_LEFT_BLUE = 0,
|
||||
IIDX_IO_TOP_LAMP_LEFT_GREEN = 1,
|
||||
IIDX_IO_TOP_LAMP_LEFT_YELLOW = 2,
|
||||
IIDX_IO_TOP_LAMP_LEFT_RED = 3,
|
||||
IIDX_IO_TOP_LAMP_RIGHT_BLUE = 4,
|
||||
IIDX_IO_TOP_LAMP_RIGHT_GREEN = 5,
|
||||
IIDX_IO_TOP_LAMP_RIGHT_YELLOW = 6,
|
||||
IIDX_IO_TOP_LAMP_RIGHT_RED = 7,
|
||||
};
|
||||
|
||||
/* The first function that will be called on your DLL. You will be supplied
|
||||
with four function pointers that may be used to log messages to the game's
|
||||
log file. See comments in glue.h for further information. */
|
||||
|
||||
@@ -3,6 +3,27 @@
|
||||
|
||||
#include "bio2/bio2.h"
|
||||
|
||||
enum bi2a_iidx_panel_button {
|
||||
BI2A_IIDX_PANEL_BUTTON_START_P1 = 0,
|
||||
BI2A_IIDX_PANEL_BUTTON_START_P2 = 1,
|
||||
BI2A_IIDX_PANEL_BUTTON_VEFX = 2,
|
||||
BI2A_IIDX_PANEL_BUTTON_EFFECT = 3,
|
||||
};
|
||||
|
||||
enum bi2a_iidx_spotlight_left {
|
||||
BI2A_IIDX_SPOTLIGHT_LEFT_BLUE = 0,
|
||||
BI2A_IIDX_SPOTLIGHT_LEFT_GREEN = 1,
|
||||
BI2A_IIDX_SPOTLIGHT_LEFT_YELLOW = 2,
|
||||
BI2A_IIDX_SPOTLIGHT_LEFT_RED = 3,
|
||||
};
|
||||
|
||||
enum bi2a_iidx_spotlight_right {
|
||||
BI2A_IIDX_SPOTLIGHT_RIGHT_RED = 0,
|
||||
BI2A_IIDX_SPOTLIGHT_RIGHT_YELLOW = 1,
|
||||
BI2A_IIDX_SPOTLIGHT_RIGHT_GREEN = 2,
|
||||
BI2A_IIDX_SPOTLIGHT_RIGHT_BLUE = 3,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct bi2a_iidx_slider {
|
||||
uint8_t s_unk : 4;
|
||||
@@ -30,7 +51,7 @@ struct bi2a_iidx_panel {
|
||||
uint8_t y_start1 : 1;
|
||||
};
|
||||
|
||||
struct bi2a_iidx_state_out {
|
||||
struct bi2a_iidx_state_in {
|
||||
struct bi2a_iidx_slider SLIDER1;
|
||||
struct bi2a_iidx_system SYSTEM;
|
||||
struct bi2a_iidx_slider SLIDER2;
|
||||
@@ -39,7 +60,7 @@ struct bi2a_iidx_state_out {
|
||||
uint8_t UNK2;
|
||||
struct bi2a_iidx_slider SLIDER4;
|
||||
struct bi2a_iidx_slider SLIDER5;
|
||||
uint8_t UNK3; // coin mech?
|
||||
uint8_t coins; // coin mech?
|
||||
struct bi2a_iidx_panel PANEL;
|
||||
uint8_t UNK4;
|
||||
uint8_t UNK5;
|
||||
@@ -84,23 +105,25 @@ struct bi2a_iidx_light {
|
||||
uint8_t l_state : 1;
|
||||
};
|
||||
|
||||
struct bi2a_iidx_state_in {
|
||||
struct bi2a_iidx_state_out {
|
||||
struct bi2a_iidx_light UNK1[3];
|
||||
struct bi2a_iidx_light PANEL[4];
|
||||
struct bi2a_iidx_light DECKSW[14];
|
||||
uint8_t UNK2[2];
|
||||
uint8_t SEG16[9];
|
||||
// right
|
||||
struct bi2a_iidx_light SPOTLIGHT1[4];
|
||||
struct bi2a_iidx_light NEONLAMP;
|
||||
// left
|
||||
struct bi2a_iidx_light SPOTLIGHT2[4];
|
||||
uint8_t UNK3[7];
|
||||
};
|
||||
_Static_assert(
|
||||
sizeof(struct bi2a_iidx_state_in) == 48,
|
||||
"bi2a_iidx_state_in is the wrong size");
|
||||
_Static_assert(
|
||||
sizeof(struct bi2a_iidx_state_out) == 46,
|
||||
sizeof(struct bi2a_iidx_state_out) == 48,
|
||||
"bi2a_iidx_state_out is the wrong size");
|
||||
_Static_assert(
|
||||
sizeof(struct bi2a_iidx_state_in) == 46,
|
||||
"bi2a_iidx_state_in is the wrong size");
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ struct bi2a_sdvx_state_in {
|
||||
uint16_t raw[8];
|
||||
struct {
|
||||
struct bi2a_sdvx_analog analogs[4];
|
||||
uint8_t unk_1; // coin mech?
|
||||
uint8_t coins;
|
||||
struct bi2a_sdvx_buttons1 buttons_1;
|
||||
struct bi2a_sdvx_buttons2 buttons_2;
|
||||
uint8_t unk_2[5];
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
#include <stdint.h>
|
||||
|
||||
enum bio2_bi2a_cmd {
|
||||
// Custom Stuff
|
||||
BIO2_BI2A_CMD_UNK_0100 = 0x0100,
|
||||
BIO2_BI2A_CMD_UNK_0120 = 0x0120,
|
||||
// Same as AC_IO_CMD_CLEAR but called differently
|
||||
// with a parameter required to initialize the IO correctly
|
||||
BIO2_BI2A_CMD_INIT = 0x0100,
|
||||
BIO2_BI2A_CMD_WATCHDOG = 0x0120,
|
||||
BIO2_BI2A_CMD_POLL = 0x0152, // For IIDX
|
||||
};
|
||||
|
||||
|
||||
@@ -6,4 +6,5 @@ libs_bio2drv := \
|
||||
src_bio2drv := \
|
||||
detect.c \
|
||||
config-bio2.c \
|
||||
bi2a-sdvx.c \
|
||||
bi2a-iidx.c \
|
||||
bi2a-sdvx.c
|
||||
|
||||
106
src/main/bio2drv/bi2a-iidx.c
Normal file
106
src/main/bio2drv/bi2a-iidx.c
Normal file
@@ -0,0 +1,106 @@
|
||||
#define LOG_MODULE "bio2drv-bi2a_iidx"
|
||||
|
||||
#include "bio2drv/bi2a-iidx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aciodrv/device.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
// Must be provided on init command. Actual meaning unknown right now.
|
||||
// Not providing this will not initialize the IO correctly resulting
|
||||
// in all inputs and outputs (over sub IO) other than 14 keys to not work.
|
||||
static const uint8_t _BIO2DR_BI2A_IIDX_INIT_DATA = 0x2D;
|
||||
|
||||
static bool bio2drv_bi2a_iidx_init_io(uint8_t node_id)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
msg.addr = node_id + 1;
|
||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
||||
msg.cmd.nbytes = 1;
|
||||
msg.cmd.param = _BIO2DR_BI2A_IIDX_INIT_DATA;
|
||||
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
log_warning("Init node failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_warning("Init of node %d, status: %d", node_id, msg.cmd.status);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool bio2drv_bi2a_iidx_watchdog_start(uint8_t node_id)
|
||||
{
|
||||
// exit early and don't actually call watchdog
|
||||
// the watchdog call actually returns different sized packets depending on
|
||||
// the state this results in an issue during packet processing (see: #68)
|
||||
return true;
|
||||
|
||||
/*
|
||||
struct ac_io_message msg;
|
||||
|
||||
msg.addr = node_id + 1;
|
||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
|
||||
msg.cmd.nbytes = 2;
|
||||
msg.cmd.nbytes = 2;
|
||||
|
||||
// uint16_t: 6000
|
||||
msg.cmd.raw[0] = 23;
|
||||
msg.cmd.raw[1] = 112;
|
||||
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 2
|
||||
)) {
|
||||
log_warning("Starting watchdog failed"); return false;
|
||||
}
|
||||
|
||||
log_warning("Started watchdog of node %d, status: %d",
|
||||
node_id, msg.cmd.status);
|
||||
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
bool bio2drv_bi2a_iidx_init(uint8_t node_id)
|
||||
{
|
||||
if (!bio2drv_bi2a_iidx_init_io(node_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bio2drv_bi2a_iidx_watchdog_start(node_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bio2drv_bi2a_iidx_poll(
|
||||
uint8_t node_id,
|
||||
const struct bi2a_iidx_state_out *pout,
|
||||
struct bi2a_iidx_state_in *pin)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
msg.addr = node_id + 1;
|
||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_POLL);
|
||||
msg.cmd.nbytes = sizeof(*pout);
|
||||
/* buffer size of data we expect */
|
||||
*(struct bi2a_iidx_state_out *) msg.cmd.raw = *pout;
|
||||
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
|
||||
log_warning("Polling of node %d failed", node_id + 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pin != NULL) {
|
||||
memcpy(pin, &msg.cmd.raw, sizeof(*pin));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
33
src/main/bio2drv/bi2a-iidx.h
Normal file
33
src/main/bio2drv/bi2a-iidx.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef BIO2DRV_BI2A_IIDX_H
|
||||
#define BIO2DRV_BI2A_IIDX_H
|
||||
|
||||
#include "bio2/bi2a-iidx.h"
|
||||
|
||||
/**
|
||||
* Initialize a BI2A node.
|
||||
*
|
||||
* @param node_id Id of the node to initialize (0 based).
|
||||
* @return True if successful, false on error.
|
||||
* @note This module is supposed to be used in combination with the common
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool bio2drv_bi2a_iidx_init(uint8_t node_id);
|
||||
|
||||
/**
|
||||
* Poll the BI2A board
|
||||
*
|
||||
* @param node_id Id of the node to query (0 based).
|
||||
* @param state Pointer to a state struct to return the current state to
|
||||
* (optional, NULL for none).
|
||||
* @return True on success, false on error.
|
||||
* @note This module is supposed to be used in combination with the common
|
||||
* device driver foundation.
|
||||
* @see driver.h
|
||||
*/
|
||||
bool bio2drv_bi2a_iidx_poll(
|
||||
uint8_t node_id,
|
||||
const struct bi2a_iidx_state_out *pout,
|
||||
struct bi2a_iidx_state_in *pin);
|
||||
|
||||
#endif
|
||||
@@ -9,15 +9,17 @@
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
static const uint8_t _BIO2DR_BI2A_SDVX_INIT_DATA = 0x3B;
|
||||
|
||||
// this is probably InitIO
|
||||
static bool bio2drv_bi2a_sdvx_init_io(uint8_t node_id)
|
||||
{
|
||||
struct ac_io_message msg;
|
||||
|
||||
msg.addr = node_id + 1;
|
||||
msg.cmd.code = ac_io_u16(AC_IO_CMD_CLEAR);
|
||||
msg.cmd.code = ac_io_u16(BIO2_BI2A_CMD_INIT);
|
||||
msg.cmd.nbytes = 1;
|
||||
msg.cmd.count = 0x3B;
|
||||
msg.cmd.param = _BIO2DR_BI2A_SDVX_INIT_DATA;
|
||||
|
||||
if (!aciodrv_send_and_recv(
|
||||
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
|
||||
|
||||
@@ -24,7 +24,7 @@ void bio2drv_config_bio2_init(struct cconfig *config)
|
||||
config,
|
||||
BIO2DRV_CONFIG_BIO2_PORT_KEY,
|
||||
BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE,
|
||||
"BIO2 serial port");
|
||||
"BIO2 serial port. Optional, if autodetect property is turned on");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
#include <windows.h> /* for _BitScanForward */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "acioemu/emu.h"
|
||||
#include "util/math.h"
|
||||
|
||||
#include "bemanitools/iidxio.h"
|
||||
|
||||
@@ -24,6 +26,13 @@ static void bio2_emu_bi2a_send_status(
|
||||
|
||||
static int default_sliders[5];
|
||||
static bool poll_delay;
|
||||
static bool coin_latch;
|
||||
static uint8_t coin_count;
|
||||
|
||||
static bool tt_multiplier_set;
|
||||
static float tt_multiplier = 1.f;
|
||||
static uint8_t tt_accum[2];
|
||||
static int16_t tt_last[2];
|
||||
|
||||
int get_default_slider_valid(size_t idx)
|
||||
{
|
||||
@@ -34,6 +43,12 @@ int get_default_slider_valid(size_t idx)
|
||||
}
|
||||
}
|
||||
|
||||
void bio2_emu_bi2a_set_tt_multiplier(float multiplier)
|
||||
{
|
||||
tt_multiplier_set = true;
|
||||
tt_multiplier = multiplier;
|
||||
}
|
||||
|
||||
void bio2_emu_bi2a_init(
|
||||
struct bio2emu_port *bio2_emu, bool disable_poll_limiter)
|
||||
{
|
||||
@@ -70,9 +85,13 @@ void bio2_emu_bi2a_dispatch_request(
|
||||
cmd_code = ac_io_u16(req->cmd.code);
|
||||
|
||||
switch (cmd_code) {
|
||||
case BIO2_BI2A_CMD_UNK_0100:
|
||||
case BIO2_BI2A_CMD_UNK_0120:
|
||||
log_misc("BIO2_BI2A_CMD_UNK_%04X(%d)", cmd_code, req->addr);
|
||||
case BIO2_BI2A_CMD_INIT:
|
||||
log_misc("BIO2_BI2A_CMD_INIT(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
|
||||
break;
|
||||
|
||||
case BIO2_BI2A_CMD_WATCHDOG:
|
||||
log_misc("BIO2_BI2A_CMD_WATCHDOGX(%d)", req->addr);
|
||||
bio2_emu_bi2a_send_status(&bio2port->acio, req, 0x00);
|
||||
break;
|
||||
|
||||
@@ -156,12 +175,21 @@ static void bio2_emu_bi2a_send_status(
|
||||
ac_io_emu_response_push(emu, &resp, 0);
|
||||
}
|
||||
|
||||
static int16_t tt_mult_delta(size_t tt_no) {
|
||||
int16_t current_tt = iidx_io_ep2_get_turntable(tt_no);
|
||||
int16_t delta = get_wrapped_delta_s16(current_tt, tt_last[tt_no], 256);
|
||||
|
||||
tt_last[tt_no] = current_tt;
|
||||
|
||||
return round(delta * tt_multiplier);
|
||||
}
|
||||
|
||||
static void
|
||||
bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
{
|
||||
struct ac_io_message resp;
|
||||
struct bi2a_iidx_state_out *body;
|
||||
struct bi2a_iidx_state_in *req_bi2a;
|
||||
struct bi2a_iidx_state_in *body;
|
||||
struct bi2a_iidx_state_out *req_bi2a;
|
||||
|
||||
uint8_t input_sys = 0;
|
||||
uint8_t input_panel = 0;
|
||||
@@ -176,8 +204,8 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
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 = sizeof(struct bi2a_iidx_state_out);
|
||||
req_bi2a = (struct bi2a_iidx_state_in *) req->cmd.raw;
|
||||
resp.cmd.nbytes = sizeof(struct bi2a_iidx_state_in);
|
||||
req_bi2a = (struct bi2a_iidx_state_out *) req->cmd.raw;
|
||||
|
||||
packed_lights.panel_lights = 0;
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
@@ -218,8 +246,8 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
return bio2_emu_bi2a_send_status(emu, req, 0);
|
||||
}
|
||||
|
||||
body = (struct bi2a_iidx_state_out *) &resp.cmd.raw;
|
||||
memset(body, 0, sizeof(struct bi2a_iidx_state_out));
|
||||
body = (struct bi2a_iidx_state_in *) &resp.cmd.raw;
|
||||
memset(body, 0, sizeof(struct bi2a_iidx_state_in));
|
||||
|
||||
// IIDX25 polls really really fast, this limits it to 1000Hz
|
||||
if (poll_delay) {
|
||||
@@ -231,8 +259,16 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
return bio2_emu_bi2a_send_status(emu, req, 0);
|
||||
}
|
||||
|
||||
body->TURNTABLE1 = iidx_io_ep2_get_turntable(0);
|
||||
body->TURNTABLE2 = iidx_io_ep2_get_turntable(1);
|
||||
if (tt_multiplier_set) {
|
||||
tt_accum[0] += tt_mult_delta(0);
|
||||
tt_accum[1] += tt_mult_delta(1);
|
||||
|
||||
body->TURNTABLE1 = tt_accum[0];
|
||||
body->TURNTABLE2 = tt_accum[1];
|
||||
} else {
|
||||
body->TURNTABLE1 = iidx_io_ep2_get_turntable(0);
|
||||
body->TURNTABLE2 = iidx_io_ep2_get_turntable(1);
|
||||
}
|
||||
|
||||
body->SLIDER1.s_val = get_default_slider_valid(0) ?
|
||||
default_sliders[0] :
|
||||
@@ -277,5 +313,16 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
body->SYSTEM.v_service = (input_sys >> IIDX_IO_SYS_SERVICE) & 1;
|
||||
body->SYSTEM.v_coin = (input_sys >> IIDX_IO_SYS_COIN) & 1;
|
||||
|
||||
if (body->SYSTEM.v_coin) {
|
||||
if (!coin_latch) {
|
||||
coin_latch = true;
|
||||
coin_count += 1;
|
||||
}
|
||||
} else {
|
||||
coin_latch = false;
|
||||
}
|
||||
|
||||
body->coins = coin_count;
|
||||
|
||||
ac_io_emu_response_push(emu, &resp, 0);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "bio2emu/emu.h"
|
||||
|
||||
void bio2_emu_bi2a_init(struct bio2emu_port *in, bool disable_poll_limiter);
|
||||
void bio2_emu_bi2a_set_tt_multiplier(float multiplier);
|
||||
void bio2_emu_bi2a_dispatch_request(
|
||||
struct bio2emu_port *bio2port, const struct ac_io_message *req);
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#define D3D9EXHOOK_CONFIG_GFX_FORCED_REFRESHRATE_KEY "gfx.forced_refresh_rate"
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEVICE_ADAPTER_KEY "gfx.device_adapter"
|
||||
#define D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY "gfx.force_orientation"
|
||||
#define D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY "gfx.force_screen_res.width"
|
||||
#define D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY "gfx.force_screen_res.height"
|
||||
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FRAMED_VALUE false
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_WINDOWED_VALUE false
|
||||
@@ -25,6 +27,8 @@
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCED_RR_VALUE -1
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_DEVICE_ADAPTER_VALUE -1
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE -1
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE -1
|
||||
#define D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE -1
|
||||
|
||||
void d3d9exhook_config_gfx_init(struct cconfig *config)
|
||||
{
|
||||
@@ -78,6 +82,20 @@ void d3d9exhook_config_gfx_init(struct cconfig *config)
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE,
|
||||
"Orientation to force monitor into, -1 to use default, "
|
||||
"0, 1, 2, 3 to do 0, 90, 180, 270 degrees");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE,
|
||||
"Force a screen resolution (width), -1 to disable. Use this if the game does not auto "
|
||||
"detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE,
|
||||
"Force a screen resolution (height), -1 to disable. Use this if the game does not auto "
|
||||
"detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720.");
|
||||
}
|
||||
|
||||
void d3d9exhook_config_gfx_get(
|
||||
@@ -178,4 +196,28 @@ void d3d9exhook_config_gfx_get(
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_ORIENTATION_KEY,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_ORIENTATION_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY,
|
||||
&config_gfx->force_screen_res.width,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_WIDTH_KEY,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_WIDTH_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY,
|
||||
&config_gfx->force_screen_res.height,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
D3D9EXHOOK_CONFIG_GFX_FORCE_SCREEN_RES_HEIGHT_KEY,
|
||||
D3D9EXHOOK_CONFIG_GFX_DEFAULT_FORCE_SCREEN_RES_HEIGHT_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ struct d3d9exhook_config_gfx {
|
||||
int32_t forced_refresh_rate;
|
||||
int32_t device_adapter;
|
||||
int32_t force_orientation;
|
||||
|
||||
struct force_screen_res {
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
} force_screen_res;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,6 +91,8 @@ static int32_t d3d9ex_window_height = -1;
|
||||
static bool d3d9ex_window_framed;
|
||||
static int32_t d3d9ex_device_adapter = -1;
|
||||
static int32_t d3d9ex_force_orientation = -1;
|
||||
static int32_t d3d9ex_force_screen_res_width = -1;
|
||||
static int32_t d3d9ex_force_screen_res_height = -1;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
@@ -242,14 +244,78 @@ static HRESULT STDCALL my_CreateDeviceEx(
|
||||
D3DDISPLAYMODEEX *fdm,
|
||||
IDirect3DDevice9Ex **pdev)
|
||||
{
|
||||
log_assert(self);
|
||||
log_assert(pp);
|
||||
log_assert(pdev);
|
||||
|
||||
IDirect3D9Ex *real = com_proxy_downcast(self)->real;
|
||||
HRESULT hr;
|
||||
|
||||
log_misc(
|
||||
"CreateDeviceEx parameters: adapter %d, type %d, hwnd %p, flags %lX, "
|
||||
"pdev %p",
|
||||
adapter,
|
||||
type,
|
||||
hwnd,
|
||||
flags,
|
||||
pdev);
|
||||
|
||||
if (fdm) {
|
||||
log_misc(
|
||||
"CreateDeviceEx display mode: size %d, width %d, height %d, refresh rate %d, format %d, "
|
||||
"scan line ordering %d",
|
||||
fdm->Size,
|
||||
fdm->Width,
|
||||
fdm->Height,
|
||||
fdm->RefreshRate,
|
||||
fdm->Format,
|
||||
fdm->ScanLineOrdering);
|
||||
}
|
||||
|
||||
log_misc(
|
||||
"D3D9EX presenter parameters: BackBufferWidth %d, BackBufferHeight "
|
||||
"%d, BackBufferFormat %d, "
|
||||
"BackBufferCount %d, MultiSampleType %d, MultiSampleQuality %ld, SwapEffect %d, "
|
||||
"hDeviceWindow %p, Windowed %d, "
|
||||
"EnableAutoDepthStencil "
|
||||
"%d, AutoDepthStencilFormat %d, Flags %lX, "
|
||||
"FullScreen_RefreshRateInHz %d, PresentationInterval %d",
|
||||
pp->BackBufferWidth,
|
||||
pp->BackBufferHeight,
|
||||
pp->BackBufferFormat,
|
||||
pp->BackBufferCount,
|
||||
pp->MultiSampleType,
|
||||
pp->MultiSampleQuality,
|
||||
pp->SwapEffect,
|
||||
pp->hDeviceWindow,
|
||||
pp->Windowed,
|
||||
pp->EnableAutoDepthStencil,
|
||||
pp->AutoDepthStencilFormat,
|
||||
pp->Flags,
|
||||
pp->FullScreen_RefreshRateInHz,
|
||||
pp->PresentationInterval);
|
||||
|
||||
if (d3d9ex_device_adapter >= 0) {
|
||||
log_info("Forcing adapter %d -> %d", adapter, d3d9ex_device_adapter);
|
||||
adapter = d3d9ex_device_adapter;
|
||||
}
|
||||
|
||||
if (d3d9ex_force_screen_res_width > 0 && d3d9ex_force_screen_res_height > 0) {
|
||||
log_info("Overriding screen resolution/back buffer of %dx%d -> %dx%d",
|
||||
pp->BackBufferWidth,
|
||||
pp->BackBufferHeight,
|
||||
d3d9ex_force_screen_res_width,
|
||||
d3d9ex_force_screen_res_height);
|
||||
|
||||
pp->BackBufferWidth = d3d9ex_force_screen_res_width;
|
||||
pp->BackBufferHeight = d3d9ex_force_screen_res_height;
|
||||
|
||||
if (fdm) {
|
||||
fdm->Width = pp->BackBufferWidth;
|
||||
fdm->Height = pp->BackBufferHeight;
|
||||
}
|
||||
}
|
||||
|
||||
if (d3d9ex_windowed) {
|
||||
fdm = NULL;
|
||||
pp->Windowed = TRUE;
|
||||
@@ -389,6 +455,14 @@ void d3d9ex_configure(struct d3d9exhook_config_gfx *gfx_config)
|
||||
d3d9ex_force_refresh_rate = gfx_config->forced_refresh_rate;
|
||||
d3d9ex_device_adapter = gfx_config->device_adapter;
|
||||
d3d9ex_force_orientation = gfx_config->force_orientation;
|
||||
|
||||
d3d9ex_force_screen_res_width = gfx_config->force_screen_res.width;
|
||||
d3d9ex_force_screen_res_height = gfx_config->force_screen_res.height;
|
||||
|
||||
if (d3d9ex_force_screen_res_width * d3d9ex_force_screen_res_height > 0) {
|
||||
log_warning("Force screen res: Only one, either width or height, is > 0."
|
||||
" Force screen res not activate");
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
12
src/main/iidx-bio2-exit-hook/Module.mk
Normal file
12
src/main/iidx-bio2-exit-hook/Module.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
dlls += iidx-bio2-exit-hook
|
||||
|
||||
ldflags_iidx-bio2-exit-hook := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_iidx-bio2-exit-hook := \
|
||||
bio2drv \
|
||||
hook \
|
||||
util \
|
||||
|
||||
src_iidx-bio2-exit-hook := \
|
||||
main.c \
|
||||
4
src/main/iidx-bio2-exit-hook/iidx-bio2-exit-hook.def
Normal file
4
src/main/iidx-bio2-exit-hook/iidx-bio2-exit-hook.def
Normal file
@@ -0,0 +1,4 @@
|
||||
LIBRARY iidx-bio2-exit-hook
|
||||
|
||||
EXPORTS
|
||||
DllMain@12 @1 NONAME
|
||||
255
src/main/iidx-bio2-exit-hook/main.c
Normal file
255
src/main/iidx-bio2-exit-hook/main.c
Normal file
@@ -0,0 +1,255 @@
|
||||
#define LOG_MODULE "iidx-bio2-exit-hook"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "acio/acio.h"
|
||||
|
||||
#include "bio2/bi2a-iidx.h"
|
||||
#include "bio2drv/detect.h"
|
||||
|
||||
#include "hook/iobuf.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/proc.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static const size_t _SIZE_ACIO_WRITE_SOF = sizeof(uint8_t);
|
||||
// See struct ac_io_message: addr + code + seq_no + nbytes
|
||||
static const size_t _SIZE_ACIO_WRITE_MSG_HEADER =
|
||||
sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint8_t) * 2;
|
||||
static const uint8_t _ACIO_NODE_BIO2 = 0x01;
|
||||
|
||||
static wchar_t _device_path[MAX_PATH];
|
||||
static HANDLE _device_handle;
|
||||
|
||||
static struct iobuf _buffer;
|
||||
static struct iobuf _buffer_unescaped;
|
||||
|
||||
static void _unescape_acio_buffer(struct iobuf* in, struct iobuf* out)
|
||||
{
|
||||
log_assert(in);
|
||||
log_assert(out);
|
||||
|
||||
bool next_escaped;
|
||||
|
||||
next_escaped = false;
|
||||
|
||||
for (size_t i = 0; i < in->pos; i++) {
|
||||
uint8_t b = in->bytes[i];
|
||||
|
||||
if (next_escaped) {
|
||||
out->bytes[out->pos++] = ~b;
|
||||
next_escaped = false;
|
||||
} else {
|
||||
if (b == AC_IO_SOF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (b == AC_IO_ESCAPE) {
|
||||
next_escaped = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
out->bytes[out->pos++] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _switch_off_all_lights(struct bi2a_iidx_state_out *state_out)
|
||||
{
|
||||
log_assert(state_out);
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(state_out->PANEL); i++) {
|
||||
state_out->PANEL[i].l_state = 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(state_out->DECKSW); i++) {
|
||||
state_out->DECKSW[i].l_state = 0;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(state_out->SEG16); i++) {
|
||||
state_out->SEG16[i] = ' ';
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(state_out->SPOTLIGHT1); i++) {
|
||||
state_out->SPOTLIGHT1[i].l_state = 0;
|
||||
}
|
||||
|
||||
state_out->NEONLAMP.l_state = 0;
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(state_out->SPOTLIGHT2); i++) {
|
||||
state_out->SPOTLIGHT2[i].l_state = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT _iohook_handler(struct irp *irp)
|
||||
{
|
||||
HRESULT result;
|
||||
|
||||
if (irp->op == IRP_OP_OPEN && _device_handle == INVALID_HANDLE_VALUE) {
|
||||
|
||||
if (!wcscmp(irp->open_filename, _device_path)) {
|
||||
result = iohook_invoke_next(irp);
|
||||
|
||||
if (result == S_OK) {
|
||||
_device_handle = irp->fd;
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
} else if (irp->fd == _device_handle) {
|
||||
switch (irp->op) {
|
||||
case IRP_OP_READ:
|
||||
result = iohook_invoke_next(irp);
|
||||
|
||||
if (result != S_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t to_read = irp->read.nbytes;
|
||||
|
||||
if (_buffer.pos + to_read >= _buffer.nbytes) {
|
||||
log_warning("Read buffer size exceeded");
|
||||
to_read = _buffer.nbytes - _buffer.pos;
|
||||
}
|
||||
|
||||
memcpy(_buffer.bytes + _buffer.pos, irp->read.bytes, to_read);
|
||||
|
||||
_buffer.pos += to_read;
|
||||
|
||||
return result;
|
||||
|
||||
case IRP_OP_WRITE:
|
||||
// Use write as a trigger to evaluate buffered data of previous reads.
|
||||
// Good enough to check for some button press combincation to exit the game
|
||||
// Not implementing a full acio stack for performance reasons
|
||||
// and to keep the complexity of this rather low for such crude feature.
|
||||
|
||||
// Un-escape the buffer to prepare it for further evaluation
|
||||
_buffer_unescaped.pos = 0;
|
||||
_unescape_acio_buffer(&_buffer, &_buffer_unescaped);
|
||||
|
||||
struct ac_io_message *msg = (struct ac_io_message*) _buffer_unescaped.bytes;
|
||||
|
||||
if (msg->addr == (AC_IO_RESPONSE_FLAG | _ACIO_NODE_BIO2) &&
|
||||
ac_io_u16(msg->cmd.code) == BIO2_BI2A_CMD_POLL) {
|
||||
struct bi2a_iidx_state_in *state_in = (struct bi2a_iidx_state_in*) msg->cmd.raw;
|
||||
|
||||
if (state_in->PANEL.y_start1 && state_in->PANEL.y_start2 &&
|
||||
state_in->PANEL.y_vefx && state_in->PANEL.y_effect) {
|
||||
log_info("Exit hook triggered");
|
||||
|
||||
// Last opportunity to write some output data to switch off lights
|
||||
// Hacky, since we don't have an acio stack but some checks to
|
||||
// protect from bad things happening
|
||||
|
||||
if (irp->write.nbytes >=
|
||||
_SIZE_ACIO_WRITE_SOF +
|
||||
_SIZE_ACIO_WRITE_MSG_HEADER +
|
||||
sizeof(struct bi2a_iidx_state_out)) {
|
||||
log_misc("Switching off lights");
|
||||
|
||||
// +_SIZE_ACIO_WRITE_SOF: Skip leading 0xAA
|
||||
struct ac_io_message *msg_out =
|
||||
(struct ac_io_message*) (irp->write.bytes + _SIZE_ACIO_WRITE_SOF);
|
||||
|
||||
// Guard assumption that reading poll is always followed by a writing
|
||||
// poll (according to traffic dumps from iidx 27, that's the case)
|
||||
if (msg_out->addr == _ACIO_NODE_BIO2 &&
|
||||
ac_io_u16(msg_out->cmd.code) == BIO2_BI2A_CMD_POLL &&
|
||||
msg_out->cmd.count == sizeof(struct bi2a_iidx_state_out)) {
|
||||
struct bi2a_iidx_state_out *state_out =
|
||||
(struct bi2a_iidx_state_out*) msg_out->cmd.raw;
|
||||
|
||||
_switch_off_all_lights(state_out);
|
||||
|
||||
result = iohook_invoke_next(irp);
|
||||
|
||||
if (result != S_OK) {
|
||||
log_warning("Writing output to switch lights off failed: %lX",
|
||||
result);
|
||||
}
|
||||
} else {
|
||||
log_warning("Skipping switching off lights, write output not "
|
||||
"identified as a poll message");
|
||||
}
|
||||
} else {
|
||||
log_warning(
|
||||
"Skipped switching off lights due to insufficient buffer size");
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
/* Don't use ExitProcess. This might result in deadlocks
|
||||
on newer games which rely more on multi threading */
|
||||
proc_terminate_current_process(0);
|
||||
}
|
||||
}
|
||||
|
||||
_buffer.pos = 0;
|
||||
|
||||
return iohook_invoke_next(irp);
|
||||
|
||||
case IRP_OP_CLOSE:
|
||||
_device_handle = INVALID_HANDLE_VALUE;
|
||||
return iohook_invoke_next(irp);
|
||||
|
||||
default:
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
} else {
|
||||
return iohook_invoke_next(irp);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE mod, DWORD reason, void *ctx)
|
||||
{
|
||||
log_to_writer(log_writer_stdout, NULL);
|
||||
|
||||
if (reason != DLL_PROCESS_ATTACH) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_device_handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
char buffer[MAX_PATH];
|
||||
|
||||
if (!bio2drv_detect(
|
||||
DETECT_DEVICEID,
|
||||
0,
|
||||
buffer,
|
||||
sizeof(buffer))) {
|
||||
log_warning("Autodetecting IIDX BIO2 failed, disabling exit hook");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
log_info("BIO2 device found: %s", buffer);
|
||||
|
||||
wchar_t* buffer_widen = str_widen(buffer);
|
||||
|
||||
wcscpy(_device_path, buffer_widen);
|
||||
free(buffer_widen);
|
||||
|
||||
// should be enough for this use-case
|
||||
_buffer.nbytes = 1024;
|
||||
_buffer.pos = 0;
|
||||
_buffer.bytes = xmalloc(_buffer.nbytes);
|
||||
|
||||
_buffer_unescaped.nbytes = 1024;
|
||||
_buffer_unescaped.pos = 0;
|
||||
_buffer_unescaped.bytes = xmalloc(_buffer_unescaped.nbytes);
|
||||
|
||||
iohook_push_handler(_iohook_handler);
|
||||
|
||||
log_info("Initialized");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/proc.h"
|
||||
|
||||
static BOOL STDCALL my_DeviceIoControl(
|
||||
HANDLE fd,
|
||||
@@ -163,12 +164,7 @@ static BOOL STDCALL my_DeviceIoControl(
|
||||
|
||||
/* Don't use ExitProcess. This might result in deadlocks
|
||||
on newer games which rely more on multi threading */
|
||||
HANDLE hnd;
|
||||
hnd = OpenProcess(
|
||||
SYNCHRONIZE | PROCESS_TERMINATE,
|
||||
TRUE,
|
||||
GetCurrentProcessId());
|
||||
TerminateProcess(hnd, 0);
|
||||
proc_terminate_current_process(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/proc.h"
|
||||
|
||||
#define IOCTL_VEND_USB_REQ 0x220024
|
||||
|
||||
@@ -124,12 +125,7 @@ static BOOL STDCALL my_DeviceIoControl(
|
||||
|
||||
/* Don't use ExitProcess. This might result in deadlocks
|
||||
on newer games which rely more on multi threading */
|
||||
HANDLE hnd;
|
||||
hnd = OpenProcess(
|
||||
SYNCHRONIZE | PROCESS_TERMINATE,
|
||||
TRUE,
|
||||
GetCurrentProcessId());
|
||||
TerminateProcess(hnd, 0);
|
||||
proc_terminate_current_process(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ src_iidxhook-util := \
|
||||
clock.c \
|
||||
config-eamuse.c \
|
||||
config-gfx.c \
|
||||
config-io.c \
|
||||
config-misc.c \
|
||||
config-sec.c \
|
||||
d3d9.c \
|
||||
|
||||
56
src/main/iidxhook-util/config-io.c
Normal file
56
src/main/iidxhook-util/config-io.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "iidxhook-util/config-io.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY \
|
||||
"io.disable_card_reader_emu"
|
||||
#define IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY "io.disable_io_emu"
|
||||
|
||||
#define IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
|
||||
#define IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE false
|
||||
|
||||
void iidxhook_config_io_init(struct cconfig *config)
|
||||
{
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE,
|
||||
"Disable card reader emulation and enable usage of real card reader "
|
||||
"hardware on COM1 (for games supporting slotted/wavepass readers)");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE,
|
||||
"Disable ezusb IO emulation and enable usage of real ezusb1/2 IO hardware");
|
||||
}
|
||||
|
||||
void iidxhook_config_io_get(
|
||||
struct iidxhook_config_io *config_io, struct cconfig *config)
|
||||
{
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
&config_io->disable_card_reader_emu,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_CARD_READER_EMU_KEY,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY,
|
||||
&config_io->disable_io_emu,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DISABLE_IO_EMU_KEY,
|
||||
IIDXHOOK_UTIL_CONFIG_IO_DEFAULT_DISABLE_IO_EMU_VALUE);
|
||||
}
|
||||
}
|
||||
18
src/main/iidxhook-util/config-io.h
Normal file
18
src/main/iidxhook-util/config-io.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef IIDXHOOK_UTIL_CONFIG_IO_H
|
||||
#define IIDXHOOK_UTIL_CONFIG_IO_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
struct iidxhook_config_io {
|
||||
bool disable_card_reader_emu;
|
||||
bool disable_io_emu;
|
||||
};
|
||||
|
||||
void iidxhook_config_io_init(struct cconfig *config);
|
||||
|
||||
void iidxhook_config_io_get(
|
||||
struct iidxhook_config_io *config_io, struct cconfig *config);
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "iidxhook-util/acio.h"
|
||||
#include "iidxhook-util/chart-patch.h"
|
||||
#include "iidxhook-util/config-gfx.h"
|
||||
#include "iidxhook-util/config-io.h"
|
||||
#include "iidxhook-util/d3d9.h"
|
||||
#include "iidxhook-util/log-server.h"
|
||||
#include "iidxhook-util/settings.h"
|
||||
@@ -48,6 +49,8 @@ static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
|
||||
iidxhook_util_d3d9_irp_handler,
|
||||
};
|
||||
|
||||
static struct iidxhook_config_io config_io;
|
||||
|
||||
static void
|
||||
iidxhook4_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
|
||||
{
|
||||
@@ -104,6 +107,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
config = cconfig_init();
|
||||
|
||||
iidxhook_config_gfx_init(config);
|
||||
iidxhook_config_io_init(config);
|
||||
|
||||
if (!cconfig_hook_config_init(
|
||||
config,
|
||||
@@ -115,6 +119,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
}
|
||||
|
||||
iidxhook_config_gfx_get(&config_gfx, config);
|
||||
iidxhook_config_io_get(&config_io, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
@@ -123,24 +128,34 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
iidxhook4_setup_d3d9_hooks(&config_gfx);
|
||||
|
||||
/* Start up IIDXIO.DLL */
|
||||
log_info("Starting IIDX IO backend");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_info("Starting IIDX IO backend");
|
||||
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("IIDX IO emulation backend disabled");
|
||||
}
|
||||
|
||||
/* Start up EAMIO.DLL */
|
||||
log_misc("Initializing card reader backend");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Initializing card reader backend");
|
||||
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("Card reader emulation backend disabled");
|
||||
}
|
||||
|
||||
/* iohooks are okay, even if emu is diabled since the fake handlers won't be
|
||||
* used */
|
||||
/* Set up IO emulation hooks _after_ IO API setup to allow
|
||||
API implementations with real IO devices */
|
||||
iohook_push_handler(ezusb2_emu_device_dispatch_irp);
|
||||
@@ -148,13 +163,17 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
iohook_push_handler(iidxhook_util_chart_patch_dispatch_irp);
|
||||
iohook_push_handler(settings_hook_dispatch_irp);
|
||||
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
if (!config_io.disable_io_emu) {
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
}
|
||||
|
||||
/* Card reader emulation, same issue with hooking as IO emulation */
|
||||
rs232_hook_init();
|
||||
|
||||
iidxhook_util_acio_init(true);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
iidxhook_util_acio_init(true);
|
||||
}
|
||||
|
||||
log_info("-------------------------------------------------------------");
|
||||
log_info("---------------- End iidxhook dll_entry_init ----------------");
|
||||
@@ -171,11 +190,15 @@ static bool my_dll_entry_main(void)
|
||||
|
||||
iidxhook_util_chart_patch_fini();
|
||||
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
}
|
||||
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
}
|
||||
|
||||
log_server_fini();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "iidxhook-util/acio.h"
|
||||
#include "iidxhook-util/config-gfx.h"
|
||||
#include "iidxhook-util/config-io.h"
|
||||
#include "iidxhook-util/d3d9.h"
|
||||
#include "iidxhook-util/log-server.h"
|
||||
#include "iidxhook-util/settings.h"
|
||||
@@ -47,6 +48,8 @@ static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
|
||||
iidxhook_util_d3d9_irp_handler,
|
||||
};
|
||||
|
||||
static struct iidxhook_config_io config_io;
|
||||
|
||||
static void
|
||||
iidxhook5_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
|
||||
{
|
||||
@@ -86,6 +89,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
config = cconfig_init();
|
||||
|
||||
iidxhook_config_gfx_init(config);
|
||||
iidxhook_config_io_init(config);
|
||||
|
||||
if (!cconfig_hook_config_init(
|
||||
config,
|
||||
@@ -97,6 +101,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
}
|
||||
|
||||
iidxhook_config_gfx_get(&config_gfx, config);
|
||||
iidxhook_config_io_get(&config_io, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
@@ -105,22 +110,30 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
iidxhook5_setup_d3d9_hooks(&config_gfx);
|
||||
|
||||
/* Start up IIDXIO.DLL */
|
||||
log_info("Starting IIDX IO backend");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_info("Starting IIDX IO backend");
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("IIDX IO emulation backend disabled");
|
||||
}
|
||||
|
||||
/* Start up EAMIO.DLL */
|
||||
log_misc("Initializing card reader backend");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Initializing card reader backend");
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("Card reader emulation backend disabled");
|
||||
}
|
||||
|
||||
/* Set up IO emulation hooks _after_ IO API setup to allow
|
||||
@@ -129,14 +142,18 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
iohook_push_handler(iidxhook_util_acio_dispatch_irp);
|
||||
iohook_push_handler(settings_hook_dispatch_irp);
|
||||
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
if (!config_io.disable_io_emu) {
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
}
|
||||
|
||||
/* Card reader emulation, same issue with hooking as IO emulation */
|
||||
rs232_hook_init();
|
||||
|
||||
/* Do not use legacy mode, first version with wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
/* Do not use legacy mode, first version with wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
}
|
||||
|
||||
log_info("-------------------------------------------------------------");
|
||||
log_info("---------------- End iidxhook dll_entry_init ----------------");
|
||||
@@ -151,11 +168,15 @@ static bool my_dll_entry_main(void)
|
||||
|
||||
result = app_hook_invoke_main();
|
||||
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
}
|
||||
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
}
|
||||
|
||||
log_server_fini();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "iidxhook-util/acio.h"
|
||||
#include "iidxhook-util/config-gfx.h"
|
||||
#include "iidxhook-util/config-io.h"
|
||||
#include "iidxhook-util/d3d9.h"
|
||||
#include "iidxhook-util/log-server.h"
|
||||
|
||||
@@ -46,6 +47,8 @@ static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
|
||||
iidxhook_util_d3d9_irp_handler,
|
||||
};
|
||||
|
||||
static struct iidxhook_config_io config_io;
|
||||
|
||||
static void
|
||||
iidxhook6_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
|
||||
{
|
||||
@@ -85,6 +88,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
config = cconfig_init();
|
||||
|
||||
iidxhook_config_gfx_init(config);
|
||||
iidxhook_config_io_init(config);
|
||||
|
||||
if (!cconfig_hook_config_init(
|
||||
config,
|
||||
@@ -96,6 +100,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
}
|
||||
|
||||
iidxhook_config_gfx_get(&config_gfx, config);
|
||||
iidxhook_config_io_get(&config_io, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
@@ -104,37 +109,51 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
iidxhook6_setup_d3d9_hooks(&config_gfx);
|
||||
|
||||
/* Start up IIDXIO.DLL */
|
||||
log_info("Starting IIDX IO backend");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_info("Starting IIDX IO backend");
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("IIDX IO emulation backend disabled");
|
||||
}
|
||||
|
||||
/* Start up EAMIO.DLL */
|
||||
log_misc("Initializing card reader backend");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Initializing card reader backend");
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("Card reader emulation backend disabled");
|
||||
}
|
||||
|
||||
/* iohooks are okay, even if emu is diabled since the fake handlers won't be
|
||||
* used */
|
||||
/* Set up IO emulation hooks _after_ IO API setup to allow
|
||||
API implementations with real IO devices */
|
||||
iohook_push_handler(ezusb2_emu_device_dispatch_irp);
|
||||
iohook_push_handler(iidxhook_util_acio_dispatch_irp);
|
||||
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
if (!config_io.disable_io_emu) {
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
}
|
||||
|
||||
/* Card reader emulation, same issue with hooking as IO emulation */
|
||||
rs232_hook_init();
|
||||
|
||||
/* Do not use legacy mode, wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
/* Do not use legacy mode, wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
}
|
||||
|
||||
log_info("-------------------------------------------------------------");
|
||||
log_info("---------------- End iidxhook dll_entry_init ----------------");
|
||||
@@ -149,11 +168,15 @@ static bool my_dll_entry_main(void)
|
||||
|
||||
result = app_hook_invoke_main();
|
||||
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
}
|
||||
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
}
|
||||
|
||||
log_server_fini();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "iidxhook-util/acio.h"
|
||||
#include "iidxhook-util/config-gfx.h"
|
||||
#include "iidxhook-util/config-io.h"
|
||||
#include "iidxhook-util/d3d9.h"
|
||||
#include "iidxhook-util/log-server.h"
|
||||
|
||||
@@ -46,6 +47,8 @@ static const hook_d3d9_irp_handler_t iidxhook_d3d9_handlers[] = {
|
||||
iidxhook_util_d3d9_irp_handler,
|
||||
};
|
||||
|
||||
static struct iidxhook_config_io config_io;
|
||||
|
||||
static void
|
||||
iidxhook7_setup_d3d9_hooks(const struct iidxhook_config_gfx *config_gfx)
|
||||
{
|
||||
@@ -85,6 +88,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
config = cconfig_init();
|
||||
|
||||
iidxhook_config_gfx_init(config);
|
||||
iidxhook_config_io_init(config);
|
||||
|
||||
if (!cconfig_hook_config_init(
|
||||
config,
|
||||
@@ -96,6 +100,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
}
|
||||
|
||||
iidxhook_config_gfx_get(&config_gfx, config);
|
||||
iidxhook_config_io_get(&config_io, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
@@ -104,37 +109,51 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
|
||||
iidxhook7_setup_d3d9_hooks(&config_gfx);
|
||||
|
||||
/* Start up IIDXIO.DLL */
|
||||
log_info("Starting IIDX IO backend");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_info("Starting IIDX IO backend");
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!iidx_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing IIDX IO backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("IIDX IO emulation backend disabled");
|
||||
}
|
||||
|
||||
/* Start up EAMIO.DLL */
|
||||
log_misc("Initializing card reader backend");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Initializing card reader backend");
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
eam_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!eam_io_init(avs_thread_create, avs_thread_join, avs_thread_destroy)) {
|
||||
log_fatal("Initializing card reader backend failed");
|
||||
}
|
||||
} else {
|
||||
log_info("Card reader emulation backend disabled");
|
||||
}
|
||||
|
||||
/* iohooks are okay, even if emu is diabled since the fake handlers won't be
|
||||
* used */
|
||||
/* Set up IO emulation hooks _after_ IO API setup to allow
|
||||
API implementations with real IO devices */
|
||||
iohook_push_handler(ezusb2_emu_device_dispatch_irp);
|
||||
iohook_push_handler(iidxhook_util_acio_dispatch_irp);
|
||||
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
if (!config_io.disable_io_emu) {
|
||||
hook_setupapi_init(&ezusb2_emu_desc_device.setupapi);
|
||||
ezusb2_emu_device_hook_init(ezusb2_iidx_emu_msg_init());
|
||||
}
|
||||
|
||||
/* Card reader emulation, same issue with hooking as IO emulation */
|
||||
rs232_hook_init();
|
||||
|
||||
/* Do not use legacy mode, wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
/* Do not use legacy mode, wave pass readers */
|
||||
iidxhook_util_acio_init(false);
|
||||
}
|
||||
|
||||
log_info("-------------------------------------------------------------");
|
||||
log_info("---------------- End iidxhook dll_entry_init ----------------");
|
||||
@@ -149,11 +168,15 @@ static bool my_dll_entry_main(void)
|
||||
|
||||
result = app_hook_invoke_main();
|
||||
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
if (!config_io.disable_card_reader_emu) {
|
||||
log_misc("Shutting down card reader backend");
|
||||
eam_io_fini();
|
||||
}
|
||||
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
if (!config_io.disable_io_emu) {
|
||||
log_misc("Shutting down IIDX IO backend");
|
||||
iidx_io_fini();
|
||||
}
|
||||
|
||||
log_server_fini();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define IIDXHOOK9_CONFIG_IO_LIGHTNING_MODE_KEY "io.lightning_mode"
|
||||
#define IIDXHOOK9_CONFIG_IO_DISABLE_CAMS_KEY "io.disable_cams"
|
||||
#define IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks"
|
||||
#define IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY "io.tt_multiplier"
|
||||
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false
|
||||
@@ -18,6 +19,7 @@
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_LIGHTNING_MODE_VALUE false
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_CAMS_VALUE false
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false
|
||||
#define IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE 1.0
|
||||
|
||||
void iidxhook9_config_io_init(struct cconfig *config)
|
||||
{
|
||||
@@ -57,6 +59,12 @@ void iidxhook9_config_io_init(struct cconfig *config)
|
||||
IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
|
||||
IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE,
|
||||
"Disables the built in file hooks, requiring manual file creation");
|
||||
|
||||
cconfig_util_set_float(
|
||||
config,
|
||||
IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY,
|
||||
IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE,
|
||||
"Turntable sensitivity multiplier (1.0 is default)");
|
||||
}
|
||||
|
||||
void iidxhook9_config_io_get(
|
||||
@@ -133,4 +141,16 @@ void iidxhook9_config_io_get(
|
||||
IIDXHOOK9_CONFIG_IO_DISABLE_FILE_HOOKS_KEY,
|
||||
IIDXHOOK9_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_float(
|
||||
config,
|
||||
IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY,
|
||||
&config_io->tt_multiplier,
|
||||
IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%f'",
|
||||
IIDXHOOK9_CONFIG_IO_TT_MULTIPLIER_KEY,
|
||||
IIDXHOOK9_CONFIG_IO_DEFAULT_TT_MULTIPLIER_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ struct iidxhook9_config_io {
|
||||
bool lightning_mode;
|
||||
bool disable_cams;
|
||||
bool disable_file_hooks;
|
||||
float tt_multiplier;
|
||||
};
|
||||
|
||||
void iidxhook9_config_io_init(struct cconfig *config);
|
||||
|
||||
@@ -166,6 +166,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param)
|
||||
if (!iidxhook9_config_io.disable_bio2_emu) {
|
||||
if (!iidxhook9_config_io.lightning_mode) {
|
||||
bio2emu_init();
|
||||
bio2_emu_bi2a_set_tt_multiplier(iidxhook9_config_io.tt_multiplier);
|
||||
bio2_emu_bi2a_init(&bio2_emu, iidxhook9_config_io.disable_poll_limiter);
|
||||
}
|
||||
}
|
||||
|
||||
13
src/main/iidxio-bio2/Module.mk
Normal file
13
src/main/iidxio-bio2/Module.mk
Normal file
@@ -0,0 +1,13 @@
|
||||
dlls += iidxio-bio2
|
||||
|
||||
ldflags_iidxio-bio2 := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_iidxio-bio2 := \
|
||||
aciodrv \
|
||||
bio2drv \
|
||||
cconfig \
|
||||
util \
|
||||
|
||||
src_iidxio-bio2 := \
|
||||
iidxio.c \
|
||||
18
src/main/iidxio-bio2/iidxio-bio2.def
Normal file
18
src/main/iidxio-bio2/iidxio-bio2.def
Normal file
@@ -0,0 +1,18 @@
|
||||
LIBRARY iidxio
|
||||
|
||||
EXPORTS
|
||||
iidx_io_ep1_send
|
||||
iidx_io_ep1_set_deck_lights
|
||||
iidx_io_ep1_set_panel_lights
|
||||
iidx_io_ep1_set_top_lamps
|
||||
iidx_io_ep1_set_top_neons
|
||||
iidx_io_ep2_get_keys
|
||||
iidx_io_ep2_get_panel
|
||||
iidx_io_ep2_get_sys
|
||||
iidx_io_ep2_get_slider
|
||||
iidx_io_ep2_get_turntable
|
||||
iidx_io_ep2_recv
|
||||
iidx_io_ep3_write_16seg
|
||||
iidx_io_fini
|
||||
iidx_io_init
|
||||
iidx_io_set_loggers
|
||||
355
src/main/iidxio-bio2/iidxio.c
Normal file
355
src/main/iidxio-bio2/iidxio.c
Normal file
@@ -0,0 +1,355 @@
|
||||
#include <windows.h>
|
||||
|
||||
#define LOG_MODULE "iidxio-bio2"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bemanitools/glue.h"
|
||||
#include "bemanitools/iidxio.h"
|
||||
|
||||
#include "cconfig/cconfig-main.h"
|
||||
|
||||
#include "aciodrv/device.h"
|
||||
#include "bio2drv/bi2a-iidx.h"
|
||||
#include "bio2drv/config-bio2.h"
|
||||
#include "bio2drv/detect.h"
|
||||
|
||||
#define log_misc(...) iidx_io_log_misc(LOG_MODULE, __VA_ARGS__)
|
||||
#define log_info(...) iidx_io_log_info(LOG_MODULE, __VA_ARGS__)
|
||||
#define log_warning(...) iidx_io_log_warning(LOG_MODULE, __VA_ARGS__)
|
||||
#define log_fatal(...) iidx_io_log_fatal(LOG_MODULE, __VA_ARGS__)
|
||||
|
||||
static log_formatter_t iidx_io_log_misc;
|
||||
static log_formatter_t iidx_io_log_info;
|
||||
static log_formatter_t iidx_io_log_warning;
|
||||
static log_formatter_t iidx_io_log_fatal;
|
||||
|
||||
static char autodetect_buffer[512];
|
||||
|
||||
static atomic_bool running;
|
||||
static atomic_bool processing_io;
|
||||
static int16_t bio2_node_id;
|
||||
|
||||
static struct bi2a_iidx_state_in pin_cur;
|
||||
static struct bi2a_iidx_state_out pout_staging;
|
||||
static struct bi2a_iidx_state_out pout_ready;
|
||||
|
||||
static bool _bio2_iidx_io_poll(
|
||||
const struct bi2a_iidx_state_out *pout, struct bi2a_iidx_state_in *pin)
|
||||
{
|
||||
if (!running) {
|
||||
return false;
|
||||
}
|
||||
|
||||
processing_io = true;
|
||||
|
||||
if (!bio2drv_bi2a_iidx_poll(bio2_node_id, pout, pin)) {
|
||||
processing_io = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
processing_io = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void iidx_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
iidx_io_log_misc = misc;
|
||||
iidx_io_log_info = info;
|
||||
iidx_io_log_warning = warning;
|
||||
iidx_io_log_fatal = fatal;
|
||||
|
||||
bio2drv_set_loggers(misc, info, warning, fatal);
|
||||
}
|
||||
|
||||
bool iidx_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
struct cconfig *config;
|
||||
struct bio2drv_config_bio2 config_bio2;
|
||||
|
||||
config = cconfig_init();
|
||||
|
||||
bio2drv_config_bio2_init(config);
|
||||
|
||||
if (!cconfig_main_config_init(
|
||||
config,
|
||||
"--bio2-config",
|
||||
"iidxio-bio2.conf",
|
||||
"--help",
|
||||
"-h",
|
||||
"iidxio-bio2",
|
||||
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
|
||||
cconfig_finit(config);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bio2drv_config_bio2_get(&config_bio2, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
const char *selected_port = config_bio2.port;
|
||||
|
||||
if (config_bio2.autodetect) {
|
||||
log_info("Attempting autodetect");
|
||||
|
||||
if (bio2drv_detect(
|
||||
DETECT_DEVICEID,
|
||||
0,
|
||||
autodetect_buffer,
|
||||
sizeof(autodetect_buffer))) {
|
||||
selected_port = autodetect_buffer;
|
||||
} else {
|
||||
log_info("Autodetect failed, falling back to using specified port");
|
||||
}
|
||||
}
|
||||
|
||||
if (!aciodrv_device_open(selected_port, config_bio2.baud)) {
|
||||
log_info("Opening BIO2 device on [%s] failed", selected_port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_info("Opening BIO2 device on [%s] successful", selected_port);
|
||||
|
||||
uint8_t node_count = aciodrv_device_get_node_count();
|
||||
log_info("Enumerated %d nodes", node_count);
|
||||
|
||||
bio2_node_id = -1;
|
||||
|
||||
for (uint8_t i = 0; i < node_count; i++) {
|
||||
char product[4];
|
||||
|
||||
aciodrv_device_get_node_product_ident(i, product);
|
||||
|
||||
log_info(
|
||||
"> %d: %c%c%c%c\n",
|
||||
i,
|
||||
product[0],
|
||||
product[1],
|
||||
product[2],
|
||||
product[3]);
|
||||
|
||||
if (!memcmp(product, "BI2A", 4)) {
|
||||
if (bio2_node_id != -1) {
|
||||
log_warning("Multiple BI2A found! Using highest node id.");
|
||||
}
|
||||
bio2_node_id = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (bio2_node_id != -1) {
|
||||
log_warning("Using BI2A on node: %d", bio2_node_id);
|
||||
|
||||
if (!bio2drv_bi2a_iidx_init(bio2_node_id)) {
|
||||
log_warning("Unable to start BI2A on node: %d", bio2_node_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
running = true;
|
||||
log_warning("iidxio-bio2 now running");
|
||||
} else {
|
||||
log_warning("No bio2 device found");
|
||||
}
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
void iidx_io_fini(void)
|
||||
{
|
||||
// Pushing some final state before closing the IO to the actual outputs, e.g. lights on/off
|
||||
// can be a bit finicky. Do a few polls to "enforce"/flush this final state
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
iidx_io_ep1_send();
|
||||
iidx_io_ep2_recv();
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
running = false;
|
||||
|
||||
while (processing_io) {
|
||||
// avoid banging
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
aciodrv_device_close();
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_deck_lights(uint16_t deck_lights)
|
||||
{
|
||||
for (uint8_t i = 0; i < sizeof(pout_staging.DECKSW); i++) {
|
||||
pout_staging.DECKSW[i].l_state = (deck_lights & (1 << i)) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_panel_lights(uint8_t panel_lights)
|
||||
{
|
||||
pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_START_P1].l_state =
|
||||
(panel_lights & (1 << IIDX_IO_PANEL_P1_START)) > 0;
|
||||
pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_START_P2].l_state =
|
||||
(panel_lights & (1 << IIDX_IO_PANEL_P2_START)) > 0;
|
||||
pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_VEFX].l_state =
|
||||
(panel_lights & (1 << IIDX_IO_PANEL_VEFX)) > 0;
|
||||
pout_staging.PANEL[BI2A_IIDX_PANEL_BUTTON_EFFECT].l_state =
|
||||
(panel_lights & (1 << IIDX_IO_PANEL_EFFECT)) > 0;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_top_lamps(uint8_t top_lamps)
|
||||
{
|
||||
pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_RED].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_RED)) > 0;
|
||||
pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_YELLOW].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_YELLOW)) > 0;
|
||||
pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_GREEN].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_GREEN)) > 0;
|
||||
pout_staging.SPOTLIGHT1[BI2A_IIDX_SPOTLIGHT_RIGHT_BLUE].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_RIGHT_BLUE)) > 0;
|
||||
|
||||
pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_RED].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_RED)) > 0;
|
||||
pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_YELLOW].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_YELLOW)) > 0;
|
||||
pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_GREEN].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_GREEN)) > 0;
|
||||
pout_staging.SPOTLIGHT2[BI2A_IIDX_SPOTLIGHT_LEFT_BLUE].l_state =
|
||||
(top_lamps & (1 << IIDX_IO_TOP_LAMP_LEFT_BLUE)) > 0;
|
||||
}
|
||||
|
||||
void iidx_io_ep1_set_top_neons(bool top_neons)
|
||||
{
|
||||
pout_staging.NEONLAMP.l_state = top_neons;
|
||||
}
|
||||
|
||||
bool iidx_io_ep1_send(void)
|
||||
{
|
||||
memcpy(&pout_ready, &pout_staging, sizeof(struct bi2a_iidx_state_out));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iidx_io_ep2_recv(void)
|
||||
{
|
||||
if (!_bio2_iidx_io_poll(&pout_ready, &pin_cur)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_turntable(uint8_t player_no)
|
||||
{
|
||||
switch (player_no) {
|
||||
case 0:
|
||||
return pin_cur.TURNTABLE1;
|
||||
case 1:
|
||||
return pin_cur.TURNTABLE2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_slider(uint8_t slider_no)
|
||||
{
|
||||
switch (slider_no) {
|
||||
case 0:
|
||||
return pin_cur.SLIDER1.s_val & 0xF;
|
||||
case 1:
|
||||
return pin_cur.SLIDER2.s_val & 0xF;
|
||||
case 2:
|
||||
return pin_cur.SLIDER3.s_val & 0xF;
|
||||
case 3:
|
||||
return pin_cur.SLIDER4.s_val & 0xF;
|
||||
case 4:
|
||||
return pin_cur.SLIDER5.s_val & 0xF;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_sys(void)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
if (pin_cur.SYSTEM.v_test) {
|
||||
state |= (1 << IIDX_IO_SYS_TEST);
|
||||
}
|
||||
|
||||
if (pin_cur.SYSTEM.v_service) {
|
||||
state |= (1 << IIDX_IO_SYS_SERVICE);
|
||||
}
|
||||
|
||||
if (pin_cur.SYSTEM.v_coin) {
|
||||
state |= (1 << IIDX_IO_SYS_COIN);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
uint8_t iidx_io_ep2_get_panel(void)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
if (pin_cur.PANEL.y_start1) {
|
||||
state |= (1 << IIDX_IO_PANEL_P1_START);
|
||||
}
|
||||
|
||||
if (pin_cur.PANEL.y_start2) {
|
||||
state |= (1 << IIDX_IO_PANEL_P2_START);
|
||||
}
|
||||
|
||||
if (pin_cur.PANEL.y_vefx) {
|
||||
state |= (1 << IIDX_IO_PANEL_VEFX);
|
||||
}
|
||||
|
||||
if (pin_cur.PANEL.y_effect) {
|
||||
state |= (1 << IIDX_IO_PANEL_EFFECT);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
uint16_t iidx_io_ep2_get_keys(void)
|
||||
{
|
||||
uint16_t state;
|
||||
|
||||
state = 0;
|
||||
|
||||
state |= ((pin_cur.P1SW1.b_val > 0) << IIDX_IO_KEY_P1_1);
|
||||
state |= ((pin_cur.P1SW2.b_val > 0) << IIDX_IO_KEY_P1_2);
|
||||
state |= ((pin_cur.P1SW3.b_val > 0) << IIDX_IO_KEY_P1_3);
|
||||
state |= ((pin_cur.P1SW4.b_val > 0) << IIDX_IO_KEY_P1_4);
|
||||
state |= ((pin_cur.P1SW5.b_val > 0) << IIDX_IO_KEY_P1_5);
|
||||
state |= ((pin_cur.P1SW6.b_val > 0) << IIDX_IO_KEY_P1_6);
|
||||
state |= ((pin_cur.P1SW7.b_val > 0) << IIDX_IO_KEY_P1_7);
|
||||
|
||||
state |= ((pin_cur.P2SW1.b_val > 0) << IIDX_IO_KEY_P2_1);
|
||||
state |= ((pin_cur.P2SW2.b_val > 0) << IIDX_IO_KEY_P2_2);
|
||||
state |= ((pin_cur.P2SW3.b_val > 0) << IIDX_IO_KEY_P2_3);
|
||||
state |= ((pin_cur.P2SW4.b_val > 0) << IIDX_IO_KEY_P2_4);
|
||||
state |= ((pin_cur.P2SW5.b_val > 0) << IIDX_IO_KEY_P2_5);
|
||||
state |= ((pin_cur.P2SW6.b_val > 0) << IIDX_IO_KEY_P2_6);
|
||||
state |= ((pin_cur.P2SW7.b_val > 0) << IIDX_IO_KEY_P2_7);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool iidx_io_ep3_write_16seg(const char *text)
|
||||
{
|
||||
memcpy(pout_staging.SEG16, text, sizeof(pout_staging.SEG16));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -75,13 +75,30 @@ bool iidx_io_init(
|
||||
} else {
|
||||
log_info(
|
||||
"Connected ezusb: vid 0x%X, pid 0x%X", ident.vid, ident.pid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Random data returned by device, likely not properly initalized on device side
|
||||
// Triggers random inputs and lights
|
||||
// Flush that by execute a few polls
|
||||
for (int i = 0; i < 10; i++) {
|
||||
iidx_io_ep2_recv();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void iidx_io_fini(void)
|
||||
{
|
||||
// Pushing some final state before closing the IO to the actual outputs, e.g. lights on/off
|
||||
// can be a bit finicky. Do a few polls to "enforce"/flush this final state
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
iidx_io_ep1_send();
|
||||
iidx_io_ep2_recv();
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
ezusb_close(iidx_io_ezusb_handle);
|
||||
iidx_io_ezusb_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,44 @@
|
||||
#include "util/log.h"
|
||||
#include "util/thread.h"
|
||||
|
||||
static uint8_t _fix_top_lamps_order(uint8_t top_lamps)
|
||||
{
|
||||
uint8_t out;
|
||||
|
||||
out = 0;
|
||||
|
||||
out |= ((1 << 0) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_RED) : 0;
|
||||
out |= ((1 << 1) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_YELLOW) : 0;
|
||||
out |= ((1 << 2) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_GREEN) : 0;
|
||||
out |= ((1 << 3) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_LEFT_BLUE) : 0;
|
||||
|
||||
out |= ((1 << 4) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_BLUE) : 0;
|
||||
out |= ((1 << 5) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_GREEN) : 0;
|
||||
out |= ((1 << 6) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_YELLOW) : 0;
|
||||
out |= ((1 << 7) & top_lamps) > 0 ? (1 << IIDX_IO_TOP_LAMP_RIGHT_RED) : 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void _all_lights_off_shutdown()
|
||||
{
|
||||
iidx_io_ep1_set_deck_lights(0);
|
||||
iidx_io_ep1_set_panel_lights(0);
|
||||
iidx_io_ep1_set_top_lamps(0);
|
||||
iidx_io_ep1_set_top_neons(false);
|
||||
|
||||
// Depending on the IO, pushing the state to the actual outputs, e.g. lights on/off
|
||||
// can be a bit finicky. Do a few times to "enforce" the state
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
iidx_io_ep1_send();
|
||||
// Required to handle iidxio-ezusb specific quirks with flushing 16seg text
|
||||
iidx_io_ep2_recv();
|
||||
iidx_io_ep3_write_16seg(" ");
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool to test your implementations of iidxio.
|
||||
*/
|
||||
@@ -150,7 +188,7 @@ int main(int argc, char **argv)
|
||||
|
||||
iidx_io_ep1_set_deck_lights(deck_lights);
|
||||
iidx_io_ep1_set_panel_lights(panel_lights);
|
||||
iidx_io_ep1_set_top_lamps(top_lamps);
|
||||
iidx_io_ep1_set_top_lamps(_fix_top_lamps_order(top_lamps));
|
||||
iidx_io_ep1_set_top_neons(top_neons);
|
||||
|
||||
/* light up keys when pressed */
|
||||
@@ -202,22 +240,6 @@ int main(int argc, char **argv)
|
||||
|
||||
switch (c) {
|
||||
case '1': {
|
||||
/* one last update to turn off the lights */
|
||||
iidx_io_ep1_set_deck_lights(0);
|
||||
iidx_io_ep1_set_panel_lights(0);
|
||||
iidx_io_ep1_set_top_lamps(0);
|
||||
iidx_io_ep1_set_top_neons(false);
|
||||
|
||||
if (!iidx_io_ep3_write_16seg(" ")) {
|
||||
printf("ERROR: Sending ep3 failed\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (!iidx_io_ep1_send()) {
|
||||
printf("ERROR: Sending ep1 failed\n");
|
||||
return -4;
|
||||
}
|
||||
|
||||
loop = false;
|
||||
break;
|
||||
}
|
||||
@@ -288,6 +310,9 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
system("cls");
|
||||
|
||||
_all_lights_off_shutdown();
|
||||
|
||||
iidx_io_fini();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -77,7 +77,7 @@ static void avs_boot_replace_property_str(
|
||||
property_node_remove(tmp);
|
||||
}
|
||||
|
||||
tmp = property_node_create(NULL, node, PSMAP_TYPE_STR_LEGACY, name, val);
|
||||
tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
|
||||
|
||||
if (tmp) {
|
||||
property_node_datasize(tmp);
|
||||
|
||||
11
src/main/jbio-magicbox/Module.mk
Normal file
11
src/main/jbio-magicbox/Module.mk
Normal file
@@ -0,0 +1,11 @@
|
||||
dlls += jbio-magicbox
|
||||
imps += ch341
|
||||
|
||||
deplibs_jbio-magicbox := \
|
||||
ch341 \
|
||||
|
||||
src_jbio-magicbox := \
|
||||
jbio.c \
|
||||
|
||||
libs_jbio-magicbox := \
|
||||
util \
|
||||
11
src/main/jbio-magicbox/jbio-magicbox.def
Normal file
11
src/main/jbio-magicbox/jbio-magicbox.def
Normal file
@@ -0,0 +1,11 @@
|
||||
LIBRARY jbio
|
||||
|
||||
EXPORTS
|
||||
jb_io_fini
|
||||
jb_io_get_panel_inputs
|
||||
jb_io_get_sys_inputs
|
||||
jb_io_init
|
||||
jb_io_read_inputs
|
||||
jb_io_set_loggers
|
||||
jb_io_set_rgb_led
|
||||
jb_io_write_outputs
|
||||
141
src/main/jbio-magicbox/jbio.c
Normal file
141
src/main/jbio-magicbox/jbio.c
Normal file
@@ -0,0 +1,141 @@
|
||||
// This implementation is ported from the device.dll source graciously
|
||||
// provided by zyp
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "bemanitools/jbio.h"
|
||||
#include "imports/ch341.h"
|
||||
#include "util/defs.h"
|
||||
|
||||
static uint16_t jb_io_panels;
|
||||
static uint8_t jb_io_sys_buttons;
|
||||
|
||||
static bool is_initialized = false;
|
||||
|
||||
static log_formatter_t jb_io_log_misc;
|
||||
static log_formatter_t jb_io_log_info;
|
||||
static log_formatter_t jb_io_log_warning;
|
||||
static log_formatter_t jb_io_log_fatal;
|
||||
|
||||
union magicbox_input {
|
||||
uint32_t dword;
|
||||
uint8_t bytes[4];
|
||||
};
|
||||
|
||||
void jb_io_set_loggers(
|
||||
log_formatter_t misc,
|
||||
log_formatter_t info,
|
||||
log_formatter_t warning,
|
||||
log_formatter_t fatal)
|
||||
{
|
||||
jb_io_log_misc = misc;
|
||||
jb_io_log_info = info;
|
||||
jb_io_log_warning = warning;
|
||||
jb_io_log_fatal = fatal;
|
||||
}
|
||||
|
||||
bool jb_io_init(
|
||||
thread_create_t thread_create,
|
||||
thread_join_t thread_join,
|
||||
thread_destroy_t thread_destroy)
|
||||
{
|
||||
if (CH341OpenDevice(0) < 0) {
|
||||
jb_io_log_warning("jbio", "Can't open CH341 device.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
is_initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void jb_io_fini(void)
|
||||
{
|
||||
CH341CloseDevice(0);
|
||||
}
|
||||
|
||||
static const uint32_t magic_panel_mappings[] = {
|
||||
(1 << 0x08),
|
||||
(1 << 0x0a),
|
||||
(1 << 0x0c),
|
||||
(1 << 0x0e),
|
||||
(1 << 0x07),
|
||||
(1 << 0x05),
|
||||
(1 << 0x03),
|
||||
(1 << 0x01),
|
||||
(1 << 0x09),
|
||||
(1 << 0x0b),
|
||||
(1 << 0x0d),
|
||||
(1 << 0x0f),
|
||||
(1 << 0x06),
|
||||
(1 << 0x04),
|
||||
(1 << 0x02),
|
||||
(1 << 0x00),
|
||||
};
|
||||
|
||||
static const uint32_t magic_sys_mappings[] = {
|
||||
(1 << 0x11), // TEST
|
||||
(1 << 0x10), // SERVICE
|
||||
(1 << 0x13), // COIN
|
||||
};
|
||||
|
||||
bool jb_io_read_inputs(void)
|
||||
{
|
||||
// Read IO board
|
||||
unsigned long size;
|
||||
union magicbox_input input;
|
||||
|
||||
input.dword = -1;
|
||||
jb_io_panels = 0;
|
||||
jb_io_sys_buttons = 0;
|
||||
|
||||
CH341EppSetAddr(0, 255);
|
||||
CH341EppSetAddr(0, 1);
|
||||
CH341EppSetAddr(0, 255);
|
||||
CH341EppSetAddr(0, 0);
|
||||
size = sizeof(uint8_t);
|
||||
CH341EppReadData(0, &input.bytes[0], &size);
|
||||
CH341EppSetAddr(0, 255);
|
||||
CH341EppSetAddr(0, 0);
|
||||
size = sizeof(uint8_t);
|
||||
CH341EppReadData(0, &input.bytes[1], &size);
|
||||
CH341EppSetAddr(0, 255);
|
||||
CH341EppSetAddr(0, 0);
|
||||
size = sizeof(uint8_t);
|
||||
CH341EppReadData(0, &input.bytes[2], &size);
|
||||
CH341EppSetAddr(0, 255);
|
||||
|
||||
for (uint8_t i = 0; i < lengthof(magic_panel_mappings); i++) {
|
||||
if ((input.dword & magic_panel_mappings[i]) == 0) {
|
||||
jb_io_panels |= 1 << i;
|
||||
}
|
||||
}
|
||||
for (uint8_t i = 0; i < lengthof(magic_sys_mappings); i++) {
|
||||
if ((input.dword & magic_sys_mappings[i]) == 0) {
|
||||
jb_io_sys_buttons |= 1 << i;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool jb_io_write_outputs(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t jb_io_get_sys_inputs(void)
|
||||
{
|
||||
return jb_io_sys_buttons;
|
||||
}
|
||||
|
||||
uint16_t jb_io_get_panel_inputs(void)
|
||||
{
|
||||
return jb_io_panels;
|
||||
}
|
||||
|
||||
void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
// I mean I guess there's reactive LEDs on the sides? I'm not going to the
|
||||
// effort to work out if they're controllable or not
|
||||
}
|
||||
@@ -160,3 +160,31 @@ void ea3_ident_to_property(
|
||||
|
||||
property_psmap_export(ea3_config, NULL, ident, ea3_ident_psmap);
|
||||
}
|
||||
|
||||
void ea3_ident_replace_property_bool(
|
||||
struct property_node *node, const char *name, uint8_t val)
|
||||
{
|
||||
struct property_node *tmp;
|
||||
|
||||
tmp = property_search(NULL, node, name);
|
||||
|
||||
if (tmp) {
|
||||
property_node_remove(tmp);
|
||||
}
|
||||
|
||||
property_node_create(NULL, node, PROPERTY_TYPE_BOOL, name, val);
|
||||
}
|
||||
|
||||
void ea3_ident_replace_property_str(
|
||||
struct property_node *node, const char *name, const char *val)
|
||||
{
|
||||
struct property_node *tmp;
|
||||
|
||||
tmp = property_search(NULL, node, name);
|
||||
|
||||
if (tmp) {
|
||||
property_node_remove(tmp);
|
||||
}
|
||||
|
||||
tmp = property_node_create(NULL, node, PROPERTY_TYPE_STR, name, val);
|
||||
}
|
||||
|
||||
@@ -38,5 +38,9 @@ bool ea3_ident_invoke_module_init(
|
||||
struct property_node *app_config);
|
||||
void ea3_ident_to_property(
|
||||
const struct ea3_ident *ident, struct property *ea3_config);
|
||||
void ea3_ident_replace_property_bool(
|
||||
struct property_node *node, const char *name, uint8_t val);
|
||||
void ea3_ident_replace_property_str(
|
||||
struct property_node *node, const char *name, const char *val);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -94,7 +94,8 @@ static AVS_LOG_WRITER(log_callback, chars, nchars, ctx)
|
||||
free(utf16);
|
||||
}
|
||||
|
||||
static void load_hook_dlls(struct array* hook_dlls) {
|
||||
static void load_hook_dlls(struct array *hook_dlls)
|
||||
{
|
||||
const char *hook_dll;
|
||||
|
||||
for (size_t i = 0; i < hook_dlls->nitems; i++) {
|
||||
@@ -283,6 +284,25 @@ int main(int argc, const char **argv)
|
||||
|
||||
ea3_ident_to_property(&ea3, ea3_config);
|
||||
|
||||
if (options.override_urlslash_enabled) {
|
||||
log_info(
|
||||
"Overriding url_slash to: %d", options.override_urlslash_value);
|
||||
|
||||
ea3_ident_replace_property_bool(
|
||||
ea3_config_root,
|
||||
"/network/url_slash",
|
||||
options.override_urlslash_value);
|
||||
}
|
||||
|
||||
if (options.override_service != NULL) {
|
||||
log_info("Overriding service url to: %s", options.override_service);
|
||||
|
||||
ea3_ident_replace_property_str(
|
||||
ea3_config_root,
|
||||
"/network/services",
|
||||
options.override_service);
|
||||
}
|
||||
|
||||
/* Start up e-Amusement client */
|
||||
|
||||
ea3_boot(ea3_config_root);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "imports/avs.h"
|
||||
|
||||
@@ -24,6 +25,10 @@ void options_init(struct options *options)
|
||||
options->remote_debugger = false;
|
||||
array_init(&options->hook_dlls);
|
||||
array_init(&options->before_hook_dlls);
|
||||
|
||||
options->override_service = NULL;
|
||||
options->override_urlslash_enabled = false;
|
||||
options->override_urlslash_value = false;
|
||||
}
|
||||
|
||||
bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
@@ -135,6 +140,34 @@ bool options_read_cmdline(struct options *options, int argc, const char **argv)
|
||||
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (i + 1 >= argc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
options->override_service = argv[++i];
|
||||
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
if (i + 1 >= argc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
options->override_urlslash_enabled = true;
|
||||
|
||||
const char * urlslash_value = argv[++i];
|
||||
|
||||
options->override_urlslash_value = false;
|
||||
if (_stricmp(urlslash_value, "1") == 0) {
|
||||
options->override_urlslash_value = true;
|
||||
}
|
||||
if (_stricmp(urlslash_value, "true") == 0) {
|
||||
options->override_urlslash_value = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
options->remote_debugger = true;
|
||||
|
||||
@@ -179,6 +212,8 @@ void options_print_usage(void)
|
||||
#endif
|
||||
" -P [pcbid] Specify PCBID (default: use ea3 config)\n"
|
||||
" -R [pcbid] Specify Soft ID (default: use ea3 config)\n"
|
||||
" -S [url] Specify service url (default: use ea3 config)\n"
|
||||
" -U [0/1] Specify url_slash (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 "
|
||||
|
||||
@@ -19,6 +19,9 @@ struct options {
|
||||
struct array hook_dlls;
|
||||
struct array before_hook_dlls;
|
||||
bool remote_debugger;
|
||||
const char *override_service;
|
||||
bool override_urlslash_enabled;
|
||||
bool override_urlslash_value;
|
||||
};
|
||||
|
||||
void options_init(struct options *options);
|
||||
|
||||
@@ -27,6 +27,9 @@ static bool poll_delay;
|
||||
|
||||
static bool force_headphones_on;
|
||||
|
||||
static bool coin_latch;
|
||||
static uint8_t coin_count;
|
||||
|
||||
void bio2_emu_bi2a_init(
|
||||
struct bio2emu_port *bio2_emu,
|
||||
bool disable_poll_limiter,
|
||||
@@ -241,10 +244,22 @@ bio2_emu_bi2a_send_state(struct ac_io_emu *emu, const struct ac_io_message *req)
|
||||
pin->analogs[0].a_val = sdvx_io_get_spinner_pos(0);
|
||||
pin->analogs[1].a_val = sdvx_io_get_spinner_pos(1);
|
||||
|
||||
pin->analogs[0].a_coin = check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN);
|
||||
pin->analogs[0].a_test = check_pin(sys, SDVX_IO_IN_GPIO_SYS_TEST);
|
||||
pin->analogs[0].a_service = check_pin(sys, SDVX_IO_IN_GPIO_SYS_SERVICE) ||
|
||||
check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN);
|
||||
pin->analogs[0].a_service = check_pin(sys, SDVX_IO_IN_GPIO_SYS_SERVICE);
|
||||
pin->analogs[0].a_coin = check_pin(sys, SDVX_IO_IN_GPIO_SYS_COIN);
|
||||
|
||||
if (pin->analogs[0].a_coin) {
|
||||
if (!coin_latch) {
|
||||
coin_latch = true;
|
||||
coin_count += 1;
|
||||
}
|
||||
} else {
|
||||
coin_latch = false;
|
||||
}
|
||||
|
||||
// this is NOT byteswapped, only the analogs are
|
||||
pin->coins = coin_count;
|
||||
|
||||
pin->raw[0] = ac_io_u16(pin->raw[0]);
|
||||
pin->raw[1] = ac_io_u16(pin->raw[1]);
|
||||
|
||||
|
||||
@@ -10,10 +10,12 @@ src_util := \
|
||||
iobuf.c \
|
||||
list.c \
|
||||
log.c \
|
||||
math.c \
|
||||
mem.c \
|
||||
msg-thread.c \
|
||||
net.c \
|
||||
os.c \
|
||||
proc.c \
|
||||
signal.c \
|
||||
str.c \
|
||||
thread.c \
|
||||
|
||||
22
src/main/util/math.c
Normal file
22
src/main/util/math.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include "util/math.h"
|
||||
|
||||
int16_t get_wrapped_delta_s16(int16_t val, int16_t last, int16_t bound) {
|
||||
int16_t half_point = bound / 2;
|
||||
|
||||
int16_t delta = val - last;
|
||||
|
||||
if (delta > half_point) {
|
||||
delta -= bound;
|
||||
}
|
||||
|
||||
if (delta < -half_point) {
|
||||
delta += bound;
|
||||
}
|
||||
|
||||
// delta is now between (-half_point - half_point)
|
||||
return delta;
|
||||
}
|
||||
|
||||
int16_t sign_s16(int16_t x) {
|
||||
return (x > 0) - (x < 0);
|
||||
}
|
||||
9
src/main/util/math.h
Normal file
9
src/main/util/math.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef UTIL_MATH_H
|
||||
#define UTIL_MATH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int16_t get_wrapped_delta_s16(int16_t val, int16_t last, int16_t bound);
|
||||
int16_t sign_s16(int16_t x);
|
||||
|
||||
#endif
|
||||
15
src/main/util/proc.c
Normal file
15
src/main/util/proc.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void proc_terminate_current_process(uint32_t exit_code)
|
||||
{
|
||||
HANDLE hnd;
|
||||
|
||||
hnd = OpenProcess(
|
||||
SYNCHRONIZE | PROCESS_TERMINATE,
|
||||
TRUE,
|
||||
GetCurrentProcessId());
|
||||
|
||||
TerminateProcess(hnd, 0);
|
||||
}
|
||||
5
src/main/util/proc.h
Normal file
5
src/main/util/proc.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void proc_terminate_current_process(uint32_t exit_code);
|
||||
22
src/main/vigem-iidxio/Module.mk
Normal file
22
src/main/vigem-iidxio/Module.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
exes += vigem-iidxio
|
||||
|
||||
deplibs_vigem-iidxio := \
|
||||
ViGEmClient \
|
||||
|
||||
cppflags_vigem-iidxio := \
|
||||
-I src/imports \
|
||||
|
||||
ldflags_vigem-iidxio := \
|
||||
-lsetupapi \
|
||||
|
||||
libs_vigem-iidxio := \
|
||||
cconfig \
|
||||
iidxio \
|
||||
util \
|
||||
vigemstub \
|
||||
|
||||
src_vigem-iidxio := \
|
||||
cab-16seg-sequencer.c \
|
||||
cab-light-sequencer.c \
|
||||
main.c \
|
||||
config.c \
|
||||
87
src/main/vigem-iidxio/cab-16seg-sequencer.c
Normal file
87
src/main/vigem-iidxio/cab-16seg-sequencer.c
Normal file
@@ -0,0 +1,87 @@
|
||||
#define LOG_MODULE "vigem-iidx-cab-16seg-sequencer"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static const uint8_t _MAX_LEN_16SEG = 9;
|
||||
|
||||
static bool _enabled;
|
||||
|
||||
static uint64_t _time_counter;
|
||||
static size_t _text_pos;
|
||||
|
||||
static char _text[1024 + 1];
|
||||
static size_t _text_len;
|
||||
|
||||
static uint32_t _scroll_cycle_time_ms;
|
||||
|
||||
static void _create_display_string_with_wrap_around(char* out_16seg)
|
||||
{
|
||||
size_t cur_text_pos = _text_pos;
|
||||
|
||||
for (uint8_t i = 0; i < _MAX_LEN_16SEG; i++) {
|
||||
if (cur_text_pos >= _text_len) {
|
||||
cur_text_pos = 0;
|
||||
}
|
||||
|
||||
out_16seg[i] = _text[cur_text_pos];
|
||||
cur_text_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
void vigem_iidxio_cab_16seg_sequencer_init(const char* text, uint32_t scroll_cycle_time_ms)
|
||||
{
|
||||
log_assert(text);
|
||||
|
||||
_text_len = strlen(text);
|
||||
|
||||
if (_text_len + 1 > sizeof(_text)) {
|
||||
log_warning("Truncating input text as it exceeds the max size");
|
||||
strncpy(_text, text, sizeof(_text) - 1);
|
||||
} else {
|
||||
strcpy(_text, text);
|
||||
}
|
||||
|
||||
_scroll_cycle_time_ms = scroll_cycle_time_ms;
|
||||
|
||||
_time_counter = time_get_counter();
|
||||
_enabled = true;
|
||||
|
||||
if (_enabled) {
|
||||
log_info("Initialized, cycle time %d ms, text \"%s\"", _scroll_cycle_time_ms, _text);
|
||||
}
|
||||
}
|
||||
|
||||
void vigem_iidxio_cab_16seg_sequencer_update(char* out_16seg)
|
||||
{
|
||||
log_assert(out_16seg);
|
||||
|
||||
memset(out_16seg, ' ', _MAX_LEN_16SEG);
|
||||
|
||||
if (!_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t counter_now = time_get_counter();
|
||||
uint32_t cycle_time_elapsed_ms = time_get_elapsed_ms(counter_now - _time_counter);
|
||||
|
||||
if (cycle_time_elapsed_ms >= _scroll_cycle_time_ms) {
|
||||
_time_counter = counter_now;
|
||||
_text_pos++;
|
||||
|
||||
if (_text_pos >= _text_len) {
|
||||
_text_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Have static text if not exceeding 16seg display size
|
||||
if (_text_len <= _MAX_LEN_16SEG) {
|
||||
memcpy(out_16seg, _text, _text_len);
|
||||
} else {
|
||||
_create_display_string_with_wrap_around(out_16seg);
|
||||
}
|
||||
}
|
||||
8
src/main/vigem-iidxio/cab-16seg-sequencer.h
Normal file
8
src/main/vigem-iidxio/cab-16seg-sequencer.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef VIGEM_IIDXIO_CAB_16SEG_SEQUENCER_H
|
||||
#define VIGEM_IIDXIO_CAB_16SEG_SEQUENCER_H
|
||||
|
||||
void vigem_iidxio_cab_16seg_sequencer_init(const char* text, uint32_t scroll_cycle_time_ms);
|
||||
|
||||
void vigem_iidxio_cab_16seg_sequencer_update(char* out_16seg);
|
||||
|
||||
#endif
|
||||
120
src/main/vigem-iidxio/cab-light-sequencer.c
Normal file
120
src/main/vigem-iidxio/cab-light-sequencer.c
Normal file
@@ -0,0 +1,120 @@
|
||||
#define LOG_MODULE "vigem-iidx-cab-light-sequencer"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "vigem-iidxio/cab-light-sequencer.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/math.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static const uint32_t _SEQ_CYCLE_TIME_MS = 2000;
|
||||
|
||||
static enum vigem_iidxio_cab_light_sequencer_mode _light_seq_mode;
|
||||
|
||||
static bool _first_update;
|
||||
static uint64_t _time_counter;
|
||||
|
||||
static uint8_t _tt_prev[2];
|
||||
static int32_t _tt_neon_on_state;
|
||||
|
||||
void _update_neons_seq_flash(bool* out_neon)
|
||||
{
|
||||
uint64_t counter_now = time_get_counter();
|
||||
uint32_t cycle_time_elapsed_ms = time_get_elapsed_ms(counter_now - _time_counter);
|
||||
|
||||
if (cycle_time_elapsed_ms < _SEQ_CYCLE_TIME_MS / 2) {
|
||||
*out_neon = false;
|
||||
} else {
|
||||
*out_neon = true;
|
||||
}
|
||||
|
||||
if (cycle_time_elapsed_ms >= _SEQ_CYCLE_TIME_MS) {
|
||||
_time_counter = counter_now;
|
||||
}
|
||||
}
|
||||
|
||||
void _update_neons_flash_tt_input(uint8_t tt_p1, uint8_t tt_p2, bool* out_neon)
|
||||
{
|
||||
if (_first_update) {
|
||||
_tt_prev[0] = tt_p1;
|
||||
_tt_prev[1] = tt_p2;
|
||||
return;
|
||||
}
|
||||
|
||||
int8_t delta[2];
|
||||
|
||||
delta[0] = tt_p1 - _tt_prev[0];
|
||||
delta[1] = tt_p2 - _tt_prev[1];
|
||||
|
||||
// Debounce to avoid too much flickering
|
||||
if (abs(_tt_neon_on_state) < 20) {
|
||||
if (delta[0] != 0) {
|
||||
_tt_neon_on_state += delta[0] * 4;
|
||||
}
|
||||
|
||||
if (delta[1] != 0) {
|
||||
_tt_neon_on_state += delta[1] * 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (_tt_neon_on_state != 0) {
|
||||
*out_neon = true;
|
||||
} else {
|
||||
*out_neon = false;
|
||||
}
|
||||
|
||||
if (_tt_neon_on_state > 0) {
|
||||
_tt_neon_on_state--;
|
||||
} else if (_tt_neon_on_state < 0) {
|
||||
_tt_neon_on_state++;
|
||||
}
|
||||
|
||||
_tt_prev[0] = tt_p1;
|
||||
_tt_prev[1] = tt_p2;
|
||||
}
|
||||
|
||||
void vigem_iidxio_cab_light_sequencer_init(
|
||||
enum vigem_iidxio_cab_light_sequencer_mode light_seq_mode)
|
||||
{
|
||||
_time_counter = time_get_counter();
|
||||
_light_seq_mode = light_seq_mode;
|
||||
|
||||
_first_update = true;
|
||||
|
||||
if (_light_seq_mode != LIGHT_SEQ_MODE_OFF) {
|
||||
log_info("Initialized");
|
||||
}
|
||||
}
|
||||
|
||||
void vigem_iidxio_cab_light_sequencer_update(
|
||||
uint16_t keys,
|
||||
uint8_t tt_p1,
|
||||
uint8_t tt_p2,
|
||||
bool* out_neon,
|
||||
uint8_t* out_spots)
|
||||
{
|
||||
log_assert(out_neon);
|
||||
log_assert(out_spots);
|
||||
|
||||
switch (_light_seq_mode) {
|
||||
case LIGHT_SEQ_MODE_NEONS_FLASH:
|
||||
_update_neons_seq_flash(out_neon);
|
||||
break;
|
||||
|
||||
case LIGHT_SEQ_MODE_NEONS_FLASH_TT_INPUT:
|
||||
_update_neons_flash_tt_input(tt_p1, tt_p2, out_neon);
|
||||
break;
|
||||
|
||||
case LIGHT_SEQ_MODE_OFF:
|
||||
// fallthrough
|
||||
default:
|
||||
*out_neon = false;
|
||||
*out_spots = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
_first_update = false;
|
||||
}
|
||||
23
src/main/vigem-iidxio/cab-light-sequencer.h
Normal file
23
src/main/vigem-iidxio/cab-light-sequencer.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef VIGEM_IIDXIO_CAB_LIGHT_SEQUENCER_H
|
||||
#define VIGEM_IIDXIO_CAB_LIGHT_SEQUENCER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum vigem_iidxio_cab_light_sequencer_mode {
|
||||
LIGHT_SEQ_MODE_OFF = 0,
|
||||
LIGHT_SEQ_MODE_NEONS_FLASH = 1,
|
||||
LIGHT_SEQ_MODE_NEONS_FLASH_TT_INPUT = 2,
|
||||
};
|
||||
|
||||
void vigem_iidxio_cab_light_sequencer_init(
|
||||
enum vigem_iidxio_cab_light_sequencer_mode light_seq_mode);
|
||||
|
||||
void vigem_iidxio_cab_light_sequencer_update(
|
||||
uint16_t keys,
|
||||
uint8_t tt_p1,
|
||||
uint8_t tt_p2,
|
||||
bool* out_neon,
|
||||
uint8_t* out_spots);
|
||||
|
||||
#endif
|
||||
227
src/main/vigem-iidxio/config.c
Normal file
227
src/main/vigem-iidxio/config.c
Normal file
@@ -0,0 +1,227 @@
|
||||
#include "cconfig/cconfig-main.h"
|
||||
#include "cconfig/cconfig-util.h"
|
||||
|
||||
#include "vigem-iidxio/config.h"
|
||||
|
||||
#include "util/log.h"
|
||||
|
||||
#define VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY "vigem.iidxio.tt.anlog.relative"
|
||||
#define VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY "vigem.iidxio.tt.anlog.relative_sensitivity"
|
||||
#define VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY "vigem.iidxio.tt.button.debounce"
|
||||
#define VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY "vigem.iidxio.tt.button.threshold"
|
||||
#define VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY "vigem.iidxio.tt.debug_output"
|
||||
#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY "vigem.iidxio.cab_light.enable_keylight"
|
||||
#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY "vigem.iidxio.cab_light.light_mode"
|
||||
#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY "vigem.iidxio.cab_light.text_16seg"
|
||||
#define VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY "vigem.iidxio.cab_light.text_scroll_cycle_time_ms"
|
||||
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE false
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE 1024
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE 20
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE 2
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE false
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE true
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE 0
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE ""
|
||||
#define VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE 500
|
||||
|
||||
static void _vigem_iidxio_config_init(struct cconfig *config)
|
||||
{
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE,
|
||||
"Use relative mode analog mapping instead of absolute analog values");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE,
|
||||
"Sensitivity value for relative mode (1 to 32767). Tweak if you are having issues with "
|
||||
"jittering/misfiring/unresponsiveness");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE,
|
||||
"Button turntable: \"debounce\" value (1 to 50, recommend 20). Tweak if you are having "\
|
||||
"issues with TT button misfiring/unresponsiveness");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE,
|
||||
"Button turntable: minimum ticks required within (debounce * 2) ms to register movement "
|
||||
"(1 to 4, recommend 2). Tweak if you button input is too (un-) responsive");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE,
|
||||
"Print verbose debug output to the console for debugging turntable sensitivity issues");
|
||||
|
||||
cconfig_util_set_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE,
|
||||
"Enable input based key lighting");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE,
|
||||
"Different cabinet light modes: 0 = off, 1 = neons sequence, 2 = neons flash on TT spin");
|
||||
|
||||
cconfig_util_set_str(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE,
|
||||
"Display text on 16seg. If text exceeds 9 char display limit, it will scroll + cycle");
|
||||
|
||||
cconfig_util_set_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE,
|
||||
"Cycle time/scroll speed for text exceeding 16seg display length (9) to scroll from right");
|
||||
}
|
||||
|
||||
static void _vigem_iidxio_config_get(
|
||||
struct vigem_iidxio_config *vigem_config, struct cconfig *config)
|
||||
{
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY,
|
||||
&vigem_config->tt.analog.relative,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY,
|
||||
&vigem_config->tt.analog.relative_sensitivity,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_TT_ANALOG_RELATIVE_SENSITIVITY_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_ANALOG_RELATIVE_SENSITIVITY_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY,
|
||||
&vigem_config->tt.button.debounce,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_DEBOUNCE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_DEBOUNCE_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY,
|
||||
&vigem_config->tt.button.threshold,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_TT_BUTTON_THRESHOLD_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_BUTTON_THRESHOLD_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY,
|
||||
&vigem_config->tt.debug_output,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_TT_DEBUG_OUTPUT_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_TT_DEBUG_OUTPUT_VALUE);
|
||||
}
|
||||
|
||||
|
||||
if (!cconfig_util_get_bool(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY,
|
||||
&vigem_config->cab_light.enable_keylight,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_ENABLE_KEYLIGHT_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_ENABLE_KEYLIGHT_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY,
|
||||
&vigem_config->cab_light.light_mode,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_LIGHT_MODE_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_LIGHT_MODE_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_str(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY,
|
||||
vigem_config->cab_light.text_16seg,
|
||||
sizeof(vigem_config->cab_light.text_16seg),
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%s'",
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_16SEG_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_16SEG_VALUE);
|
||||
}
|
||||
|
||||
if (!cconfig_util_get_int(
|
||||
config,
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY,
|
||||
&vigem_config->cab_light.text_scroll_cycle_time_ms,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE)) {
|
||||
log_warning(
|
||||
"Invalid value for key '%s' specified, fallback "
|
||||
"to default '%d'",
|
||||
VIGEM_IIDXIO_CONFIG_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_KEY,
|
||||
VIGEM_IIDXIO_CONFIG_DEFAULT_CAB_LIGHT_TEXT_SCROLL_CYCLE_TIME_MS_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
bool vigem_iidxio_config_get(struct vigem_iidxio_config *config_out)
|
||||
{
|
||||
struct cconfig *config;
|
||||
|
||||
config = cconfig_init();
|
||||
|
||||
_vigem_iidxio_config_init(config);
|
||||
|
||||
if (!cconfig_main_config_init(
|
||||
config,
|
||||
"--config",
|
||||
"vigem-iidxio.conf",
|
||||
"--help",
|
||||
"-h",
|
||||
"vigem-iidxio",
|
||||
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
|
||||
cconfig_finit(config);
|
||||
return false;
|
||||
}
|
||||
|
||||
_vigem_iidxio_config_get(config_out, config);
|
||||
|
||||
cconfig_finit(config);
|
||||
|
||||
return true;
|
||||
}
|
||||
33
src/main/vigem-iidxio/config.h
Normal file
33
src/main/vigem-iidxio/config.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef VIGEM_IIDXIO_CONFIG_H
|
||||
#define VIGEM_IIDXIO_CONFIG_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "cconfig/cconfig.h"
|
||||
|
||||
struct vigem_iidxio_config {
|
||||
struct tt {
|
||||
struct analog {
|
||||
bool relative;
|
||||
int32_t relative_sensitivity;
|
||||
} analog;
|
||||
|
||||
struct button {
|
||||
int32_t debounce;
|
||||
int32_t threshold;
|
||||
} button;
|
||||
|
||||
bool debug_output;
|
||||
} tt;
|
||||
|
||||
struct cab_light {
|
||||
bool enable_keylight;
|
||||
int32_t light_mode;
|
||||
char text_16seg[1024 + 1];
|
||||
int32_t text_scroll_cycle_time_ms;
|
||||
} cab_light;
|
||||
};
|
||||
|
||||
bool vigem_iidxio_config_get(struct vigem_iidxio_config *config_out);
|
||||
|
||||
#endif
|
||||
419
src/main/vigem-iidxio/main.c
Normal file
419
src/main/vigem-iidxio/main.c
Normal file
@@ -0,0 +1,419 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ViGEm/Client.h>
|
||||
|
||||
#include "bemanitools/iidxio.h"
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/math.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/time.h"
|
||||
|
||||
#include "vigem-iidxio/cab-16seg-sequencer.h"
|
||||
#include "vigem-iidxio/cab-light-sequencer.h"
|
||||
#include "vigem-iidxio/config.h"
|
||||
|
||||
#include "vigemstub/helper.h"
|
||||
|
||||
#define JOYSTICKS_NUM 3
|
||||
#define TURNTABLE_NUM 2
|
||||
|
||||
static uint8_t _tt_last_raw[TURNTABLE_NUM];
|
||||
static int32_t _tt_state_for_analog[TURNTABLE_NUM];
|
||||
static int16_t _tt_state_for_btn[TURNTABLE_NUM];
|
||||
|
||||
static int16_t _convert_analog_to_s16(uint8_t val)
|
||||
{
|
||||
// TT analog value is 8 bit, upscale to 16 bit
|
||||
return (int64_t) val * 256;
|
||||
}
|
||||
|
||||
static int16_t _filter_floor(int32_t value, int16_t floor) {
|
||||
if (abs(value) < floor) {
|
||||
return 0;
|
||||
}
|
||||
if (value > INT16_MAX) {
|
||||
value = INT16_MAX;
|
||||
}
|
||||
if (value < INT16_MIN) {
|
||||
value = INT16_MIN;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int32_t _convert_relative_analog(
|
||||
uint8_t val, uint8_t last, int32_t buffered_last, int16_t multiplier)
|
||||
{
|
||||
int16_t delta = get_wrapped_delta_s16(val, last, UINT8_MAX);
|
||||
|
||||
if (delta == 0) {
|
||||
// ease the stick back to 0 like a real stick would
|
||||
return buffered_last / 2.f;
|
||||
} else {
|
||||
int64_t result = buffered_last;
|
||||
result += delta * multiplier;
|
||||
|
||||
// we use an i32 to store the buffered value
|
||||
// so that we can overshoot an i16 by up to 1.5x
|
||||
// this allows users to stay at the min/max stick positions
|
||||
// without perfect knob turning
|
||||
if (result > INT16_MAX * 1.5) {
|
||||
result = INT16_MAX * 1.5;
|
||||
}
|
||||
if (result < INT16_MIN * 1.5) {
|
||||
result = INT16_MIN * 1.5;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static bool _check_key(uint16_t input, size_t idx_in)
|
||||
{
|
||||
if ((input >> idx_in) & 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint16_t _check_assign_key(uint16_t input, size_t idx_in, size_t bit_out)
|
||||
{
|
||||
if (_check_key(input, idx_in)) {
|
||||
return bit_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t _handle_turntable_analog(
|
||||
const struct vigem_iidxio_config* config,
|
||||
uint8_t tt_cur,
|
||||
uint8_t tt_last,
|
||||
int32_t tt_state,
|
||||
XUSB_REPORT *pad_state)
|
||||
{
|
||||
int32_t state = tt_state;
|
||||
|
||||
if (config->tt.analog.relative) {
|
||||
state = _convert_relative_analog(
|
||||
tt_cur, tt_last, state, config->tt.analog.relative_sensitivity);
|
||||
|
||||
pad_state->sThumbLX = _filter_floor(state, config->tt.analog.relative_sensitivity / 2);
|
||||
} else {
|
||||
pad_state->sThumbLX = _convert_analog_to_s16(tt_cur);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static int16_t _handle_turntable_as_button(
|
||||
const struct vigem_iidxio_config* config,
|
||||
uint8_t tt_cur,
|
||||
uint8_t tt_last,
|
||||
int16_t tt_state,
|
||||
XUSB_REPORT *pad_state)
|
||||
{
|
||||
const uint8_t btn_inc = config->tt.button.debounce;
|
||||
const uint16_t btn_threshhold = btn_inc * config->tt.button.threshold;
|
||||
const uint16_t btn_max = btn_threshhold * 2;
|
||||
|
||||
int8_t delta = tt_cur - tt_last;
|
||||
int16_t state = tt_state;
|
||||
|
||||
if (config->tt.debug_output) {
|
||||
printf("delta_button %d, ", delta);
|
||||
}
|
||||
|
||||
// TT direction changed suddendly -> fast scratchin' action like a real DJ
|
||||
// Reset state to avoid lag with state having to decrease from high values
|
||||
if (delta > 0 && delta >= config->tt.button.threshold && state < 0) {
|
||||
state = 0;
|
||||
} else if (delta < 0 && abs(delta) >= config->tt.button.threshold && state > 0) {
|
||||
state = 0;
|
||||
}
|
||||
|
||||
// Update state according to delta, debounce and max values
|
||||
if (delta > 0 && state < btn_max) {
|
||||
state += btn_inc;
|
||||
} else if (delta < 0 && abs(state) < btn_max) {
|
||||
state -= btn_inc;
|
||||
}
|
||||
|
||||
// With each update, automatically counter the player's TT movement to turn the state
|
||||
// back to 0, e.g. player moves TT -> state += 20. with no additional movement, neutral state
|
||||
// (0) is back in 20 ticks
|
||||
if (state > 0) {
|
||||
state--;
|
||||
} else if (state < 0) {
|
||||
state++;
|
||||
}
|
||||
|
||||
if (state > btn_threshhold) {
|
||||
pad_state->wButtons |= XUSB_GAMEPAD_LEFT_THUMB;
|
||||
} else if (state < (int16_t) btn_threshhold * -1) {
|
||||
pad_state->wButtons |= XUSB_GAMEPAD_RIGHT_THUMB;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static void _handle_turntable(
|
||||
const struct vigem_iidxio_config* config,
|
||||
uint8_t* tt,
|
||||
XUSB_REPORT *state)
|
||||
{
|
||||
for (uint8_t i = 0; i < TURNTABLE_NUM; i++) {
|
||||
if (config->tt.debug_output) {
|
||||
printf("TT (%d): last_raw %d, raw %d, ", i, _tt_last_raw[i], tt[i]);
|
||||
}
|
||||
|
||||
_tt_state_for_btn[i] = _handle_turntable_as_button(
|
||||
config, tt[i], _tt_last_raw[i], _tt_state_for_btn[i], &state[i]);
|
||||
|
||||
_tt_state_for_analog[i] = _handle_turntable_analog(
|
||||
config, tt[i], _tt_last_raw[i], _tt_state_for_analog[i], &state[i]);
|
||||
|
||||
_tt_last_raw[i] = tt[i];
|
||||
|
||||
if (config->tt.debug_output) {
|
||||
printf("state_btn %d, state_rel_analog %d\n",
|
||||
_tt_state_for_btn[i], _tt_state_for_analog[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _handle_buttons_14keys(uint16_t keys, XUSB_REPORT *state)
|
||||
{
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_1, XUSB_GAMEPAD_A);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_2, XUSB_GAMEPAD_B);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_3, XUSB_GAMEPAD_X);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_4, XUSB_GAMEPAD_Y);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_5, XUSB_GAMEPAD_LEFT_SHOULDER);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_6, XUSB_GAMEPAD_RIGHT_SHOULDER);
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P1_7, XUSB_GAMEPAD_BACK);
|
||||
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_1, XUSB_GAMEPAD_A);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_2, XUSB_GAMEPAD_B);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_3, XUSB_GAMEPAD_X);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_4, XUSB_GAMEPAD_Y);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_5, XUSB_GAMEPAD_LEFT_SHOULDER);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_6, XUSB_GAMEPAD_RIGHT_SHOULDER);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
keys, IIDX_IO_KEY_P2_7, XUSB_GAMEPAD_BACK);
|
||||
}
|
||||
|
||||
static void _handle_buttons_panel(uint8_t panel, XUSB_REPORT *state)
|
||||
{
|
||||
state[0].wButtons |= _check_assign_key(
|
||||
panel, IIDX_IO_PANEL_LIGHT_P1_START, XUSB_GAMEPAD_START);
|
||||
state[1].wButtons |= _check_assign_key(
|
||||
panel, IIDX_IO_PANEL_LIGHT_P2_START, XUSB_GAMEPAD_START);
|
||||
|
||||
state[2].wButtons |= _check_assign_key(
|
||||
panel, IIDX_IO_PANEL_LIGHT_VEFX, XUSB_GAMEPAD_B);
|
||||
state[2].wButtons |= _check_assign_key(
|
||||
panel, IIDX_IO_PANEL_LIGHT_EFFECT, XUSB_GAMEPAD_A);
|
||||
}
|
||||
|
||||
static void _handle_buttons_system(uint8_t system, XUSB_REPORT *state)
|
||||
{
|
||||
state[2].wButtons |= _check_assign_key(
|
||||
system, IIDX_IO_SYS_TEST, XUSB_GAMEPAD_X);
|
||||
state[2].wButtons |= _check_assign_key(
|
||||
system, IIDX_IO_SYS_SERVICE, XUSB_GAMEPAD_Y);
|
||||
state[2].wButtons |= _check_assign_key(
|
||||
system, IIDX_IO_SYS_COIN, XUSB_GAMEPAD_START);
|
||||
}
|
||||
|
||||
static void _all_lights_off()
|
||||
{
|
||||
iidx_io_ep1_set_deck_lights(0);
|
||||
iidx_io_ep1_set_panel_lights(0);
|
||||
iidx_io_ep1_set_top_lamps(0);
|
||||
iidx_io_ep1_set_top_neons(false);
|
||||
iidx_io_ep3_write_16seg(" ");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
log_to_writer(log_writer_stdout, NULL);
|
||||
|
||||
struct vigem_iidxio_config config;
|
||||
|
||||
if (!vigem_iidxio_config_get(&config)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
iidx_io_set_loggers(
|
||||
log_impl_misc, log_impl_info, log_impl_warning, log_impl_fatal);
|
||||
|
||||
if (!iidx_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy)) {
|
||||
log_warning("Initializing iidxio failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PVIGEM_CLIENT client = vigem_helper_setup();
|
||||
|
||||
if (!client) {
|
||||
log_warning("VIGEM client failed to connect");
|
||||
|
||||
iidx_io_fini();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
PVIGEM_TARGET pad[JOYSTICKS_NUM];
|
||||
bool failed;
|
||||
|
||||
failed = false;
|
||||
|
||||
for (uint8_t i = 0; i < JOYSTICKS_NUM; i++) {
|
||||
pad[i] = vigem_helper_add_pad(client);
|
||||
|
||||
if (!pad[i]) {
|
||||
log_warning("vigem_alloc pad %d failed", i);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
iidx_io_fini();
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool loop = true;
|
||||
|
||||
XUSB_REPORT state[JOYSTICKS_NUM];
|
||||
|
||||
log_info("vigem init succeeded, beginning poll loop");
|
||||
|
||||
// Create clean output state
|
||||
_all_lights_off();
|
||||
|
||||
vigem_iidxio_cab_light_sequencer_init(config.cab_light.light_mode);
|
||||
|
||||
if (config.cab_light.text_16seg[0] != '\0') {
|
||||
vigem_iidxio_cab_16seg_sequencer_init(
|
||||
config.cab_light.text_16seg, config.cab_light.text_scroll_cycle_time_ms);
|
||||
}
|
||||
|
||||
while (loop) {
|
||||
for (uint8_t i = 0; i < JOYSTICKS_NUM; i++) {
|
||||
memset(&state[i], 0, sizeof(state[i]));
|
||||
}
|
||||
|
||||
if (!iidx_io_ep2_recv()) {
|
||||
log_warning("iidxio receiving failed");
|
||||
break;
|
||||
}
|
||||
|
||||
// Keys/buttons
|
||||
|
||||
uint16_t keys = iidx_io_ep2_get_keys();
|
||||
uint8_t panel = iidx_io_ep2_get_panel();
|
||||
uint8_t system = iidx_io_ep2_get_sys();
|
||||
|
||||
_handle_buttons_14keys(keys, state);
|
||||
_handle_buttons_panel(panel, state);
|
||||
_handle_buttons_system(system, state);
|
||||
|
||||
// Turntable
|
||||
|
||||
uint8_t turntable[TURNTABLE_NUM];
|
||||
|
||||
for (uint8_t i = 0; i < TURNTABLE_NUM; i++) {
|
||||
turntable[i] = iidx_io_ep2_get_turntable(i);
|
||||
}
|
||||
|
||||
_handle_turntable(&config, turntable, state);
|
||||
|
||||
// Pad update
|
||||
|
||||
for (uint8_t i = 0; i < JOYSTICKS_NUM; i++) {
|
||||
vigem_target_x360_update(client, pad[i], state[i]);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// Light related outputs
|
||||
|
||||
if (config.cab_light.enable_keylight) {
|
||||
iidx_io_ep1_set_deck_lights(keys);
|
||||
iidx_io_ep1_set_panel_lights(panel);
|
||||
}
|
||||
|
||||
if (config.cab_light.light_mode != LIGHT_SEQ_MODE_OFF) {
|
||||
bool neon;
|
||||
uint8_t spots;
|
||||
|
||||
neon = false;
|
||||
spots = 0;
|
||||
|
||||
vigem_iidxio_cab_light_sequencer_update(
|
||||
keys,
|
||||
turntable[0],
|
||||
turntable[1],
|
||||
&neon,
|
||||
&spots);
|
||||
|
||||
iidx_io_ep1_set_top_neons(neon);
|
||||
iidx_io_ep1_set_top_lamps(spots);
|
||||
}
|
||||
|
||||
if (config.cab_light.text_16seg[0] != '\0') {
|
||||
char buffer_16seg[9];
|
||||
|
||||
vigem_iidxio_cab_16seg_sequencer_update(buffer_16seg);
|
||||
iidx_io_ep3_write_16seg(buffer_16seg);
|
||||
}
|
||||
|
||||
if (!iidx_io_ep1_send()) {
|
||||
log_warning("iidxio sending failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if (_check_key(system, IIDX_IO_SYS_TEST) &&
|
||||
_check_key(system, IIDX_IO_SYS_SERVICE)) {
|
||||
log_info("Test + service pressed, exiting...");
|
||||
loop = false;
|
||||
}
|
||||
|
||||
// Avoid CPU banging
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < JOYSTICKS_NUM; i++) {
|
||||
vigem_target_remove(client, pad[i]);
|
||||
vigem_target_free(pad[i]);
|
||||
}
|
||||
|
||||
vigem_free(client);
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
_all_lights_off();
|
||||
|
||||
iidx_io_fini();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user