Compare commits

...

128 Commits
5.33 ... 5.35

Author SHA1 Message Date
Will Xyen
54e7d783ef Update changelog for 5.35 2021-06-23 11:17:29 -07:00
CrazyRedMachine
4ea1397af2 aciodrv: add PANB support (+ aciotest handler)
add aciodrv-proc module

explanation : PANB works differently from other acio devices ; you send
one "start auto input" command without expecting a reply, and then the
piano keeps spamming "recv poll" commands on the acio bus and never replies
to any other commands.. failure to process these messages quickly enough
will saturate the serial buffer and cause checksum errors after a while.

for this reason, aciodrv-proc module was added in order to create a
thread which manages these recv poll commands and keeps the latest
known button state in memory so that it can be retrieved easily.
2021-05-03 20:14:21 +02:00
icex2
fb593df4a1 Update Bug.md, fix comment not closing 2021-05-02 10:54:45 +00:00
icex2
f0c33663e9 Update bug template, add info to run with default config 2021-05-02 10:54:24 +00:00
icex2
87ee37d059 Fix typo in log message 2021-05-02 10:39:55 +00:00
Will Xyen
5688fb7319 aciodrv: refactor aciodrv_device_init function 2021-05-01 10:42:55 -07:00
Will Xyen
d529ee484f aciodrv: Update aciodrv_device_init to properly reset the device 2021-05-01 10:30:02 -07:00
Will Xyen
7c43fb7163 doc: Make doc.zip include the whole folder
Also update vigem docs
2021-04-30 20:24:13 -07:00
Will Xyen
652d2ef633 aciodrv: fix pointer logging 2021-04-26 12:50:22 -07:00
Will Toohey
78884aebad Clarify how eamio-icca works with jbio-p4io 2021-04-06 21:04:34 +10:00
Will Toohey
549f00bfb3 Add default jbio-h44b.conf to /dist 2021-04-06 20:58:47 +10:00
Will T
aab45f145f Add missing backticks in jbio-p4io.md 2021-04-06 10:54:20 +00:00
Will Toohey
6171f0dc60 Make h44b light mapping explicit 2021-04-06 20:52:19 +10:00
Will Toohey
2f05760f4e Add enum p4io_roundplug_type for clarity 2021-04-06 20:35:14 +10:00
Will Toohey
7b5e4772ea Clarify p4io_cmd_init's lack of response checking 2021-04-06 20:30:47 +10:00
Will Toohey
e266aed1f9 p4io/usb: clarify jamma reads use interrupt handle 2021-04-06 20:28:08 +10:00
Will Toohey
0b0e7faef0 jbio-magicbox: comment nonfunctional jb_io_set_panel_mode 2021-04-06 20:25:07 +10:00
Will Toohey
53866130cb p4io: change magic AA to P4IO_SOF 2021-04-06 20:23:01 +10:00
Will Toohey
dbb8c45a9f H44B drv: add missed deinit code, comments 2021-04-06 20:19:19 +10:00
Will Toohey
8ed7d6db71 remove spurious warning 2021-04-04 18:35:21 +10:00
Will Toohey
4c746df6a8 Fix warnings on format strings 2021-04-04 17:19:16 +10:00
Will Toohey
7d485e7c7e Improve robustness of p4iodrv/usb 2021-04-04 17:16:19 +10:00
Will Toohey
deb6e5cf77 Fix const warning in aciodrv-icca 2021-04-04 16:41:59 +10:00
Will Toohey
2a03690772 Update jbio for testmenu support and add jbio-p4io 2021-04-04 16:41:45 +10:00
Will Xyen
6ce4cce500 eamio-icca: Fix state being mis-fired during felica poll (causing errors in IIDX13-18) 2021-03-21 04:19:39 +00:00
ab3a6534ca292e2c3580175f809ec08257496a8e
c6e59bae9b Updates dev.s-ul.eu URLs and fixes bad doc link for vigem 2021-03-19 18:09:07 +00:00
Will Xyen
31e15ec5ea sdvxhook: re-order hooks so eamio-icca can be used 2021-03-17 16:06:31 -07:00
Will Xyen
9cef7c03d0 aciodrv: address some magic numbers with felica polling 2021-03-17 14:42:14 -07:00
Will Xyen
f9b37c7a72 aciodrv: Add wavepass support to ICCA (#1)
Tested with:
aciotest / eamiotest:
 - DDR Slotted: Node 1: type 3, flag 0, version 1.1.0, product ICCA, build date: Oct 26 2005 13:55:03
 - DDR Slotted: Node 2: type 3, flag 0, version 1.1.0, product ICCA, build date: Oct 26 2005 13:55:03
(tested with just 1, as well as a pair)

aciotest / eamiotest / IIDX10,12,27:
 - IIDX Wavepass: Node 1: type 3, flag 0, version 1.5.1, product ICCB, build date: Apr 12 2010 09:29:00
 - IIDX Wavepass: Node 2: type 3, flag 0, version 1.5.1, product ICCB, build date: Apr 12 2010 09:29:00
(IIDX13 errors on card-in, probably issue with how eamio is being used as previously eamio-icca had no use on it)

aciotest / eamiotest / sdvx1-5:
 - SDVX Wavepass: Node 1: type 3, flag 0, version 1.5.1, product ICCB, build date: Apr 12 2010 09:29:00

aciotest:
 - Jubeat Wavepass:  Node 1: type 3, flag 0, version 1.7.3, product ICCC, build date: Oct 05 2012 20:26:53
 - Museca Wavepass:  Node 2: type 3, flag 0, version 1.7.4, product ICCC, build date: Feb 27 2013 16:44:51
2021-03-17 10:34:30 -07:00
Will Xyen
609c19b0ca sdvxio-kfca: fix build 2021-03-16 16:51:10 -07:00
Will Xyen
75b27d5992 aciomgr: move internal init stuff to manager-init.h 2021-03-16 22:06:21 +00:00
Will Xyen
965df98093 aciomgr: cleanup and address comments 2021-03-16 22:06:21 +00:00
Will Xyen
0c06d224cc eamio-icca: fix config prefix 2021-03-16 22:06:21 +00:00
Will Xyen
fb3d2ea312 eamio-icca: add config to allow port to be set
also fixes issue where no logging would show up in eamiotest
2021-03-16 22:06:21 +00:00
Will Xyen
089253a537 aciomgr: Add acio manager dll 2021-03-16 22:06:21 +00:00
Will Xyen
a4436747de aciodrv: fix build warnings for logging format strings 2021-03-16 22:06:21 +00:00
a5a845f95bba57bc03c1a6bfabfbca25c2de8e01
43b11c8778 doc: minor update to bio2-sub-io-turntable-bypass-cable 2021-03-16 00:48:47 +00:00
Will Xyen
dd7fd860b5 launcher: add 2.15.9 def
(same as 2.15.8 except with new kbt, and different log ordinals)
2021-02-12 02:11:07 -08:00
Will Xyen
18842a1dd3 d3d9ex: override adapter mode information when all the info is pre-provided by the user
This speeds up IIDX load times, as well as allows you to use "unsupported" resolutions/refresh rates on weird monitors
2021-02-06 16:25:33 -08:00
Will Xyen
18f6d9ef70 d3d9ex: add windowed position setting 2021-02-04 23:38:54 -08:00
Will Xyen
592967e191 d3d9ex: revert previous window size fix, and fix it properly 2021-02-04 23:04:56 -08:00
Will Xyen
6614cc801e d3d9ex: fix framed and window sizes for IIDX 2021-02-04 22:57:29 -08:00
Will Xyen
8e1151ac02 aciodrv: address review
also some formatting fixes
2021-01-19 21:10:34 -08:00
Will Xyen
4b60cb6c6c aciodrv: fix pointer format, and missing close context 2021-01-14 11:05:46 -08:00
Will Xyen
770bae4169 aciodrv: support multi-sized response packets by divining the packet size 2021-01-14 10:57:38 -08:00
Will Xyen
49d0bc638b aciodrv: refactor to support multiple active drivers (with specified ports) 2021-01-14 10:02:27 -08:00
icex2
837affc66c Readme: Update with release process steps for devs 2021-01-07 22:01:52 +01:00
icex2
ec76ba075f gitlab-ci: Fix pipeline to include build step for tagged release 2021-01-07 20:30:09 +00:00
icex2
f438f04f2a gitlab-ci: Build + automatic upload of tagged releases 2021-01-07 21:05:41 +01:00
icex2
865980991e Bump version to 5.35 2021-01-06 22:17:30 +01:00
icex2
37384c15ec Update changelog for 5.34 2021-01-06 22:05:11 +01:00
icex2
f0d62cc938 Bump version to 5.34 2021-01-06 21:44:31 +01:00
icex2
bf067de633 iidxio-bio2: Add missing aciodrv on finit to cleanup acio stuff 2021-01-06 20:34:34 +00:00
icex2
f3b07aeb0a iidxio-ezusb: Fix same flushing issue on shutdown as bio2 2021-01-06 20:34:34 +00:00
icex2
a1a67697c4 iidxio-bio2: Properly fix flushing on shutdown
Moved this hardware/iidxio impl specific logic from vigem-iidxio
to iidxio-bio2. Other hardware impls should follow this if
necessary to ensure a transparent and deterministic interface
(as good as possible)
2021-01-06 20:34:33 +00:00
icex2
ce5b1b2eac vigem-iidxio: Reduce random flickering cab-light on tt spin 2021-01-06 20:34:33 +00:00
icex2
3f2aed65e4 vigem-iidxio: Add default configuration to dist files
Aligns with established idea in BT5 to always provide default configs
2021-01-06 20:34:33 +00:00
icex2
22f3845609 vigem/doc: Minor fixes and improvements 2021-01-06 20:34:33 +00:00
icex2
de0d70d808 vigem-iidxio: Improve responsiveness on fast direction change TT 2021-01-06 20:34:33 +00:00
icex2
12c52bb0d8 vigem-iidxio: Major refactoring incorporating features from Grim's branch
- 3 turntable modes: analog (raw), relative and button mapped
- re-structure main to make it easier to maintain and less
repetitive code
2021-01-06 20:34:33 +00:00
icex2
279d4de4b3 vigem-iidxio: Fix cab light sequencer blink on TT spin
Similar to the TT analog to button code in main
2021-01-06 20:34:32 +00:00
icex2
2b52fbe211 vigem-iidxio: Bugfix missing break in switch 2021-01-06 20:34:32 +00:00
icex2
78e7c05876 vigem-iidxio: Refactor configuration
Add more properties from Grim's implementation to support the
additional features. Re-structure struct to be less repetitive
on variable names.
2021-01-06 20:34:32 +00:00
icex2
9a5418f6a3 vigem-iidxio: Fix Luncatic Rave 2 incompatible button mappings
Reported by Grim:
LR2 cannot make use of the d-pad as buttons for inputs because
reasons. Create a third virtual gamepad to allow handling all
inputs as "normal buttons" including turntables.
2021-01-06 20:34:32 +00:00
icex2
2363498f73 vigem-iidxio: Support multiple different light sequence modes
Add new one suggested and implemented by Grim to flash the neons
when spinning the turntables
2021-01-06 20:34:32 +00:00
icex2
edbbe5ae67 iidxio-ezusb: Bugfix random input/outputs on startup 2021-01-06 20:34:32 +00:00
icex2
d799b69d12 doc: Add index README for vigem stuff, add vigem info to root readme 2021-01-06 20:34:31 +00:00
icex2
91f83cd975 doc: Collect vigem related documentation in own subfolder in doc 2021-01-06 20:34:31 +00:00
icex2
adeabbea19 doc: Add vigem-iidxio documentation 2021-01-06 20:34:31 +00:00
icex2
41187091b0 vigem-iidxio: Add vigem implementation with iidxio interface
This uses vigem to create two virtual xbox gamepads and hooks
up the iidxio API to them. It allows you to use anything that
implements the BT5's iidxio API as a game controller, e.g.
iidxio-bio2, iidxio-ezusb1/2 to play any game that supports
xbox game controllers, e.g. lunatic rave, IIDX infinitas.

Further features include setting your own custom 16seg text
from a configuration file or enable some hardcoded light
sequence to make your cabinet look bad ass even when playing
"Big Rigs: Over the Road Racing"
2021-01-06 20:34:31 +00:00
icex2
5658658d3a vigem-sdvxio: Add missing free for cleaning up vigem client 2021-01-06 20:34:31 +00:00
icex2
79a74b2d2f vigem-sdvxio: Make private functions static 2021-01-06 20:34:31 +00:00
icex2
51484b1d3d iidxiotest: Bugfix, properly turn off lights on exit 2021-01-06 18:08:18 +00:00
Will Xyen
df8f3bc96a iidxhook9: set TT multiplier 2021-01-02 20:11:03 +00:00
icex2
ec435e7a7b iidxio-bio2 conf: Improve doc, port optional if autodetect on 2021-01-02 12:07:00 +00:00
icex2
f8a01ed92f dist/iidx: Add default iidxio-bio2 conf
We have stock/default configs for everything else, e.g. hooks.
2021-01-02 12:07:00 +00:00
Matt Bilker
2b1dd866d0 dist: add jubeat heap size
- Sourced from L44-011's bootstrap.xml

Jubeat clan 2018081401 clean data ran out of memory.

jubeat clan 2018081401 has a slightly larger achievement_info.xml
so that may have caused the problem.
2020-12-31 17:56:57 +01:00
Will Xyen
7d129a3e63 launcher: Actually init the default service override options and make override_urlslash_value more clear 2020-12-21 10:03:48 -08:00
Will Xyen
29db89cebe launcher: allow overriding service url and url slash from the command line 2020-12-21 09:59:06 -08:00
icex2
f7e1c8b3f9 doc: Add a bunch of root readme files to various levels, enhance doc
Not complete, but a start to make documentation browsable and
therefore more accessible.
2020-12-20 17:06:27 +01:00
icex2
f667ae5601 doc: Add doc for using bio2 exit hook 2020-12-20 17:06:13 +01:00
icex2
4b061bdf8f Add iidx-bio2-exit-hook: Exit games with bio2 with button combination
Press Start P1 + Start P2 + Effect + VEFX at the same time to
terminate the game. Useful for multi game setups running some
sort of game loader/selector and not having to use a keyboard.
2020-12-20 16:39:00 +01:00
icex2
13600db1d5 iidx-ezusb1/2 exit hook: Replace duplicate code with util function 2020-12-20 16:38:06 +01:00
icex2
e4126500ef util/proc: Create util module for handling process related stuff 2020-12-20 16:37:40 +01:00
icex2
049f1b4564 doc/hardware: Add information about bio2 turntable bypass cable 2020-12-20 15:25:16 +01:00
icex2
687c000000 doc/iidxhook9: Add notes about BIO2 driver usage 2020-12-20 15:25:16 +01:00
icex2
1b593a8e23 doc: Improve visibility of iidxio API implementations 2020-12-20 15:25:16 +01:00
icex2
24178121f0 doc: Add iidxio-bio2 documentation 2020-12-20 15:25:16 +01:00
icex2
62ad4e0616 hardware doc: ezusb RJ45 to DIN8 connector pinout
Can be used to build adapter cables to up-/downgrade cabinets with
C02 to IO2 and IO2 to C02 wiring.
2020-12-20 15:25:16 +01:00
icex2
c348a41d22 bi2a-iidx: Fix incorrect init command data
Taken from a communication dump of the real IO with iidx 27,
this needs to be 0x2D in order to get a fully working setup with
BIO2 and sub IO board connected.
2020-12-20 15:25:16 +01:00
icex2
ef377f40d8 bi2a: Clarify data field usage on init command
The single byte is a specific parameter required to initialize
the IO correctly. Otherwise, it either will only work partially
or not worked at all. The full impact and meaning of that byte
is not entirely known, yet.
2020-12-20 15:25:16 +01:00
icex2
0c88518a1f bio2: Add BIO2_BI2A_CMD_INIT command
Turns out this is different from the generic CLEAR command used
on other ACIO devices. Has further implications when initializing
BIO2 boards for specific games, e.g. IIDX.
2020-12-20 15:25:16 +01:00
icex2
0bc87db8da dev doc: Documented BIO2 package dumps used for debugging 2020-12-20 15:25:16 +01:00
icex2
53f8cb3bf3 iidxio-bio2: Add iidxio implementation using bio2 iidx driver
Use the original bio2 hardware with anything that supports BT5's
iidxio interface, e.g. old IIDX versions of BT5.
2020-12-20 15:25:16 +01:00
icex2
41edfec702 bio2drv: Add implementation for iidx
Basically, a copy-paste of SDVX KFCA with minor tweaks.
2020-12-20 15:25:16 +01:00
icex2
c6c3bdb075 bio2/iidx: Add enums to easily map top lamps and panel buttons
Naturally, this also serves as documentation
2020-12-20 15:25:16 +01:00
icex2
b3a89012ca bio2/iidx: Deduplicate node command, use common acio base command 2020-12-20 15:25:16 +01:00
icex2
f0bc87f1d6 iidxiotool: Fix incorrect top lamp order for setting output 2020-12-20 15:25:16 +01:00
icex2
7508c43119 bt5 api/iidxio: Add missing enum to easily identify top lamp order 2020-12-20 15:25:16 +01:00
icex2
34be731211 doc/api: Add missing sdvxio implementations to list 2020-12-20 15:25:16 +01:00
icex2
bac1ce62e5 Module.mk: Apply lex sort to includes 2020-12-20 15:25:16 +01:00
icex2
58689bbc30 Add missing iidx 27 avs version info to list 2020-12-20 15:25:16 +01:00
icex2
d5e186ffe2 bio2/iidx: Swap in and out struct names to align with sdvx definitions
From hosts perspective:
- "in" for inputs received from device
- "out" for outputs to send to device
2020-12-20 15:25:16 +01:00
icex2
34c95561c4 bio2: Update unknown commands
Credits to xyen for this
2020-12-20 15:25:16 +01:00
icex2
81d697d59a doc/iidxhook9: Add doc to FAQ how and when to use force screen res 2020-12-19 23:18:36 +01:00
icex2
3bdda4d123 dist/iidx: Update dist config file with new parameters force screen res 2020-12-19 23:18:36 +01:00
icex2
ea8842b58a d3d9ex: Add force screen resolution feature
For details, see the commit adding doc to the iidxhook9 readme
2020-12-19 23:18:34 +01:00
icex2
e89889806b d3d9ex: Add new config parameters for forcing screen resolution 2020-12-19 16:57:11 +01:00
icex2
b3b2f8f433 d3d9ex: Log parameters of CreateDeviceEx for debugging and tracing 2020-12-19 16:37:02 +01:00
icex2
1cdf330cbf iidxhook8/9 faq: Add force refresh rate on high freq monitors entry 2020-12-19 01:52:07 +01:00
Will Xyen
89c3ada28f iidxhook9: Add turntable multiplier 2020-12-09 17:22:40 -08:00
aa0f384305e16816d055f34ff91a93cad4c6d179
d9cb953b67 Update README.md 2020-11-26 03:52:56 +00:00
icex2
7ebb80d600 doc/iidxhook1: Add info about AMD GPU scaling causing slow downs 2020-11-15 00:22:16 +01:00
Will Xyen
e737d60893 Actually implement the coin mech in BIO2 based games
Properly fixes #45
2020-11-10 18:08:16 -08:00
Will Toohey
f39843b41f Better comments in ch341.h 2020-11-08 15:32:42 +01:00
Will Toohey
98d0debd05 Cleanup 2020-11-08 15:32:42 +01:00
Will Toohey
950584f025 Formatting 2020-11-08 15:32:42 +01:00
Will Toohey
e4081c057f Add jbio-magicbox.dll 2020-11-08 15:32:42 +01:00
icex2
8c3030354a Improve contributing documentation
- Summary of "golden rules" in main readme
- Improve contirbution document by outlining steps
2020-11-08 13:05:13 +01:00
icex2
9777eddaa0 gitlab: Update bug template to point out how to log to file 2020-11-08 12:02:39 +01:00
icex2
671723febd doc/iidxhook: Update documentation, explain new io feature switches 2020-11-08 00:24:52 +01:00
icex2
c1f6166e1b dist/iidx: Update default configs with new io config entries 2020-11-08 00:24:39 +01:00
icex2
538650f7ac iidxhook7: Support new IO config feature switches 2020-11-08 00:23:44 +01:00
icex2
efd243fd9d iidxhook6: Support new IO config feature switches 2020-11-08 00:23:35 +01:00
icex2
383b301d3c iidxhook5: : Support new IO config feature switches 2020-11-08 00:23:21 +01:00
icex2
a9d201691a iidxhook4: Support new IO config feature switches 2020-11-08 00:22:25 +01:00
icex2
ebb6f811b4 sqash 2020-11-08 00:22:12 +01:00
icex2
9e96cf074f iidxhook-util: Add config for io stuff
Switches to disable card reader and IO emulation
2020-11-08 00:20:55 +01:00
187 changed files with 6934 additions and 807 deletions

View File

@@ -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

View File

@@ -8,9 +8,12 @@
<!--- 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
<!-- Try running the game with a default configuration as well. If that also causes issues, please point that out here in the report. This might speed up the debugging process.-->
<!--- Provide a detailed step by step description how to reproduce this issue -->
1.
2.
@@ -29,16 +32,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 -->

View File

@@ -1,4 +1,27 @@
# Release history
## 5.35
* Jubeat: Add jbio-p4io
* Nostalgia: Add nostio-panb
* Misc: Refactor aciodrv to support multiple devices using the same port (with aciomgr)
* Misc: Fix d3d9ex windowed hook not behaving correctly (size/framed)
* Misc: Fix docs not being included with release
* Various bugfixes
## 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

View File

@@ -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).

View File

@@ -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

View File

@@ -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 \
@@ -70,17 +72,19 @@ cflags += \
# that is still ABI-compatible with the real build its target links against.
avsvers_32 := 1700 1603 1601 1508 1403 1304 1101 803 0
avsvers_64 := 1700 1603 1601 1508
avsvers_64 := 1700 1603 1601 1509 1508
imps += avs avs-ea3
include src/main/aciodrv/Module.mk
include src/main/aciodrv-proc/Module.mk
include src/main/acioemu/Module.mk
include src/main/aciomgr/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 +92,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,42 +129,47 @@ 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-p4io/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
include src/main/p3io/Module.mk
include src/main/p3ioemu/Module.mk
include src/main/p4iodrv/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 +186,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 +205,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 \
@@ -370,17 +382,27 @@ $(zipdir)/iidx-27.zip: \
$(V)zip -j $@ $^
$(zipdir)/iidx-hwio-x86.zip: \
build/bin/indep-32/aciomgr.dll \
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/aciomgr.dll \
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 $@ $^
@@ -425,6 +447,17 @@ $(zipdir)/jb-08.zip: \
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/jb-hwio.zip: \
build/bin/indep-32/aciomgr.dll \
build/bin/indep-32/eamio-icca.dll \
build/bin/indep-32/jbio-magicbox.dll \
build/bin/indep-32/jbio-p4io.dll \
dist/jb/jbio-h44b.conf \
dist/jb/eamio-icc.conf \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -j $@ $^
$(zipdir)/sdvx-01-to-04.zip: \
build/bin/avs2_1508-32/launcher.exe \
build/bin/avs2_1508-32/sdvxhook.dll \
@@ -467,6 +500,8 @@ $(zipdir)/sdvx-05-cn.zip: \
$(V)zip -j $@ $^
$(zipdir)/sdvx-hwio-x86.zip: \
build/bin/indep-32/aciomgr.dll \
build/bin/indep-32/eamio-icca.dll \
build/bin/indep-32/sdvxio-kfca.dll \
build/bin/indep-32/sdvxio-bio2.dll \
build/bin/indep-32/vigem-sdvxio.exe \
@@ -475,6 +510,8 @@ $(zipdir)/sdvx-hwio-x86.zip: \
$(V)zip -j $@ $^
$(zipdir)/sdvx-hwio-x64.zip: \
build/bin/indep-64/aciomgr.dll \
build/bin/indep-64/eamio-icca.dll \
build/bin/indep-64/sdvxio-kfca.dll \
build/bin/indep-64/sdvxio-bio2.dll \
build/bin/indep-64/vigem-sdvxio.exe \
@@ -533,10 +570,7 @@ $(zipdir)/bst.zip: \
$(V)zip -j $@ $^
$(zipdir)/doc.zip: \
doc/iidxhook \
doc/sdvxhook \
doc/jbhook \
doc/tools \
doc/ \
| $(zipdir)/
$(V)echo ... $@
$(V)zip -r $@ $^
@@ -586,6 +620,7 @@ $(BUILDDIR)/bemanitools.zip: \
$(zipdir)/jb-01.zip \
$(zipdir)/jb-05-to-07.zip \
$(zipdir)/jb-08.zip \
$(zipdir)/jb-hwio.zip \
$(zipdir)/sdvx-01-to-04.zip \
$(zipdir)/sdvx-05.zip \
$(zipdir)/sdvx-05-cn.zip \

View File

@@ -1,7 +1,7 @@
# Bemanitools 5
[![pipeline status](https://dev.s-ul.eu/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.eu/djhackers/bemanitools/commits/master)
[![pipeline status](https://dev.s-ul.net/djhackers/bemanitools/badges/master/pipeline.svg)](https://dev.s-ul.net/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](doc/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,46 @@ 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
## Release process
Steps for the release process:
1. Update the corresponding section in the [changelog](CHANGELOG.md) with bullet points reflecting
major features merged into master since the previous release
1. Make sure you have the latest `master` state pulled to your local copy
1. Tag the release with the next release number which also be found at the
[top of the readme](#bemanitools-5) as it always reflects the current version beinged worked on
on the `master` branch , e.g. 5.35: `git tag 5.35`
1. Push the tag to upstream: `git push origin 5.35`
1. The [build pipeline](https://dev.s-ul.net/djhackers/bemanitools/-/pipelines) should start
automatically once the tag is pushed including the steps `build` and `upload-release`
1. Once completed successfully, the release is uploaded
1. Take the changelog of the published version and notify the pigs in the stall about it:
1. New post in thread
```
<insert version here> released: <direct link to published version>
Changelog:
<paste changelog here>
```
1. Update the OP title by bumping the version number in it
1. Update the OP post by extending it accordingly (see previous entries)
1. Bump the version number at the [top of this readme](#bemanitools-5) and add a new empty section
in the [changelog](CHANGELOG.md) with the new version number as title. Commit changes and push to
`master` branch
1. Continue developing and merging MRs until you decide its time for another release
## License
Source code license is the Unlicense; you are permitted to do with this as thou wilt. For details, please refer to the
[LICENSE file](LICENSE) included with the source code.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
@@ -31,7 +34,7 @@ gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Confine mouse coursor to window
# Confine mouse cursor to window
gfx.confined=false
# Windowed width, -1 for default size
@@ -40,6 +43,12 @@ gfx.window_width=-1
# Windowed height, -1 for default size
gfx.window_height=-1
# Windowed X, -1 for default X position
gfx.window_x=-1
# Windowed Y, -1 for default Y position
gfx.window_y=-1
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1
@@ -49,6 +58,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
View 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
View 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

5
dist/jb/eamio-icc.conf vendored Normal file
View File

@@ -0,0 +1,5 @@
# ICCA serial port
icc.port=COM2
# ICCA bus baudrate (real devices expect 57600)
icc.baud=57600

View File

@@ -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

5
dist/jb/jbio-h44b.conf vendored Normal file
View File

@@ -0,0 +1,5 @@
# H44B serial port
h44b.port=COM2
# H44B bus baudrate (real devices expect 57600)
h44b.baud=57600

View File

@@ -19,7 +19,7 @@ gfx.framed=true
# Run the game windowed
gfx.windowed=false
# Confine mouse coursor to window
# Confine mouse cursor to window
gfx.confined=false
# Windowed width, -1 for default size
@@ -28,6 +28,12 @@ gfx.window_width=1080
# Windowed height, -1 for default size
gfx.window_height=1920
# Windowed X, -1 for default X position
gfx.window_x=-1
# Windowed Y, -1 for default Y position
gfx.window_y=-1
# Forced refresh rate, -1 to not force any (try 59 or 60 if monitor check fails to lock on high refresh rate monitors)
gfx.forced_refresh_rate=-1

21
doc/README.md Normal file
View 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

View File

@@ -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
View 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.

View 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
```

View File

@@ -0,0 +1,55 @@
# BIO2 sub IO turntable bypass cable
If you upgraded a C02 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 by emulating the wiring of a
D01 cabinet, reducing latency significantly.
This cable could be ordered with the IIDX Rootage upgrade kit 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 |

View 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 |

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View 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).

View 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`

18
doc/jbhook/jbio-p4io.md Normal file
View File

@@ -0,0 +1,18 @@
This library talks to a P4IO (panel) and H44B through ACIO (lights) of a jubeat cab and implements the jbio API of BT5.
Thus, it allows you to use a modern jubeat cab with *any* version of jubeat that is supported by BT5.
# Setup
* Rename `jbio-p4io.dll` to `jbio.dll`.
* Make sure `jbio.dll` is in the same folder as both `jbhook.dll`, `aciomgr.dll` and `jubeat.dll`
* If you want IC card support via eamio-icca, ensure you also rename `eamio-icca.dll` to `eamio.dll`
* 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`
* If you have P4IO but no H44B, lights will be disabled
* You can change the port and baudrate of the H44B node by editing the `jbio-h44b.conf` that should be created by default
* If you are using IC card support, you can edit `eamio-icc.conf` to change the port and baudrate
* If you are playing on a real cab, the port and baud of H44B and ICCA should be identical

38
doc/tools/README.md Normal file
View 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

View 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
View 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
View 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
* If you can't find some of these files, see bemanitools-supplements
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)

View File

@@ -19,6 +19,8 @@ Thus, it allows you to use a real cab with *any* game that supports xinput.
* VOL LR are mapped to L thumbstick X/Y (either in absolute or relative mode depending on the config)
# 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))
* 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
* If you can't find some of these files, see bemanitools-supplements
* Make sure to ewfmgr C: -commit and reboot after installing the drivers (this only needs to be done once)

View File

@@ -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
View 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

View File

@@ -0,0 +1,7 @@
LIBRARY ch341dll
EXPORTS
CH341OpenDevice@4=CH341OpenDevice
CH341CloseDevice@4=CH341CloseDevice
CH341EppReadData@12=CH341EppReadData
CH341EppSetAddr@8=CH341EppSetAddr

View File

@@ -0,0 +1,7 @@
LIBRARY libavs-win64-ea3
EXPORTS
ea3_boot @8 NONAME
ea3_get_boot_status @11 NONAME
ea3_get_pp_status @10 NONAME
ea3_shutdown @9 NONAME

View File

@@ -0,0 +1,32 @@
LIBRARY libavs-win64
EXPORTS
avs_boot @285 NONAME
avs_fs_close @65 NONAME
avs_fs_lseek @59 NONAME
avs_fs_lseek64 @60 NONAME
avs_fs_open @58 NONAME
avs_fs_read @61 NONAME
avs_net_ctrl @98 NONAME
avs_shutdown @286 NONAME
avs_thread_create @6 NONAME
avs_thread_destroy @8 NONAME
avs_thread_exit @12 NONAME
avs_thread_join @13 NONAME
log_body_fatal @357 NONAME
log_body_info @359 NONAME
log_body_misc @360 NONAME
log_body_warning @358 NONAME
property_create @127 NONAME
property_desc_to_buffer @129 NONAME
property_destroy @128 NONAME
property_insert_read @131 NONAME
property_node_create @145 NONAME
property_node_refer @158 NONAME
property_node_remove @146 NONAME
property_psmap_export @162 NONAME
property_psmap_import @161 NONAME
property_read_query_memsize @159 NONAME
property_search @144 NONAME
std_getenv @207 NONAME
std_setenv @208 NONAME

View File

@@ -5,9 +5,11 @@
#include <stdint.h>
#include <stdlib.h>
#include "acio/h44b.h"
#include "acio/hdxs.h"
#include "acio/icca.h"
#include "acio/kfca.h"
#include "acio/panb.h"
#define AC_IO_SOF 0xAA
#define AC_IO_ESCAPE 0xFF
@@ -37,6 +39,7 @@ enum ac_io_node_type {
AC_IO_NODE_TYPE_KFCA = 0x09060000,
AC_IO_NODE_TYPE_BI2A = 0x0d060000,
AC_IO_NODE_TYPE_RVOL = 0x09060001,
AC_IO_NODE_TYPE_PANB = 0x090E0000,
};
#pragma pack(push, 1)
@@ -66,14 +69,20 @@ 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_h44b_output h44b_output;
struct ac_io_icca_misc icca_misc;
struct ac_io_icca_state icca_state;
struct ac_io_kfca_poll_in kfca_poll_in;
struct ac_io_kfca_poll_out kfca_poll_out;
struct ac_io_panb_poll_in panb_poll_in;
struct ac_io_panb_poll_out panb_poll_out;
struct ac_io_hdxs_output hdxs_output;
};
} cmd;

View File

@@ -14,6 +14,6 @@ struct ac_io_h44b_output {
uint8_t right_rgb[3];
uint8_t title_rgb[3];
uint8_t woofer_rgb[3];
};
} __attribute__((__packed__));
#endif
#endif

View File

@@ -29,6 +29,14 @@ enum ac_io_icca_sensor_state {
AC_IO_ICCA_SENSOR_MASK_BACK_ON = (1 << 5)
};
enum ac_io_icca_status_code {
AC_IO_ICCA_STATUS_FAULT = 0x00,
AC_IO_ICCA_STATUS_IDLE = 0x01,
AC_IO_ICCA_STATUS_GOT_UID = 0x02,
AC_IO_ICCA_STATUS_IDLE_NEW = 0x04,
AC_IO_ICCA_STATUS_BUSY_NEW = 0x01,
};
enum ac_io_icca_keypad_mask {
AC_IO_ICCA_KEYPAD_MASK_EMPTY = (1 << 0),
AC_IO_ICCA_KEYPAD_MASK_3 = (1 << 1),

42
src/main/acio/panb.h Normal file
View File

@@ -0,0 +1,42 @@
#ifndef AC_IO_PANB_H
#define AC_IO_PANB_H
#include <stdint.h>
#define AC_IO_CMD_PANB_POLL_REPLY 0x0110
#define AC_IO_CMD_PANB_SEND_LAMP 0x0111
#define AC_IO_CMD_PANB_START_AUTO_INPUT 0x0115
#define AC_IO_PANB_NUM_NODES 4
#define AC_IO_PANB_MAX_KEYS (7*AC_IO_PANB_NUM_NODES)
#define AC_IO_PANB_MAX_KEYPAIRS (AC_IO_PANB_MAX_KEYS/2)
struct ac_io_panb_keypair {
uint8_t key2 : 4;
uint8_t key1 : 4;
};
#pragma pack(push, 1)
struct ac_io_panb_poll_in {
/* last received command sequence number (start_auto_input / send_lamp) */
uint8_t sub_seq1;
/* auto-increment sequence number for autopoll reports */
uint8_t sub_seq2;
struct ac_io_panb_keypair keypair[AC_IO_PANB_MAX_KEYPAIRS];
};
#pragma pack(pop)
struct ac_io_panb_color {
uint8_t red;
uint8_t green;
uint8_t blue;
};
#pragma pack(push, 1)
struct ac_io_panb_poll_out {
struct ac_io_panb_color key[AC_IO_PANB_MAX_KEYS];
};
#pragma pack(pop)
#endif

View File

@@ -0,0 +1,7 @@
libs += aciodrv-proc
libs_aciodrv-proc := \
src_aciodrv-proc := \
panb.c \

View File

@@ -0,0 +1,90 @@
#define LOG_MODULE "aciodrv-proc-panb"
#include <string.h>
#include "aciodrv/device.h"
#include "aciodrv/panb.h"
#include "util/thread.h"
#include "util/log.h"
static int auto_poll_proc(void *auto_poll_param);
static int auto_poll_threadid;
static CRITICAL_SECTION keypair_lock;
static struct ac_io_panb_keypair _keypair[AC_IO_PANB_MAX_KEYPAIRS];
static CRITICAL_SECTION auto_poll_stop_lock;
static bool auto_poll_stop;
static int auto_poll_proc(void * param)
{
struct aciodrv_device_ctx * device = (struct aciodrv_device_ctx *) param;
struct ac_io_panb_poll_in poll_in;
bool stop;
do {
aciodrv_panb_recv_poll(device, &poll_in);
EnterCriticalSection(&keypair_lock);
memcpy(_keypair, poll_in.keypair, AC_IO_PANB_MAX_KEYPAIRS);
LeaveCriticalSection(&keypair_lock);
EnterCriticalSection(&auto_poll_stop_lock);
stop = auto_poll_stop;
LeaveCriticalSection(&auto_poll_stop_lock);
} while (!stop);
return 0;
}
bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device)
{
log_assert(device);
if (!aciodrv_panb_start_auto_input(device, 0, AC_IO_PANB_NUM_NODES)) {
return false;
}
auto_poll_stop = false;
InitializeCriticalSection(&keypair_lock);
InitializeCriticalSection(&auto_poll_stop_lock);
auto_poll_threadid = thread_create(auto_poll_proc, (void *)device, 0x4000, 0);
return true;
}
bool aciodrv_proc_panb_get_state(uint8_t *button_state)
{
struct ac_io_panb_keypair keypair[AC_IO_PANB_MAX_KEYPAIRS];
EnterCriticalSection(&keypair_lock);
memcpy(keypair, _keypair, AC_IO_PANB_MAX_KEYPAIRS);
LeaveCriticalSection(&keypair_lock);
/* splice the keypairs into separate button values */
for (int i=0; i<AC_IO_PANB_MAX_KEYPAIRS; i++) {
uint8_t but1 = keypair[i].key1;
uint8_t but2 = keypair[i].key2;
button_state[2*i] = but1;
button_state[2*i+1] = but2;
}
return true;
}
void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device)
{
EnterCriticalSection(&auto_poll_stop_lock);
auto_poll_stop = true;
LeaveCriticalSection(&auto_poll_stop_lock);
thread_join(auto_poll_threadid, NULL);
thread_destroy(auto_poll_threadid);
DeleteCriticalSection(&keypair_lock);
DeleteCriticalSection(&auto_poll_stop_lock);
/* reset is the only way to disable the auto polling on device side */
aciodrv_device_reset(device);
}

View File

@@ -0,0 +1,32 @@
#ifndef ACIODRV_PROC_PANB_H
#define ACIODRV_PROC_PANB_H
#include "aciodrv/panb.h"
/**
* Initialize a PANB device. This will take care of setting up the auto-poll and processing
* the poll messages in a separate thread (this is necessary as failing to process messages
* fast enough will cause the device to malfunction).
*
* @param device Context of opened device
* @return True if successful, false on error.
* @note This function spawns a thread. Caller must call aciodrv_proc_panb_fini to properly
* terminate.
*/
bool aciodrv_proc_panb_init(struct aciodrv_device_ctx *device);
/**
* Retrieve latest known button state from the PANB device.
*
* @param button_state 28 cell array to store button state
* (mandatory, upon calling the array contains values between 0 to 15 indicating the keys velocity).
* @return True on success, false on error.
*/
bool aciodrv_proc_panb_get_state(uint8_t *button_state);
/**
* Properly terminate the thread and reset the device (this is the only way to stop the auto polling).
*/
void aciodrv_proc_panb_fini(struct aciodrv_device_ctx *device);
#endif

View File

@@ -1,10 +1,12 @@
libs += aciodrv
libs_aciodrv := \
src_aciodrv := \
device.c \
h44b.c \
icca.c \
kfca.c \
panb.c \
port.c \

View File

@@ -1,5 +1,6 @@
#define LOG_MODULE "aciodrv-device"
#include <inttypes.h>
#include <string.h>
#include "aciodrv/device.h"
@@ -8,34 +9,64 @@
#include "util/hex.h"
#include "util/log.h"
#include "util/mem.h"
/* Enable to dump all data to the logger */
//#define AC_IO_MSG_LOG
static uint8_t aciodrv_device_msg_counter = 1;
static uint8_t aciodrv_device_node_count;
static char aviodrv_device_node_products[16][4];
#define ACIO_MAX_NODES_PER_PORT 16
static bool aciodrv_device_init(void)
struct aciodrv_device_ctx {
HANDLE fd;
struct aciodrv_device_node_version node_versions[ACIO_MAX_NODES_PER_PORT];
uint8_t msg_counter;
uint8_t node_count;
};
bool aciodrv_device_reset(struct aciodrv_device_ctx *device)
{
uint8_t reset_seq[525] = {0};
/* init/reset the device by sending 525 NULL bytes */
log_info("Resetting device");
if (aciodrv_port_write(device->fd, reset_seq, sizeof(reset_seq)) <= 0) {
return false;
}
/* signal to device for a reset */
EscapeCommFunction(device->fd, SETBREAK);
Sleep(1450);
EscapeCommFunction(device->fd, CLRBREAK);
Sleep(1200);
/* ignore the next 100 reads (of whatever length) */
for (size_t i = 0; i < 100; ++i) {
aciodrv_port_read(device->fd, reset_seq, sizeof(reset_seq));
}
return true;
}
static bool aciodrv_device_sof_flush(struct aciodrv_device_ctx *device)
{
uint8_t init_seq[1] = {AC_IO_SOF};
uint8_t read_buff[1] = {0x00};
uint8_t read_buff[1] = {0};
/* init/reset the device by sending 0xAA until 0xAA is returned */
/* wait for reset to finish */
int read = 0;
do {
if (aciodrv_port_write(init_seq, sizeof(init_seq)) <= 0) {
if (aciodrv_port_write(device->fd, init_seq, sizeof(init_seq)) <= 0) {
return false;
}
read = aciodrv_port_read(read_buff, sizeof(read_buff));
read = aciodrv_port_read(device->fd, read_buff, sizeof(read_buff));
} while ((read <= 0) || (read_buff[0] != init_seq[0]));
if (read > 0) {
log_warning("Obtained SOF, clearing out buffer now");
log_info("Obtained SOF, clearing out buffer now");
/* empty buffer by reading all data */
while (read > 0) {
read = aciodrv_port_read(init_seq, sizeof(init_seq));
read = aciodrv_port_read(device->fd, init_seq, sizeof(init_seq));
}
log_warning("Cleared buffer, init done");
@@ -46,30 +77,39 @@ static bool aciodrv_device_init(void)
}
}
static bool aciodrv_device_init(struct aciodrv_device_ctx *device)
{
if (!aciodrv_device_reset(device)) {
log_warning("Reset failed");
return false;
}
return aciodrv_device_sof_flush(device);
}
#ifdef AC_IO_MSG_LOG
static void
aciodrv_device_log_buffer(const char *msg, const uint8_t *buffer, int length)
aciodrv_device_log_buffer(struct aciodrv_device_ctx *device, const char *msg, const uint8_t *buffer, int length)
{
char str[4096];
hex_encode_uc((const void *) buffer, length, str, sizeof(str));
log_misc("%s, length %d: %s", msg, length, str);
log_misc("[%p] %s, length %d: %s", device->fd, msg, length, str);
}
#endif
static bool aciodrv_device_send(const uint8_t *buffer, int length)
static bool aciodrv_device_send(struct aciodrv_device_ctx *device, const uint8_t *buffer, int length)
{
uint8_t send_buf[512];
int send_buf_pos = 0;
uint8_t checksum = 0;
if (length > sizeof(send_buf)) {
log_warning("Send buffer overflow");
log_warning("[%p] Send buffer overflow", device->fd);
return false;
}
#ifdef AC_IO_MSG_LOG
aciodrv_device_log_buffer("Send (1)", buffer, length);
aciodrv_device_log_buffer(device, "Send (1)", buffer, length);
#endif
send_buf[send_buf_pos++] = AC_IO_SOF;
@@ -95,18 +135,18 @@ static bool aciodrv_device_send(const uint8_t *buffer, int length)
}
#ifdef AC_IO_MSG_LOG
aciodrv_device_log_buffer("Send (2)", send_buf, send_buf_pos);
aciodrv_device_log_buffer(device, "Send (2)", send_buf, send_buf_pos);
#endif
if (aciodrv_port_write(send_buf, send_buf_pos) != send_buf_pos) {
log_warning("Sending data with length %d failed", send_buf_pos);
if (aciodrv_port_write(device->fd, send_buf, send_buf_pos) != send_buf_pos) {
log_warning("[%p] Sending data with length %d failed", device->fd, send_buf_pos);
return false;
}
return true;
}
static int aciodrv_device_receive(uint8_t *buffer, int size)
static int aciodrv_device_receive(struct aciodrv_device_ctx *device, uint8_t *buffer, int max_resp_size)
{
uint8_t recv_buf[512];
int recv_size = 0;
@@ -118,16 +158,14 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
of 0xAAs before we get a valid message. */
recv_buf[0] = AC_IO_SOF;
do {
read = aciodrv_port_read(recv_buf, 1);
read = aciodrv_port_read(device->fd, recv_buf, 1);
} while (recv_buf[0] == AC_IO_SOF);
if (read > 0) {
size += 1;
if (read > 0) {
/* recv_buf[0] is already the first byte of the message.
now read until nothing's left */
recv_size++;
size--;
/* important: we have to know how much data we expect
and have to read until we reach the requested amount.
@@ -135,9 +173,10 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
need to handle escaping (which relies on an up to
date recv_buf[recv_size]) we loop until we get a
non-zero read. */
while (size > 0) {
size_t expected_size = offsetof(struct ac_io_message, cmd.nbytes) + 1;
while (recv_size < expected_size) {
do {
read = aciodrv_port_read(recv_buf + recv_size, 1);
read = aciodrv_port_read(device->fd, recv_buf + recv_size, 1);
} while (read == 0);
if (read < 0) {
@@ -150,7 +189,8 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
/* next byte is our real data
overwrite escape byte */
do {
read = aciodrv_port_read(recv_buf + recv_size, 1);
read = aciodrv_port_read(
device->fd, recv_buf + recv_size, 1);
} while (read == 0);
if (read < 0) {
@@ -161,15 +201,23 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
}
recv_size += read;
size -= read;
if (recv_size > offsetof(struct ac_io_message, cmd.nbytes)) {
// header + data + checksum
expected_size = offsetof(struct ac_io_message, cmd.raw) + ((struct ac_io_message*)recv_buf)->cmd.nbytes + 1;
}
}
#ifdef AC_IO_MSG_LOG
aciodrv_device_log_buffer("Recv (1)", recv_buf, recv_size);
log_warning("Expected %d got %d", recv_buf[4], recv_size - 6);
aciodrv_device_log_buffer(device, "Recv (1)", recv_buf, recv_size);
log_warning("Expected %d got %d", max_resp_size - 6, recv_buf[4]);
#endif
/* recv_size - 1: omit checksum for checksum calc */
if ((recv_size - 1) > max_resp_size) {
log_warning("[%p] Expected %d got %d", device->fd, max_resp_size - 6, recv_buf[4]);
return -1;
}
for (int i = 0; i < recv_size - 1; i++) {
checksum += recv_buf[i];
buffer[i] = recv_buf[i];
@@ -178,12 +226,13 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
result_size = recv_size - 1;
#ifdef AC_IO_MSG_LOG
aciodrv_device_log_buffer("Recv (2)", buffer, result_size);
aciodrv_device_log_buffer(device, "Recv (2)", buffer, result_size);
#endif
if (checksum != recv_buf[recv_size - 1]) {
log_warning(
"Invalid message checksum: %02X != %02X",
"[%p] Invalid message checksum: %02X != %02X",
device->fd,
checksum,
recv_buf[recv_size - 1]);
return -1;
@@ -195,7 +244,7 @@ static int aciodrv_device_receive(uint8_t *buffer, int size)
return -1;
}
static uint8_t aciodrv_device_enum_nodes(void)
static uint8_t aciodrv_device_enum_nodes(struct aciodrv_device_ctx *device)
{
struct ac_io_message msg;
@@ -205,7 +254,9 @@ static uint8_t aciodrv_device_enum_nodes(void)
msg.cmd.count = 0;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Enumerating nodes failed");
return 0;
}
@@ -215,7 +266,7 @@ static uint8_t aciodrv_device_enum_nodes(void)
return msg.cmd.count;
}
static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
static bool aciodrv_device_get_version(struct aciodrv_device_ctx *device, uint8_t node_id, struct aciodrv_device_node_version *version)
{
struct ac_io_message msg;
@@ -224,6 +275,7 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
msg.cmd.nbytes = 0;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) +
sizeof(struct ac_io_version))) {
@@ -247,12 +299,15 @@ static bool aciodrv_device_get_version(uint8_t node_id, char product[4])
msg.cmd.version.date,
msg.cmd.version.time);
memcpy(product, msg.cmd.version.product_code, 4);
memcpy(version->product, msg.cmd.version.product_code, ACIO_NODE_PRODUCT_CODE_LEN);
version->major = msg.cmd.version.major;
version->minor = msg.cmd.version.minor;
version->revision = msg.cmd.version.revision;
return true;
}
static bool aciodrv_device_start_node(uint8_t node_id)
static bool aciodrv_device_start_node(struct aciodrv_device_ctx *device, uint8_t node_id)
{
struct ac_io_message msg;
@@ -261,7 +316,9 @@ static bool aciodrv_device_start_node(uint8_t node_id)
msg.cmd.nbytes = 0;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Starting node %d failed", node_id);
return false;
}
@@ -270,80 +327,127 @@ static bool aciodrv_device_start_node(uint8_t node_id)
return true;
}
bool aciodrv_device_open(const char *port, int baud)
// deprecated name
struct aciodrv_device_ctx *aciodrv_device_open(const char *port_path, int baud)
{
if (!aciodrv_port_open(port, baud)) {
return aciodrv_device_open_path(port_path, baud);
}
struct aciodrv_device_ctx *aciodrv_device_open_path(const char *port_path, int baud)
{
HANDLE port = aciodrv_port_open(port_path, baud);
if (!port) {
return NULL;
}
struct aciodrv_device_ctx *device = xmalloc(sizeof(struct aciodrv_device_ctx));
memset(device, 0, sizeof(struct aciodrv_device_ctx));
device->fd = port;
device->msg_counter = 1;
if (!aciodrv_device_init(device)) {
aciodrv_device_close(device);
return NULL;
}
device->node_count = aciodrv_device_enum_nodes(device);
if (device->node_count == 0) {
aciodrv_device_close(device);
return false;
}
if (!aciodrv_device_init()) {
return false;
}
aciodrv_device_node_count = aciodrv_device_enum_nodes();
if (aciodrv_device_node_count == 0) {
return false;
}
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
for (uint8_t i = 0; i < device->node_count; i++) {
if (!aciodrv_device_get_version(
i + 1, aviodrv_device_node_products[i])) {
return false;
device, i + 1, &device->node_versions[i])) {
aciodrv_device_close(device);
return NULL;
}
}
for (uint8_t i = 0; i < aciodrv_device_node_count; i++) {
if (!aciodrv_device_start_node(i + 1)) {
return false;
for (uint8_t i = 0; i < device->node_count; i++) {
if (!aciodrv_device_start_node(device, i + 1)) {
aciodrv_device_close(device);
return NULL;
}
}
return true;
log_info("Opening ACIO device on [%p]", device->fd);
return device;
}
uint8_t aciodrv_device_get_node_count(void)
uint8_t aciodrv_device_get_node_count(struct aciodrv_device_ctx *device)
{
return aciodrv_device_node_count;
return device->node_count;
}
bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4])
bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, uint8_t node_id, char product[ACIO_NODE_PRODUCT_CODE_LEN])
{
if (aciodrv_device_node_count == 0 || node_id > aciodrv_device_node_count) {
if (device->node_count == 0 || node_id > device->node_count) {
return false;
}
memcpy(product, aviodrv_device_node_products[node_id], 4);
memcpy(product, device->node_versions[node_id].product, ACIO_NODE_PRODUCT_CODE_LEN);
return true;
}
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
const struct aciodrv_device_node_version *aciodrv_device_get_node_product_version(struct aciodrv_device_ctx *device, uint8_t node_id)
{
msg->cmd.seq_no = aciodrv_device_msg_counter++;
if (device->node_count == 0 || node_id > device->node_count) {
return NULL;
}
return &device->node_versions[node_id];
}
bool aciodrv_send(struct aciodrv_device_ctx *device, struct ac_io_message *msg)
{
msg->cmd.seq_no = device->msg_counter++;
int send_size = offsetof(struct ac_io_message, cmd.raw) + msg->cmd.nbytes;
#ifdef AC_IO_MSG_LOG
log_info(
"Beginning send on %d: %04x (%d b)",
"[%p] Beginning send on %d: %04x (%d b)",
device->fd,
msg->addr,
msg->cmd.code,
send_size);
#endif
if (aciodrv_device_send((uint8_t *) msg, send_size) <= 0) {
if (aciodrv_device_send(device, (uint8_t *) msg, send_size) <= 0) {
return false;
}
return true;
}
bool aciodrv_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size)
{
#ifdef AC_IO_MSG_LOG
log_info("[%p] Beginning recv: (%d b)", device->fd, max_resp_size);
#endif
if (aciodrv_device_receive(device, (uint8_t *) msg, max_resp_size) <= 0) {
return false;
}
return true;
}
bool aciodrv_send_and_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size)
{
if (!aciodrv_send(device, msg)) {
return false;
}
uint16_t req_code = msg->cmd.code;
#ifdef AC_IO_MSG_LOG
log_info("Beginning recv: (%d b)", resp_size);
#endif
if (aciodrv_device_receive((uint8_t *) msg, resp_size) <= 0) {
if (!aciodrv_recv(device, msg, max_resp_size)) {
return false;
}
if (req_code != msg->cmd.code) {
log_warning(
"Received invalid response %04X for request %04X",
"[%p] Received invalid response %04X for request %04X",
device->fd,
msg->cmd.code,
req_code);
return false;
@@ -352,7 +456,13 @@ bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size)
return true;
}
void aciodrv_device_close(void)
void aciodrv_device_close(struct aciodrv_device_ctx *device)
{
aciodrv_port_close();
log_assert(device);
log_info("Closing ACIO on [%p]", device->fd);
aciodrv_port_close(device->fd);
free(device);
}

View File

@@ -5,48 +5,109 @@
#include "acio/acio.h"
#include "windows.h"
#define ACIO_NODE_PRODUCT_CODE_LEN 4
struct aciodrv_device_ctx;
struct aciodrv_device_node_version {
char product[ACIO_NODE_PRODUCT_CODE_LEN];
uint8_t major;
uint8_t minor;
uint8_t revision;
};
/**
* Open an ACIO device connected to a serial port.
*
* @param port Port the device is connected to (e.g. "COM1")
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
* @return True if opening the port and resetting the device was successful,
* false on error.
* @return opened device context, NULL on error
*/
bool aciodrv_device_open(const char *port, int baud);
struct aciodrv_device_ctx *aciodrv_device_open(const char *port_path, int baud)
#ifdef __GNUC__
__attribute__((deprecated("Use aciomgr instead if device is shareable, else aciodrv_device_open_path")))
#endif
;
struct aciodrv_device_ctx *aciodrv_device_open_path(const char *port_path, int baud);
/**
* Get the node count on the opened device.
*
* @param device Context of opened device
* @return Total num of nodes enumerated on the ACIO device.
*/
uint8_t aciodrv_device_get_node_count(void);
uint8_t aciodrv_device_get_node_count(struct aciodrv_device_ctx *device);
/**
* Get the product identifier of an enumerated node.
*
* @param device Context of opened device
* @param node_id Id of the node. Needs to be in range of the total node count.
* @param product Buffer to return the product id to.
* @return True on success, false on error. If True the variable product
* contains the identifier of the queried node.
*/
bool aciodrv_device_get_node_product_ident(uint8_t node_id, char product[4]);
bool aciodrv_device_get_node_product_ident(struct aciodrv_device_ctx *device, uint8_t node_id, char product[ACIO_NODE_PRODUCT_CODE_LEN]);
/**
* Get the product version of an enumerated node.
*
* @param device Context of opened device
* @param node_id Id of the node. Needs to be in range of the total node count.
* @return Pointer to the version struct
*/
const struct aciodrv_device_node_version *aciodrv_device_get_node_product_version(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Send a message to the ACIO bus and receive an answer.
* Use this to implement the protocol for each type of device that can be
* part of the bus.
*
* @param device Context of opened device
* @param msg Msg to send to the bus. Make sure that the buffer backing
* this message is big enough to receive the response as well.
* @param resp_size Size of the expecting response.
* @return True on success, false on error.
*/
bool aciodrv_send_and_recv(struct ac_io_message *msg, int resp_size);
bool aciodrv_send_and_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size);
/**
* Send a message to the ACIO bus.
*
* @param device Context of opened device
* @param msg Msg to send to the bus.
* @return True on success, false on error.
* @note Prefer the use of aciodrv_send_and_recv when possible. This is for commands which don't trigger a reply.
*/
bool aciodrv_send(struct aciodrv_device_ctx *device, struct ac_io_message *msg);
/**
* Read a message from the ACIO bus.
*
* @param device Context of opened device
* @param msg Msg to send to the bus. Make sure that the buffer
* is big enough to receive the response.
* @return True on success, false on error.
* @note Prefer the use of aciodrv_send_and_recv when possible. This is for unsollicited incoming messages.
*/
bool aciodrv_recv(struct aciodrv_device_ctx *device, struct ac_io_message *msg, int max_resp_size);
/**
* Reset an opened device.
*
* @param device Context of opened device
* @return Total num of nodes enumerated on the ACIO device.
*/
bool aciodrv_device_reset(struct aciodrv_device_ctx *device);
/**
* Close the previously opened ACIO device.
*
* @param device Context of opened device
*/
void aciodrv_device_close(void);
void aciodrv_device_close(struct aciodrv_device_ctx *device);
#endif

45
src/main/aciodrv/h44b.c Normal file
View File

@@ -0,0 +1,45 @@
#define LOG_MODULE "aciodrv-h44b"
#include <stdio.h>
#include <string.h>
#include "acio/h44b.h"
#include "aciodrv/device.h"
#include "util/log.h"
bool aciodrv_h44b_init(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
// unlike input devices like KFCA, H44B has no watchdog or special init code
// requirements - shared ACIO node initialisation is enough
return true;
}
bool aciodrv_h44b_lights(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_h44b_output *lights)
{
struct ac_io_message msg;
log_assert(device);
log_assert(lights);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_H44B_CMD_SET_OUTPUTS);
msg.cmd.nbytes = sizeof(*lights);
msg.cmd.h44b_output = *lights;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}
return true;
}

32
src/main/aciodrv/h44b.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef ACIODRV_H44B_H
#define ACIODRV_H44B_H
#include "aciodrv/device.h"
#include "acio/h44b.h"
/**
* Initialize an H44B node.
*
* @param device Context of opened device
* @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 aciodrv_h44b_init(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Set the H44B LEDs
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @param lights Packed lights struct to send
* @return True on success, false on error.
*/
bool aciodrv_h44b_lights(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_h44b_output *lights);
#endif

View File

@@ -3,20 +3,27 @@
#include <string.h>
#include "aciodrv/device.h"
#include "aciodrv/icca.h"
#include "util/log.h"
static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
static bool aciodrv_icca_queue_loop_start(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_QUEUE_LOOP_START);
msg.cmd.nbytes = 1;
msg.cmd.status = 0;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Starting queue loop failed");
return false;
}
@@ -27,9 +34,11 @@ static bool aciodrv_icca_queue_loop_start(uint8_t node_id)
return true;
}
bool aciodrv_icca_init(uint8_t node_id)
bool aciodrv_icca_init(struct aciodrv_device_ctx *device, uint8_t node_id)
{
if (!aciodrv_icca_queue_loop_start(node_id + 1)) {
log_assert(device);
if (!aciodrv_icca_queue_loop_start(device, node_id + 1)) {
return false;
}
@@ -37,10 +46,15 @@ bool aciodrv_icca_init(uint8_t node_id)
}
bool aciodrv_icca_set_state(
uint8_t node_id, int slot_state, struct ac_io_icca_state *state)
struct aciodrv_device_ctx *device,
uint8_t node_id,
int slot_state,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_SET_SLOT_STATE);
msg.cmd.nbytes = 2;
@@ -49,7 +63,9 @@ bool aciodrv_icca_set_state(
msg.cmd.raw[1] = slot_state;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.raw[0])) {
log_warning("Setting state of node %d failed", node_id + 1);
return false;
}
@@ -61,10 +77,15 @@ bool aciodrv_icca_set_state(
return true;
}
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
bool aciodrv_icca_get_state(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL);
msg.cmd.nbytes = 1;
@@ -72,7 +93,9 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
msg.cmd.count = sizeof(struct ac_io_icca_state);
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Getting state of node %d failed", node_id + 1);
return false;
}
@@ -84,10 +107,15 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state)
return true;
}
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
bool aciodrv_icca_read_card(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_ENGAGE);
msg.cmd.nbytes = 1;
@@ -95,7 +123,9 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
msg.cmd.count = sizeof(struct ac_io_icca_state);
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Reading card of node %d failed", node_id + 1);
return false;
}
@@ -105,4 +135,53 @@ bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state)
}
return true;
}
}
bool aciodrv_icca_is_slotted(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
const struct aciodrv_device_node_version *version;
version = aciodrv_device_get_node_product_version(device, node_id);
// current heuristic is to check if version >= 1.5
if (version) {
if (version->major == 1) {
if (version->minor >= 5) {
return false;
}
}
}
return true;
}
bool aciodrv_icca_poll_felica(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_ICCA_CMD_POLL_FELICA);
msg.cmd.nbytes = 4;
/* buffer size of data we expect */
msg.cmd.count = 1;
// additional data, not sure
msg.cmd.raw[1] = 0x03;
msg.cmd.raw[2] = 0xFF;
msg.cmd.raw[3] = 0xFF;
if (!aciodrv_send_and_recv(
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + msg.cmd.count)) {
log_warning("Reading card of node %d failed", node_id + 1);
return false;
}
return true;
}

View File

@@ -6,17 +6,19 @@
/**
* Initialize an ICCA node.
*
* @param device Context of opened device
* @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 aciodrv_icca_init(uint8_t node_id);
bool aciodrv_icca_init(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Set the state of on ICCA node.
*
* @param device Context of opened device
* @param node_id Id of the node to set the state for (0 based).
* @param slot_state State of the slot (refer to corresponding enum).
* @param state Pointer to a state struct to return the current state to
@@ -27,11 +29,15 @@ bool aciodrv_icca_init(uint8_t node_id);
* @see driver.h
*/
bool aciodrv_icca_set_state(
uint8_t node_id, int slot_state, struct ac_io_icca_state *state);
struct aciodrv_device_ctx *device,
uint8_t node_id,
int slot_state,
struct ac_io_icca_state *state);
/**
* Get the current state of an ICCA node.
*
* @param device Context of opened device
* @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).
@@ -40,7 +46,10 @@ bool aciodrv_icca_set_state(
* device driver foundation.
* @see driver.h
*/
bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
bool aciodrv_icca_get_state(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state);
/**
* Trigger a card read action on the ICCA reader. Make sure to call this
@@ -48,6 +57,7 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
* to get the most recent card data. Make sure to re-get the state after
* a read call. The state returned here might not be up to date for some reason.
*
* @param device Context of opened device
* @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).
@@ -56,6 +66,46 @@ bool aciodrv_icca_get_state(uint8_t node_id, struct ac_io_icca_state *state);
* device driver foundation.
* @see driver.h
*/
bool aciodrv_icca_read_card(uint8_t node_id, struct ac_io_icca_state *state);
bool aciodrv_icca_read_card(
struct aciodrv_device_ctx *device,
uint8_t node_id,
struct ac_io_icca_state *state);
#endif
/**
* Uses some heruistics based on the product ident to determine if the detected
* device is a slotted (true) or wavepass reader (false).
*
* This function will also return false if the provided node_id is invalid.
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @return True on slotted, false on wavepass.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_icca_is_slotted(
struct aciodrv_device_ctx *device,
uint8_t node_id);
/**
* Polls the felica chip on wavepass readers. This will cause the state of the
* reader to be AC_IO_ICCA_STATUS_BUSY_NEW for a few polls, before returning
* either: AC_IO_ICCA_STATUS_IDLE_NEW or AC_IO_ICCA_STATUS_GOT_UID.
*
* The user should take care to call this every so often to actually get new
* felica UIDs, instead of just old NFC idents. The game seems to do it every
* 5 or so polls after the last AC_IO_ICCA_STATUS_BUSY_NEW poll.
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @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 aciodrv_icca_poll_felica(
struct aciodrv_device_ctx *device,
uint8_t node_id);
#endif

View File

@@ -7,37 +7,35 @@
#include "util/log.h"
static bool aciodrv_kfca_watchdog_start(uint8_t node_id)
static bool aciodrv_kfca_watchdog_start(
struct aciodrv_device_ctx *device,
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;
log_assert(device);
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;
if (!aciodrv_send_and_recv(
device, &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);
log_warning("Started watchdog of node %d, sz: %d, status: %d",
node_id, msg.cmd.nbytes, msg.cmd.status);
return true;
*/
}
bool aciodrv_kfca_amp(
struct aciodrv_device_ctx *device,
uint8_t node_id,
uint8_t primary,
uint8_t headphone,
@@ -46,6 +44,8 @@ bool aciodrv_kfca_amp(
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
msg.cmd.nbytes = 4;
@@ -56,7 +56,9 @@ bool aciodrv_kfca_amp(
msg.cmd.raw[3] = subwoofer;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Setting AMP failed");
return false;
}
@@ -66,13 +68,17 @@ bool aciodrv_kfca_amp(
return true;
}
bool aciodrv_kfca_init(uint8_t node_id)
bool aciodrv_kfca_init(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
if (!aciodrv_kfca_watchdog_start(node_id)) {
log_assert(device);
if (!aciodrv_kfca_watchdog_start(device, node_id)) {
return false;
}
if (!aciodrv_kfca_amp(node_id, 0, 0, 0, 0)) {
if (!aciodrv_kfca_amp(device, node_id, 0, 0, 0, 0)) {
return false;
}
@@ -80,12 +86,15 @@ bool aciodrv_kfca_init(uint8_t node_id)
}
bool aciodrv_kfca_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_kfca_poll_out *pout,
struct ac_io_kfca_poll_in *pin)
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
msg.cmd.nbytes = sizeof(*pout);
@@ -93,7 +102,9 @@ bool aciodrv_kfca_poll(
msg.cmd.kfca_poll_out = *pout;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}

View File

@@ -6,17 +6,19 @@
/**
* Initialize an KFCA node.
*
* @param device Context of opened device
* @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 aciodrv_kfca_init(uint8_t node_id);
bool aciodrv_kfca_init(struct aciodrv_device_ctx *device, uint8_t node_id);
/**
* Poll the KFCA io board
*
* @param device Context of opened device
* @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).
@@ -26,6 +28,7 @@ bool aciodrv_kfca_init(uint8_t node_id);
* @see driver.h
*/
bool aciodrv_kfca_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct ac_io_kfca_poll_out *pout,
struct ac_io_kfca_poll_in *pin);
@@ -33,6 +36,7 @@ bool aciodrv_kfca_poll(
/**
* Set the KFCA digital amp level
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @param primary primary volume (96-0)
* @param headphone headphone volume (96-0)
@@ -42,6 +46,7 @@ bool aciodrv_kfca_poll(
* @note Note 96 (or 100?) is lowest volume level, 0 is highest
*/
bool aciodrv_kfca_amp(
struct aciodrv_device_ctx *device,
uint8_t node_id,
uint8_t primary,
uint8_t headphone,

80
src/main/aciodrv/panb.c Normal file
View File

@@ -0,0 +1,80 @@
#define LOG_MODULE "aciodrv-panb"
#include <string.h>
#include "aciodrv/device.h"
#include "aciodrv/panb.h"
#include "util/thread.h"
#include "util/log.h"
bool aciodrv_panb_start_auto_input(struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t node_count)
{
log_assert(device);
struct ac_io_message msg;
/* only the first node is handling the commands */
if (node_id != 0) {
return true;
}
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_START_AUTO_INPUT);
msg.cmd.nbytes = 1;
msg.cmd.count = node_count;
if (!aciodrv_send(device, &msg)) {
log_warning("Starting auto input failed");
return false;
}
log_info("Started auto input for %d nodes", node_count);
return true;
}
bool aciodrv_panb_recv_poll(struct aciodrv_device_ctx *device, struct ac_io_panb_poll_in *poll_in)
{
log_assert(device);
struct ac_io_message msg;
struct ac_io_panb_poll_in *poll_res = (struct ac_io_panb_poll_in *) &msg.cmd.raw;
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_POLL_REPLY);
msg.cmd.nbytes = sizeof(struct ac_io_panb_poll_in);
if (!aciodrv_recv(device,
&msg, offsetof(struct ac_io_message, cmd.raw) + msg.cmd.nbytes + 1)) {
log_warning("Getting state failed");
return false;
}
if (poll_in != NULL){
memcpy(poll_in, poll_res, sizeof(struct ac_io_panb_poll_in));
}
return true;
}
bool aciodrv_panb_send_lamp(struct aciodrv_device_ctx *device,
uint8_t node_id, struct ac_io_panb_poll_out *state)
{
log_assert(device);
struct ac_io_message msg;
/* only the first node is handling the commands */
if (node_id != 0) {
return true;
}
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_PANB_SEND_LAMP);
msg.cmd.nbytes = 0x54;
memcpy(&msg.cmd.raw, state, sizeof(struct ac_io_panb_poll_out));
if (!aciodrv_send(device, &msg)) {
log_warning("Sending lamp state failed");
return false;
}
return true;
}

56
src/main/aciodrv/panb.h Normal file
View File

@@ -0,0 +1,56 @@
#ifndef ACIODRV_PANB_H
#define ACIODRV_PANB_H
#include "acio/panb.h"
/**
* Send the AC_IO_CMD_PANB_START_AUTO_INPUT command on a PANB device.
*
* @param device Context of opened device.
* @param node_id node_id Id of the node to query (0 based).
* @param node_count The number of nodes to poll.
* @return True if successful, false on error.
* @note node_id should be 0, PANB internally manages the other nodes.
* @note Upon calling, the device will stop replying to commands and just keep sending
* AC_IO_CMD_PANB_POLL_REPLY messages indefinitely. Failure to retrieve them fast enough
* will cause the device to malfunction. It is thus advised to make use of the aciodrv-proc
* module to spawn a thread that will handle these messages and provide an easy access to the
* latest input state.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_panb_start_auto_input(struct aciodrv_device_ctx *device, uint8_t node_id, uint8_t node_count);
/**
* Retrieve a AC_IO_CMD_PANB_POLL_REPLY message from a PANB device. This assumes that there
* is such message incoming (ie. that start_auto_input has been called prior).
*
* @param device Context of opened device.
* @param poll_in Buffer to hold the received message, or NULL.
* @return True if successful, false on error.
* @note node_id should be 0, PANB internally manages the other nodes.
* @note Failure to retrieve the incoming messages fast enough will cause the device to malfunction.
* It is thus advised to make use of the aciodrv-proc module to spawn a thread that will handle these
* messages and provide an easy access to the latest input state.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_panb_recv_poll(struct aciodrv_device_ctx *device, struct ac_io_panb_poll_in *poll_in);
/**
* Light lamps on a PANB device.
*
* @param node_id Id of the node to query (0 based).
* @param state Pointer to a lamp state struct
* (mandatory).
* @return True on success, false on error.
* @note node_id should be 0, PANB internally manages the other nodes.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool aciodrv_panb_send_lamp(struct aciodrv_device_ctx *device, uint8_t node_id, struct ac_io_panb_poll_out *state);
#endif

View File

@@ -1,5 +1,6 @@
#define LOG_MODULE "aciodrv-port"
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
@@ -7,17 +8,15 @@
#include "util/log.h"
static HANDLE aciodrv_port_fd;
bool aciodrv_port_open(const char *port, int baud)
HANDLE aciodrv_port_open(const char *port_path, int baud)
{
COMMTIMEOUTS ct;
DCB dcb;
log_info("Opening ACIO on %s at %d baud", port, baud);
log_info("Opening ACIO on %s at %d baud", port_path, baud);
aciodrv_port_fd = CreateFile(
port,
HANDLE port_fd = CreateFile(
port_path,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
@@ -25,26 +24,26 @@ bool aciodrv_port_open(const char *port, int baud)
FILE_FLAG_WRITE_THROUGH | FILE_ATTRIBUTE_NORMAL,
NULL);
if (aciodrv_port_fd == INVALID_HANDLE_VALUE) {
log_warning("Failed to open %s", port);
if (port_fd == INVALID_HANDLE_VALUE) {
log_warning("Failed to open %s", port_path);
goto early_fail;
}
if (!SetCommMask(aciodrv_port_fd, EV_RXCHAR)) {
if (!SetCommMask(port_fd, EV_RXCHAR)) {
log_warning("SetCommMask failed");
goto fail;
}
if (!SetupComm(aciodrv_port_fd, 0x1000, 0x1000)) {
if (!SetupComm(port_fd, 0x1000, 0x1000)) {
log_warning("SetupComm failed");
goto fail;
}
if (!PurgeComm(
aciodrv_port_fd,
port_fd,
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)) {
log_warning("PurgeComm failed");
@@ -57,7 +56,7 @@ bool aciodrv_port_open(const char *port, int baud)
ct.ReadTotalTimeoutMultiplier = 0;
ct.WriteTotalTimeoutMultiplier = 0;
if (!SetCommTimeouts(aciodrv_port_fd, &ct)) {
if (!SetCommTimeouts(port_fd, &ct)) {
log_warning("SetCommTimeouts failed");
goto fail;
@@ -65,7 +64,7 @@ bool aciodrv_port_open(const char *port, int baud)
dcb.DCBlength = sizeof(dcb);
if (!GetCommState(aciodrv_port_fd, &dcb)) {
if (!GetCommState(port_fd, &dcb)) {
log_warning("GetCommState failed");
goto fail;
@@ -90,46 +89,47 @@ bool aciodrv_port_open(const char *port, int baud)
dcb.XonLim = 100;
dcb.XoffLim = 100;
if (!SetCommState(aciodrv_port_fd, &dcb)) {
if (!SetCommState(port_fd, &dcb)) {
log_warning("SetCommState failed");
goto fail;
}
if (!EscapeCommFunction(aciodrv_port_fd, SETDTR)) {
if (!EscapeCommFunction(port_fd, SETDTR)) {
log_warning("SETDTR failed: err = %lu", GetLastError());
goto fail;
}
log_info("Opened ACIO device on %s", port);
log_info("[%p] Opened ACIO device on %s", port_fd, port_path);
return true;
return port_fd;
fail:
CloseHandle(aciodrv_port_fd);
CloseHandle(port_fd);
early_fail:
aciodrv_port_fd = NULL;
return false;
return NULL;
}
int aciodrv_port_read(void *bytes, int nbytes)
int aciodrv_port_read(HANDLE port_fd, void *bytes, int nbytes)
{
DWORD nread;
if (aciodrv_port_fd == NULL) {
log_assert(bytes);
if (port_fd == NULL) {
return -1;
}
if (!ClearCommError(aciodrv_port_fd, NULL, NULL)) {
log_warning("ClearCommError failed");
if (!ClearCommError(port_fd, NULL, NULL)) {
log_warning("[%p] ClearCommError failed", port_fd);
return -1;
}
if (!ReadFile(aciodrv_port_fd, bytes, nbytes, &nread, NULL)) {
log_warning("ReadFile failed: err = %lu", GetLastError());
if (!ReadFile(port_fd, bytes, nbytes, &nread, NULL)) {
log_warning("[%p] ReadFile failed: err = %lu", port_fd, GetLastError());
return -1;
}
@@ -137,16 +137,18 @@ int aciodrv_port_read(void *bytes, int nbytes)
return nread;
}
int aciodrv_port_write(const void *bytes, int nbytes)
int aciodrv_port_write(HANDLE port_fd, const void *bytes, int nbytes)
{
DWORD nwrit;
if (aciodrv_port_fd == NULL) {
log_assert(bytes);
if (port_fd == NULL) {
return -1;
}
if (!WriteFile(aciodrv_port_fd, bytes, nbytes, &nwrit, NULL)) {
log_warning("WriteFile failed: err = %lu", GetLastError());
if (!WriteFile(port_fd, bytes, nbytes, &nwrit, NULL)) {
log_warning("[%p] WriteFile failed: err = %lu", port_fd, GetLastError());
return -1;
}
@@ -154,9 +156,9 @@ int aciodrv_port_write(const void *bytes, int nbytes)
return nwrit;
}
void aciodrv_port_close(void)
void aciodrv_port_close(HANDLE port_fd)
{
if (aciodrv_port_fd != NULL) {
CloseHandle(aciodrv_port_fd);
if (port_fd != NULL) {
CloseHandle(port_fd);
}
}

View File

@@ -4,39 +4,45 @@
#include <stdbool.h>
#include <stdint.h>
#include <windows.h>
/**
* Open a serial port for communication with a ACIO device.
*
* @param port Port the device is connected to (e.g. "COM1")
* @param baud Baud rate for communication (e.g. 57600 for ICCA)
* @return True if opening the com port was successful, false on error.
* @return HANDLE of the port, NULL on error
* @note This will open and setup the com port, only.
*/
bool aciodrv_port_open(const char *port, int baud);
HANDLE aciodrv_port_open(const char *port_path, int baud);
/**
* Read data from the opened com port.
*
* @param port_fd HANDLE of opened serial port
* @param bytes Pointer to an allocated buffer to read the data into.
* @param nbytes Number of bytes to read. Has to be less or equal the allocated
* buffer size.
* @return Number of bytes read on success or -1 on error.
*/
int aciodrv_port_read(void *bytes, int nbytes);
int aciodrv_port_read(HANDLE port_fd, void *bytes, int nbytes);
/**
* Write data to the opened com port.
*
* @param port_fd HANDLE of opened serial port
* @param bytes Pointer to an allocated buffer with data to write.
* @param nbytes Number of bytes to write. Has to be equal or less the size
* of the allocated buffer.
* @return Number of bytes written on success or -1 on error.
*/
int aciodrv_port_write(const void *bytes, int nbytes);
int aciodrv_port_write(HANDLE port_fd, const void *bytes, int nbytes);
/**
* Close the previously opened com port.
*
* @param port_fd HANDLE of opened serial port
*/
void aciodrv_port_close(void);
void aciodrv_port_close(HANDLE port_fd);
#endif

View File

@@ -134,6 +134,7 @@ static HRESULT ac_io_emu_write(struct ac_io_emu *emu, struct irp *irp)
break;
}
// this supplies a single SOF byte per byte read
ac_io_in_supply(&emu->in, NULL, 0);
ac_io_out_consume_message(&emu->out);
}

View File

@@ -61,7 +61,7 @@ void ac_io_emu_h44b_dispatch_request(
req->cmd.raw[i * 3 + 2]);
}
jb_io_write_outputs();
jb_io_write_lights();
ac_io_emu_h44b_send_status(h44b, req, 0x00);

View File

@@ -29,13 +29,6 @@ enum ac_io_icca_flag {
AC_IO_ICCA_FLAG_SOLENOID = 0x40
};
enum ac_io_icca_status_code {
AC_IO_ICCA_STATUS_FAULT = 0x00,
AC_IO_ICCA_STATUS_IDLE = 0x01,
AC_IO_ICCA_STATUS_GOT_UID = 0x02,
AC_IO_ICCA_STATUS_IDLE_NEW = 0x04
};
static void ac_io_emu_icca_cmd_send_version(
struct ac_io_emu_icca *icca, const struct ac_io_message *req);

View File

@@ -169,6 +169,10 @@ static void ac_io_emu_iccb_send_state(
/* state update */
if (!eam_io_poll(iccb->unit_no)) {
log_warning("Polling eamio failed");
}
sensor = eam_io_get_sensor_state(iccb->unit_no);
if (sensor != iccb->last_sensor) {

View File

@@ -0,0 +1,9 @@
dlls += aciomgr
libs_aciomgr := \
aciodrv \
util \
src_aciomgr := \
dllmain.c \
manager.c \

View File

@@ -0,0 +1,12 @@
LIBRARY aciomgr
EXPORTS
aciomgr_set_loggers
aciomgr_port_init
aciomgr_port_fini
aciomgr_get_node_count
aciomgr_get_node_product_ident
aciomgr_port_submit_packet
aciomgr_port_checkout
aciomgr_port_checkin
DllMain@12 @1 NONAME

View File

@@ -0,0 +1,16 @@
#include <windows.h>
#include "manager-init.h"
BOOL WINAPI DllMain(HMODULE self, DWORD reason, void *ctx)
{
if (reason == DLL_PROCESS_ATTACH) {
_aciomgr_init();
}
if (reason == DLL_PROCESS_DETACH) {
_aciomgr_fini();
}
return TRUE;
}

View File

@@ -0,0 +1,8 @@
#ifndef ACIOMGR_MANAGER_INIT_H
#define ACIOMGR_MANAGER_INIT_H
// internal, used by DllMain
void _aciomgr_init();
void _aciomgr_fini();
#endif

210
src/main/aciomgr/manager.c Normal file
View File

@@ -0,0 +1,210 @@
#define LOG_MODULE "aciomgr-manager"
#include <windows.h>
#include <stdatomic.h>
#include "aciomgr/manager-init.h"
#include "aciomgr/manager.h"
#include "acio/acio.h"
#include "aciodrv/device.h"
#include "util/array.h"
#include "util/log.h"
#define MAX_PORT_PATH_LENGTH 256
struct aciomgr_port_dispatcher {
CRITICAL_SECTION cs;
atomic_size_t references;
struct aciodrv_device_ctx *device;
char path[MAX_PORT_PATH_LENGTH];
int baud;
bool has_failure;
};
static void _aciomgr_setup_port_dispatcher(
struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud);
static void
_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher);
// DLL-globals
static atomic_bool running;
static CRITICAL_SECTION mgr_cs;
static struct array active_ports;
static void _aciomgr_setup_port_dispatcher(
struct aciomgr_port_dispatcher *dispatcher, const char *path, int baud)
{
InitializeCriticalSection(&dispatcher->cs);
strcpy(dispatcher->path, path);
dispatcher->baud = baud;
dispatcher->device = aciodrv_device_open_path(path, baud);
dispatcher->has_failure = false;
if (dispatcher->device == NULL) {
log_info("Opening ACIO device on %s failed", path);
dispatcher->has_failure = true;
}
dispatcher->references = 0;
}
static void
_aciomgr_destroy_port_dispatcher(struct aciomgr_port_dispatcher *dispatcher)
{
aciodrv_device_close(dispatcher->device);
DeleteCriticalSection(&dispatcher->cs);
}
void _aciomgr_init()
{
if (running) {
log_warning("_aciomgr_init called when already running");
_aciomgr_fini();
}
InitializeCriticalSection(&mgr_cs);
array_init(&active_ports);
running = true;
}
void _aciomgr_fini()
{
if (!running) {
log_warning("_aciomgr_fini called when not running");
}
running = false;
DeleteCriticalSection(&mgr_cs);
array_fini(&active_ports);
}
void aciomgr_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal)
{
log_to_external(misc, info, warning, fatal);
}
struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud)
{
if (!running) {
log_warning("aciomgr_port_init: called when not running");
return NULL;
}
if (strlen(path) >= MAX_PORT_PATH_LENGTH) {
log_warning("aciomgr_port_init: path too long");
return NULL;
}
struct aciomgr_port_dispatcher *entry;
EnterCriticalSection(&mgr_cs);
for (size_t i = 0; i < active_ports.nitems; i++) {
entry = array_item(struct aciomgr_port_dispatcher, &active_ports, i);
if (strcmp(entry->path, path) == 0) {
// found
if (entry->baud != baud) {
log_warning(
"Device at %s opened with baud of %d, but requested %d",
path,
entry->baud,
baud);
}
goto done;
}
}
entry = array_append(struct aciomgr_port_dispatcher, &active_ports);
_aciomgr_setup_port_dispatcher(entry, path, baud);
done:
if (!entry->has_failure) {
entry->references++;
}
LeaveCriticalSection(&mgr_cs);
if (entry->has_failure) {
return NULL;
}
return entry;
}
void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher)
{
if (!running) {
log_warning("aciomgr_port_fini: called when not running");
return;
}
EnterCriticalSection(&mgr_cs);
dispatcher->references--;
LeaveCriticalSection(&mgr_cs);
if (dispatcher->references == 0) {
_aciomgr_destroy_port_dispatcher(dispatcher);
}
}
// this function don't require the lock
uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher)
{
return aciodrv_device_get_node_count(dispatcher->device);
}
// this function don't require the lock
bool aciomgr_get_node_product_ident(
struct aciomgr_port_dispatcher *dispatcher,
uint8_t node_id,
char product[ACIOMGR_NODE_PRODUCT_CODE_LEN])
{
return aciodrv_device_get_node_product_ident(
dispatcher->device, node_id, product);
}
bool aciomgr_port_submit_packet(
struct aciomgr_port_dispatcher *dispatcher,
struct ac_io_message *msg,
int max_resp_size)
{
// CS's although lightweight, may still be a burden, short circuit
if (dispatcher->references > 1) {
EnterCriticalSection(&dispatcher->cs);
bool response =
aciodrv_send_and_recv(dispatcher->device, msg, max_resp_size);
LeaveCriticalSection(&dispatcher->cs);
return response;
}
return aciodrv_send_and_recv(dispatcher->device, msg, max_resp_size);
}
struct aciodrv_device_ctx *
aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher)
{
if (dispatcher->references > 1) {
EnterCriticalSection(&dispatcher->cs);
}
return dispatcher->device;
}
void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher)
{
if (dispatcher->references > 1) {
LeaveCriticalSection(&dispatcher->cs);
}
}

View File

@@ -0,0 +1,86 @@
#ifndef ACIOMGR_MANAGER_H
#define ACIOMGR_MANAGER_H
#include <stdbool.h>
#include "bemanitools/glue.h"
#define ACIOMGR_NODE_PRODUCT_CODE_LEN 4
struct ac_io_message;
struct aciodrv_device_ctx;
struct aciomgr_port_dispatcher;
/**
* 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.
*/
void aciomgr_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
/**
* Init and open, or return the existing handle to an acio port
*
* @param path Port the device is connected to (e.g. "COM1")
* @return opened port dispatcher context, NULL on error
*/
struct aciomgr_port_dispatcher *aciomgr_port_init(const char *path, int baud);
void aciomgr_port_fini(struct aciomgr_port_dispatcher *dispatcher);
/**
* Get the node count on the opened device.
*
* @param dispatcher dispatcher context from aciomgr_port_init
* @return Total num of nodes enumerated on the ACIO device.
*/
uint8_t aciomgr_get_node_count(struct aciomgr_port_dispatcher *dispatcher);
/**
* Get the product identifier of an enumerated node.
*
* @param dispatcher dispatcher context from aciomgr_port_init
* @param node_id Id of the node. Needs to be in range of the total node count.
* @param product Buffer to return the product id to.
* @return True on success, false on error. If True the variable product
* contains the identifier of the queried node.
*/
bool aciomgr_get_node_product_ident(
struct aciomgr_port_dispatcher *dispatcher,
uint8_t node_id,
char product[ACIOMGR_NODE_PRODUCT_CODE_LEN]);
/**
* Submit and wait for the response of the specified packet
*
* @param dispatcher dispatcher context from aciomgr_port_init
* @param msg pointer to the message buffer to read from / write to
* @param max_resp_size pointer to the max size response we expect
* @return false on error
*/
bool aciomgr_port_submit_packet(
struct aciomgr_port_dispatcher *dispatcher,
struct ac_io_message *msg,
int max_resp_size);
/**
* Checkout the device handler for this port dispatcher on this thread
*
* @param dispatcher dispatcher context from aciomgr_port_init
* @return the device context
*/
struct aciodrv_device_ctx *
aciomgr_port_checkout(struct aciomgr_port_dispatcher *dispatcher);
/**
* Checkin the device handler that this thread holds
*
* @param dispatcher dispatcher context from aciomgr_port_init
*/
void aciomgr_port_checkin(struct aciomgr_port_dispatcher *dispatcher);
#endif

View File

@@ -3,10 +3,12 @@ exes += aciotest
libs_aciotest := \
bio2drv \
aciodrv \
aciodrv-proc \
util \
src_aciotest := \
icca.c \
kfca.c \
bi2a-sdvx.c \
panb.c \
main.c \

View File

@@ -8,22 +8,24 @@
#include "bio2drv/bi2a-sdvx.h"
bool aciotest_bi2a_sdvx_handler_init(uint8_t node_id, void **ctx)
bool aciotest_bi2a_sdvx_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t *) *ctx) = 0;
return bio2drv_bi2a_sdvx_init(node_id);
return bio2drv_bi2a_sdvx_init(device, node_id);
}
bool aciotest_bi2a_sdvx_handler_update(uint8_t node_id, void *ctx)
bool aciotest_bi2a_sdvx_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
struct bi2a_sdvx_state_in pin;
struct bi2a_sdvx_state_out pout;
memset(&pout, 0, sizeof(pout));
if (!bio2drv_bi2a_sdvx_poll(node_id, &pout, &pin)) {
if (!bio2drv_bi2a_sdvx_poll(device, node_id, &pout, &pin)) {
return false;
}

View File

@@ -4,7 +4,11 @@
#include <stdbool.h>
#include <stdint.h>
bool aciotest_bi2a_sdvx_handler_init(uint8_t node_id, void **ctx);
bool aciotest_bi2a_sdvx_handler_update(uint8_t node_id, void *ctx);
#include "aciodrv/device.h"
bool aciotest_bi2a_sdvx_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
bool aciotest_bi2a_sdvx_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
#endif

View File

@@ -1,6 +1,8 @@
#ifndef ACIOTEST_HANDLER_H
#define ACIOTEST_HANDLER_H
#include "aciodrv/device.h"
static const uint8_t aciotest_handler_max = 16;
/**
@@ -8,8 +10,10 @@ static const uint8_t aciotest_handler_max = 16;
*/
struct aciotest_handler_node_handler {
void *ctx;
bool (*init)(uint8_t node_id, void **ctx);
bool (*update)(uint8_t node_id, void *ctx);
bool (*init)(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
bool (*update)(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
};
#endif

View File

@@ -5,29 +5,52 @@
#include "aciodrv/icca.h"
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t *) *ctx) = 0;
return aciodrv_icca_init(node_id);
#define IDLE_RESPONSES_BETWEEN_FELICA_POLLS 5
struct icca_handler_ctx {
bool init;
bool slotted_reader;
uint8_t last_poll;
};
bool aciotest_icca_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(struct icca_handler_ctx));
struct icca_handler_ctx *icca_ctx = (struct icca_handler_ctx*)*ctx;
icca_ctx->init = false;
icca_ctx->slotted_reader = true;
icca_ctx->last_poll = 0;
icca_ctx->slotted_reader = aciodrv_icca_is_slotted(device, node_id);
return aciodrv_icca_init(device, node_id);
}
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
bool aciotest_icca_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
if (*((uint32_t *) ctx) == 0) {
*((uint32_t *) ctx) = 1;
struct icca_handler_ctx *icca_ctx = (struct icca_handler_ctx*)ctx;
/* eject cards that were left in the reader */
if (!aciodrv_icca_set_state(
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
return false;
if (icca_ctx->init == false) {
icca_ctx->init = true;
if (icca_ctx->slotted_reader) {
/* eject cards that were left in the reader */
if (!aciodrv_icca_set_state(
device, node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
return false;
}
}
}
struct ac_io_icca_state state;
if (!aciodrv_icca_get_state(node_id, &state)) {
if (!aciodrv_icca_get_state(device, node_id, &state)) {
return false;
}
@@ -58,33 +81,48 @@ bool aciotest_icca_handler_update(uint8_t node_id, void *ctx)
state.key_events[0],
state.key_events[1]);
/* eject card with "empty" key */
if (state.key_state & AC_IO_ICCA_KEYPAD_MASK_EMPTY) {
if (!aciodrv_icca_set_state(
node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
return false;
}
}
/* allow new card to be inserted when slot is clear */
if (!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
if (!aciodrv_icca_set_state(
node_id, AC_IO_ICCA_SLOT_STATE_OPEN, NULL)) {
return false;
}
}
/* lock the card when fully inserted */
if ((state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
if (!aciodrv_icca_set_state(
node_id, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL)) {
return false;
if (icca_ctx->slotted_reader) {
/* eject card with "empty" key */
if (state.key_state & AC_IO_ICCA_KEYPAD_MASK_EMPTY) {
if (!aciodrv_icca_set_state(
device, node_id, AC_IO_ICCA_SLOT_STATE_EJECT, NULL)) {
return false;
}
}
if (!aciodrv_icca_read_card(node_id, NULL)) {
return false;
/* allow new card to be inserted when slot is clear */
if (!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
!(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
if (!aciodrv_icca_set_state(
device, node_id, AC_IO_ICCA_SLOT_STATE_OPEN, NULL)) {
return false;
}
}
/* lock the card when fully inserted */
if ((state.sensor_state & AC_IO_ICCA_SENSOR_MASK_BACK_ON) &&
(state.sensor_state & AC_IO_ICCA_SENSOR_MASK_FRONT_ON)) {
if (!aciodrv_icca_set_state(
device, node_id, AC_IO_ICCA_SLOT_STATE_CLOSE, NULL)) {
return false;
}
if (!aciodrv_icca_read_card(device, node_id, NULL)) {
return false;
}
}
} else {
// wavepass reader, see eamio-icca for why this is done this way
if (state.status_code != AC_IO_ICCA_STATUS_BUSY_NEW) {
++icca_ctx->last_poll;
}
if (icca_ctx->last_poll >= IDLE_RESPONSES_BETWEEN_FELICA_POLLS) {
if (!aciodrv_icca_poll_felica(device, node_id)) {
return false;
}
icca_ctx->last_poll = 0;
}
}

View File

@@ -4,7 +4,11 @@
#include <stdbool.h>
#include <stdint.h>
bool aciotest_icca_handler_init(uint8_t node_id, void **ctx);
bool aciotest_icca_handler_update(uint8_t node_id, void *ctx);
#include "aciodrv/device.h"
bool aciotest_icca_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
bool aciotest_icca_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
#endif

View File

@@ -8,15 +8,17 @@
#include "aciodrv/kfca.h"
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx)
bool aciotest_kfca_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
*ctx = malloc(sizeof(uint32_t));
*((uint32_t *) *ctx) = 0;
return aciodrv_kfca_init(node_id);
return aciodrv_kfca_init(device, node_id);
}
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
bool aciotest_kfca_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
struct ac_io_kfca_poll_in pin;
struct ac_io_kfca_poll_out pout;
@@ -28,7 +30,7 @@ bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx)
pout.gpio |= 1 << gpio_test_pin;
pout.gpio = ac_io_u32(pout.gpio);
if (!aciodrv_kfca_poll(node_id, &pout, &pin)) {
if (!aciodrv_kfca_poll(device, node_id, &pout, &pin)) {
return false;
}

View File

@@ -4,7 +4,11 @@
#include <stdbool.h>
#include <stdint.h>
bool aciotest_kfca_handler_init(uint8_t node_id, void **ctx);
bool aciotest_kfca_handler_update(uint8_t node_id, void *ctx);
#include "aciodrv/device.h"
bool aciotest_kfca_handler_init(
struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
bool aciotest_kfca_handler_update(
struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
#endif

View File

@@ -10,6 +10,7 @@
#include "aciotest/handler.h"
#include "aciotest/icca.h"
#include "aciotest/kfca.h"
#include "aciotest/panb.h"
#include "util/log.h"
@@ -37,6 +38,13 @@ static bool aciotest_assign_handler(
return true;
}
if (!memcmp(product, "PANB", 4)) {
handler->init = aciotest_panb_handler_init;
handler->update = aciotest_panb_handler_update;
return true;
}
if (!memcmp(product, "BI2A", 4)) {
if (bi2a_mode == 0) {
handler->init = aciotest_bi2a_sdvx_handler_init;
@@ -70,14 +78,17 @@ int main(int argc, char **argv)
log_to_writer(log_writer_stdout, NULL);
if (!aciodrv_device_open(argv[1], atoi(argv[2]))) {
struct aciodrv_device_ctx *device = aciodrv_device_open_path(argv[1], atoi(argv[2]));
if (!device) {
printf("Opening acio device failed\n");
return -1;
}
printf("Opening acio device successful\n");
uint8_t node_count = aciodrv_device_get_node_count();
uint8_t node_count = aciodrv_device_get_node_count(device);
printf("Enumerated %d nodes\n", node_count);
struct aciotest_handler_node_handler handler[aciotest_handler_max];
@@ -88,7 +99,7 @@ int main(int argc, char **argv)
for (uint8_t i = 0; i < node_count; i++) {
char product[4];
aciodrv_device_get_node_product_ident(i, product);
aciodrv_device_get_node_product_ident(device, i, product);
printf(
"> %d: %c%c%c%c\n",
i + 1,
@@ -110,7 +121,7 @@ int main(int argc, char **argv)
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
if (handler[i].init != NULL) {
if (!handler[i].init(i, &handler[i].ctx)) {
if (!handler[i].init(device, i, &handler[i].ctx)) {
printf("ERROR: Initializing node %d failed\n", i);
handler[i].update = NULL;
}
@@ -129,7 +140,7 @@ int main(int argc, char **argv)
for (uint8_t i = 0; i < aciotest_handler_max; i++) {
if (handler[i].update != NULL) {
if (!handler[i].update(i, handler[i].ctx)) {
if (!handler[i].update(device, i, handler[i].ctx)) {
printf("ERROR: Updating node %d, removed from loop\n", i);
handler[i].update = NULL;
Sleep(5000);

76
src/main/aciotest/panb.c Normal file
View File

@@ -0,0 +1,76 @@
#include "aciotest/panb.h"
#include <stdio.h>
#include <stdlib.h>
#include "aciodrv/panb.h"
#include "aciodrv-proc/panb.h"
struct panb_handler_ctx {
bool running;
};
bool aciotest_panb_handler_init(struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx)
{
if (node_id != 0) {
return true;
}
*ctx = malloc(sizeof(struct panb_handler_ctx));
struct panb_handler_ctx *panb_ctx = (struct panb_handler_ctx*)*ctx;
panb_ctx->running = true;
return aciodrv_proc_panb_init(device);
}
bool aciotest_panb_handler_update(struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx)
{
uint8_t button[AC_IO_PANB_MAX_KEYS];
struct ac_io_panb_poll_out state;
struct panb_handler_ctx *panb_ctx = (struct panb_handler_ctx *) ctx;
if (node_id != 0) {
return true;
}
if (!panb_ctx->running) {
printf(">>> PANB:\nDevice has been closed. Press Ctrl+C to exit.");
return true;
}
if (!aciodrv_proc_panb_get_state(button)) {
return false;
}
printf(">>> PANB:\nPress first and last keys to close device\n");
for (int i=0; i<AC_IO_PANB_MAX_KEYS; i++) {
printf("%01X ", button[i]);
}
printf("\n");
/* I added a key combo to properly close the module.
* Leaving the PANB device in autopolling state without ever
* reading packets from the serial interface eventually
* makes it fall into a state where it doesn't send anything anymore
* and won't even respond to a reset, thus requiring a power cycle.
*/
if (button[0] && button[AC_IO_PANB_MAX_KEYS-1]) {
aciodrv_proc_panb_fini(device);
panb_ctx->running = false;
return true;
}
/* light the panel */
for (int i=0; i<AC_IO_PANB_MAX_KEYS; i++) {
state.key[i].green = (button[i])? 0x7F : 0;
state.key[i].red = 0;
state.key[i].blue = (button[i])? 0x23 : 0;
}
if (!aciodrv_panb_send_lamp(device, node_id, &state)) {
return false;
}
return true;
}

12
src/main/aciotest/panb.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef ACIOTEST_PANB_H
#define ACIOTEST_PANB_H
#include <stdbool.h>
#include <stdint.h>
#include "aciodrv/device.h"
bool aciotest_panb_handler_init(struct aciodrv_device_ctx *device, uint8_t node_id, void **ctx);
bool aciotest_panb_handler_update(struct aciodrv_device_ctx *device, uint8_t node_id, void *ctx);
#endif

View File

@@ -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. */

View File

@@ -29,6 +29,17 @@ enum jb_io_panel_bit {
JB_IO_PANEL_16 = 0x0F,
};
/* input "single button mode" mappings. Allows you to check each corner of each
button to determine any flaky inputs
*/
enum jb_io_panel_mode {
JB_IO_PANEL_MODE_ALL = 0, // any of the four corners will trigger a panel
JB_IO_PANEL_MODE_TOP_LEFT = 1,
JB_IO_PANEL_MODE_TOP_RIGHT = 2,
JB_IO_PANEL_MODE_BOTTOM_RIGHT = 3,
JB_IO_PANEL_MODE_BOTTOM_LEFT = 4,
};
/* Bit mappings for "system" inputs */
enum jb_io_sys_bit {
JB_IO_SYS_TEST = 0x00,
@@ -73,17 +84,36 @@ bool jb_io_init(
void jb_io_fini(void);
/* TODO doc */
/* Read input state */
bool jb_io_read_inputs(void);
bool jb_io_write_outputs(void);
/* Get state of coin, test, service inputs */
uint8_t jb_io_get_sys_inputs(void);
/* Get panel button state. Will return either any button being pressed, or a
particular panel corner depending on previous call to jb_io_set_panel_mode */
uint16_t jb_io_get_panel_inputs(void);
/* Set state of a PWM (dimmable) light */
void jb_io_set_rgb_led(
enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b);
/* Transmit the light state to the IOPCB */
bool jb_io_write_lights(void);
/* Select operating mode for the panel. Should be immediately sent to the IOPCB */
bool jb_io_set_panel_mode(enum jb_io_panel_mode mode);
/* Open or close the coin chute - true will redirect all coins to the return
slot. Required for jb_io_set_panel_mode to operate correctly on p4io.
Should be immediately sent to the IOPCB */
bool jb_io_set_coin_blocker(bool blocked);
#endif

View File

@@ -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

View File

@@ -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];

View File

@@ -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
};

View File

@@ -6,4 +6,5 @@ libs_bio2drv := \
src_bio2drv := \
detect.c \
config-bio2.c \
bi2a-sdvx.c \
bi2a-iidx.c \
bi2a-sdvx.c

View File

@@ -0,0 +1,122 @@
#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(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
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(
device,
&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(
struct aciodrv_device_ctx *device,
uint8_t node_id)
{
log_assert(device);
// 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;
// uint16_t: 6000
msg.cmd.raw[0] = 23;
msg.cmd.raw[1] = 112;
if (!aciodrv_send_and_recv(
device, &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(struct aciodrv_device_ctx *device, uint8_t node_id)
{
log_assert(device);
if (!bio2drv_bi2a_iidx_init_io(device, node_id)) {
return false;
}
if (!bio2drv_bi2a_iidx_watchdog_start(device, node_id)) {
return false;
}
return true;
}
bool bio2drv_bi2a_iidx_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct bi2a_iidx_state_out *pout,
struct bi2a_iidx_state_in *pin)
{
struct ac_io_message msg;
// log_assert(device);
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(
device,
&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;
}

View File

@@ -0,0 +1,40 @@
#ifndef BIO2DRV_BI2A_IIDX_H
#define BIO2DRV_BI2A_IIDX_H
#include "aciodrv/device.h"
#include "bio2/bi2a-iidx.h"
/**
* Initialize a BI2A node.
*
* @param device Context of opened device
* @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(
struct aciodrv_device_ctx *device,
uint8_t node_id);
/**
* Poll the BI2A board
*
* @param device Context of opened device
* @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(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct bi2a_iidx_state_out *pout,
struct bi2a_iidx_state_in *pin);
#endif

View File

@@ -9,18 +9,24 @@
#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)
static bool bio2drv_bi2a_sdvx_init_io(struct aciodrv_device_ctx *device, uint8_t node_id)
{
struct ac_io_message msg;
log_assert(device);
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)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Init node failed");
return 0;
}
@@ -30,8 +36,10 @@ static bool bio2drv_bi2a_sdvx_init_io(uint8_t node_id)
return 1;
}
static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
static bool bio2drv_bi2a_sdvx_watchdog_start(struct aciodrv_device_ctx *device, uint8_t node_id)
{
log_assert(device);
// 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)
@@ -50,7 +58,7 @@ static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
msg.cmd.raw[1] = 112;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 2
device, &msg, offsetof(struct ac_io_message, cmd.raw) + 2
)) {
log_warning("Starting watchdog failed"); return false;
}
@@ -63,6 +71,7 @@ static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
}
bool bio2drv_bi2a_sdvx_amp(
struct aciodrv_device_ctx *device,
uint8_t node_id,
uint8_t unused_1,
uint8_t unused_2,
@@ -71,6 +80,8 @@ bool bio2drv_bi2a_sdvx_amp(
{
struct ac_io_message msg;
log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
msg.cmd.nbytes = 4;
@@ -84,7 +95,9 @@ bool bio2drv_bi2a_sdvx_amp(
msg.cmd.raw[3] = right;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Setting AMP failed");
return false;
}
@@ -94,17 +107,19 @@ bool bio2drv_bi2a_sdvx_amp(
return true;
}
bool bio2drv_bi2a_sdvx_init(uint8_t node_id)
bool bio2drv_bi2a_sdvx_init(struct aciodrv_device_ctx *device, uint8_t node_id)
{
if (!bio2drv_bi2a_sdvx_init_io(node_id)) {
log_assert(device);
if (!bio2drv_bi2a_sdvx_init_io(device, node_id)) {
return false;
}
if (!bio2drv_bi2a_sdvx_watchdog_start(node_id)) {
if (!bio2drv_bi2a_sdvx_watchdog_start(device, node_id)) {
return false;
}
if (!bio2drv_bi2a_sdvx_amp(node_id, 0, 0, 0, 0)) {
if (!bio2drv_bi2a_sdvx_amp(device, node_id, 0, 0, 0, 0)) {
return false;
}
@@ -112,12 +127,15 @@ bool bio2drv_bi2a_sdvx_init(uint8_t node_id)
}
bool bio2drv_bi2a_sdvx_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct bi2a_sdvx_state_out *pout,
struct bi2a_sdvx_state_in *pin)
{
struct ac_io_message msg;
// log_assert(device);
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
msg.cmd.nbytes = sizeof(*pout);
@@ -125,7 +143,9 @@ bool bio2drv_bi2a_sdvx_poll(
*(struct bi2a_sdvx_state_out *) msg.cmd.raw = *pout;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
device,
&msg,
offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}

View File

@@ -1,22 +1,28 @@
#ifndef BIO2DRV_BI2A_H
#define BIO2DRV_BI2A_H
#ifndef BIO2DRV_BI2A_SDVX_H
#define BIO2DRV_BI2A_SDVX_H
#include "aciodrv/device.h"
#include "bio2/bi2a-sdvx.h"
/**
* Initialize a BI2A node.
*
* @param device Context of opened device
* @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_sdvx_init(uint8_t node_id);
bool bio2drv_bi2a_sdvx_init(
struct aciodrv_device_ctx *device,
uint8_t node_id);
/**
* Poll the board
*
* @param device Context of opened device
* @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).
@@ -26,6 +32,7 @@ bool bio2drv_bi2a_sdvx_init(uint8_t node_id);
* @see driver.h
*/
bool bio2drv_bi2a_sdvx_poll(
struct aciodrv_device_ctx *device,
uint8_t node_id,
const struct bi2a_sdvx_state_out *pout,
struct bi2a_sdvx_state_in *pin);
@@ -33,6 +40,7 @@ bool bio2drv_bi2a_sdvx_poll(
/**
* Set the BIO2 BI2A SDVX digital amp level
*
* @param device Context of opened device
* @param node_id Id of the node to query (0 based).
* @param primary primary volume (96-0)
* @param headphone headphone volume (96-0)
@@ -42,6 +50,7 @@ bool bio2drv_bi2a_sdvx_poll(
* @note Note 96 is lowest volume level, 0 is highest
*/
bool bio2drv_bi2a_sdvx_amp(
struct aciodrv_device_ctx *device,
uint8_t node_id,
uint8_t unused_1,
uint8_t unused_2,

View File

@@ -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,

Some files were not shown because too many files have changed in this diff Show More